コード例 #1
0
static void
art_cb (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue *data, RBNotificationPlugin *plugin)
{
	RhythmDBEntry *entry;

	entry = rb_shell_player_get_playing_entry (plugin->shell_player);
	if (entry == NULL) {
		return;
	}

	if (rhythmdb_entry_matches_ext_db_key (plugin->db, entry, store_key)) {
		guint elapsed = 0;

		plugin->notify_art_path = g_strdup (filename);

		rb_shell_player_get_playing_time (plugin->shell_player, &elapsed, NULL);
		if (elapsed < PLAYING_ENTRY_NOTIFY_TIME) {
			notify_playing_entry (plugin, FALSE);
		}

		if (plugin->notify_art_key != NULL)
			rb_ext_db_key_free (plugin->notify_art_key);
		plugin->notify_art_key = rb_ext_db_key_copy (store_key);
	}

	rhythmdb_entry_unref (entry);
}
コード例 #2
0
static gboolean
is_playing_entry (RBNotificationPlugin *plugin, RhythmDBEntry *entry)
{
	RhythmDBEntry *playing;

	playing = rb_shell_player_get_playing_entry (plugin->shell_player);
	if (playing == NULL) {
		return FALSE;
	}

	rhythmdb_entry_unref (playing);
	return (entry == playing);
}
コード例 #3
0
static void
impl_activate (PeasActivatable *activatable)
{
	RBVisualizerPlugin *pi = RB_VISUALIZER_PLUGIN (activatable);
	RBDisplayPageGroup *page_group;
	RhythmDBEntry *entry;
	GtkToggleAction *fullscreen;
	GtkWidget *menu;
	RBShell *shell;

	g_object_get (pi, "object", &shell, NULL);

	pi->settings = g_settings_new ("org.gnome.rhythmbox.plugins.visualizer");
	g_signal_connect_object (pi->settings, "changed", G_CALLBACK (settings_changed_cb), pi, 0);

	/* create UI actions and menus and stuff */
	fullscreen = gtk_toggle_action_new ("VisualizerFullscreen",
					    _("Fullscreen"),
					    _("Toggle fullscreen visual effects"),
					    GTK_STOCK_FULLSCREEN);
	menu = rb_visualizer_create_popup_menu (fullscreen);
	g_object_ref_sink (menu);

	/* create visualizer page */
	pi->page = rb_visualizer_page_new (G_OBJECT (pi), shell, fullscreen, menu);
	g_signal_connect_object (pi->page, "start", G_CALLBACK (start_visualizer_cb), pi, 0);
	g_signal_connect_object (pi->page, "stop", G_CALLBACK (stop_visualizer_cb), pi, 0);

	/* don't do anything if we couldn't create a video sink (clutter is broken, etc.) */
	g_object_get (pi->page, "sink", &pi->sink, NULL);
	if (pi->sink == NULL) {
		g_object_unref (shell);
		return;
	}

	/* prepare style stuff for fullscreen display */
	rb_visualizer_fullscreen_load_style (G_OBJECT (pi));

	/* add the visualizer page to the UI */
	page_group = rb_display_page_group_get_by_id ("display");
	if (page_group == NULL) {
		page_group = rb_display_page_group_new (G_OBJECT (shell),
							"display",
							_("Display"),
							RB_DISPLAY_PAGE_GROUP_CATEGORY_TOOLS);
		rb_shell_append_display_page (shell, RB_DISPLAY_PAGE (page_group), NULL);
	}
	g_object_set (pi->page, "visibility", FALSE, NULL);

	rb_shell_append_display_page (shell, RB_DISPLAY_PAGE (pi->page), RB_DISPLAY_PAGE (page_group));

	/* get player objects */
	g_object_get (shell, "shell-player", &pi->shell_player, NULL);
	g_object_get (pi->shell_player, "player", &pi->player, NULL);

	/* only show the page in the page tree when playing something */
	g_signal_connect_object (pi->shell_player, "playing-song-changed", G_CALLBACK (playing_song_changed_cb), pi, 0);
	entry = rb_shell_player_get_playing_entry (pi->shell_player);
	playing_song_changed_cb (pi->shell_player, entry, pi);
	if (entry != NULL) {
		rhythmdb_entry_unref (entry);
	}

	/* figure out how to insert the visualizer into the playback pipeline */
	if (g_object_class_find_property (G_OBJECT_GET_CLASS (pi->player), "playbin")) {

		rb_debug ("using playbin-based visualization");
		pi->playbin_notify_id = g_signal_connect_object (pi->player,
								 "notify::playbin",
								 G_CALLBACK (playbin_notify_cb),
								 pi,
								 0);
		g_object_get (pi->player, "playbin", &pi->playbin, NULL);
		if (pi->playbin != NULL) {
			mutate_playbin (pi, pi->playbin);
		}
	} else if (RB_IS_PLAYER_GST_TEE (pi->player)) {
		rb_debug ("using tee-based visualization");
	} else {
		g_warning ("unknown player backend type");
		g_object_unref (pi->player);
		pi->player = NULL;
	}

	g_object_unref (shell);
}
コード例 #4
0
static ClutterActor *
create_track_info (RBShell *shell)
{
    RBShellPlayer *player;
    RhythmDB *db;
    ClutterActor *box;
    ClutterActor *box2;
    ClutterActor *widget;
    ClutterActor *frame;
    RhythmDBEntry *entry;
    GValue *value;
    guint elapsed;

    g_object_get (shell, "shell-player", &player, "db", &db, NULL);
    entry = rb_shell_player_get_playing_entry (player);

    box = mx_box_layout_new ();
    mx_box_layout_set_orientation (MX_BOX_LAYOUT (box), MX_ORIENTATION_HORIZONTAL);
    mx_box_layout_set_spacing (MX_BOX_LAYOUT (box), 16);
    mx_stylable_set_style_class (MX_STYLABLE (box), "TrackInfoBox");
    mx_stylable_set_style (MX_STYLABLE (box), style);

    /* XXX rtl? */

    /* image container */
    frame = mx_frame_new ();
    mx_stylable_set_style_class (MX_STYLABLE (frame), "TrackInfoImage");
    mx_stylable_set_style (MX_STYLABLE (frame), style);
    mx_box_layout_add_actor (MX_BOX_LAYOUT (box), frame, 0);
    clutter_container_child_set (CLUTTER_CONTAINER (box), frame,
                                 "expand", FALSE,
                                 NULL);
    set_blank_image (MX_FRAME (frame));
    clutter_actor_show_all (CLUTTER_ACTOR (frame));

    g_signal_connect_object (player, "playing-song-changed", G_CALLBACK (cover_art_entry_changed_cb), frame, 0);
    request_cover_art (MX_FRAME (frame), entry);

    box2 = mx_box_layout_new ();
    mx_box_layout_set_orientation (MX_BOX_LAYOUT (box2), MX_ORIENTATION_VERTICAL);
    mx_box_layout_set_spacing (MX_BOX_LAYOUT (box2), 16);
    mx_stylable_set_style (MX_STYLABLE (box2), style);
    mx_box_layout_add_actor (MX_BOX_LAYOUT (box), box2, 1);
    clutter_container_child_set (CLUTTER_CONTAINER (box), box2,
                                 "expand", TRUE,
                                 "x-fill", TRUE,
                                 "y-fill", TRUE,
                                 "y-align", MX_ALIGN_MIDDLE,
                                 NULL);

    /* track info */
    widget = mx_label_new ();
    mx_stylable_set_style_class (MX_STYLABLE (widget), "TrackInfoText");
    mx_stylable_set_style (MX_STYLABLE (widget), style);
    mx_box_layout_add_actor (MX_BOX_LAYOUT (box2), widget, 1);
    clutter_container_child_set (CLUTTER_CONTAINER (box2), widget,
                                 "expand", FALSE,
                                 "x-fill", TRUE,
                                 "y-fill", TRUE,
                                 "y-align", MX_ALIGN_MIDDLE,
                                 NULL);

    g_signal_connect_object (player, "playing-song-changed", G_CALLBACK (playing_song_changed_cb), widget, 0);
    g_signal_connect_object (db, "entry-changed", G_CALLBACK (entry_changed_cb), widget, 0);
    g_signal_connect_object (db, "entry-extra-metadata-notify::" RHYTHMDB_PROP_STREAM_SONG_TITLE, G_CALLBACK (streaming_title_notify_cb), widget, 0);

    value = rhythmdb_entry_request_extra_metadata (db, entry, RHYTHMDB_PROP_STREAM_SONG_TITLE);
    if (value != NULL) {
        update_track_info (MX_LABEL (widget), db, entry, g_value_get_string (value));
        g_value_unset (value);
        g_free (value);
    } else {
        update_track_info (MX_LABEL (widget), db, entry, NULL);
    }

    /* elapsed/duration */
    widget = mx_label_new ();
    mx_stylable_set_style_class (MX_STYLABLE (widget), "TrackTimeText");
    mx_stylable_set_style (MX_STYLABLE (widget), style);
    mx_box_layout_add_actor (MX_BOX_LAYOUT (box2), widget, 2);
    clutter_container_child_set (CLUTTER_CONTAINER (box2), widget,
                                 "expand", FALSE,
                                 "x-fill", TRUE,
                                 "y-fill", TRUE,
                                 "y-align", MX_ALIGN_MIDDLE,
                                 NULL);

    g_signal_connect_object (player, "elapsed-changed", G_CALLBACK (elapsed_changed_cb), widget, 0);
    if (rb_shell_player_get_playing_time (player, &elapsed, NULL)) {
        update_elapsed (widget, player, elapsed);
    }

    rhythmdb_entry_unref (entry);
    g_object_unref (player);
    g_object_unref (db);
    return box;
}
コード例 #5
0
static void
info_available_cb (RBPlayer *backend,
		   const char *uri,
		   RBMetaDataField field,
		   GValue *value,
		   RBIRadioSource *source)
{
	RhythmDBEntry *entry;
        RhythmDBPropType entry_field = 0;
        gboolean set_field = FALSE;
	char *str = NULL;

	/* sanity check */
	if (!rb_player_opened (backend)) {
		rb_debug ("Got info_available but not playing");
		return;
	}

	GDK_THREADS_ENTER ();

	entry = rb_shell_player_get_playing_entry (source->priv->player);
	if (check_entry_type (source, entry) == FALSE)
		goto out_unlock;

	/* validate the value */
	switch (field) {
	case RB_METADATA_FIELD_TITLE:
	case RB_METADATA_FIELD_ARTIST:
	case RB_METADATA_FIELD_GENRE:
	case RB_METADATA_FIELD_COMMENT:
		str = g_value_dup_string (value);
		if (!g_utf8_validate (str, -1, NULL)) {
			g_warning ("Invalid UTF-8 from internet radio: %s", str);
			g_free (str);
			goto out_unlock;
		}
		break;
	default:
		break;
	}


	switch (field) {
		/* streaming song information */
	case RB_METADATA_FIELD_TITLE:
	{
		rb_streaming_source_set_streaming_title (RB_STREAMING_SOURCE (source), str);
		break;
	}
	case RB_METADATA_FIELD_ARTIST:
	{
		rb_streaming_source_set_streaming_artist (RB_STREAMING_SOURCE (source), str);
		break;
	}

		/* station information */
	case RB_METADATA_FIELD_GENRE:
	{
		const char *existing;

		/* check if the db entry already has a genre; if so, don't change it */
		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE);
		if ((existing == NULL) ||
		    (strcmp (existing, "") == 0) ||
		    (strcmp (existing, _("Unknown")) == 0)) {
			entry_field = RHYTHMDB_PROP_GENRE;
			rb_debug ("setting genre of iradio station to %s", str);
			set_field = TRUE;
		} else {
			rb_debug ("iradio station already has genre: %s; ignoring %s", existing, str);
		}
		break;
	}
	case RB_METADATA_FIELD_COMMENT:
	{
		const char *existing;
		const char *location;

		/* check if the db entry already has a title; if so, don't change it.
		 * consider title==URI to be the same as no title, since that's what
		 * happens for stations imported by DnD or commandline args.
		 * if the station title really is the same as the URI, then surely
		 * the station title in the stream metadata will say that too..
		 */
		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
		location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
		if ((existing == NULL) ||
		    (strcmp (existing, "") == 0) ||
		    (strcmp (existing, location) == 0)) {
			entry_field = RHYTHMDB_PROP_TITLE;
			rb_debug ("setting title of iradio station to %s", str);
			set_field = TRUE;
		} else {
			rb_debug ("iradio station already has title: %s; ignoring %s", existing, str);
		}
		break;
	}
	case RB_METADATA_FIELD_BITRATE:
		if (!rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_BITRATE)) {
			gulong bitrate;

			/* GStreamer sends us bitrate in bps, but we need it in kbps*/
			bitrate = g_value_get_ulong (value);
			g_value_set_ulong (value, bitrate/1000);

			rb_debug ("setting bitrate of iradio station to %lu",
				  g_value_get_ulong (value));
			entry_field = RHYTHMDB_PROP_BITRATE;
			set_field = TRUE;
		}
		break;
	default:
		break;
	}

	if (set_field && entry_field != 0) {
		rhythmdb_entry_set (source->priv->db, entry, entry_field, value);
		rhythmdb_commit (source->priv->db);
	}

	g_free (str);
 out_unlock:
	GDK_THREADS_LEAVE ();
}