1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2 
3    nemo-monitor.c: file and directory change monitoring for nemo
4 
5    Copyright (C) 2000, 2001 Eazel, Inc.
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16 
17    You should have received a copy of the GNU General Public
18    License along with this program; if not, write to the
19    Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
20    Boston, MA 02110-1335, USA.
21 
22    Authors: Seth Nickell <seth@eazel.com>
23             Darin Adler <darin@bentspoon.com>
24 	    Alex Graveley <alex@ximian.com>
25 */
26 
27 #include <config.h>
28 #include "nemo-monitor.h"
29 #include "nemo-file-changes-queue.h"
30 #include "nemo-file-utilities.h"
31 
32 #include <gio/gio.h>
33 
34 struct NemoMonitor {
35 	GFileMonitor *monitor;
36     GVolumeMonitor *volume_monitor;
37     GFile *location;
38 };
39 
40 gboolean
nemo_monitor_active(void)41 nemo_monitor_active (void)
42 {
43 	static gboolean tried_monitor = FALSE;
44 	static gboolean monitor_success;
45 	GFileMonitor *dir_monitor;
46 	GFile *file;
47 
48 	if (tried_monitor == FALSE) {
49 		file = g_file_new_for_path (g_get_home_dir ());
50 		dir_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
51 		g_object_unref (file);
52 
53 		monitor_success = (dir_monitor != NULL);
54 		if (dir_monitor) {
55 			g_object_unref (dir_monitor);
56 		}
57 
58 		tried_monitor = TRUE;
59 	}
60 
61 	return monitor_success;
62 }
63 
64 static gboolean call_consume_changes_idle_id = 0;
65 
66 static gboolean
call_consume_changes_idle_cb(gpointer not_used)67 call_consume_changes_idle_cb (gpointer not_used)
68 {
69 	nemo_file_changes_consume_changes (TRUE);
70 	call_consume_changes_idle_id = 0;
71 	return FALSE;
72 }
73 
74 static void
schedule_call_consume_changes(void)75 schedule_call_consume_changes (void)
76 {
77   if (call_consume_changes_idle_id == 0) {
78       call_consume_changes_idle_id =
79           g_idle_add (call_consume_changes_idle_cb, NULL);
80   }
81 }
82 
83 static void
mount_removed(GVolumeMonitor * volume_monitor,GMount * mount,gpointer user_data)84 mount_removed (GVolumeMonitor *volume_monitor,
85          GMount *mount,
86          gpointer user_data)
87 {
88   NemoMonitor *monitor = user_data;
89   GFile *mount_location;
90 
91   mount_location = g_mount_get_root (mount);
92 
93   if (g_file_has_prefix (monitor->location, mount_location)) {
94       nemo_file_changes_queue_file_removed (monitor->location);
95       schedule_call_consume_changes ();
96   }
97 
98   g_object_unref (mount_location);
99 }
100 
101 static void
dir_changed(GFileMonitor * monitor,GFile * child,GFile * other_file,GFileMonitorEvent event_type,gpointer user_data)102 dir_changed (GFileMonitor* monitor,
103 	     GFile *child,
104 	     GFile *other_file,
105 	     GFileMonitorEvent event_type,
106 	     gpointer user_data)
107 {
108 	char *uri, *to_uri;
109 
110 	uri = g_file_get_uri (child);
111     // g_printerr ("ATT CHANGED %s  %d\n", uri, event_type);
112 	to_uri = NULL;
113 	if (other_file) {
114 		to_uri = g_file_get_uri (other_file);
115 	}
116 
117 	switch (event_type) {
118         case G_FILE_MONITOR_EVENT_MOVED:
119         case G_FILE_MONITOR_EVENT_RENAMED:
120         case G_FILE_MONITOR_EVENT_MOVED_IN:
121         case G_FILE_MONITOR_EVENT_MOVED_OUT:
122 	default:
123 	case G_FILE_MONITOR_EVENT_CHANGED:
124 		/* ignore */
125 		break;
126 	case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
127 	case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
128 		nemo_file_changes_queue_file_changed (child);
129 		break;
130 	case G_FILE_MONITOR_EVENT_DELETED:
131 		nemo_file_changes_queue_file_removed (child);
132 		break;
133 	case G_FILE_MONITOR_EVENT_CREATED:
134 		nemo_file_changes_queue_file_added (child);
135 		break;
136 
137 	case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
138 		/* TODO: Do something */
139 		break;
140 	case G_FILE_MONITOR_EVENT_UNMOUNTED:
141 		/* TODO: Do something */
142 		break;
143 	}
144 
145 	g_free (uri);
146 	g_free (to_uri);
147 
148     schedule_call_consume_changes ();
149 }
150 
151 NemoMonitor *
nemo_monitor_directory(GFile * location)152 nemo_monitor_directory (GFile *location)
153 {
154 	GFileMonitor *dir_monitor;
155 	NemoMonitor *ret;
156 
157     ret = g_new0 (NemoMonitor, 1);
158 	dir_monitor = g_file_monitor_directory (location, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
159 
160     if (dir_monitor != NULL) {
161         ret->monitor = dir_monitor;
162     } else if (!g_file_is_native (location)) {
163         ret->location = g_object_ref (location);
164         ret->volume_monitor = g_volume_monitor_get ();
165     }
166 
167     if (ret->monitor != NULL) {
168         g_signal_connect (ret->monitor, "changed",
169                           G_CALLBACK (dir_changed), ret);
170     }
171 
172 
173     if (ret->volume_monitor != NULL) {
174         g_signal_connect (ret->volume_monitor, "mount-removed",
175                           G_CALLBACK (mount_removed), ret);
176     }
177 
178 	/* We return a monitor even on failure, so we can avoid later trying again */
179 	return ret;
180 }
181 
182 void
nemo_monitor_cancel(NemoMonitor * monitor)183 nemo_monitor_cancel (NemoMonitor *monitor)
184 {
185 	if (monitor->monitor != NULL) {
186 		g_signal_handlers_disconnect_by_func (monitor->monitor, dir_changed, monitor);
187 		g_file_monitor_cancel (monitor->monitor);
188 		g_object_unref (monitor->monitor);
189 	}
190 
191     if (monitor->volume_monitor != NULL) {
192         g_signal_handlers_disconnect_by_func (monitor->volume_monitor, mount_removed, monitor);
193         g_object_unref (monitor->volume_monitor);
194     }
195 
196     g_clear_object (&monitor->location);
197 	g_free (monitor);
198 }
199