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