static gboolean request_album_art_idle (RequestAlbumArtData *data) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (data->source); const char *album; /* pretty sure we don't need any extra locking here - we only touch the artwork * request map on the main thread anyway. */ album = rhythmdb_entry_get_string (data->entry, RHYTHMDB_PROP_ALBUM); if (g_hash_table_lookup (priv->artwork_request_map, album) == NULL) { GValue *metadata; RhythmDB *db = get_db_for_source (data->source); rb_debug ("requesting cover art image for album %s", album); g_hash_table_insert (priv->artwork_request_map, (gpointer) album, GINT_TO_POINTER (1)); metadata = rhythmdb_entry_request_extra_metadata (db, data->entry, "rb:coverArt"); if (metadata) { artwork_notify_cb (db, data->entry, "rb:coverArt", metadata, data->source); g_value_unset (metadata); g_free (metadata); } g_object_unref (db); } g_object_unref (data->source); rhythmdb_entry_unref (data->entry); g_free (data); return FALSE; }
static LIBMTP_filetype_t mimetype_to_filetype (RBMtpSource *source, const char *mimetype) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); if (!strcmp (mimetype, "audio/mpeg") || !strcmp (mimetype, "application/x-id3")) { return LIBMTP_FILETYPE_MP3; } else if (!strcmp (mimetype, "audio/x-wav")) { return LIBMTP_FILETYPE_WAV; } else if (!strcmp (mimetype, "application/ogg")) { return LIBMTP_FILETYPE_OGG; } else if (!strcmp (mimetype, "audio/x-m4a") || !strcmp (mimetype, "video/quicktime")) { /* try a few different filetypes that might work */ if (priv->supported_types[LIBMTP_FILETYPE_M4A]) return LIBMTP_FILETYPE_M4A; else if (!priv->supported_types[LIBMTP_FILETYPE_AAC] && priv->supported_types[LIBMTP_FILETYPE_MP4]) return LIBMTP_FILETYPE_MP4; else return LIBMTP_FILETYPE_AAC; } else if (!strcmp (mimetype, "audio/x-ms-wma") || !strcmp (mimetype, "audio/x-ms-asf")) { return LIBMTP_FILETYPE_WMA; } else if (!strcmp (mimetype, "video/x-ms-asf")) { return LIBMTP_FILETYPE_ASF; } else if (!strcmp (mimetype, "audio/x-flac")) { return LIBMTP_FILETYPE_FLAC; } else { rb_debug ("\"%s\" is not a supported mimetype", mimetype); return LIBMTP_FILETYPE_UNKNOWN; } }
static void queue_free_space_update (RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); rb_mtp_thread_queue_callback (priv->device_thread, (RBMtpThreadCallback) update_free_space_cb, source, NULL); }
static void unmount_done_cb (GObject *object, GAsyncResult *result, gpointer psource) { GMount *mount; RBMtpSource *source; gboolean ok; GError *error = NULL; RBMtpSourcePrivate *priv; mount = G_MOUNT (object); source = RB_MTP_SOURCE (psource); priv = MTP_SOURCE_GET_PRIVATE (source); ok = g_mount_unmount_with_operation_finish (mount, result, &error); if (ok) { rb_debug ("successfully unmounted mtp device"); priv->remount_volume = g_mount_get_volume (mount); open_device (source); } else { g_warning ("Unable to unmount MTP device: %s", error->message); g_error_free (error); } g_object_unref (mount); g_object_unref (source); }
static void prepare_source (RBMtpSource *source, const char *stream_uri, GObject *src) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); RhythmDBEntry *entry; RhythmDB *db; /* make sure this stream is for a file on our device */ if (g_str_has_prefix (stream_uri, "xrbmtp://") == FALSE) return; db = get_db_for_source (source); entry = rhythmdb_entry_lookup_by_location (db, stream_uri); g_object_unref (db); if (entry == NULL) return; if (_rb_source_check_entry_type (RB_SOURCE (source), entry) == FALSE) { rhythmdb_entry_unref (entry); return; } rb_debug ("setting device-thread for stream %s", stream_uri); g_object_set (src, "device-thread", priv->device_thread, NULL); rhythmdb_entry_unref (entry); }
static guint64 impl_get_free_space (RBMediaPlayerSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); /* probably need a lock for this */ return priv->free_space; }
static void rb_mtp_source_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (object); LIBMTP_raw_device_t *raw_device; switch (prop_id) { case PROP_RAW_DEVICE: raw_device = g_value_get_pointer (value); priv->raw_device = *raw_device; break; #if defined(HAVE_GUDEV) case PROP_UDEV_DEVICE: priv->udev_device = g_value_dup_object (value); break; #else case PROP_UDI: priv->udi = g_value_dup_string (value); break; #endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void artwork_notify_cb (RhythmDB *db, RhythmDBEntry *entry, const char *property_name, const GValue *metadata, RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); GdkPixbuf *pixbuf; const char *album_name; album_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM); /* check if we're looking for art for this entry, and if we actually got some */ if (g_hash_table_remove (priv->artwork_request_map, album_name) == FALSE) return; if (G_VALUE_HOLDS (metadata, GDK_TYPE_PIXBUF) == FALSE) return; pixbuf = GDK_PIXBUF (g_value_get_object (metadata)); rb_mtp_thread_set_album_image (priv->device_thread, album_name, pixbuf); queue_free_space_update (source); }
static gboolean ensure_loaded (RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); #if defined(HAVE_GUDEV) GMount *mount; #endif if (priv->tried_open) { RBSourceLoadStatus status; g_object_get (source, "load-status", &status, NULL); return (status == RB_SOURCE_LOAD_STATUS_LOADED); } priv->tried_open = TRUE; /* try to open the device. if gvfs has mounted it, unmount it first */ #if defined(HAVE_GUDEV) mount = find_mount_for_device (priv->udev_device); if (mount != NULL) { rb_debug ("device is already mounted, waiting until activated"); g_mount_unmount_with_operation (mount, G_MOUNT_UNMOUNT_NONE, NULL, NULL, unmount_done_cb, g_object_ref (source)); /* mount gets unreffed in callback */ } else { rb_debug ("device isn't mounted"); open_device (source); } #else open_device (source); #endif return FALSE; }
static void rb_mtp_source_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (object); switch (prop_id) { case PROP_RAW_DEVICE: g_value_set_pointer (value, &priv->raw_device); break; #if defined(HAVE_GUDEV) case PROP_UDEV_DEVICE: g_value_set_object (value, priv->udev_device); break; #else case PROP_UDI: g_value_set_string (value, priv->udi); break; #endif case PROP_DEVICE_SERIAL: g_value_set_string (value, priv->serial); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static char * rb_mtp_source_get_playback_uri (RhythmDBEntry *entry, gpointer data) { RBMtpSourcePrivate *priv; LIBMTP_track_t *track; char *path; char *uri = NULL; GError *error = NULL; priv = MTP_SOURCE_GET_PRIVATE (data); track = g_hash_table_lookup (priv->entry_map, entry); path = g_strdup_printf ("%s/%s-%s", g_get_tmp_dir (), rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ARTIST), rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_TITLE)); uri = g_filename_to_uri (path, NULL, &error); g_free (path); if (error != NULL) { g_warning ("unable to convert path %s to filename: %s", path, error->message); g_error_free (error); g_free (path); return NULL; } if (rb_mtp_source_transfer_track_to_disk (priv->device, track, uri) == TRUE) { rb_debug ("playback URI for %s: %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), uri); return uri; } else { g_free (uri); return NULL; } }
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); }
/* this callback runs on the device handling thread, so it can call libmtp directly */ static void mtp_device_open_cb (LIBMTP_mtpdevice_t *device, RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); DeviceOpenedData *data; if (device == NULL) { /* can't delete the source on this thread, so move it to the main thread */ g_idle_add ((GSourceFunc) device_open_failed_idle, g_object_ref (source)); return; } /* set the source name to match the device, ignoring some * particular broken device names. */ data = g_new0 (DeviceOpenedData, 1); data->source = g_object_ref (source); data->name = LIBMTP_Get_Friendlyname (device); if (data->name == NULL || strcmp (data->name, "?????") == 0) { g_free (data->name); data->name = LIBMTP_Get_Modelname (device); } if (data->name == NULL) { data->name = g_strdup (_("Digital Audio Player")); } /* get some other device information that doesn't change */ priv->manufacturer = LIBMTP_Get_Manufacturername (device); priv->device_version = LIBMTP_Get_Deviceversion (device); priv->model_name = LIBMTP_Get_Modelname (device); priv->serial = LIBMTP_Get_Serialnumber (device); /* calculate the device capacity */ priv->capacity = 0; if (LIBMTP_Get_Storage (device, LIBMTP_STORAGE_SORTBY_NOTSORTED) == 0) { LIBMTP_devicestorage_t *storage; for (storage = device->storage; storage != NULL; storage = storage->next) { priv->capacity += storage->MaxCapacity; } } update_free_space_cb (device, RB_MTP_SOURCE (source)); /* figure out the set of formats supported by the device */ if (LIBMTP_Get_Supported_Filetypes (device, &data->types, &data->num_types) != 0) { rb_mtp_thread_report_errors (priv->device_thread, FALSE); } g_idle_add ((GSourceFunc) device_opened_idle, data); /* now get the track list */ rb_mtp_thread_get_track_list (priv->device_thread, (RBMtpTrackListCallback) mtp_tracklist_cb, g_object_ref (source), g_object_unref); }
static void rb_mtp_source_init (RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); priv->entry_map = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) LIBMTP_destroy_track_t); priv->track_transfer_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); }
static void rb_mtp_source_name_changed_cb (RBMtpSource *source, GParamSpec *spec, gpointer data) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); char *name = NULL; g_object_get (source, "name", &name, NULL); rb_mtp_thread_set_device_name (priv->device_thread, name); g_free (name); }
static void open_device (RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); rb_debug ("actually opening device"); priv->device_thread = rb_mtp_thread_new (); rb_mtp_thread_open_device (priv->device_thread, &priv->raw_device, (RBMtpOpenCallback)mtp_device_open_cb, g_object_ref (source), g_object_unref); }
static void rb_mtp_source_name_changed_cb (RBMtpSource *source, GParamSpec *spec, gpointer data) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); char *name = NULL; g_object_get (source, "name", &name, NULL); if (LIBMTP_Set_Friendlyname (priv->device, name) != 0) { report_libmtp_errors (priv->device, TRUE); } g_free (name); }
static void rb_mtp_source_init (RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); priv->entry_map = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) LIBMTP_destroy_track_t); priv->album_map = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) LIBMTP_destroy_album_t); priv->artwork_request_map = g_hash_table_new (g_direct_hash, g_direct_equal); }
static void rb_mtp_source_finalize (GObject *object) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (object); g_hash_table_destroy (priv->entry_map); g_hash_table_destroy (priv->album_map); g_hash_table_destroy (priv->artwork_request_map); g_free (priv->udi); LIBMTP_Release_Device (priv->device); G_OBJECT_CLASS (rb_mtp_source_parent_class)->finalize (object); }
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 art_request_cb (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue *data, RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); if (G_VALUE_HOLDS (data, GDK_TYPE_PIXBUF)) { GdkPixbuf *pixbuf; const char *album_name; pixbuf = GDK_PIXBUF (g_value_get_object (data)); album_name = rb_ext_db_key_get_field (key, "album"); rb_mtp_thread_set_album_image (priv->device_thread, album_name, pixbuf); queue_free_space_update (source); } }
static gboolean impl_track_added (RBRemovableMediaSource *isource, RhythmDBEntry *entry, const char *dest, guint64 filesize, const char *mimetype) { RBMtpSource *source = RB_MTP_SOURCE (isource); RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); GFile *file; char *path; LIBMTP_track_t *track = NULL; file = g_file_new_for_uri (dest); path = g_file_get_path (file); track = transfer_track (source, priv->device, entry, path, filesize, mimetype); g_free (path); g_file_delete (file, NULL, NULL); if (track != NULL) { RhythmDB *db = get_db_for_source (source); if (priv->album_art_supported) { const char *album; album = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM); if (g_hash_table_lookup (priv->artwork_request_map, album) == NULL) { GValue *metadata; rb_debug ("requesting cover art image for album %s", album); g_hash_table_insert (priv->artwork_request_map, (gpointer) album, GINT_TO_POINTER (1)); metadata = rhythmdb_entry_request_extra_metadata (db, entry, "rb:coverArt"); if (metadata) { artwork_notify_cb (db, entry, "rb:coverArt", metadata, source); g_value_unset (metadata); g_free (metadata); } } } add_mtp_track_to_db (source, db, track); g_object_unref (db); } return FALSE; }
static gboolean impl_uri_is_source (RBSource *source, const char *uri) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); char *source_uri; gboolean result; if (g_str_has_prefix (uri, "gphoto2://") == FALSE) return FALSE; source_uri = g_strdup_printf ("gphoto2://[usb:%03d,%03d]/", priv->raw_device.bus_location, priv->raw_device.devnum); result = g_str_has_prefix (uri, source_uri); g_free (source_uri); return result; }
static gboolean impl_track_add_error (RBRemovableMediaSource *source, RhythmDBEntry *entry, const char *dest, GError *error) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); /* we don't actually do anything with the error here, we just need to clean up the transfer map */ LIBMTP_track_t *track = g_hash_table_lookup (priv->track_transfer_map, dest); if (track != NULL) { LIBMTP_destroy_track_t (track); g_hash_table_remove (priv->track_transfer_map, dest); } else { rb_debug ("track-add-error called, but can't find a track for dest URI %s", dest); } return TRUE; }
static void update_free_space_cb (LIBMTP_mtpdevice_t *device, RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); LIBMTP_devicestorage_t *storage; int ret; ret = LIBMTP_Get_Storage (device, LIBMTP_STORAGE_SORTBY_NOTSORTED); if (ret != 0) { rb_mtp_thread_report_errors (priv->device_thread, FALSE); } /* probably need a lock for this.. */ priv->free_space = 0; for (storage = device->storage; storage != NULL; storage = storage->next) { priv->free_space += storage->FreeSpaceInBytes; } }
static void add_track_to_album (RBMtpSource *source, const char *album_name, LIBMTP_track_t *track) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); LIBMTP_album_t *album; album = g_hash_table_lookup (priv->album_map, album_name); if (album != NULL) { /* add track to album */ album->tracks = realloc (album->tracks, sizeof(uint32_t) * (album->no_tracks+1)); album->tracks[album->no_tracks] = track->item_id; album->no_tracks++; rb_debug ("adding track ID %d to album ID %d; now %d tracks", track->item_id, album->album_id, album->no_tracks); if (LIBMTP_Update_Album (priv->device, album) != 0) { rb_debug ("LIBMTP_Update_Album failed.."); report_libmtp_errors (priv->device, FALSE); } } else { /* add new album */ album = LIBMTP_new_album_t (); album->name = strdup (album_name); album->no_tracks = 1; album->tracks = malloc (sizeof(uint32_t)); album->tracks[0] = track->item_id; album->storage_id = track->storage_id; /* fill in artist and genre? */ rb_debug ("creating new album (%s) for track ID %d", album->name, track->item_id); if (LIBMTP_Create_New_Album (priv->device, album) != 0) { LIBMTP_destroy_album_t (album); rb_debug ("LIBMTP_Create_New_Album failed.."); report_libmtp_errors (priv->device, FALSE); } else { g_hash_table_insert (priv->album_map, album->name, album); } } }
static gboolean device_open_failed_idle (RBMtpSource *source) { /* libmtp doesn't give us a useful error message in this case, so * all we can offer is this generic message. */ RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); rb_error_dialog (NULL, _("Media player device error"), /* Translators: first %s is the device manufacturer, * second is the product name. */ _("Unable to open the %s %s device"), priv->raw_device.device_entry.vendor, priv->raw_device.device_entry.product); rb_source_delete_thyself (RB_SOURCE (source)); g_object_unref (source); return FALSE; }
static GList * impl_copy (RBSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (RB_MTP_SOURCE (source)); RhythmDB *db; GList *selected_entries; GList *iter; GList *copy_entries; int ret = -1; LIBMTP_track_t *track = NULL; db = get_db_for_source (RB_MTP_SOURCE (source)); copy_entries = NULL; selected_entries = rb_entry_view_get_selected_entries (rb_source_get_entry_view (source)); for (iter = selected_entries; iter != NULL; iter = g_list_next (iter)) { RhythmDBEntry *entry; char *path; char *uri; entry = (RhythmDBEntry *)iter->data; track = g_hash_table_lookup (priv->entry_map, entry); if (track == NULL) continue; path = g_strdup_printf ("%s/%s", g_get_tmp_dir (), track->filename); uri = g_filename_to_uri (path, NULL, NULL); g_free (path); ret = rb_mtp_source_transfer_track_to_disk (priv->device, track, uri); if (ret == 0) { entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_LOCATION, uri); copy_entries = g_list_prepend (copy_entries, entry); } g_free (uri); } g_list_free (selected_entries); g_object_unref (G_OBJECT (db)); return copy_entries; }
static gboolean impl_track_added (RBTransferTarget *target, RhythmDBEntry *entry, const char *dest, guint64 filesize, const char *media_type) { LIBMTP_track_t *track = NULL; RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (target); RhythmDB *db; track = g_hash_table_lookup (priv->track_transfer_map, dest); if (track == NULL) { rb_debug ("track-added called, but can't find a track for dest URI %s", dest); return FALSE; } g_hash_table_remove (priv->track_transfer_map, dest); if (strcmp (track->album, _("Unknown")) != 0) { rb_mtp_thread_add_to_album (priv->device_thread, track, track->album); if (priv->album_art_supported) { RBExtDBKey *key; /* need to do this in an idle handler? */ key = rb_ext_db_key_create_lookup ("album", track->album); rb_ext_db_key_add_field (key, "artist", track->artist); rb_ext_db_request (priv->art_store, key, (RBExtDBRequestCallback) art_request_cb, g_object_ref (target), (GDestroyNotify) g_object_unref); rb_ext_db_key_free (key); } } db = get_db_for_source (RB_MTP_SOURCE (target)); add_mtp_track_to_db (RB_MTP_SOURCE (target), db, track); g_object_unref (db); queue_free_space_update (RB_MTP_SOURCE (target)); return FALSE; }
static void rb_mtp_source_dispose (GObject *object) { RBMtpSource *source = RB_MTP_SOURCE (object); RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); RhythmDBEntryType *entry_type; RhythmDB *db; if (priv->device_thread != NULL) { g_object_unref (priv->device_thread); priv->device_thread = NULL; } #if defined(HAVE_GUDEV) if (priv->remount_volume != NULL) { rb_debug ("remounting gvfs volume for mtp device"); /* the callback will unref remount_volume */ g_volume_mount (priv->remount_volume, G_MOUNT_MOUNT_NONE, NULL, NULL, remount_done_cb, NULL); priv->remount_volume = NULL; } #endif if (priv->art_store != NULL) { g_object_unref (priv->art_store); priv->art_store = NULL; } db = get_db_for_source (source); g_object_get (G_OBJECT (source), "entry-type", &entry_type, NULL); rhythmdb_entry_delete_by_type (db, entry_type); g_object_unref (entry_type); rhythmdb_commit (db); g_object_unref (db); G_OBJECT_CLASS (rb_mtp_source_parent_class)->dispose (object); }