/**
 * rb_debug_real:
 * @func: function name
 * @file: file name
 * @line: line number
 * @newline: if TRUE, add a newline to the output
 * @message: the debug message
 *
 * If the debug output settings match the function or file names,
 * the debug message will be formatted and written to standard error.
 */
void
rb_debug_real (const char *func, const char *file, const int line, gboolean newline, const char *message)
{
	if (rb_debug_matches (func, file)) {
		_rb_debug_print (func, file, line, newline, message);
	}
}
/**
 * rb_debug_realf:
 * @func: function name
 * @file: file name
 * @line: line number
 * @newline: if TRUE, add a newline to the output
 * @format: printf style format specifier
 * @Varargs: substitution values for @format
 *
 * If the debug output settings match the function or file names,
 * the debug message will be formatted and written to standard error.
 */
void
rb_debug_realf (const char *func,
		const char *file,
		const int line,
		gboolean newline,
		const char *format, ...)
{
	va_list args;
	char buffer[1025];

	if (!rb_debug_matches (func, file))
		return;

	va_start (args, format);

	g_vsnprintf (buffer, 1024, format, args);

	va_end (args);

	_rb_debug_print (func, file, line, newline, buffer);
}
static gboolean
load_playlist (RBGenericPlayerPlaylistSource *source)
{
	RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (source);
	TotemPlParser *parser;
	gboolean result;
	GFile *file;
	char *name;
	char *uri;

	if (priv->playlist_path == NULL) {
		/* this happens when we're creating a new playlist */
		rb_debug ("playlist has no path; obviously can't load it");
		g_object_set (source, "name", "", NULL);
		return TRUE;
	}

	priv->loading = TRUE;
	file = g_file_new_for_path (priv->playlist_path);

	/* make a default name for the playlist based on the filename */
	name = g_file_get_basename (file);
	g_object_set (source, "name", name, NULL);
	g_free (name);

	parser = totem_pl_parser_new ();
	if (rb_debug_matches ("totem_pl_parser_parse", "totem-pl-parser.c")) {
		g_object_set (parser, "debug", TRUE, NULL);
	}

	rb_generic_player_source_set_supported_formats (priv->player_source, parser);
	g_signal_connect (parser,
			  "entry-parsed", G_CALLBACK (handle_playlist_entry_cb),
			  source);
	g_signal_connect (parser,
			  "playlist-started", G_CALLBACK (handle_playlist_start_cb),
			  source);
	g_object_set (G_OBJECT (parser), "recurse", FALSE, NULL);

	uri = g_file_get_uri (file);
	switch (totem_pl_parser_parse_with_base (parser, uri, priv->device_root, FALSE)) {
	case TOTEM_PL_PARSER_RESULT_SUCCESS:
		rb_debug ("playlist parsed successfully");
		result = TRUE;
		break;

	case TOTEM_PL_PARSER_RESULT_ERROR:
		rb_debug ("playlist parser returned an error");
		result = FALSE;
		break;

	case TOTEM_PL_PARSER_RESULT_UNHANDLED:
		rb_debug ("playlist parser didn't handle the file");
		result = FALSE;
		break;

	case TOTEM_PL_PARSER_RESULT_IGNORED:
		rb_debug ("playlist parser ignored the file");
		result = FALSE;
		break;
	default:
		g_assert_not_reached ();
	}
	g_free (uri);
	g_object_unref (file);

	priv->loading = FALSE;
	return result;
}
static gboolean
save_playlist (RBGenericPlayerPlaylistSource *source)
{
	TotemPlParser *parser;
	TotemPlParserType playlist_type;
	RhythmDBQueryModel *query_model;
	char *name;
	char *temp_path;
	GError *error = NULL;
	RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (source);
	GFile *file;
	gboolean result;
	SavePlaylistData data;

	priv->save_playlist_id = 0;
	playlist_type = rb_generic_player_source_get_playlist_format (priv->player_source);

	g_object_get (source,
		      "name", &name,
		      "base-query-model", &query_model,
		      NULL);

	/* if we don't already have a name for this playlist, make one now */
	if (priv->playlist_path == NULL) {
		char *playlist_dir;
		char *mount_uri;
		char *filename;
		const char *ext;
		GFile *dir;
		GFile *playlist;

		ext = playlist_format_extension (playlist_type);

		if (name == NULL || name[0] == '\0') {
			/* now what? */
			filename = g_strdup_printf ("unnamed%s", ext);
		} else {
			filename = g_strdup_printf ("%s%s", name, ext);
		}

		playlist_dir = rb_generic_player_source_get_playlist_path (priv->player_source);
		mount_uri = rb_generic_player_source_get_mount_path (priv->player_source);

		dir = g_file_new_for_uri (mount_uri);
		if (playlist_dir != NULL) {
			GFile *pdir;

			pdir = g_file_resolve_relative_path (dir, playlist_dir);
			g_object_unref (dir);
			dir = pdir;
		}

		playlist = g_file_resolve_relative_path (dir, filename);
		priv->playlist_path = g_file_get_path (playlist);
		
		g_free (mount_uri);
		g_free (playlist_dir);

		g_object_unref (dir);
	}

	temp_path = g_strdup_printf ("%s%06X", priv->playlist_path, g_random_int_range (0, 0xFFFFFF));
	file = g_file_new_for_path (temp_path);

	parser = totem_pl_parser_new ();
	data.source = source;
	data.playlist_type = playlist_type;
#if TOTEM_PL_PARSER_CHECK_VERSION(2,29,1)
	data.playlist = totem_pl_playlist_new ();

	gtk_tree_model_foreach (GTK_TREE_MODEL (query_model),
				(GtkTreeModelForeachFunc) save_playlist_foreach,
				&data);
	if (rb_debug_matches ("totem_pl_parser_save", "totem-pl-parser.c")) {
		g_object_set (parser, "debug", TRUE, NULL);
	}

	result = totem_pl_parser_save (parser, data.playlist, file, name, playlist_type, &error);
	g_object_unref (data.playlist);
	data.playlist = NULL;
#else
	if (rb_debug_matches ("totem_pl_parser_write_with_title", "totem-pl-parser.c")) {
		g_object_set (parser, "debug", TRUE, NULL);
	}

	result = totem_pl_parser_write_with_title (parser,
						   GTK_TREE_MODEL (query_model),
						   (TotemPlParserIterFunc) save_playlist_entry,
						   temp_path,
						   name,
						   playlist_type,
						   &data,
						   &error);
#endif
	if (result == FALSE) {
		/* XXX report this more usefully */
		g_warning ("Playlist save failed: %s", error ? error->message : "<no error>");
	} else {
		GFile *dest;

		dest = g_file_new_for_path (priv->playlist_path);
		g_file_move (file, dest, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NO_FALLBACK_FOR_MOVE, NULL, NULL, NULL, &error);
		if (error != NULL) {
			/* XXX report this more usefully */
			g_warning ("moving %s => %s failed: %s", temp_path, priv->playlist_path, error->message);
		}

		g_object_unref (dest);
	}

	g_clear_error (&error);
	g_free (name);
	g_free (temp_path);
	g_object_unref (query_model);
	g_object_unref (parser);
	g_object_unref (file);

	return FALSE;
}
static gboolean
save_playlist (RBGenericPlayerPlaylistSource *source)
{
	TotemPlParser *parser;
	TotemPlParserType playlist_type;
	RhythmDBQueryModel *query_model;
	char *name;
	char *temp_uri;
	GError *error = NULL;
	RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (source);

	priv->save_playlist_id = 0;
	playlist_type = rb_generic_player_source_get_playlist_format (priv->player_source);

	g_object_get (source,
		      "name", &name,
		      "base-query-model", &query_model,
		      NULL);

	/* if we don't already have a name for this playlist, make one now */
	if (priv->playlist_path == NULL) {
		char *playlist_dir;
		char *mount_uri;
		char *filename;
		const char *ext;
		GFile *dir;
		GFile *playlist;

		ext = playlist_format_extension (playlist_type);

		if (name == NULL || name[0] == '\0') {
			/* now what? */
			filename = g_strdup_printf ("unnamed%s", ext);
		} else {
			filename = g_strdup_printf ("%s%s", name, ext);
		}

		playlist_dir = rb_generic_player_source_get_playlist_path (priv->player_source);
		mount_uri = rb_generic_player_source_get_mount_path (priv->player_source);

		dir = g_file_new_for_uri (mount_uri);
		if (playlist_dir != NULL) {
			GFile *pdir;

			pdir = g_file_resolve_relative_path (dir, playlist_dir);
			g_object_unref (dir);
			dir = pdir;
		}

		playlist = g_file_resolve_relative_path (dir, filename);
		priv->playlist_path = g_file_get_path (playlist);
		
		g_free (mount_uri);
		g_free (playlist_dir);

		g_object_unref (dir);
	}

	temp_uri = g_strdup_printf ("%s%06X", priv->playlist_path, g_random_int_range (0, 0xFFFFFF));

	parser = totem_pl_parser_new ();
	if (rb_debug_matches ("totem_pl_parser_write_with_title", "totem-pl-parser.c")) {
		g_object_set (parser, "debug", TRUE, NULL);
	}
	if (totem_pl_parser_write_with_title (parser,
					      GTK_TREE_MODEL (query_model),
					      (TotemPlParserIterFunc) save_playlist_entry,
					      temp_uri,
					      name,
					      playlist_type,
					      source,
					      &error) == FALSE) {
		/* XXX report this more usefully */
		g_warning ("Playlist save failed: %s", error->message);
	} else {
		GFile *dest;
		GFile *src;

		dest = g_file_new_for_path (priv->playlist_path);
		src = g_file_new_for_path (temp_uri);
		g_file_move (src, dest, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NO_FALLBACK_FOR_MOVE, NULL, NULL, NULL, &error);
		if (error != NULL) {
			/* XXX report this more usefully */
			g_warning ("Replacing playlist failed: %s", error->message);
		}

		g_object_unref (dest);
		g_object_unref (src);
	}

	g_clear_error (&error);
	g_free (name);
	g_free (temp_uri);
	g_object_unref (query_model);

	return FALSE;
}
Ejemplo n.º 6
0
static void
rb_removable_media_manager_init (RBRemovableMediaManager *mgr)
{
	RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (mgr);

	priv->volume_mapping = g_hash_table_new (NULL, NULL);
	priv->mount_mapping = g_hash_table_new (NULL, NULL);
	priv->device_mapping = g_hash_table_new (g_direct_hash, g_direct_equal);
	priv->transfer_queue = g_async_queue_new ();

	/*
	 * Monitor new (un)mounted file systems to look for new media;
	 * we watch for both volumes and mounts because for some devices,
	 * we don't require the volume to actually be mounted.
	 *
	 * both pre-unmount and unmounted callbacks are registered because it is
	 * better to do it before the unmount, but sometimes we don't get those
	 * (e.g. someone pressing the eject button on a cd drive). If we get the
	 * pre-unmount signal, the corresponding unmounted signal is ignored
	 */
	priv->volume_monitor = g_object_ref (g_volume_monitor_get ());

	priv->volume_added_id = g_signal_connect_object (priv->volume_monitor,
							 "volume-added",
							 G_CALLBACK (volume_added_cb),
							 mgr, 0);
	priv->volume_removed_id = g_signal_connect_object (priv->volume_monitor,
							   "volume-removed",
							   G_CALLBACK (volume_removed_cb),
							   mgr, 0);
	priv->mount_added_id = g_signal_connect_object (priv->volume_monitor,
							"mount-added",
							G_CALLBACK (mount_added_cb),
							mgr, 0);
	priv->mount_pre_unmount_id = g_signal_connect_object (priv->volume_monitor,
							      "mount-pre-unmount",
							      G_CALLBACK (mount_removed_cb),
							      mgr, 0);
	priv->mount_removed_id = g_signal_connect_object (G_OBJECT (priv->volume_monitor),
							  "mount-removed",
							  G_CALLBACK (mount_removed_cb),
							  mgr, 0);

#if defined(HAVE_GUDEV)
	/*
	 * Monitor udev device events - we're only really interested in events
	 * for USB devices.
	 */
	{
		const char * const subsystems[] = { "usb", NULL };
		priv->gudev_client = g_udev_client_new (subsystems);
	}

	priv->uevent_id = g_signal_connect_object (priv->gudev_client,
						   "uevent",
						   G_CALLBACK (uevent_cb),
						   mgr, 0);
#endif

	/* enable debugging of media player device lookups if requested */
	if (rb_debug_matches ("mpid", "")) {
		mpid_enable_debug (TRUE);
	}
}