hythmbox-2.98/rhythmdb/rhythmdb-song-entry-types.c

No issues found

  1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  2  *
  3  *  Copyright (C) 2010  Jonathan Matthew  <jonathan@d14n.org>
  4  *
  5  *  This program is free software; you can redistribute it and/or modify
  6  *  it under the terms of the GNU General Public License as published by
  7  *  the Free Software Foundation; either version 2 of the License, or
  8  *  (at your option) any later version.
  9  *
 10  *  The Rhythmbox authors hereby grant permission for non-GPL compatible
 11  *  GStreamer plugins to be used and distributed together with GStreamer
 12  *  and Rhythmbox. This permission is above and beyond the permissions granted
 13  *  by the GPL license by which Rhythmbox is covered. If you modify this code
 14  *  you may extend this exception to your version of the code, but you are not
 15  *  obligated to do so. If you do not wish to do so, delete this exception
 16  *  statement from your version.
 17  *
 18  *  This program is distributed in the hope that it will be useful,
 19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21  *  GNU General Public License for more details.
 22  *
 23  *  You should have received a copy of the GNU General Public License
 24  *  along with this program; if not, write to the Free Software
 25  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
 26  *
 27  */
 28 
 29 #include "config.h"
 30 
 31 #include "rhythmdb-entry-type.h"
 32 #include "rhythmdb-private.h"
 33 #include "rb-util.h"
 34 #include "rb-debug.h"
 35 
 36 static RhythmDBEntryType *song_entry_type = NULL;
 37 static RhythmDBEntryType *error_entry_type = NULL;
 38 static RhythmDBEntryType *ignore_entry_type = NULL;
 39 
 40 
 41 typedef struct _RhythmDBEntryType RhythmDBSongEntryType;
 42 typedef struct _RhythmDBEntryTypeClass RhythmDBSongEntryTypeClass;
 43 
 44 static void rhythmdb_song_entry_type_class_init (RhythmDBSongEntryTypeClass *klass);
 45 static void rhythmdb_song_entry_type_init (RhythmDBSongEntryType *etype);
 46 GType rhythmdb_song_entry_type_get_type (void);
 47 G_DEFINE_TYPE (RhythmDBSongEntryType, rhythmdb_song_entry_type, RHYTHMDB_TYPE_ENTRY_TYPE);
 48 
 49 
 50 typedef struct _RhythmDBEntryType RhythmDBErrorEntryType;
 51 typedef struct _RhythmDBEntryTypeClass RhythmDBErrorEntryTypeClass;
 52 
 53 static void rhythmdb_error_entry_type_class_init (RhythmDBErrorEntryTypeClass *klass);
 54 static void rhythmdb_error_entry_type_init (RhythmDBErrorEntryType *etype);
 55 GType rhythmdb_error_entry_type_get_type (void);
 56 G_DEFINE_TYPE (RhythmDBErrorEntryType, rhythmdb_error_entry_type, RHYTHMDB_TYPE_ENTRY_TYPE);
 57 
 58 
 59 typedef struct _RhythmDBEntryType RhythmDBIgnoreEntryType;
 60 typedef struct _RhythmDBEntryTypeClass RhythmDBIgnoreEntryTypeClass;
 61 
 62 static void rhythmdb_ignore_entry_type_class_init (RhythmDBIgnoreEntryTypeClass *klass);
 63 static void rhythmdb_ignore_entry_type_init (RhythmDBIgnoreEntryType *etype);
 64 GType rhythmdb_ignore_entry_type_get_type (void);
 65 G_DEFINE_TYPE (RhythmDBIgnoreEntryType, rhythmdb_ignore_entry_type, RHYTHMDB_TYPE_ENTRY_TYPE);
 66 
 67 static void
 68 update_entry_last_seen (RhythmDB *db, RhythmDBEntry *entry)
 69 {
 70 	GTimeVal time;
 71 	GValue val = {0, };
 72 
 73 	g_get_current_time (&time);
 74 	g_value_init (&val, G_TYPE_ULONG);
 75 	g_value_set_ulong (&val, time.tv_sec);
 76 	rhythmdb_entry_set_internal (db, entry, FALSE, RHYTHMDB_PROP_LAST_SEEN, &val);
 77 	g_value_unset (&val);
 78 }
 79 
 80 static gboolean
 81 check_entry_grace_period (RhythmDB *db, RhythmDBEntry *entry)
 82 {
 83 	GTimeVal time;
 84 	gulong last_seen;
 85 	gulong grace_period;
 86 	GError *error;
 87 
 88 	error = NULL;
 89 	grace_period = g_settings_get_int (db->priv->settings, "grace-period");
 90 	if (error != NULL) {
 91 		g_error_free (error);
 92 		return FALSE;
 93 	}
 94 
 95 	/* This is a bit silly, but I prefer to make sure we won't
 96 	 * overflow in the following calculations
 97 	 */
 98 	if ((grace_period <= 0) || (grace_period > 20000)) {
 99 		return FALSE;
100 	}
101 
102 	/* Convert from days to seconds */
103 	grace_period = grace_period * 60 * 60 * 24;
104 	g_get_current_time (&time);
105 	last_seen = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_LAST_SEEN);
106 
107 	return (last_seen + grace_period < time.tv_sec);
108 }
109 
110 static void
111 song_sync_metadata (RhythmDBEntryType *entry_type,
112 		    RhythmDBEntry *entry,
113 		    GSList *changes,
114 		    GError **error)
115 {
116 	RhythmDB *db;
117 
118 	g_object_get (entry_type, "db", &db, NULL);
119 	rhythmdb_entry_write_metadata_changes (db, entry, changes, error);
120 	g_object_unref (db);
121 }
122 
123 
124 static gboolean
125 song_can_sync_metadata (RhythmDBEntryType *entry_type,
126 			RhythmDBEntry *entry)
127 {
128 	const char *media_type;
129 	gboolean can_sync;
130 	RhythmDB *db;
131 
132 	g_object_get (entry_type, "db", &db, NULL);
133 
134 	media_type = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE);
135 	can_sync = rb_metadata_can_save (db->priv->metadata, media_type);
136 
137 	g_object_unref (db);
138 	return can_sync;
139 }
140 
141 static void
142 song_update_availability (RhythmDBEntryType *entry_type,
143 			  RhythmDBEntry *entry,
144 			  RhythmDBEntryAvailability avail)
145 {
146 	RhythmDB *db;
147 
148 	g_object_get (entry_type, "db", &db, NULL);
149 	switch (avail) {
150 	case RHYTHMDB_ENTRY_AVAIL_MOUNTED:
151 		rhythmdb_entry_set_visibility (db, entry, TRUE);
152 		break;
153 
154 	case RHYTHMDB_ENTRY_AVAIL_CHECKED:
155 		update_entry_last_seen (db, entry);
156 		rhythmdb_entry_set_visibility (db, entry, TRUE);
157 		break;
158 
159 	case RHYTHMDB_ENTRY_AVAIL_UNMOUNTED:
160 		/* update the last-seen time if the entry is currently visible */
161 		if (rhythmdb_entry_get_boolean (entry, RHYTHMDB_PROP_HIDDEN) == FALSE) {
162 			update_entry_last_seen (db, entry);
163 		}
164 		rhythmdb_entry_set_visibility (db, entry, FALSE);
165 		break;
166 
167 	case RHYTHMDB_ENTRY_AVAIL_NOT_FOUND:
168 		if (check_entry_grace_period (db, entry)) {
169 			rb_debug ("deleting entry %s; not seen for too long",
170 				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
171 			rhythmdb_entry_delete (db, entry);
172 		} else {
173 			rhythmdb_entry_set_visibility (db, entry, FALSE);
174 		}
175 		break;
176 
177 	default:
178 		g_assert_not_reached ();
179 	}
180 	g_object_unref (db);
181 }
182 
183 static void
184 import_error_update_availability (RhythmDBEntryType *entry_type,
185 				  RhythmDBEntry *entry,
186 				  RhythmDBEntryAvailability avail)
187 {
188 	RhythmDB *db;
189 
190 	switch (avail) {
191 	case RHYTHMDB_ENTRY_AVAIL_MOUNTED:
192 	case RHYTHMDB_ENTRY_AVAIL_CHECKED:
193 		/* do nothing; should never happen anyway */
194 		break;
195 	case RHYTHMDB_ENTRY_AVAIL_UNMOUNTED:
196 	case RHYTHMDB_ENTRY_AVAIL_NOT_FOUND:
197 		/* no need to keep error entries if the file is unavailable */
198 		g_object_get (entry_type, "db", &db, NULL);
199 		rhythmdb_entry_delete (db, entry);
200 		g_object_unref (db);
201 		break;
202 
203 	default:
204 		g_assert_not_reached ();
205 	}
206 }
207 
208 
209 /**
210  * rhythmdb_get_song_entry_type:
211  *
212  * Returns the #RhythmDBEntryType for normal songs.
213  *
214  * Returns: (transfer none): the entry type for normal songs
215  */
216 RhythmDBEntryType *
217 rhythmdb_get_song_entry_type (void)
218 {
219 	return song_entry_type;
220 }
221 
222 /**
223  * rhythmdb_get_ignore_entry_type:
224  *
225  * Returns the #RhythmDBEntryType for ignored files
226  *
227  * Return value: (transfer none): the entry type for ignored files
228  */
229 RhythmDBEntryType *
230 rhythmdb_get_ignore_entry_type (void)
231 {
232 	return ignore_entry_type;
233 }
234 
235 /**
236  * rhythmdb_get_error_entry_type:
237  *
238  * Returns the #RhythmDBEntryType for import errors
239  *
240  * Return value: (transfer none): the entry type for import errors
241  */
242 RhythmDBEntryType *
243 rhythmdb_get_error_entry_type (void)
244 {
245 	return error_entry_type;
246 }
247 
248 
249 static void
250 rhythmdb_song_entry_type_class_init (RhythmDBSongEntryTypeClass *klass)
251 {
252 	RhythmDBEntryTypeClass *etype_class = RHYTHMDB_ENTRY_TYPE_CLASS (klass);
253 
254 	etype_class->can_sync_metadata = song_can_sync_metadata;
255 	etype_class->sync_metadata = song_sync_metadata;
256 	etype_class->update_availability = song_update_availability;
257 }
258 
259 static void
260 rhythmdb_song_entry_type_init (RhythmDBSongEntryType *etype)
261 {
262 }
263 
264 static void
265 rhythmdb_error_entry_type_class_init (RhythmDBErrorEntryTypeClass *klass)
266 {
267 	RhythmDBEntryTypeClass *etype_class = RHYTHMDB_ENTRY_TYPE_CLASS (klass);
268 
269 	etype_class->get_playback_uri = (RhythmDBEntryTypeStringFunc) rb_null_function;
270 	etype_class->can_sync_metadata = (RhythmDBEntryTypeBooleanFunc) rb_true_function;
271 	etype_class->sync_metadata = (RhythmDBEntryTypeSyncFunc) rb_null_function;
272 	etype_class->update_availability = import_error_update_availability;
273 }
274 
275 static void
276 rhythmdb_error_entry_type_init (RhythmDBErrorEntryType *etype)
277 {
278 }
279 
280 static void
281 rhythmdb_ignore_entry_type_class_init (RhythmDBIgnoreEntryTypeClass *klass)
282 {
283 	RhythmDBEntryTypeClass *etype_class = RHYTHMDB_ENTRY_TYPE_CLASS (klass);
284 
285 	etype_class->get_playback_uri = (RhythmDBEntryTypeStringFunc) rb_null_function;
286 	etype_class->update_availability = song_update_availability;
287 }
288 
289 static void
290 rhythmdb_ignore_entry_type_init (RhythmDBIgnoreEntryType *etype)
291 {
292 }
293 
294 
295 void
296 rhythmdb_register_song_entry_types (RhythmDB *db)
297 {
298 	g_assert (song_entry_type == NULL);
299 	g_assert (error_entry_type == NULL);
300 	g_assert (ignore_entry_type == NULL);
301 
302 	song_entry_type = g_object_new (rhythmdb_song_entry_type_get_type (),
303 					"db", db,
304 					"name", "song",
305 					"save-to-disk", TRUE,
306 					"has-playlists", TRUE,
307 					NULL);
308 
309 	ignore_entry_type = g_object_new (rhythmdb_ignore_entry_type_get_type (),
310 					  "db", db,
311 					  "name", "ignore",
312 					  "save-to-disk", TRUE,
313 					  "category", RHYTHMDB_ENTRY_VIRTUAL,
314 					  NULL);
315 
316 	error_entry_type = g_object_new (rhythmdb_error_entry_type_get_type (),
317 					 "db", db,
318 					 "name", "import-error",
319 					 "category", RHYTHMDB_ENTRY_VIRTUAL,
320 					 NULL);
321 
322 	rhythmdb_register_entry_type (db, song_entry_type);
323 	rhythmdb_register_entry_type (db, error_entry_type);
324 	rhythmdb_register_entry_type (db, ignore_entry_type);
325 }