Commits

ryanackley committed ede1a92

Linux file watch working

Comments (0)

Files changed (6)

X11/DialogManagerX11.cpp~

+#include <string>
+#include <boost/thread.hpp>
+
+#include "DialogManagerX11.h"
+#include "BrowserHost.h"
+#include "PluginWindowX11.h"
+
+DialogManager* DialogManager::get()
+{
+    static DialogManagerX11 inst;
+    return &inst;
+}
+
+void DialogManagerX11::OpenFolderDialog(const FB::BrowserHostPtr& host, FB::PluginWindow* win, const PathCallback& cb)
+{
+    FB::PluginWindowX11* x11Win = dynamic_cast<FB::PluginWindowX11*>(win);
+    GdkNativeWindow nativeWin = x11Win->getBrowserWindow();
+    GtkWindow* gtkWin = gdk_window_lookup(nativeWin);
+    host->ScheduleOnMainThread(boost::shared_ptr<DialogManagerX11>(), boost::bind(&DialogManagerX11::_showFolderDialog, this, gtkWin, cb));
+}
+
+void DialogManagerX11::_showFolderDialog(GtkWindow* win, const PathCallback& cb)
+{
+    std::string out;
+    GtkWidget *dialog;
+    dialog = gtk_file_chooser_dialog_new ("Open File",
+				      win,
+				      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+				      NULL);
+    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+        char *filename;
+        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+        out = filename;
+        g_free (filename);
+    }
+    gtk_widget_destroy (dialog);
+    cb(out);
+}

X11/DialogManagerX11.h~

+//  Created by Ryan Ackley on 4/10/12.
+//  Copyright (c) 2012 Benryan Software Inc. All rights reserved.
+//
+
+#ifndef DialogManagerX11_h__
+#define DialogManagerX11_h__
+
+#include <boost/noncopyable.hpp>
+#include <string>
+#include <gtk/gtk.h>
+
+#include "../DialogManager.h"
+
+class DialogManagerX11 : public DialogManager
+{
+public:
+    void OpenFolderDialog(const FB::BrowserHostPtr& host, FB::PluginWindow* win, const PathCallback& cb);
+    void _showFolderDialog(GtkWindow* win, const PathCallback& cb);
+    
+protected:
+    DialogManagerX11() {};
+    ~DialogManagerX11() {};
+    friend class DialogManager;
+};
+#endif // DialogManagerX11_h__

X11/FileWatcherTaskX11.cpp

+/*
+ * FileWatcherTaskX11.cpp
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+
+
+#include "FileWatcherTaskX11.h"
+#include <boost/thread.hpp>
+#include <sys/inotify.h>
+#include <iostream>
+#include "variant_list.h"
+
+#define EVENT_SIZE  ( sizeof (struct inotify_event) )
+#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )
+
+using namespace boost::filesystem;
+
+void FileWatcherTaskX11::Watch(boost::filesystem::path p, FB::JSObjectPtr callback)
+{
+	boost::thread thread = boost::thread(boost::bind(&FileWatcherTaskX11::ListenForFileEvents, this, p, callback));
+	thread.detach();
+}
+
+void FileWatcherTaskX11::ListenForFileEvents(boost::filesystem::path path, FB::JSObjectPtr callback)
+{
+	int length;//, i = 0;
+	int fd;
+	int wd;
+	char buffer[EVENT_BUF_LEN];
+
+	/*creating the INOTIFY instance*/
+	fd = inotify_init();
+
+	/*checking for error*/
+	if ( fd < 0 ) {
+		std::cerr << "inotify_init" ;
+	}
+
+	std::map<int, boost::filesystem::path*> wdMap;
+
+	/*adding the  directory into watch list. Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/
+	//wd = inotify_add_watch( fd, path.c_str(), IN_MODIFY | IN_MOVED_TO);
+	this->AddWatchToDir(fd, path, wdMap );
+
+	/*read to determine the event change happens on “/tmp” directory. Actually this read blocks until the change event occurs*/
+	while (!this->_ShouldStop())
+	{
+		int i = 0;
+		struct timeval time;
+		fd_set set;
+
+		time.tv_sec = 10;
+		time.tv_usec = 0;
+
+		FD_ZERO(&set);
+		FD_SET(fd, &set);
+
+		int sr = select (FD_SETSIZE, &set, NULL, NULL, &time);
+		if (!sr) //timeout
+		{
+			continue;
+		}
+		else if (sr > 0)
+		{
+			length = read( fd, buffer, EVENT_BUF_LEN );
+
+			/*checking for error*/
+			if ( length < 0 )
+			{
+				std::cerr << "read";
+			}
+
+			/*actually read return the list of change events happens. Here, read the change event one by one and process it accordingly.*/
+			while ( i < length )
+			{
+				struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
+				if ( event->len )
+				{
+					if ( ((event->mask & IN_MODIFY) || (event->mask & IN_MOVED_TO)) &&  !(event->mask & IN_ISDIR) )
+					{
+						std::string filename = event->name;
+						if (filename[0] != '.')
+						{
+							boost::filesystem::path* root = wdMap[event->wd];
+							boost::filesystem::path fsPath = *root / filename;
+							callback->Invoke("", FB::variant_list_of(fsPath.generic_string()));
+						}
+					}
+				}
+				i += EVENT_SIZE + event->len;
+			}
+		}
+		else
+		{
+			std::cerr << "select";
+			break;
+		}
+	}
+	/*removing the “/tmp” directory from the watch list.*/
+	std::map<int, boost::filesystem::path*>::iterator it;
+	for (it = wdMap.begin(); it != wdMap.end(); it++)
+	{
+		inotify_rm_watch( fd, (*it).first );
+		delete (*it).second;
+	}
+	//inotify_rm_watch( fd, wd );
+
+	/*closing the INOTIFY instance*/
+	close( fd );
+}
+
+void FileWatcherTaskX11::AddWatchToDir(int fd, boost::filesystem::path p, std::map<int, boost::filesystem::path*> &watchDescriptors)
+{
+	int wd = inotify_add_watch( fd, p.generic_string().c_str(), IN_MODIFY | IN_MOVED_TO);
+	watchDescriptors[wd] = new path(p);
+
+	directory_iterator di(p);
+	directory_iterator eos;
+
+	while(di != eos)
+	{
+		directory_entry de = *di;
+		if (is_directory(de.status())){
+			this->AddWatchToDir(fd, de.path(), watchDescriptors);
+		}
+		di++;
+	}
+}
+
+void FileWatcherTaskX11::StopWatching()
+{
+	this->stop = 1;
+}
+
+bool FileWatcherTaskX11::_ShouldStop()
+{
+	return this->stop != 0;
+}
+
+
+
+

X11/FileWatcherTaskX11.h

+/*
+ * FileWatcherTaskX11.h
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+#ifndef FILEWATCHERTASKX11_H_
+#define FILEWATCHERTASKX11_H_
+#define BOOST_FILESYSTEM_VERSION 3
+
+#include "JSObject.h"
+#include <boost/filesystem.hpp>
+
+class FileWatcherTaskX11 {
+public:
+	FileWatcherTaskX11(){stop = 0;};
+	~FileWatcherTaskX11(){};
+	void Watch(boost::filesystem::path path, FB::JSObjectPtr callback);
+	void StopWatching();
+
+private:
+	void ListenForFileEvents(boost::filesystem::path path, FB::JSObjectPtr callback);
+	void AddWatchToDir(int fd, boost::filesystem::path path, std::map<int, boost::filesystem::path*> &watchDescriptors);
+	bool _ShouldStop();
+	int stop;
+};
+
+#endif /* FILEWATCHERTASKX11_H_ */

X11/FileWatcherX11.cpp

+/*
+ * FileWatcherX11.cpp
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+#include "FileWatcherX11.h"
+
+FileWatcher* FileWatcher::get()
+{
+    static FileWatcherX11 inst;
+    return &inst;
+}
+
+void FileWatcherX11::WatchFile(std::string key, std::string path, FB::JSObjectPtr callback)
+{
+	FileWatcherTaskX11* task = watchers[key];
+	if (!task)
+	{
+		boost::filesystem::path p(path);
+		if (is_directory(p))
+		{
+			task = new FileWatcherTaskX11();
+			task->Watch(p, callback);
+			watchers[key] = task;
+		}
+	}
+
+}
+void FileWatcherX11::StopWatching(std::string key)
+{
+	FileWatcherTaskX11* task = watchers[key];
+	if (task)
+	{
+		task->StopWatching();
+		watchers.erase(key);
+		delete task;
+	}
+}

X11/FileWatcherX11.h

+/*
+ * FileWatcherX11.h
+ *
+ *  Created on: 22/05/2012
+ *      Author: ryan
+ */
+
+#ifndef FILEWATCHERX11_H_
+#define FILEWATCHERX11_H_
+
+#include <map>
+#include "../FileWatcher.h"
+#include "FileWatcherTaskX11.h"
+
+class FileWatcherX11 : public FileWatcher{
+
+public:
+    void WatchFile(std::string key, std::string path, FB::JSObjectPtr callback);
+    void StopWatching(std::string key);
+protected:
+	FileWatcherX11(){};
+	virtual ~FileWatcherX11(){};
+	friend class FileWatcher;
+private:
+	std::map<std::string,FileWatcherTaskX11*> watchers;
+};
+
+#endif /* FILEWATCHERX11_H_ */