static gboolean
parse_finished (ParseThreadData *data)
{
	if (data->reset_count != data->dialog->priv->reset_count) {
		rb_debug ("dialog reset while parsing");
		rb_podcast_parse_channel_free (data->channel);
		g_object_unref (data->dialog);
		g_clear_error (&data->error);
		g_free (data->url);
		g_free (data);
		return FALSE;
	}

	if (data->error != NULL) {
		gtk_label_set_label (GTK_LABEL (data->dialog->priv->info_bar_message),
				     _("Unable to load the feed. Check your network connection."));
		gtk_widget_show (data->dialog->priv->info_bar);
	} else {
		gtk_widget_hide (data->dialog->priv->info_bar);
	}

	if (data->channel->is_opml) {
		GList *l;
		/* convert each item into its own channel */
		for (l = data->channel->posts; l != NULL; l = l->next) {
			RBPodcastChannel *channel;
			RBPodcastItem *item;

			item = l->data;
			channel = g_new0 (RBPodcastChannel, 1);
			channel->url = g_strdup (item->url);
			channel->title = g_strdup (item->title);
			/* none of the other fields get populated anyway */
			insert_search_result (data->dialog, channel, FALSE);
		}
		rb_podcast_parse_channel_free (data->channel);
	} else if (data->existing) {
		/* find the row for the feed, replace the channel */
		GtkTreeIter iter;
		gboolean found = FALSE;

		if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter)) {
			do {
				RBPodcastChannel *channel;
				gtk_tree_model_get (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter,
						    FEED_COLUMN_PARSED_FEED, &channel,
						    -1);
				if (g_strcmp0 (channel->url, data->url) == 0) {
					gtk_list_store_set (data->dialog->priv->feed_model,
							    &iter,
							    FEED_COLUMN_PARSED_FEED, data->channel,
							    -1);
					found = TRUE;
					rb_podcast_parse_channel_free (channel);
					break;
				}
			} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter));
		}

		/* if the row is selected, create entries for the channel contents */
		if (found == FALSE) {
			rb_podcast_parse_channel_free (data->channel);
		} else if (data->dialog->priv->have_selection) {
			GtkTreePath *a;
			GtkTreePath *b;

			a = gtk_tree_model_get_path (GTK_TREE_MODEL (data->dialog->priv->feed_model), &iter);
			b = gtk_tree_model_get_path (GTK_TREE_MODEL (data->dialog->priv->feed_model), &data->dialog->priv->selected_feed);
			if (gtk_tree_path_compare (a, b) == 0) {
				add_posts_for_feed (data->dialog, data->channel);
			}

			gtk_tree_path_free (a);
			gtk_tree_path_free (b);
		}
	} else {
		/* model owns data->channel now */
		insert_search_result (data->dialog, data->channel, data->single);
	}

	g_object_unref (data->dialog);
	g_clear_error (&data->error);
	g_free (data->url);
	g_free (data);
	return FALSE;
}
static void
rb_mtp_source_constructed (GObject *object)
{
	RBMtpSource *source;
	RBMtpSourcePrivate *priv;
	RBEntryView *tracks;
	RBShell *shell;
	RBShellPlayer *shell_player;
	GObject *player_backend;
	GtkIconTheme *theme;
	GdkPixbuf *pixbuf;
#if defined(HAVE_GUDEV)
	GMount *mount;
#endif
	gint size;

	RB_CHAIN_GOBJECT_METHOD (rb_mtp_source_parent_class, constructed, object);
	source = RB_MTP_SOURCE (object);
	priv = MTP_SOURCE_GET_PRIVATE (source);

	/* 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
#endif
	open_device (source);

	tracks = rb_source_get_entry_view (RB_SOURCE (source));
	rb_entry_view_append_column (tracks, RB_ENTRY_VIEW_COL_RATING, FALSE);
	rb_entry_view_append_column (tracks, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);

	/* the source element needs our cooperation */
	g_object_get (source, "shell", &shell, NULL);
	shell_player = RB_SHELL_PLAYER (rb_shell_get_player (shell));
	g_object_get (shell_player, "player", &player_backend, NULL);

	g_signal_connect_object (player_backend,
				 "prepare-source",
				 G_CALLBACK (prepare_player_source_cb),
				 source, 0);

	g_object_unref (player_backend);
	g_object_unref (shell);

	g_signal_connect_object (rb_encoder_factory_get (),
				 "prepare-source",
				 G_CALLBACK (prepare_encoder_source_cb),
				 source, 0);
	g_signal_connect_object (rb_encoder_factory_get (),
				 "prepare-sink",
				 G_CALLBACK (prepare_encoder_sink_cb),
				 source, 0);

	/* icon */
	theme = gtk_icon_theme_get_default ();
	gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL);
	pixbuf = gtk_icon_theme_load_icon (theme, "multimedia-player", size, 0, NULL);

	rb_source_set_pixbuf (RB_SOURCE (source), pixbuf);
	g_object_unref (pixbuf);

	if (priv->album_art_supported) {
		RhythmDB *db;

		db = get_db_for_source (source);
		g_signal_connect_object (db, "entry-extra-metadata-notify::rb:coverArt",
					 G_CALLBACK (artwork_notify_cb), source, 0);
		g_object_unref (db);
	}
}
static gboolean
device_opened_idle (DeviceOpenedData *data)
{
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (data->source);
	int i;
	gboolean has_mp3 = FALSE;

	if (data->name != NULL) {
		g_object_set (data->source, "name", data->name, NULL);
	}

	/* when the source name changes after this, try to update the device name */
	g_signal_connect (G_OBJECT (data->source), "notify::name",
			  (GCallback)rb_mtp_source_name_changed_cb, NULL);

	rb_media_player_source_load (RB_MEDIA_PLAYER_SOURCE (data->source));

	for (i = 0; i < data->num_types; i++) {
		const char *mediatype;

		if (i <= LIBMTP_FILETYPE_UNKNOWN) {
			priv->supported_types[data->types[i]] = 1;
		}

		/* this has to work with the remapping done in
		 * rb-removable-media-source.c:impl_paste.
		 */
		switch (data->types[i]) {
		case LIBMTP_FILETYPE_WAV:
			mediatype = "audio/x-wav";
			break;
		case LIBMTP_FILETYPE_MP3:
			/* special handling for mp3: always put it at the front of the list
			 * if it's supported.
			 */
			has_mp3 = TRUE;
			mediatype = NULL;
			break;
		case LIBMTP_FILETYPE_WMA:
			mediatype = "audio/x-ms-wma";
			break;
		case LIBMTP_FILETYPE_OGG:
			mediatype = "application/ogg";
			break;
		case LIBMTP_FILETYPE_MP4:
		case LIBMTP_FILETYPE_M4A:
		case LIBMTP_FILETYPE_AAC:
			mediatype = "audio/aac";
			break;
		case LIBMTP_FILETYPE_WMV:
			mediatype = "audio/x-ms-wmv";
			break;
		case LIBMTP_FILETYPE_ASF:
			mediatype = "video/x-ms-asf";
			break;
		case LIBMTP_FILETYPE_FLAC:
			mediatype = "audio/flac";
			break;

		case LIBMTP_FILETYPE_JPEG:
			rb_debug ("JPEG (album art) supported");
			mediatype = NULL;
			priv->album_art_supported = TRUE;
			break;

		default:
			rb_debug ("unknown libmtp filetype %s supported", LIBMTP_Get_Filetype_Description (data->types[i]));
			mediatype = NULL;
			break;
		}

		if (mediatype != NULL) {
			rb_debug ("media type %s supported", mediatype);
			priv->mediatypes = g_list_prepend (priv->mediatypes,
							   g_strdup (mediatype));
		}
	}

	if (has_mp3) {
		rb_debug ("audio/mpeg supported");
		priv->mediatypes = g_list_prepend (priv->mediatypes, g_strdup ("audio/mpeg"));
	}

	g_object_unref (data->source);
	free (data->types);
	g_free (data->name);
	g_free (data);

	return FALSE;
}
static void
impl_constructed (GObject *object)
{
	RBGenericPlayerSource *source;
	RBGenericPlayerSourcePrivate *priv;
	RhythmDBEntryType *entry_type;
	char **playlist_formats;
	char **output_formats;
	char *mount_name;
	RBShell *shell;
	GFile *root;
	GFileInfo *info;
	GError *error = NULL;

	RB_CHAIN_GOBJECT_METHOD (rb_generic_player_source_parent_class, constructed, object);
	source = RB_GENERIC_PLAYER_SOURCE (object);

	priv = GET_PRIVATE (source);

	rb_device_source_set_display_details (RB_DEVICE_SOURCE (source));

	g_object_get (source,
		      "shell", &shell,
		      "entry-type", &entry_type,
		      NULL);

	g_object_get (shell, "db", &priv->db, NULL);

	priv->import_errors = rb_import_errors_source_new (shell,
							   priv->error_type,
							   entry_type,
							   priv->ignore_type);

	g_object_unref (shell);

	root = g_mount_get_root (priv->mount);
	mount_name = g_mount_get_name (priv->mount);

	info = g_file_query_filesystem_info (root, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, NULL, &error);
	if (error != NULL) {
		rb_debug ("error querying filesystem info for %s: %s", mount_name, error->message);
		g_error_free (error);
		priv->read_only = FALSE;
	} else {
		priv->read_only = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY);
		g_object_unref (info);
	}

	g_free (mount_name);
	g_object_unref (root);

	g_object_get (priv->device_info, "playlist-formats", &playlist_formats, NULL);
	if (playlist_formats != NULL && g_strv_length (playlist_formats) > 0) {
		g_object_set (entry_type, "has-playlists", TRUE, NULL);
	}
	g_strfreev (playlist_formats);
	g_object_unref (entry_type);

	g_object_get (priv->device_info, "output-formats", &output_formats, NULL);
	if (output_formats != NULL) {
		GstEncodingTarget *target;
		int i;

		target = gst_encoding_target_new ("generic-player", "device", "", NULL);
		for (i = 0; output_formats[i] != NULL; i++) {
			const char *media_type = rb_gst_mime_type_to_media_type (output_formats[i]);
			if (media_type != NULL) {
				GstEncodingProfile *profile;
				profile = rb_gst_get_encoding_profile (media_type);
				if (profile != NULL) {
					gst_encoding_target_add_profile (target, profile);
				}
			}
		}
		g_object_set (source, "encoding-target", target, NULL);
	}
	g_strfreev (output_formats);

}
Example #5
0
static void
current_folder_changed_cb (GtkFileChooser *chooser, RBImportDialog *dialog)
{
	GSettings *settings;
	RBSource *source;
	GtkWidget *label;
	const char *uri;
	char **locations;
	int i;
	
	uri = gtk_file_chooser_get_uri (chooser);
	if (g_strcmp0 (uri, dialog->priv->current_uri) == 0)
		return;
	g_free (dialog->priv->current_uri);
	dialog->priv->current_uri = g_strdup (uri);

	if (dialog->priv->import_job != NULL) {
		rhythmdb_import_job_cancel (dialog->priv->import_job);
	}

	clear_info_bar (dialog);

	source = rb_shell_guess_source_for_uri (dialog->priv->shell, uri);
	if (source != NULL) {
		if (RB_IS_DEVICE_SOURCE (source)) {
			char *msg;
			char *name;
			GtkWidget *content;

			rhythmdb_entry_delete_by_type (dialog->priv->db, dialog->priv->entry_type);
			rhythmdb_entry_delete_by_type (dialog->priv->db, dialog->priv->ignore_type);
			rhythmdb_commit (dialog->priv->db);

			dialog->priv->info_bar = gtk_info_bar_new ();
			g_object_set (dialog->priv->info_bar, "hexpand", TRUE, NULL);

			g_object_get (source, "name", &name, NULL);

			/* this isn't a terribly helpful message. */
			msg = g_strdup_printf (_("The location you have selected is on the device %s."), name);
			label = gtk_label_new (msg);
			g_free (msg);
			content = gtk_info_bar_get_content_area (GTK_INFO_BAR (dialog->priv->info_bar));
			gtk_container_add (GTK_CONTAINER (content), label);

			msg = g_strdup_printf (_("Show %s"), name);
			gtk_info_bar_add_button (GTK_INFO_BAR (dialog->priv->info_bar), msg, GTK_RESPONSE_ACCEPT);
			g_free (msg);

			g_signal_connect (dialog->priv->info_bar, "response", G_CALLBACK (device_info_bar_response_cb), dialog);

			gtk_widget_show_all (dialog->priv->info_bar);
			gtk_container_add (GTK_CONTAINER (dialog->priv->info_bar_container), dialog->priv->info_bar);
			return;
		}
	}

	/* disable copy if the selected location is already inside the library */
	settings = g_settings_new ("org.gnome.rhythmbox.rhythmdb");
	locations = g_settings_get_strv (settings, "locations");
	gtk_widget_set_sensitive (dialog->priv->copy_check, TRUE);
	for (i = 0; locations[i] != NULL; i++) {
		if (g_str_has_prefix (uri, locations[i])) {
			gtk_widget_set_sensitive (dialog->priv->copy_check, FALSE);
			break;
		}
	}
	g_strfreev (locations);
	g_object_unref (settings);

	if (dialog->priv->import_job != NULL) {
		/* wait for the previous job to finish up */
		rb_debug ("need to wait for previous import job to finish");
		g_signal_connect (dialog->priv->import_job, "complete", G_CALLBACK (start_deferred_scan), dialog);
	} else {
		start_scanning (dialog);
	}
}
Example #6
0
/**
 * rb_device_source_set_display_details:
 * @source: a #RBDeviceSource
 *
 * Sets the icon and display name for a device-based source.
 * The details come from the mount and/or volume.  This should
 * be called in the source's constructed method.
 */
void
rb_device_source_set_display_details (RBDeviceSource *source)
{
	GMount *mount = NULL;
	GVolume *volume = NULL;
	GIcon *icon = NULL;
	char *display_name;
	GdkPixbuf *pixbuf = NULL;

	if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "volume")) {
		g_object_get (source, "volume", &volume, NULL);
	}
	if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "mount")) {
		g_object_get (source, "mount", &mount, NULL);
	}

	/* prefer mount details to volume details, as the nautilus sidebar does */
	if (mount != NULL) {
		mount = g_object_ref (mount);
	} else if (volume != NULL) {
		mount = g_volume_get_mount (volume);
	} else {
		mount = NULL;
	}

	if (mount != NULL) {
		display_name = g_mount_get_name (mount);
		icon = g_mount_get_icon (mount);
		rb_debug ("details from mount: display name = %s, icon = %p", display_name, icon);
	} else if (volume != NULL) {
		display_name = g_volume_get_name (volume);
		icon = g_volume_get_icon (volume);
		rb_debug ("details from volume: display name = %s, icon = %p", display_name, icon);
	} else {
		display_name = g_strdup ("Unknown Device");
		icon = g_themed_icon_new ("multimedia-player");
	}

	g_object_set (source, "name", display_name, NULL);
	g_free (display_name);

	if (icon == NULL) {
		rb_debug ("no icon set");
		pixbuf = NULL;
	} else if (G_IS_THEMED_ICON (icon)) {
		GtkIconTheme *theme;
		const char * const *names;
		gint size;
		int i;

		theme = gtk_icon_theme_get_default ();
		gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);

		i = 0;
		names = g_themed_icon_get_names (G_THEMED_ICON (icon));
		while (names[i] != NULL && pixbuf == NULL) {
			rb_debug ("looking up themed icon: %s", names[i]);
			pixbuf = gtk_icon_theme_load_icon (theme, names[i], size, 0, NULL);
			i++;
		}

	} else if (G_IS_LOADABLE_ICON (icon)) {
		rb_debug ("loading of GLoadableIcons is not implemented yet");
		pixbuf = NULL;
	}

	if (pixbuf != NULL) {
		g_object_set (source, "pixbuf", pixbuf, NULL);
		g_object_unref (pixbuf);
	}
	if (mount != NULL) {
		g_object_unref (mount);
	}
	if (volume != NULL) {
		g_object_unref (volume);
	}
	if (icon != NULL) {
		g_object_unref (icon);
	}
}
static char *
impl_build_dest_uri (RBTransferTarget *target,
		     RhythmDBEntry *entry,
		     const char *media_type,
		     const char *extension)
{
	RBGenericPlayerSourcePrivate *priv = GET_PRIVATE (target);
	const char *in_artist;
	char *artist, *album, *title;
	gulong track_number, disc_number;
	const char *folders;
	char **audio_folders;
	char *mount_path;
	char *number;
	char *file = NULL;
	char *path;
	char *ext;

	rb_debug ("building dest uri for entry at %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));

	if (extension != NULL) {
		ext = g_strconcat (".", extension, NULL);
	} else {
		ext = g_strdup ("");
	}

	in_artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_ARTIST);
	if (in_artist[0] == '\0') {
		in_artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST);
	}
	artist = sanitize_path (in_artist);
	album = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
	title = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));

	/* we really do need to fix this so untagged entries actually have NULL rather than
	 * a translated string.
	 */
	if (strcmp (artist, _("Unknown")) == 0 && strcmp (album, _("Unknown")) == 0 &&
	    g_str_has_suffix (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), title)) {
		/* file isn't tagged, so just use the filename as-is, replacing the extension */
		char *p;

		p = g_utf8_strrchr (title, -1, '.');
		if (p != NULL) {
			*p = '\0';
		}
		file = g_strdup_printf ("%s%s", title, ext);
	}

	if (file == NULL) {
		int folder_depth;

		track_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER);
		disc_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DISC_NUMBER);
		if (disc_number > 0)
			number = g_strdup_printf ("%.02u.%.02u", (guint)disc_number, (guint)track_number);
		else
			number = g_strdup_printf ("%.02u", (guint)track_number);

		g_object_get (priv->device_info, "folder-depth", &folder_depth, NULL);
		switch (folder_depth) {
		case 0:
			/* artist - album - number - title */
			file = g_strdup_printf ("%s - %s - %s - %s%s",
						artist, album, number, title, ext);
			break;

		case 1:
			/* artist - album/number - title */
			file = g_strdup_printf ("%s - %s" G_DIR_SEPARATOR_S "%s - %s%s",
						artist, album, number, title, ext);
			break;

		default: /* use this for players that don't care */
		case 2:
			/* artist/album/number - title */
			file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s - %s%s",
						artist, album, number, title, ext);
			break;
		}
		g_free (number);
	}

	g_free (artist);
	g_free (album);
	g_free (title);
	g_free (ext);

	if (file == NULL)
		return NULL;

	g_object_get (priv->device_info, "audio-folders", &audio_folders, NULL);
	if (audio_folders != NULL && g_strv_length (audio_folders) > 0) {
		folders = g_strdup (audio_folders[0]);
	} else {
		folders = "";
	}
	g_strfreev (audio_folders);

	mount_path = rb_generic_player_source_get_mount_path (RB_GENERIC_PLAYER_SOURCE (target));
	path = g_build_filename (mount_path, folders, file, NULL);
	g_free (file);
	g_free (mount_path);

	/* TODO: check for duplicates, or just overwrite by default? */
	rb_debug ("dest file is %s", path);
	return path;
}
static gboolean
rb_tree_dnd_drag_motion_cb (GtkWidget        *widget,
                           GdkDragContext   *context,
                           gint              x,
                           gint              y,
                           guint             time)
{
	GtkTreeView *tree_view;
	GtkTreePath *path = NULL;
	GtkTreeModel *model;
	GtkTreeViewDropPosition pos;
	RbTreeDndData *priv_data;
	GdkDragAction action;

	rb_debug ("drag and drop motion: (%i,%i)", x, y);

  	tree_view = GTK_TREE_VIEW (widget);
	model = gtk_tree_view_get_model (tree_view);

	priv_data = g_object_get_data (G_OBJECT (widget), RB_TREE_DND_STRING);

	gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, &pos);

	if ((priv_data->previous_dest_path == NULL)
	    || (path == NULL)
	    || gtk_tree_path_compare(path,priv_data->previous_dest_path)) {
				remove_select_on_drag_timeout(tree_view);
	}

	if (path == NULL)
	{
	  	gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
						 NULL,
						 GTK_TREE_VIEW_DROP_BEFORE);

		if (!(priv_data->dest_flags & RB_TREE_DEST_EMPTY_VIEW_DROP)) {
			/* Can't drop here. */
			gdk_drag_status (context, 0, time);

			return TRUE;
		} else if (!filter_drop_position (widget, context, path, &pos)) {
			gdk_drag_status (context, 0, time);
			return TRUE;
		}
	}
	else
	{
		if (!filter_drop_position (widget, context, path, &pos)) {
			gdk_drag_status (context, 0, time);
			return TRUE;
		}

	  if (priv_data->scroll_timeout == 0)
	  {
		  priv_data->scroll_timeout = g_timeout_add (150, scroll_row_timeout, tree_view);
	  }
	}

	if (GTK_WIDGET (tree_view) == gtk_drag_get_source_widget (context) &&
	    context->actions & GDK_ACTION_MOVE)
		action = GDK_ACTION_MOVE;
	else
		action = context->suggested_action;

	if (path) {
		gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
		if (priv_data->dest_flags & RB_TREE_DEST_SELECT_ON_DRAG_TIMEOUT) {
			if (priv_data->previous_dest_path != NULL) {
				gtk_tree_path_free (priv_data->previous_dest_path);
			}
			priv_data->previous_dest_path = path;
			if (priv_data->select_on_drag_timeout == 0) {
				rb_debug("Setting up a new select on drag timeout");
				priv_data->select_on_drag_timeout = g_timeout_add_seconds (2, select_on_drag_timeout, tree_view);
			}
		} else {
			gtk_tree_path_free (path);
		}
	}

	gdk_drag_status (context, action, time);

	return TRUE;
}
Example #9
0
static gboolean
emit_status_changed (RhythmDBImportJob *job)
{
	g_mutex_lock (&job->priv->lock);
	job->priv->status_changed_id = 0;

	rb_debug ("emitting status changed: %d/%d", job->priv->processed, job->priv->total);
	g_signal_emit (job, signals[STATUS_CHANGED], 0, job->priv->total, job->priv->processed);
	g_object_notify (G_OBJECT (job), "task-progress");
	g_object_notify (G_OBJECT (job), "task-detail");

	/* temporary ref while emitting this signal as we're expecting the caller
	 * to release the final reference there.
	 */
	g_object_ref (job);
	if (job->priv->scan_complete && job->priv->processed >= job->priv->total) {

		if (job->priv->retry_entries != NULL && job->priv->retried == FALSE) {
			gboolean processing = FALSE;
			char **details = NULL;
			GClosure *retry;
			GSList *l;
			int i;

			/* gather missing plugin details etc. */
			i = 0;
			for (l = job->priv->retry_entries; l != NULL; l = l->next) {
				RhythmDBEntry *entry;
				char **bits;
				int j;

				entry = (RhythmDBEntry *)l->data;
				bits = g_strsplit (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_COMMENT), "\n", 0);
				for (j = 0; bits[j] != NULL; j++) {
					if (rb_str_in_strv (bits[j], (const char **)details) == FALSE) {
						details = g_realloc (details, sizeof (char *) * (i+2));
						details[i++] = g_strdup (bits[j]);
						details[i] = NULL;
					}
				}
				g_strfreev (bits);
			}

			retry = g_cclosure_new ((GCallback) missing_plugins_retry_cb,
						g_object_ref (job),
						(GClosureNotify)g_object_unref);
			g_closure_set_marshal (retry, g_cclosure_marshal_VOID__BOOLEAN);

			processing = rb_missing_plugins_install ((const char **)details, FALSE, retry);
			g_strfreev (details);
			if (processing) {
				rb_debug ("plugin installation is in progress");
			} else {
				rb_debug ("no plugin installation attempted; job complete");
				job->priv->complete = TRUE;
				g_signal_emit (job, signals[COMPLETE], 0, job->priv->total);
				g_object_notify (G_OBJECT (job), "task-outcome");
			}
			g_closure_sink (retry);
		} else {
			rb_debug ("emitting 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 if (g_cancellable_is_cancelled (job->priv->cancel) &&
		   g_queue_is_empty (job->priv->processing)) {
		rb_debug ("cancelled job has no processing entries, emitting complete");
		job->priv->complete = TRUE;
		g_signal_emit (job, signals[COMPLETE], 0, job->priv->total);
		g_object_notify (G_OBJECT (job), "task-outcome");
	}
	g_mutex_unlock (&job->priv->lock);
	g_object_unref (job);

	return FALSE;
}
Example #10
0
static void
rb_removable_media_manager_add_mount (RBRemovableMediaManager *mgr, GMount *mount)
{
	RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (mgr);
	RBRemovableMediaSource *source = NULL;
	GVolume *volume;
	GFile *mount_root;
	char *mountpoint;
	MPIDDevice *device_info;

	g_assert (mount != NULL);

	if (g_hash_table_lookup (priv->mount_mapping, mount) != NULL) {
		return;
	}
#if GLIB_CHECK_VERSION(2, 20, 0)
	if (g_mount_is_shadowed (mount) != FALSE) {
		return;
	}
#endif
	volume = g_mount_get_volume (mount);
	if (volume == NULL) {
		rb_debug ("Unhandled media, no volume for mount");
		return;
	}

	/* if we've already created a source for the volume,
	 * don't do anything with the mount.
	 */
	if (g_hash_table_lookup (priv->volume_mapping, volume) != NULL) {
		rb_debug ("already created a source for the volume, so ignoring the mount");
		g_object_unref (volume);
		return;
	}

	dump_volume_identifiers (volume);
	g_object_unref (volume);

	/* look the device up in the device info database */
	mount_root = g_mount_get_root (mount);
	if (mount_root == NULL) {
		rb_debug ("unable to get mount root, can't create a source for this mount");
		return;
	}
	mountpoint = g_file_get_path (mount_root);
	g_object_unref (mount_root);

	device_info = mpid_device_new (mountpoint);
	g_free (mountpoint);

	g_signal_emit (G_OBJECT (mgr), rb_removable_media_manager_signals[CREATE_SOURCE_MOUNT], 0, mount, device_info, &source);

	if (source) {
		g_hash_table_insert (priv->mount_mapping, mount, source);
		rb_removable_media_manager_append_media_source (mgr, RB_SOURCE (source));
	} else {
		rb_debug ("Unhandled media");
	}

	g_object_unref (device_info);
}
Example #11
0
static void
rb_grilo_plugin_init (RBGriloPlugin *plugin)
{
	rb_debug ("RBGriloPlugin initialising");
}
static gboolean
start_next (RBTrackTransferBatch *batch)
{
	GstEncodingProfile *profile = 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;

	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;
		char *media_type;
		char *extension;

		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);
		}

		profile = NULL;
		if (select_profile_for_entry (batch, entry, &profile, FALSE) == FALSE) {
			rb_debug ("skipping entry %s, can't find an encoding profile",
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
			rhythmdb_entry_unref (entry);
			batch->priv->total_fraction += fraction;
			continue;
		}

		if (profile != NULL) {
			media_type = rb_gst_encoding_profile_get_media_type (profile);
			extension = g_strdup (rb_gst_media_type_to_extension (media_type));

			rb_gst_encoding_profile_set_preset (profile, NULL);
			g_signal_emit (batch, signals[CONFIGURE_PROFILE], 0, media_type, profile);
		} else {
			media_type = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_MEDIA_TYPE);
			extension = g_strdup (rb_gst_media_type_to_extension (media_type));
			if (extension == NULL) {
				extension = get_extension_from_location (entry);
			}
		}

		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);
		g_free (media_type);
		g_free (extension);

		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;
		batch->priv->current_profile = profile;
		break;
	}

	if (batch->priv->current != NULL) {
		g_signal_emit (batch, signals[TRACK_STARTED], 0,
			       batch->priv->current,
			       batch->priv->current_dest_uri);
		start_encoding (batch, FALSE);
	}

	return TRUE;
}
/**
 * rb_track_transfer_batch_check_profiles:
 * @batch: a #RBTrackTransferBatch
 * @missing_plugin_profiles: 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
podcast_search_result_cb (RBPodcastSearch *search, RBPodcastChannel *feed, RBPodcastAddDialog *dialog)
{
	rb_debug ("got result %s from podcast search %s", feed->url, G_OBJECT_TYPE_NAME (search));
	insert_search_result (dialog, rb_podcast_parse_channel_copy (feed), FALSE);
}
Example #15
0
static void
rhythmdb_directory_change_cb (GFileMonitor *monitor,
			      GFile *file,
			      GFile *other_file,
			      GFileMonitorEvent event_type,
			      RhythmDB *db)
{
	char *canon_uri;
	char *other_canon_uri = NULL;
	RhythmDBEntry *entry;

	canon_uri = g_file_get_uri (file);
	if (other_file != NULL) {
		other_canon_uri = g_file_get_uri (other_file);
	}

	rb_debug ("directory event %d for %s", event_type, canon_uri);

	switch (event_type) {
        case G_FILE_MONITOR_EVENT_CREATED:
		{
			gboolean in_library = FALSE;
			int i;

			if (!g_settings_get_boolean (db->priv->settings, "monitor-library"))
				break;

			if (rb_uri_is_hidden (canon_uri))
				break;

			/* ignore new files outside of the library locations */
			for (i = 0; db->priv->library_locations[i] != NULL; i++) {
				if (g_str_has_prefix (canon_uri, db->priv->library_locations[i])) {
					in_library = TRUE;
					break;
				}
			}

			if (!in_library)
				break;
		}

		/* process directories immediately */
		if (rb_uri_is_directory (canon_uri)) {
			actually_add_monitor (db, file, NULL);
			rhythmdb_add_uri (db, canon_uri);
		} else {
			add_changed_file (db, canon_uri);
		}
		break;
	case G_FILE_MONITOR_EVENT_CHANGED:
        case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
		if (rhythmdb_entry_lookup_by_location (db, canon_uri)) {
			add_changed_file (db, canon_uri);
		}
		break;
	case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
		/* hmm.. */
		break;
	case G_FILE_MONITOR_EVENT_DELETED:
		entry = rhythmdb_entry_lookup_by_location (db, canon_uri);
		if (entry != NULL) {
			g_hash_table_remove (db->priv->changed_files, entry->location);
			rhythmdb_entry_set_visibility (db, entry, FALSE);
			rhythmdb_commit (db);
		}
		break;
	case G_FILE_MONITOR_EVENT_MOVED:
		if (other_canon_uri == NULL) {
			break;
		}

		entry = rhythmdb_entry_lookup_by_location (db, other_canon_uri);
		if (entry != NULL) {
			rb_debug ("file move target %s already exists in database", other_canon_uri);
			entry = rhythmdb_entry_lookup_by_location (db, canon_uri);
			if (entry != NULL) {
				g_hash_table_remove (db->priv->changed_files, entry->location);
				rhythmdb_entry_set_visibility (db, entry, FALSE);
				rhythmdb_commit (db);
			}
		} else {
			entry = rhythmdb_entry_lookup_by_location (db, canon_uri);
			if (entry != NULL) {
				GValue v = {0,};
				g_value_init (&v, G_TYPE_STRING);
				g_value_set_string (&v, other_canon_uri);
				rhythmdb_entry_set_internal (db, entry, TRUE, RHYTHMDB_PROP_LOCATION, &v);
				g_value_unset (&v);
			}
		}
		break;
	case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
	case G_FILE_MONITOR_EVENT_UNMOUNTED:
	default:
		break;
	}

	g_free (canon_uri);
	g_free (other_canon_uri);
}
int
main (int argc, char **argv)
{
	ServiceData svc = {0,};
	GError *error = NULL;
	const char *address = NULL;
	char *guid;

#ifdef ENABLE_NLS
	/* initialize i18n */
	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);
#endif
	g_type_init ();
	gst_init (NULL, NULL);
	g_set_prgname ("rhythmbox-metadata");

	if (argv[1] != NULL && strcmp(argv[1], "--debug") == 0) {
		argv++;
		rb_debug_init (TRUE);
	} else if (argv[1] != NULL && strcmp (argv[1], "--debug-match") == 0) {
		rb_debug_init_match (argv[2]);
		argv += 2;
	} else {
		rb_debug_init (FALSE);
	}

	/* bug report modes */
	if (argv[1] != NULL && strcmp(argv[1], "--load") == 0) {
		return test_load (argv[2]);
	}
	if (argv[1] != NULL && strcmp(argv[1], "--saveable-types") == 0) {
		return test_saveable_types ();
	}

	if (argv[1] != NULL && strcmp (argv[1], "--external") == 0) {
		argv++;
		svc.external = TRUE;
	}
	if (argv[1] == NULL) {
		address = "unix:tmpdir=/tmp";
	} else {
		address = argv[1];
	}

	rb_debug ("initializing metadata service; pid = %d; address = %s", getpid (), address);
	svc.metadata = rb_metadata_new ();
	svc.loop = g_main_loop_new (NULL, TRUE);

	/* create the server */
	guid = g_dbus_generate_guid ();
	svc.server = g_dbus_server_new_sync (address,
					     G_DBUS_SERVER_FLAGS_NONE,
					     guid,
					     NULL,
					     NULL,
					     &error);
	g_free (guid);
	if (error != NULL) {
		g_warning ("D-Bus server init failed: %s", error->message);
		return -1;
	}

	/* set up interface info */
	svc.node_info = g_dbus_node_info_new_for_xml (rb_metadata_iface_xml, &error);
	if (error != NULL) {
		g_warning ("D-Bus server init failed: %s", error->message);
		return -1;
	}

	g_signal_connect (svc.server, "new-connection", G_CALLBACK (new_connection_cb), &svc);
	g_dbus_server_start (svc.server);

	/* write the server address back to the parent process */
	{
		const char *addr;
		addr = g_dbus_server_get_client_address (svc.server);
		rb_debug ("D-BUS server listening on address %s", addr);
		printf ("%s\n", addr);
		fflush (stdout);
	}

	/* run main loop until we get bored */
	if (!svc.external)
		g_timeout_add_seconds (ATTENTION_SPAN / 2, (GSourceFunc) electromagnetic_shotgun, &svc);

	g_main_loop_run (svc.loop);

	if (svc.connection) {
		g_dbus_connection_close_sync (svc.connection, NULL, NULL);
		g_object_unref (svc.connection);
	}

	g_object_unref (svc.metadata);
	g_main_loop_unref (svc.loop);

	g_dbus_server_stop (svc.server);
	g_object_unref (svc.server);
	gst_deinit ();

	return 0;
}
Example #17
0
static void
default_eject (RBDeviceSource *source)
{
	GVolume *volume = NULL;
	GMount *mount = NULL;

	if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "volume")) {
		g_object_get (source, "volume", &volume, NULL);
	}
	if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "mount")) {
		g_object_get (source, "mount", &mount, NULL);
	}

	/* try ejecting based on volume first, then based on the mount,
	 * and finally try unmounting.
	 */
	if (volume != NULL) {
		if (g_volume_can_eject (volume)) {
			rb_debug ("ejecting volume");
			g_volume_eject_with_operation (volume,
						       G_MOUNT_UNMOUNT_NONE,
						       NULL,
						       NULL,
						       (GAsyncReadyCallback) eject_cb,
						       NULL);
		} else {
			/* this should never happen; the eject command will be
			 * insensitive if the selected source cannot be ejected.
			 */
			rb_debug ("don't know what to do with this volume");
		}
	} else if (mount != NULL) {
		if (g_mount_can_eject (mount)) {
			rb_debug ("ejecting mount");
			g_mount_eject_with_operation (mount,
						      G_MOUNT_UNMOUNT_NONE,
						      NULL,
						      NULL,
						      (GAsyncReadyCallback) eject_cb,
						      NULL);
		} else if (g_mount_can_unmount (mount)) {
			rb_debug ("unmounting mount");
			g_mount_unmount_with_operation (mount,
							G_MOUNT_UNMOUNT_NONE,
							NULL,
							NULL,
							(GAsyncReadyCallback) unmount_cb,
							NULL);
		} else {
			/* this should never happen; the eject command will be
			 * insensitive if the selected source cannot be ejected.
			 */
			rb_debug ("don't know what to do with this mount");
		}
	}

	if (volume != NULL) {
		g_object_unref (volume);
	}
	if (mount != NULL) {
		g_object_unref (mount);
	}
}
static gboolean
bus_cb (GstBus *bus, GstMessage *message, RBPlayerGst *mp)
{
	const GstStructure *structure;
	g_return_val_if_fail (mp != NULL, FALSE);

	switch (GST_MESSAGE_TYPE (message)) {
	case GST_MESSAGE_ERROR: {
		char *debug;
		GError *error = NULL;
		GError *sig_error = NULL;
		int code;
		gboolean emit = TRUE;

		gst_message_parse_error (message, &error, &debug);

		/* If we've already got an error, ignore 'internal data flow error'
		 * type messages, as they're too generic to be helpful.
		 */
		if (mp->priv->emitted_error &&
		    error->domain == GST_STREAM_ERROR &&
		    error->code == GST_STREAM_ERROR_FAILED) {
			rb_debug ("Ignoring generic error \"%s\"", error->message);
			emit = FALSE;
		}

		code = rb_gst_error_get_error_code (error);

		if (emit) {
			if (message_from_sink (mp->priv->audio_sink, message)) {
				rb_debug ("got error from sink: %s (%s)", error->message, debug);
				/* Translators: the parameter here is an error message */
				g_set_error (&sig_error,
					     RB_PLAYER_ERROR,
					     code,
					     _("Failed to open output device: %s"),
					     error->message);
			} else {
				rb_debug ("got error from stream: %s (%s)", error->message, debug);
				g_set_error (&sig_error,
					     RB_PLAYER_ERROR,
					     code,
					     "%s",
					     error->message);
			}
			state_change_finished (mp, sig_error);
			mp->priv->emitted_error = TRUE;
			if (mp->priv->playbin_stream_changing) {
				emit_playing_stream_and_tags (mp, TRUE);
			}
			_rb_player_emit_error (RB_PLAYER (mp), mp->priv->stream_data, sig_error);
		}

		/* close if not already closing */
		if (mp->priv->uri != NULL)
			rb_player_close (RB_PLAYER (mp), NULL, NULL);

		g_error_free (error);
		g_free (debug);
		break;
	}

	case GST_MESSAGE_EOS:
		_rb_player_emit_eos (RB_PLAYER (mp), mp->priv->stream_data, FALSE);
		break;

	case GST_MESSAGE_STATE_CHANGED:
		{
			GstState oldstate;
			GstState newstate;
			GstState pending;
			gst_message_parse_state_changed (message, &oldstate, &newstate, &pending);
			if (GST_MESSAGE_SRC (message) == GST_OBJECT (mp->priv->playbin)) {
				if (pending == GST_STATE_VOID_PENDING) {
					rb_debug ("playbin reached state %s", gst_element_state_get_name (newstate));
					state_change_finished (mp, NULL);
				}
			}
			break;
		}

	case GST_MESSAGE_TAG: {
		GstTagList *tags;
		gst_message_parse_tag (message, &tags);

		if (mp->priv->stream_change_pending || mp->priv->playbin_stream_changing) {
			mp->priv->stream_tags = g_list_append (mp->priv->stream_tags, tags);
		} else {
			gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, mp);
			gst_tag_list_free (tags);
		}
		break;
	}


	case GST_MESSAGE_BUFFERING: {
		gint progress;

		structure = gst_message_get_structure (message);
		if (!gst_structure_get_int (structure, "buffer-percent", &progress)) {
			g_warning ("Could not get value from BUFFERING message");
			break;
		}

		if (progress >= 100) {
			mp->priv->buffering = FALSE;
			if (mp->priv->playing) {
				rb_debug ("buffering done, setting pipeline back to PLAYING");
				gst_element_set_state (mp->priv->playbin, GST_STATE_PLAYING);
			} else {
				rb_debug ("buffering done, leaving pipeline PAUSED");
			}
		} else if (mp->priv->buffering == FALSE && mp->priv->playing) {

			rb_debug ("buffering - temporarily pausing playback");
			gst_element_set_state (mp->priv->playbin, GST_STATE_PAUSED);
			mp->priv->buffering = TRUE;
		}

		_rb_player_emit_buffering (RB_PLAYER (mp), mp->priv->stream_data, progress);
		break;
	}

	case GST_MESSAGE_APPLICATION:
		structure = gst_message_get_structure (message);
		_rb_player_emit_event (RB_PLAYER (mp), mp->priv->stream_data, gst_structure_get_name (structure), NULL);
		break;

	case GST_MESSAGE_ELEMENT:
		structure = gst_message_get_structure (message);
		if (gst_is_missing_plugin_message (message)) {
			handle_missing_plugin_message (mp, message);
		} else if (mp->priv->playbin_stream_changing &&
			   gst_structure_has_name (structure, "playbin2-stream-changed")) {
			rb_debug ("got playbin2-stream-changed message");
			mp->priv->playbin_stream_changing = FALSE;
			emit_playing_stream_and_tags (mp, TRUE);
		} else if (gst_structure_has_name (structure, "redirect")) {
			const char *uri = gst_structure_get_string (structure, "new-location");
			_rb_player_emit_redirect (RB_PLAYER (mp), mp->priv->stream_data, uri);
		}
		break;

	default:
		break;
	}

	/* emit message signals too, so plugins can process messages */
	gst_bus_async_signal_func (bus, message, NULL);

	return TRUE;
}
static void
rb_gpm_plugin_init (RBGPMPlugin *plugin)
{
	rb_debug ("RBGPMPlugin initialising");
}
static gboolean
construct_pipeline (RBPlayerGst *mp, GError **error)
{
	GstElement *sink;

	mp->priv->playbin = gst_element_factory_make ("playbin2", NULL);
	if (mp->priv->playbin == NULL) {
		g_set_error (error,
			     RB_PLAYER_ERROR,
			     RB_PLAYER_ERROR_GENERAL,
			     _("Failed to create %s element; check your GStreamer installation"),
			     "playbin2");
		return FALSE;
	}
	g_signal_connect_object (G_OBJECT (mp->priv->playbin),
				 "about-to-finish",
				 G_CALLBACK (about_to_finish_cb),
				 mp, 0);
	g_signal_connect_object (G_OBJECT (mp->priv->playbin),
				 "deep-notify::volume",
				 G_CALLBACK (volume_notify_cb),
				 mp, 0);
	g_signal_connect_object (G_OBJECT (mp->priv->playbin),
				 "notify::source",
				 G_CALLBACK (source_notify_cb),
				 mp, 0);

	gst_bus_add_watch (gst_element_get_bus (mp->priv->playbin),
			   (GstBusFunc) bus_cb,
			   mp);

	/* let plugins add bits to playbin */
	g_object_notify (G_OBJECT (mp), "playbin");
	g_object_notify (G_OBJECT (mp), "bus");

	/* Use gsettingsaudiosink for audio if there's no audio sink yet */
	g_object_get (mp->priv->playbin, "audio-sink", &mp->priv->audio_sink, NULL);
	if (mp->priv->audio_sink == NULL) {
		const char *try_sinks[] = { "gsettingsaudiosink", "gconfaudiosink", "autoaudiosink" };
		int i;

		for (i = 0; i < G_N_ELEMENTS (try_sinks); i++) {
			mp->priv->audio_sink = rb_player_gst_try_audio_sink (try_sinks[i], NULL);
			if (mp->priv->audio_sink != NULL) {
				g_object_set (mp->priv->playbin, "audio-sink", mp->priv->audio_sink, NULL);
				break;
			}
		}
		if (mp->priv->audio_sink == NULL) {
			g_set_error (error,
				     RB_PLAYER_ERROR,
				     RB_PLAYER_ERROR_GENERAL,
				     _("Failed to create %s element; check your GStreamer installation"),
				     "autoaudiosink");
			return FALSE;
		}
	} else {
		rb_debug ("existing audio sink found");
		g_object_unref (mp->priv->audio_sink);
	}

	{
		GstPad *pad;
		GList *l;
		GstElement *queue;
		GstPad *ghostpad;

		/* setup filterbin */
		mp->priv->filterbin = rb_gst_create_filter_bin ();

		/* set up the sinkbin with its tee element */
		mp->priv->sinkbin = gst_bin_new (NULL);
		mp->priv->tee = gst_element_factory_make ("tee", NULL);
		queue = gst_element_factory_make ("queue", NULL);

		/* link it all together and insert */
		gst_bin_add_many (GST_BIN (mp->priv->sinkbin), mp->priv->filterbin, mp->priv->tee, queue, mp->priv->audio_sink, NULL);
		gst_element_link_many (mp->priv->filterbin, mp->priv->tee, queue, mp->priv->audio_sink, NULL);

		pad = gst_element_get_pad (mp->priv->filterbin, "sink");
		ghostpad = gst_ghost_pad_new ("sink", pad);
		gst_element_add_pad (mp->priv->sinkbin, ghostpad);
		gst_object_unref (pad);

		g_object_set (G_OBJECT (mp->priv->playbin), "audio-sink", mp->priv->sinkbin, NULL);

		/* add any tees and filters that were waiting for us */
		for (l = mp->priv->waiting_tees; l != NULL; l = g_list_next (l)) {
			rb_player_gst_tee_add_tee (RB_PLAYER_GST_TEE (mp), GST_ELEMENT (l->data));
		}
		g_list_free (mp->priv->waiting_tees);
		mp->priv->waiting_tees = NULL;

		for (l = mp->priv->waiting_filters; l != NULL; l = g_list_next (l)) {
			rb_player_gst_filter_add_filter (RB_PLAYER_GST_FILTER(mp), GST_ELEMENT (l->data));
		}
		g_list_free (mp->priv->waiting_filters);
		mp->priv->waiting_filters = NULL;
	}

	/* Use fakesink for video if there's no video sink yet */
	g_object_get (mp->priv->playbin, "video-sink", &sink, NULL);
	if (sink == NULL) {
		sink = gst_element_factory_make ("fakesink", NULL);
		g_object_set (mp->priv->playbin, "video-sink", sink, NULL);
	} else {
		g_object_unref (sink);
	}

	if (mp->priv->cur_volume > 1.0)
		mp->priv->cur_volume = 1.0;
	if (mp->priv->cur_volume < 0.0)
		mp->priv->cur_volume = 0;

	rb_debug ("pipeline construction complete");
	return TRUE;
}
static void
impl_show_properties (RBMediaPlayerSource *source, GtkWidget *info_box, GtkWidget *notebook)
{
	RBGenericPlayerSourcePrivate *priv = GET_PRIVATE (source);
	RhythmDBQueryModel *model;
	GtkBuilder *builder;
	GtkWidget *widget;
	GString *str;
	char *device_name;
	char *builder_file;
	char *vendor_name;
	char *model_name;
	char *serial_id;
	GObject *plugin;
	char *text;
	GList *output_formats;
	GList *t;

	g_object_get (source, "plugin", &plugin, NULL);
	builder_file = rb_find_plugin_data_file (plugin, "generic-player-info.ui");
	g_object_unref (plugin);

	if (builder_file == NULL) {
		g_warning ("Couldn't find generic-player-info.ui");
		return;
	}

	builder = rb_builder_load (builder_file, NULL);
	g_free (builder_file);

	if (builder == NULL) {
		rb_debug ("Couldn't load generic-player-info.ui");
		return;
	}

	/* 'basic' tab stuff */

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "generic-player-basic-info"));
	gtk_box_pack_start (GTK_BOX (info_box), widget, TRUE, TRUE, 0);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "entry-device-name"));
	g_object_get (source, "name", &device_name, NULL);
	gtk_entry_set_text (GTK_ENTRY (widget), device_name);
	g_free (device_name);
	/* don't think we can support this..
	g_signal_connect (widget, "focus-out-event",
			  (GCallback)rb_mtp_source_name_changed_cb, source);
			  */

	g_object_get (source, "base-query-model", &model, NULL);
	widget = GTK_WIDGET (gtk_builder_get_object (builder, "num-tracks"));
	text = g_strdup_printf ("%d", gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL));
	gtk_label_set_text (GTK_LABEL (widget), text);
	g_free (text);
	g_object_unref (model);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "num-playlists"));
	text = g_strdup_printf ("%d", g_list_length (priv->playlists));
	gtk_label_set_text (GTK_LABEL (widget), text);
	g_free (text);

	/* 'advanced' tab stuff */
	widget = GTK_WIDGET (gtk_builder_get_object (builder, "generic-player-advanced-tab"));
	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, gtk_label_new (_("Advanced")));

	g_object_get (priv->device_info,
		      "model", &model_name,
		      "vendor", &vendor_name,
		      "serial", &serial_id,
		      NULL);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-model-value"));
	gtk_label_set_text (GTK_LABEL (widget), model_name);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-manufacturer-value"));
	gtk_label_set_text (GTK_LABEL (widget), vendor_name);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-serial-number-value"));
	gtk_label_set_text (GTK_LABEL (widget), serial_id);

	g_free (model_name);
	g_free (vendor_name);
	g_free (serial_id);

	str = g_string_new ("");
	output_formats = rb_transfer_target_get_format_descriptions (RB_TRANSFER_TARGET (source));
	for (t = output_formats; t != NULL; t = t->next) {
		if (t != output_formats) {
			g_string_append (str, "\n");
		}
		g_string_append (str, t->data);
	}
	rb_list_deep_free (output_formats);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "audio-format-list"));
	gtk_label_set_text (GTK_LABEL (widget), str->str);
	g_string_free (str, TRUE);

	g_object_unref (builder);
}
static void
rb_generic_player_plugin_init (RBGenericPlayerPlugin *plugin)
{
	rb_debug ("RBGenericPlayerPlugin initialising");
}
Example #23
0
static void
start_deferred_scan (RhythmDBImportJob *job, int total, RBImportDialog *dialog)
{
	rb_debug ("previous import job finished");
	start_scanning (dialog);
}
gchar*
rb_search_fold (const char *original)
{
	GString *string;
	gchar *normalized;
	gunichar *unicode, *cur;
	
	g_return_val_if_fail (original != NULL, NULL);

	/* old behaviour is equivalent to: return g_utf8_casefold (original, -1); */
	
	string = g_string_new (NULL);
	normalized = g_utf8_normalize(original, -1, G_NORMALIZE_DEFAULT);
	unicode = g_utf8_to_ucs4_fast (normalized, -1, NULL);
	

	for (cur = unicode; *cur != 0; cur++) {
		switch (g_unichar_type (*cur)) {
		case G_UNICODE_COMBINING_MARK:
		case G_UNICODE_ENCLOSING_MARK:
		case G_UNICODE_NON_SPACING_MARK:
		case G_UNICODE_CONNECT_PUNCTUATION:
		case G_UNICODE_DASH_PUNCTUATION:
		case G_UNICODE_CLOSE_PUNCTUATION:
		case G_UNICODE_FINAL_PUNCTUATION:
		case G_UNICODE_INITIAL_PUNCTUATION:
		case G_UNICODE_OTHER_PUNCTUATION:
		case G_UNICODE_OPEN_PUNCTUATION:
			/* remove these */
			break;

		case G_UNICODE_LOWERCASE_LETTER:
		case G_UNICODE_MODIFIER_LETTER:
		case G_UNICODE_OTHER_LETTER:
		case G_UNICODE_TITLECASE_LETTER:
		case G_UNICODE_UPPERCASE_LETTER:
			/* convert to lower case */
			*cur = g_unichar_tolower (*cur);
			/* ... and fall through */\
		case G_UNICODE_DECIMAL_NUMBER:
		case G_UNICODE_LETTER_NUMBER:
		case G_UNICODE_OTHER_NUMBER:
		/* should be keep symbols? */
		case G_UNICODE_CURRENCY_SYMBOL:
		case G_UNICODE_MODIFIER_SYMBOL:
		case G_UNICODE_MATH_SYMBOL:
		case G_UNICODE_OTHER_SYMBOL:
			g_string_append_unichar (string, *cur);
			break;

		case G_UNICODE_UNASSIGNED:
			rb_debug ("unassigned unicode character type found");
			/* fall through */

		default:
			/* leave these in */
			g_string_append_unichar (string, *cur);
		}
	}
	
	g_free (unicode);
	g_free (normalized);
			
	return g_string_free (string, FALSE);
}
Example #25
0
static void
impl_show_properties (RBMediaPlayerSource *source, GtkWidget *info_box, GtkWidget *notebook)
{
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
	GtkBuilder *builder;
	GtkWidget *widget;
	GHashTableIter iter;
	gpointer key, value;
	int num_podcasts;
	char *device_name;
	char *builder_file;
	RBPlugin *plugin;
	char *text;
	GList *output_formats;
	GList *t;
	GString *str;

	g_object_get (source, "plugin", &plugin, NULL);
	builder_file = rb_plugin_find_file (plugin, "mtp-info.ui");
	g_object_unref (plugin);

	if (builder_file == NULL) {
		g_warning ("Couldn't find mtp-info.ui");
		return;
	}

	builder = rb_builder_load (builder_file, NULL);
	g_free (builder_file);

	if (builder == NULL) {
		rb_debug ("Couldn't load mtp-info.ui");
		return;
	}

	/* 'basic' tab stuff */

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-basic-info"));
	gtk_box_pack_start (GTK_BOX (info_box), widget, TRUE, TRUE, 0);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "entry-mtp-name"));
	g_object_get (source, "name", &device_name, NULL);
	gtk_entry_set_text (GTK_ENTRY (widget), device_name);
	g_free (device_name);
	g_signal_connect (widget, "focus-out-event",
			  (GCallback)rb_mtp_source_name_changed_cb, source);

	num_podcasts = 0;
	g_hash_table_iter_init (&iter, priv->entry_map);
	while (g_hash_table_iter_next (&iter, &key, &value)) {
		LIBMTP_track_t *track = value;
		if (g_strcmp0 (track->genre, "Podcast") == 0) {
			num_podcasts++;
		}
	}

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-num-tracks"));
	text = g_strdup_printf ("%d", g_hash_table_size (priv->entry_map) - num_podcasts);
	gtk_label_set_text (GTK_LABEL (widget), text);
	g_free (text);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-num-podcasts"));
	text = g_strdup_printf ("%d", num_podcasts);
	gtk_label_set_text (GTK_LABEL (widget), text);
	g_free (text);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-num-playlists"));
	text = g_strdup_printf ("%d", 0);						/* correct, but wrong */
	gtk_label_set_text (GTK_LABEL (widget), text);
	g_free (text);

	/* 'advanced' tab stuff */
	widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtp-advanced-tab"));
	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, gtk_label_new (_("Advanced")));

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-mtp-model-value"));
	gtk_label_set_text (GTK_LABEL (widget), priv->model_name);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-serial-number-value"));
	gtk_label_set_text (GTK_LABEL (widget), priv->serial);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-firmware-version-value"));
	gtk_label_set_text (GTK_LABEL (widget), priv->device_version);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-manufacturer-value"));
	gtk_label_set_text (GTK_LABEL (widget), priv->manufacturer);

	str = g_string_new ("");
	output_formats = rb_removable_media_source_get_format_descriptions (RB_REMOVABLE_MEDIA_SOURCE (source));
	for (t = output_formats; t != NULL; t = t->next) {
		if (t != output_formats) {
			g_string_append (str, "\n");
		}
		g_string_append (str, t->data);
	}
	rb_list_deep_free (output_formats);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "label-audio-formats-value"));
	gtk_label_set_text (GTK_LABEL (widget), str->str);
	g_string_free (str, TRUE);

	g_object_unref (builder);
}
Example #26
0
static void
rb_mtp_sink_handle_message (GstBin *bin, GstMessage *message)
{
    /* when we get an EOS message from the fdsink, close the fd and upload the
     * file to the device.
     */
    if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS) {
        int fd;
        struct stat stat_buf;

        RBMTPSink *sink = RB_MTP_SINK (bin);

        /* fill in the file size and close the fd */
        g_object_get (sink->fdsink, "fd", &fd, NULL);
        fstat (fd, &stat_buf);
        sink->track->filesize = stat_buf.st_size;
        close (fd);

        rb_debug ("handling EOS from fdsink; file size is %" G_GUINT64_FORMAT, sink->track->filesize);

        /* we can just block waiting for mtp thread operations to finish here
         * as we're on a streaming thread.
         */
        g_mutex_lock (sink->upload_mutex);

        if (sink->folder_path != NULL) {
            /* find or create the target folder.
             * if this fails, we just upload to the default music folder
             * rather than giving up entirely.
             */
            sink->got_folder = FALSE;
            rb_mtp_thread_create_folder (sink->device_thread,
                                         (const char **)sink->folder_path,
                                         (RBMtpCreateFolderCallback) folder_callback,
                                         g_object_ref (sink),
                                         g_object_unref);
            while (sink->got_folder == FALSE) {
                g_cond_wait (sink->upload_cond, sink->upload_mutex);
            }
        }

        /* and upload the file */
        sink->upload_done = FALSE;
        rb_mtp_thread_upload_track (sink->device_thread,
                                    sink->track,
                                    sink->tempfile,
                                    (RBMtpUploadCallback) upload_callback,
                                    g_object_ref (sink),
                                    g_object_unref);

        while (sink->upload_done == FALSE) {
            g_cond_wait (sink->upload_cond, sink->upload_mutex);
        }
        g_mutex_unlock (sink->upload_mutex);

        /* post error message if the upload failed - this should get there before
         * this EOS message does, so it should work OK.
         */
        if (sink->upload_error != NULL) {
            int code;

            switch (sink->upload_error->code) {
            case RB_MTP_THREAD_ERROR_NO_SPACE:
                code = GST_RESOURCE_ERROR_NO_SPACE_LEFT;
                break;

            default:
            case RB_MTP_THREAD_ERROR_SEND_TRACK:
                code = GST_RESOURCE_ERROR_WRITE;
                break;
            }

            GST_WARNING_OBJECT (sink, "error: %s", sink->upload_error->message);
            gst_element_message_full (GST_ELEMENT (sink),
                                      GST_MESSAGE_ERROR,
                                      GST_RESOURCE_ERROR, code,
                                      g_strdup (sink->upload_error->message), NULL,
                                      __FILE__, GST_FUNCTION, __LINE__);
        }
    }

    GST_BIN_CLASS (parent_class)->handle_message (bin, message);
}
Example #27
0
static RhythmDBEntry *
add_mtp_track_to_db (RBMtpSource *source,
		     RhythmDB *db,
		     LIBMTP_track_t *track)
{
	RhythmDBEntry *entry = NULL;
	RhythmDBEntryType entry_type;
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
	char *name = NULL;

	/* ignore everything except audio (allow audio/video types too, since they're probably pretty common) */
	if (!(LIBMTP_FILETYPE_IS_AUDIO (track->filetype) || LIBMTP_FILETYPE_IS_AUDIOVIDEO (track->filetype))) {
		rb_debug ("ignoring non-audio item %d (filetype %s)",
			  track->item_id,
			  LIBMTP_Get_Filetype_Description (track->filetype));
		return NULL;
	}

	/* Set URI */
	g_object_get (G_OBJECT (source), "entry-type", &entry_type, NULL);
	name = g_strdup_printf ("xrbmtp://%i/%s", track->item_id, track->filename);
	entry = rhythmdb_entry_new (RHYTHMDB (db), entry_type, name);
	g_free (name);
        g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type);

	if (entry == NULL) {
		rb_debug ("cannot create entry %i", track->item_id);
		g_object_unref (G_OBJECT (db));
		return NULL;
	}

	/* Set track number */
	if (track->tracknumber != 0) {
		GValue value = {0, };
		g_value_init (&value, G_TYPE_ULONG);
		g_value_set_ulong (&value, track->tracknumber);
		rhythmdb_entry_set (RHYTHMDB (db), entry,
				    RHYTHMDB_PROP_TRACK_NUMBER,
				    &value);
		g_value_unset (&value);
	}

	/* Set length */
	if (track->duration != 0) {
		GValue value = {0, };
		g_value_init (&value, G_TYPE_ULONG);
		g_value_set_ulong (&value, track->duration/1000);
		rhythmdb_entry_set (RHYTHMDB (db), entry,
				    RHYTHMDB_PROP_DURATION,
				    &value);
		g_value_unset (&value);
	}

	/* Set file size */
	if (track->filesize != 0) {
		GValue value = {0, };
		g_value_init (&value, G_TYPE_UINT64);
		g_value_set_uint64 (&value, track->filesize);
		rhythmdb_entry_set (RHYTHMDB (db), entry,
				    RHYTHMDB_PROP_FILE_SIZE,
				    &value);
		g_value_unset (&value);
	}

	/* Set playcount */
	if (track->usecount != 0) {
		GValue value = {0, };
		g_value_init (&value, G_TYPE_ULONG);
		g_value_set_ulong (&value, track->usecount);
		rhythmdb_entry_set (RHYTHMDB (db), entry,
					       RHYTHMDB_PROP_PLAY_COUNT,
					       &value);
		g_value_unset (&value);
	}
	/* Set rating */
	if (track->rating != 0) {
		GValue value = {0, };
		g_value_init (&value, G_TYPE_DOUBLE);
		g_value_set_double (&value, track->rating/20);
		rhythmdb_entry_set (RHYTHMDB (db), entry,
					       RHYTHMDB_PROP_RATING,
					       &value);
		g_value_unset (&value);
	}

	/* Set title */
	entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_TITLE, track->title);

	/* Set album, artist and genre from MTP */
	entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_ARTIST, track->artist);
	entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_ALBUM, track->album);
	entry_set_string_prop (RHYTHMDB (db), entry, RHYTHMDB_PROP_GENRE, track->genre);

	g_hash_table_insert (priv->entry_map, entry, track);
	rhythmdb_commit (RHYTHMDB (db));

	return entry;
}
static void
got_session_key_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
{
    /* parses the session details from the response.
     * if successful then authentication is complete.
     * if the error is that the token has not been authenticated
     * then keep trying.
     * on other errors stop trying and go to logged out state.
     */
    RBAudioscrobblerAccount *account;
    JsonParser *parser;

    g_assert (RB_IS_AUDIOSCROBBLER_ACCOUNT (user_data));
    account = RB_AUDIOSCROBBLER_ACCOUNT (user_data);

    parser = json_parser_new ();

    if (msg->response_body->data != NULL &&
            json_parser_load_from_data (parser, msg->response_body->data, msg->response_body->length, NULL)) {
        JsonObject *root_object;

        root_object = json_node_get_object (json_parser_get_root (parser));
        if (json_object_has_member (root_object, "session")) {
            JsonObject *session_object;

            /* cancel the old session (and remove timeout) */
            cancel_session (account);

            session_object = json_object_get_object_member (root_object, "session");
            account->priv->username = g_strdup (json_object_get_string_member (session_object, "name"));
            account->priv->session_key = g_strdup (json_object_get_string_member (session_object, "key"));

            rb_debug ("granted session key \"%s\" for user \"%s\"",
                      account->priv->session_key,
                      account->priv->username);

            /* save our session for future use */
            save_session_settings (account);

            /* update status */
            account->priv->login_status = RB_AUDIOSCROBBLER_ACCOUNT_LOGIN_STATUS_LOGGED_IN;
            g_signal_emit (account, rb_audioscrobbler_account_signals[LOGIN_STATUS_CHANGED],
                           0, account->priv->login_status);
        } else {
            int code;
            const char *message;

            code = json_object_get_int_member (root_object, "error");
            message = json_object_get_string_member (root_object, "message");

            switch (code) {
            case 14:
                rb_debug ("auth token has not been authorised yet. will try again");
                break;
            default:
                /* some other error. most likely 4 (invalid token) or 15 (token has expired)
                 * whatever it is, we wont be retrieving a session key from it
                 */
                rb_debug ("error retrieving session key: %s", message);

                /* go back to being logged out */
                rb_audioscrobbler_account_logout (account);
                break;
            }
        }

    } else {
        /* treat as connection error */
        rb_debug ("empty or invalid response retrieving session key. treating as connection error");

        cancel_session (account);

        account->priv->login_status = RB_AUDIOSCROBBLER_ACCOUNT_LOGIN_STATUS_CONNECTION_ERROR;
        g_signal_emit (account, rb_audioscrobbler_account_signals[LOGIN_STATUS_CHANGED],
                       0, account->priv->login_status);
    }

    g_object_unref (parser);
}
static void
default_reset_filters (RBSource *source)
{
	rb_debug ("no implementation of reset_filters for this source");
}
Example #30
0
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;
}