void rb_generic_player_source_trash_or_delete_entries (RBGenericPlayerSource *source, GList *entries, gboolean _delete) { RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source); GList *tem; if (priv->read_only != FALSE) return; for (tem = entries; tem != NULL; tem = tem->next) { RhythmDBEntry *entry; const char *uri; GFile *file; GFile *dir; entry = tem->data; uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION); file = g_file_new_for_uri (uri); if (_delete) g_file_delete (file, NULL, NULL); else g_file_trash (file, NULL, NULL); /* now walk up the directory structure and delete empty dirs * until we reach the root or one of the device's audio folders. */ dir = g_file_get_parent (file); while (can_delete_directory (source, dir)) { GFile *parent; char *path; path = g_file_get_path (dir); rb_debug ("trying to delete %s", path); g_free (path); if (g_file_delete (dir, NULL, NULL) == FALSE) { break; } parent = g_file_get_parent (dir); if (parent == NULL) { break; } g_object_unref (dir); dir = parent; } g_object_unref (dir); g_object_unref (file); rhythmdb_entry_delete (priv->db, entry); } rhythmdb_commit (priv->db); }
END_TEST START_TEST (test_rhythmdb_multiple) { RhythmDBEntry *entry1, *entry2, *entry3; /* add multiple entries */ entry1 = rhythmdb_entry_new (db, RHYTHMDB_ENTRY_TYPE_IGNORE, "file:///foo.mp3"); rhythmdb_commit (db); fail_unless (entry1 != NULL, "failed to create entry"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///foo.mp3") == entry1, "entry missing"); entry2 = rhythmdb_entry_new (db, RHYTHMDB_ENTRY_TYPE_IGNORE, "file:///bar.mp3"); rhythmdb_commit (db); fail_unless (entry2 != NULL, "failed to create entry"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///bar.mp3") == entry2, "entry missing"); entry3 = rhythmdb_entry_new (db, RHYTHMDB_ENTRY_TYPE_IGNORE, "file:///baz.mp3"); rhythmdb_commit (db); fail_unless (entry3 != NULL, "failed to create entry"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///baz.mp3") == entry3, "entry missing"); /* check they're still there */ fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///foo.mp3") == entry1, "entry missing"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///bar.mp3") == entry2, "entry missing"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///baz.mp3") == entry3, "entry missing"); /* remove the middle one and check again */ rhythmdb_entry_delete (db, entry2); rhythmdb_commit (db); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///foo.mp3") == entry1, "entry missing"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///bar.mp3") == NULL, "entry not deleted"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///baz.mp3") == entry3, "entry missing"); /* and the others */ rhythmdb_entry_delete (db, entry1); rhythmdb_entry_delete (db, entry3); rhythmdb_commit (db); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///foo.mp3") == NULL, "entry not deleted"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///bar.mp3") == NULL, "entry not deleted"); fail_unless (rhythmdb_entry_lookup_by_location (db, "file:///baz.mp3") == NULL, "entry not deleted"); }
static void impl_delete_entries (RBMediaPlayerSource *source, GList *entries, RBMediaPlayerSourceDeleteCallback callback, gpointer user_data, GDestroyNotify destroy_data) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); RhythmDB *db; GList *i; TracksDeletedCallbackData *cb_data; cb_data = g_new0 (TracksDeletedCallbackData, 1); cb_data->source = g_object_ref (source); cb_data->callback_data = user_data; cb_data->callback = callback; cb_data->destroy_data = destroy_data; cb_data->check_folders = g_hash_table_new (g_direct_hash, g_direct_equal); db = get_db_for_source (RB_MTP_SOURCE (source)); for (i = entries; i != NULL; i = i->next) { LIBMTP_track_t *track; const char *uri; const char *album_name; RhythmDBEntry *entry; entry = i->data; uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION); track = g_hash_table_lookup (priv->entry_map, entry); if (track == NULL) { rb_debug ("Couldn't find track on mtp-device! (%s)", uri); continue; } album_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM); if (g_strcmp0 (album_name, _("Unknown")) != 0) { rb_mtp_thread_remove_from_album (priv->device_thread, track, album_name); } rb_mtp_thread_delete_track (priv->device_thread, track); g_hash_table_insert (cb_data->check_folders, GUINT_TO_POINTER (track->parent_id), GINT_TO_POINTER (1)); g_hash_table_remove (priv->entry_map, entry); rhythmdb_entry_delete (db, entry); } /* callback when all tracks have been deleted */ rb_mtp_thread_queue_callback (priv->device_thread, (RBMtpThreadCallback) delete_done_cb, cb_data, (GDestroyNotify) free_delete_data); rhythmdb_commit (db); }
static void copy_track_done_cb (RBTrackTransferBatch *batch, RhythmDBEntry *entry, const char *dest, guint64 dest_size, const char *mediatype, GError *error, RBImportDialog *dialog) { rhythmdb_entry_delete (dialog->priv->db, entry); rhythmdb_commit (dialog->priv->db); }
static void impl_delete (RBSource *asource) { RBImportErrorsSource *source = RB_IMPORT_ERRORS_SOURCE (asource); GList *sel, *tem; sel = rb_entry_view_get_selected_entries (source->priv->view); for (tem = sel; tem != NULL; tem = tem->next) { rhythmdb_entry_delete (source->priv->db, tem->data); rhythmdb_commit (source->priv->db); } g_list_foreach (sel, (GFunc)rhythmdb_entry_unref, NULL); g_list_free (sel); }
static void impl_delete_selected (RBSource *asource) { RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (asource); GList *sel, *tem; sel = rb_entry_view_get_selected_entries (source->priv->view); for (tem = sel; tem != NULL; tem = tem->next) { rhythmdb_entry_delete (source->priv->db, tem->data); rhythmdb_commit (source->priv->db); } g_list_foreach (sel, (GFunc)rhythmdb_entry_unref, NULL); g_list_free (sel); }
static void impl_delete (RBSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); GList *sel; GList *tem; RBEntryView *tracks; RhythmDB *db; int ret; db = get_db_for_source (RB_MTP_SOURCE (source)); tracks = rb_source_get_entry_view (source); sel = rb_entry_view_get_selected_entries (tracks); for (tem = sel; tem != NULL; tem = tem->next) { LIBMTP_track_t *track; RhythmDBEntry *entry; const char *uri; const char *album_name; entry = (RhythmDBEntry *)tem->data; uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION); track = g_hash_table_lookup (priv->entry_map, entry); if (track == NULL) { rb_debug ("Couldn't find track on mtp-device! (%s)", uri); continue; } ret = LIBMTP_Delete_Object (priv->device, track->item_id); if (ret != 0) { rb_debug ("Delete track %d failed", track->item_id); report_libmtp_errors (priv->device, TRUE); continue; } album_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM); if (strcmp (album_name, _("Unknown")) != 0) { remove_track_from_album (RB_MTP_SOURCE (source), album_name, track); } g_hash_table_remove (priv->entry_map, entry); rhythmdb_entry_delete (db, entry); } rhythmdb_commit (db); g_list_free (sel); g_list_free (tem); }
static void impl_delete (RBSource *asource) { RBIRadioSource *source = RB_IRADIO_SOURCE (asource); GList *sel; GList *l; sel = rb_entry_view_get_selected_entries (source->priv->stations); for (l = sel; l != NULL; l = g_list_next (l)) { rhythmdb_entry_delete (source->priv->db, l->data); rhythmdb_commit (source->priv->db); } g_list_foreach (sel, (GFunc)rhythmdb_entry_unref, NULL); g_list_free (sel); }
static void missing_plugins_retry_cb (gpointer instance, gboolean installed, RhythmDBImportJob *job) { GSList *retry = NULL; GSList *i; g_mutex_lock (&job->priv->lock); g_assert (job->priv->retried == FALSE); if (installed == FALSE) { rb_debug ("plugin installation was not successful; job complete"); g_signal_emit (job, signals[COMPLETE], 0, job->priv->total); } else { job->priv->retried = TRUE; /* reset the job state to just show the retry information */ job->priv->total = g_slist_length (job->priv->retry_entries); rb_debug ("plugin installation was successful, retrying %d entries", job->priv->total); job->priv->imported = 0; /* remove the import error entries and build the list of URIs to retry */ for (i = job->priv->retry_entries; i != NULL; i = i->next) { RhythmDBEntry *entry = (RhythmDBEntry *)i->data; char *uri; uri = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_LOCATION); rhythmdb_entry_delete (job->priv->db, entry); g_hash_table_insert (job->priv->outstanding, g_strdup (uri), GINT_TO_POINTER (1)); retry = g_slist_prepend (retry, uri); } rhythmdb_commit (job->priv->db); retry = g_slist_reverse (retry); } g_mutex_unlock (&job->priv->lock); for (i = retry; i != NULL; i = i->next) { char *uri = (char *)i->data; rhythmdb_add_uri_with_types (job->priv->db, uri, job->priv->entry_type, job->priv->ignore_type, job->priv->error_type); } rb_slist_deep_free (retry); }
END_TEST START_TEST (test_rhythmdb_modify_after_delete) { RhythmDBEntry *entry; GValue val = {0,}; entry = rhythmdb_entry_new (db, RHYTHMDB_ENTRY_TYPE_IGNORE, "file:///whee.ogg"); fail_unless (entry != NULL, "failed to create entry"); g_value_init (&val, G_TYPE_STRING); g_value_set_static_string (&val, "Anything"); rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_GENRE, &val); g_value_unset (&val); g_value_init (&val, G_TYPE_STRING); g_value_set_static_string (&val, "Nothing"); rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_ARTIST, &val); g_value_unset (&val); g_value_init (&val, G_TYPE_STRING); g_value_set_static_string (&val, "Something"); rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_ALBUM, &val); g_value_unset (&val); g_value_init (&val, G_TYPE_STRING); g_value_set_static_string (&val, "Thing"); rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_TITLE, &val); g_value_unset (&val); rhythmdb_commit (db); rhythmdb_entry_ref (entry); rhythmdb_entry_delete (db, entry); rhythmdb_commit (db); g_value_init (&val, G_TYPE_STRING); g_value_set_static_string (&val, "Something Else"); rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_ALBUM, &val); g_value_unset (&val); rhythmdb_commit (db); rhythmdb_entry_unref (entry); }
static void delete_entries (RBAndroidSource *source, GList *entries) { RBAndroidSourcePrivate *priv = GET_PRIVATE (source); GList *tem; for (tem = entries; tem != NULL; tem = tem->next) { RhythmDBEntry *entry; const char *uri; GFile *file; GFile *dir; entry = tem->data; uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION); file = g_file_new_for_uri (uri); g_file_delete (file, NULL, NULL); /* now walk up the directory structure and delete empty dirs * until we reach the root or one of the device's audio folders. */ dir = g_file_get_parent (file); while (can_delete_directory (source, dir)) { GFile *parent; if (g_file_delete (dir, NULL, NULL) == FALSE) { break; } parent = g_file_get_parent (dir); if (parent == NULL) { break; } g_object_unref (dir); dir = parent; } g_object_unref (dir); g_object_unref (file); rhythmdb_entry_delete (priv->db, entry); } rhythmdb_commit (priv->db); }
static void song_update_availability (RhythmDBEntryType *entry_type, RhythmDBEntry *entry, RhythmDBEntryAvailability avail) { RhythmDB *db; g_object_get (entry_type, "db", &db, NULL); switch (avail) { case RHYTHMDB_ENTRY_AVAIL_MOUNTED: rhythmdb_entry_set_visibility (db, entry, TRUE); break; case RHYTHMDB_ENTRY_AVAIL_CHECKED: update_entry_last_seen (db, entry); rhythmdb_entry_set_visibility (db, entry, TRUE); break; case RHYTHMDB_ENTRY_AVAIL_UNMOUNTED: /* update the last-seen time if the entry is currently visible */ if (rhythmdb_entry_get_boolean (entry, RHYTHMDB_PROP_HIDDEN) == FALSE) { update_entry_last_seen (db, entry); } rhythmdb_entry_set_visibility (db, entry, FALSE); break; case RHYTHMDB_ENTRY_AVAIL_NOT_FOUND: if (check_entry_grace_period (db, entry)) { rb_debug ("deleting entry %s; not seen for too long", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_delete (db, entry); } else { rhythmdb_entry_set_visibility (db, entry, FALSE); } break; default: g_assert_not_reached (); } g_object_unref (db); }
static void missing_plugins_retry_cb (gpointer instance, gboolean installed, RhythmDBImportJob *job) { GSList *i; g_mutex_lock (&job->priv->lock); g_assert (job->priv->retried == FALSE); if (installed == FALSE) { rb_debug ("plugin installation was not successful; job complete"); job->priv->complete = TRUE; g_signal_emit (job, signals[COMPLETE], 0, job->priv->total); g_object_notify (G_OBJECT (job), "task-outcome"); } else { job->priv->retried = TRUE; /* reset the job state to just show the retry information */ job->priv->total = g_slist_length (job->priv->retry_entries); rb_debug ("plugin installation was successful, retrying %d entries", job->priv->total); job->priv->processed = 0; /* remove the import error entries and build the list of URIs to retry */ for (i = job->priv->retry_entries; i != NULL; i = i->next) { RhythmDBEntry *entry = (RhythmDBEntry *)i->data; char *uri; uri = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_LOCATION); rhythmdb_entry_delete (job->priv->db, entry); g_queue_push_tail (job->priv->outstanding, g_strdup (uri)); } rhythmdb_commit (job->priv->db); } maybe_start_more (job); g_mutex_unlock (&job->priv->lock); }
static void import_error_update_availability (RhythmDBEntryType *entry_type, RhythmDBEntry *entry, RhythmDBEntryAvailability avail) { RhythmDB *db; switch (avail) { case RHYTHMDB_ENTRY_AVAIL_MOUNTED: case RHYTHMDB_ENTRY_AVAIL_CHECKED: /* do nothing; should never happen anyway */ break; case RHYTHMDB_ENTRY_AVAIL_UNMOUNTED: case RHYTHMDB_ENTRY_AVAIL_NOT_FOUND: /* no need to keep error entries if the file is unavailable */ g_object_get (entry_type, "db", &db, NULL); rhythmdb_entry_delete (db, entry); g_object_unref (db); break; default: g_assert_not_reached (); } }
END_TEST /* this tests that chained query models, where the base shows hidden entries * forwards visibility changes correctly. This is basically what static playlists do */ START_TEST (test_hidden_chain_filter) { RhythmDBQueryModel *base_model; RhythmDBQueryModel *filter_model; RhythmDBQuery *query; RhythmDBEntry *entry; GtkTreeIter iter; GValue val = {0,}; start_test_case (); /* setup */ base_model = rhythmdb_query_model_new_empty (db); g_object_set (base_model, "show-hidden", TRUE, NULL); filter_model = rhythmdb_query_model_new_empty (db); g_object_set (filter_model, "base-model", base_model, NULL); query = g_ptr_array_new (); g_object_set (filter_model, "query", query, NULL); rhythmdb_query_free (query); entry = rhythmdb_entry_new (db, RHYTHMDB_ENTRY_TYPE_IGNORE, "file:///whee.ogg"); rhythmdb_commit (db); g_value_init (&val, G_TYPE_BOOLEAN); /* add entry to base, should be in both */ rhythmdb_query_model_add_entry (base_model, entry, -1); fail_unless (rhythmdb_query_model_entry_to_iter (base_model, entry, &iter)); fail_unless (rhythmdb_query_model_entry_to_iter (filter_model, entry, &iter)); end_step (); /* hide entry, should be in base and not filtered */ g_value_set_boolean (&val, TRUE); set_waiting_signal (G_OBJECT (db), "entry-changed"); rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_HIDDEN, &val); rhythmdb_commit (db); wait_for_signal (); fail_unless (rhythmdb_query_model_entry_to_iter (base_model, entry, &iter)); fail_if (rhythmdb_query_model_entry_to_iter (filter_model, entry, &iter)); end_step (); /* show entry again, should be in both */ g_value_set_boolean (&val, FALSE); set_waiting_signal (G_OBJECT (db), "entry-changed"); rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_HIDDEN, &val); rhythmdb_commit (db); wait_for_signal (); fail_unless (rhythmdb_query_model_entry_to_iter (base_model, entry, &iter)); fail_unless (rhythmdb_query_model_entry_to_iter (filter_model, entry, &iter)); end_step (); /* tidy up */ rhythmdb_entry_delete (db, entry); g_object_unref (base_model); g_object_unref (filter_model); g_value_unset (&val); end_test_case (); }