static GPtrArray * get_missing_plugin_strings (GList *profiles, gboolean get_descriptions) { RBEncoder *encoder; GPtrArray *strings; GList *l; encoder = rb_encoder_new (); strings = g_ptr_array_new_with_free_func (g_free); for (l = profiles; l != NULL; l = l->next) { GstEncodingProfile *profile = GST_ENCODING_PROFILE (l->data); char **details, **descriptions; char **d; int i; rb_encoder_get_missing_plugins (encoder, profile, &details, &descriptions); d = get_descriptions ? descriptions : details; for (i = 0; d[i] != NULL; i++) { g_ptr_array_add (strings, g_strdup (d[i])); } g_strfreev (details); g_strfreev (descriptions); } g_ptr_array_add (strings, NULL); g_object_unref (encoder); return strings; }
static void do_transfer (RBRemovableMediaManager *manager) { RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (manager); TransferData *data; RBEncoder *encoder; g_assert (rb_is_main_thread ()); emit_progress (manager); if (priv->transfer_running) { rb_debug ("already transferring something"); return; } data = g_async_queue_try_pop (priv->transfer_queue); if (data == NULL) { rb_debug ("transfer queue is empty"); priv->transfer_total = 0; priv->transfer_done = 0; emit_progress (manager); return; } priv->transfer_running = TRUE; priv->transfer_fraction = 0.0; encoder = rb_encoder_new (); g_signal_connect (G_OBJECT (encoder), "error", G_CALLBACK (error_cb), data); g_signal_connect (G_OBJECT (encoder), "progress", G_CALLBACK (progress_cb), data); g_signal_connect (G_OBJECT (encoder), "completed", G_CALLBACK (completed_cb), data); rb_debug ("starting transfer of %s to %s", rhythmdb_entry_get_string (data->entry, RHYTHMDB_PROP_LOCATION), data->dest); if (rb_encoder_encode (encoder, data->entry, data->dest, data->mime_types) == FALSE) { rb_debug ("unable to start transfer"); } }
static void start_encoding (RBTrackTransferBatch *batch, gboolean overwrite) { if (batch->priv->current_encoder != NULL) { g_object_unref (batch->priv->current_encoder); } batch->priv->current_encoder = rb_encoder_new (); g_signal_connect_object (batch->priv->current_encoder, "progress", G_CALLBACK (encoder_progress_cb), batch, 0); g_signal_connect_object (batch->priv->current_encoder, "completed", G_CALLBACK (encoder_completed_cb), batch, 0); rb_encoder_encode (batch->priv->current_encoder, batch->priv->current, batch->priv->current_dest_uri, overwrite, batch->priv->current_profile); }
/** * rb_track_transfer_batch_check_media_types: * @batch: a #RBTrackTransferBatch * * Checks that all entries in the batch can be transferred in a format * supported by the destination. * * Return value: number of entries that cannot be transferred */ guint rb_track_transfer_batch_check_media_types (RBTrackTransferBatch *batch) { RBEncoder *encoder = rb_encoder_new (); guint count = 0; GList *l; for (l = batch->priv->entries; l != NULL; l = l->next) { RhythmDBEntry *entry = (RhythmDBEntry *)l->data; /* check that we can transfer this entry to the device */ if (rb_encoder_get_media_type (encoder, entry, batch->priv->media_types, NULL, NULL) == FALSE) { rb_debug ("unable to transfer %s (media type %s)", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE)); count++; } } g_object_unref (encoder); return count; }
/** * rb_track_transfer_batch_check_profiles: * @batch: a #RBTrackTransferBatch * @missing_plugin_profiles: (out) (element-type GstPbutils.EncodingProfile): holds a #GList of #GstEncodingProfiles on return * @error_count: holds the number of entries that cannot be transferred on return * * Checks that all entries in the batch can be transferred in a format * supported by the destination. If no encoding profile is available for * some entries, but installing additional plugins could make a profile * available, a list of profiles that require additional plugins is returned. * * Return value: %TRUE if some entries can be transferred without additional plugins */ gboolean rb_track_transfer_batch_check_profiles (RBTrackTransferBatch *batch, GList **missing_plugin_profiles, int *error_count) { RBEncoder *encoder = rb_encoder_new (); gboolean ret = FALSE; const GList *l; rb_debug ("checking profiles"); /* first, figure out which profiles that we care about would require additional plugins to use */ g_list_free (batch->priv->missing_plugin_profiles); batch->priv->missing_plugin_profiles = NULL; for (l = gst_encoding_target_get_profiles (batch->priv->target); l != NULL; l = l->next) { GstEncodingProfile *profile = GST_ENCODING_PROFILE (l->data); char *profile_media_type; profile_media_type = rb_gst_encoding_profile_get_media_type (profile); if (profile_media_type != NULL && (rb_gst_media_type_is_lossless (profile_media_type) == FALSE) && rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) { batch->priv->missing_plugin_profiles = g_list_append (batch->priv->missing_plugin_profiles, profile); } g_free (profile_media_type); } g_object_unref (encoder); rb_debug ("have %d profiles with missing plugins", g_list_length (batch->priv->missing_plugin_profiles)); for (l = batch->priv->entries; l != NULL; l = l->next) { RhythmDBEntry *entry = (RhythmDBEntry *)l->data; GstEncodingProfile *profile; profile = NULL; if (select_profile_for_entry (batch, entry, &profile, FALSE) == TRUE) { if (profile != NULL) { rb_debug ("found profile %s for %s", gst_encoding_profile_get_name (profile), rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); } else { rb_debug ("copying entry %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); } ret = TRUE; continue; } (*error_count)++; if (select_profile_for_entry (batch, entry, &profile, TRUE) == FALSE) { rb_debug ("unable to transfer %s (media type %s)", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE)); } else { rb_debug ("require additional plugins to transfer %s (media type %s)", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE)); if (*missing_plugin_profiles == NULL) { *missing_plugin_profiles = g_list_copy (batch->priv->missing_plugin_profiles); } } } return ret; }
static void missing_encoder_response_cb (GtkDialog *dialog, gint response, RBTrackTransferQueue *queue) { GClosure *retry; GstEncodingTarget *target; GPtrArray *details; GList *profiles; const GList *l; RBEncoder *encoder; switch (response) { case GTK_RESPONSE_YES: /* 'continue' -> start the batch */ rb_debug ("starting batch regardless of missing plugins"); actually_start_batch (queue); break; case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: /* 'cancel' -> cancel the batch and start the next one */ rb_debug ("cancelling batch"); _rb_track_transfer_batch_cancel (queue->priv->current); g_object_unref (queue->priv->current); queue->priv->current = NULL; start_next_batch (queue); break; case GTK_RESPONSE_ACCEPT: /* 'install plugins' -> try to install encoder/muxer */ /* get profiles that need plugins installed */ profiles = NULL; encoder = rb_encoder_new (); g_object_get (queue->priv->current, "encoding-target", &target, NULL); for (l = gst_encoding_target_get_profiles (target); l != NULL; l = l->next) { GstEncodingProfile *profile = GST_ENCODING_PROFILE (l->data); char *profile_media_type; profile_media_type = rb_gst_encoding_profile_get_media_type (profile); if (profile_media_type != NULL && (rb_gst_media_type_is_lossless (profile_media_type) == FALSE) && rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) { profiles = g_list_append (profiles, profile); } g_free (profile_media_type); } g_object_unref (encoder); g_object_unref (target); if (profiles == NULL) { rb_debug ("apparently we don't need any plugins any more"); actually_start_batch (queue); break; } rb_debug ("attempting plugin installation"); details = get_missing_plugin_strings (profiles, FALSE); retry = g_cclosure_new ((GCallback) missing_plugins_retry_cb, g_object_ref (queue), (GClosureNotify) g_object_unref); g_closure_set_marshal (retry, g_cclosure_marshal_VOID__BOOLEAN); if (rb_missing_plugins_install ((const char **)details->pdata, FALSE, retry)) { rb_debug ("attempting to install missing plugins for transcoding"); } else { rb_debug ("proceeding without the missing plugins for transcoding"); actually_start_batch (queue); } g_closure_sink (retry); g_ptr_array_free (details, TRUE); g_list_free (profiles); break; default: g_assert_not_reached (); } gtk_widget_destroy (GTK_WIDGET (dialog)); }
static gboolean start_next (RBTrackTransferBatch *batch) { char *media_type = NULL; char *extension = NULL; if (batch->priv->cancelled == TRUE) { return FALSE; } if (batch->priv->entries == NULL) { /* guess we must be done.. */ g_signal_emit (batch, signals[COMPLETE], 0); return FALSE; } batch->priv->current_fraction = 0.0; batch->priv->current_encoder = rb_encoder_new (); g_signal_connect_object (batch->priv->current_encoder, "progress", G_CALLBACK (encoder_progress_cb), batch, 0); g_signal_connect_object (batch->priv->current_encoder, "overwrite", G_CALLBACK (encoder_overwrite_cb), batch, 0); g_signal_connect_object (batch->priv->current_encoder, "completed", G_CALLBACK (encoder_completed_cb), batch, 0); rb_debug ("%d entries remain in the batch", g_list_length (batch->priv->entries)); while ((batch->priv->entries != NULL) && (batch->priv->cancelled == FALSE)) { RhythmDBEntry *entry; guint64 filesize; gulong duration; double fraction; GList *n; n = batch->priv->entries; batch->priv->entries = g_list_remove_link (batch->priv->entries, n); entry = (RhythmDBEntry *)n->data; g_list_free_1 (n); rb_debug ("attempting to transfer %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); /* calculate the fraction of the transfer that this entry represents */ filesize = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE); duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION); if (batch->priv->total_duration > 0) { g_assert (duration > 0); /* otherwise total_duration would be 0 */ fraction = ((double)duration) / (double) batch->priv->total_duration; } else if (batch->priv->total_size > 0) { g_assert (filesize > 0); /* otherwise total_size would be 0 */ fraction = ((double)filesize) / (double) batch->priv->total_size; } else { int count = g_list_length (batch->priv->entries) + g_list_length (batch->priv->done_entries) + 1; fraction = 1.0 / ((double)count); } g_free (media_type); g_free (extension); media_type = NULL; extension = NULL; if (rb_encoder_get_media_type (batch->priv->current_encoder, entry, batch->priv->media_types, &media_type, &extension) == FALSE) { rb_debug ("skipping entry %s, can't find a destination format", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } g_free (batch->priv->current_dest_uri); batch->priv->current_dest_uri = NULL; g_signal_emit (batch, signals[GET_DEST_URI], 0, entry, media_type, extension, &batch->priv->current_dest_uri); if (batch->priv->current_dest_uri == NULL) { rb_debug ("unable to build destination URI for %s, skipping", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION)); rhythmdb_entry_unref (entry); batch->priv->total_fraction += fraction; continue; } batch->priv->current = entry; batch->priv->current_entry_fraction = fraction; break; } if (batch->priv->current == NULL) { g_object_unref (batch->priv->current_encoder); batch->priv->current_encoder = NULL; } else { g_signal_emit (batch, signals[TRACK_STARTED], 0, batch->priv->current, batch->priv->current_dest_uri); rb_encoder_encode (batch->priv->current_encoder, batch->priv->current, batch->priv->current_dest_uri, media_type); } g_free (media_type); g_free (extension); return TRUE; }