static void
impl_constructed (GObject *object)
{
    RBVisualizerPage *page;
    ClutterInitError err;
    GstElement *colorspace;
    GstElement *realsink;
    GstElement *capsfilter;
    GstCaps *caps;
    GstPad *pad;

    RB_CHAIN_GOBJECT_METHOD (rb_visualizer_page_parent_class, constructed, object);
    page = RB_VISUALIZER_PAGE (object);

    err = gtk_clutter_init (NULL, NULL);
    if (err != CLUTTER_INIT_SUCCESS) {
        /* maybe do something more sensible here.  not sure if there are any user-recoverable
         * conditions that would cause clutter init to fail, though, so it may not be worth it.
         * as it is, we just won't add the page to the page tree.
         */
        g_warning ("Unable to display visual effects due to Clutter init failure");
        return;
    }

    page->texture = clutter_texture_new ();
    clutter_texture_set_sync_size (CLUTTER_TEXTURE (page->texture), TRUE);
    clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (page->texture), TRUE);

    page->sink = gst_bin_new (NULL);
    g_object_ref (page->sink);

    /* actual sink */
    realsink = gst_element_factory_make ("cluttersink", NULL);
    g_object_set (realsink, "texture", page->texture, NULL);

    colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
    /* capsfilter to force rgb format (without this we end up using ayuv) */
    capsfilter = gst_element_factory_make ("capsfilter", NULL);
    caps = gst_caps_from_string ("video/x-raw-rgb,bpp=(int)24,depth=(int)24,"
                                 "endianness=(int)4321,red_mask=(int)16711680,"
                                 "green_mask=(int)65280,blue_mask=(int)255");
    g_object_set (capsfilter, "caps", caps, NULL);
    gst_caps_unref (caps);

    gst_bin_add_many (GST_BIN (page->sink), colorspace, capsfilter, realsink, NULL);
    gst_element_link (colorspace, capsfilter);
    gst_element_link (capsfilter, realsink);

    pad = gst_element_get_static_pad (colorspace, "sink");
    gst_element_add_pad (page->sink, gst_ghost_pad_new ("sink", pad));
    gst_object_unref (pad);

    g_signal_connect_object (page->fullscreen_action,
                             "toggled",
                             G_CALLBACK (toggle_fullscreen_cb),
                             page, 0);
}
Exemplo n.º 2
0
static void
rb_audioscrobbler_account_constructed (GObject *object)
{
    RBAudioscrobblerAccount *account;

    RB_CHAIN_GOBJECT_METHOD (rb_audioscrobbler_account_parent_class, constructed, object);
    account = RB_AUDIOSCROBBLER_ACCOUNT (object);

    load_session_settings (account);
}
Exemplo n.º 3
0
static void
rb_media_player_source_constructed (GObject *object)
{
	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (object);
	RBShell *shell;

	RB_CHAIN_GOBJECT_METHOD (rb_media_player_source_parent_class, constructed, object);

	g_object_get (object, "shell", &shell, NULL);
	rb_media_player_source_init_actions (shell);
	g_object_unref (shell);

	priv->sync_action = gtk_action_group_get_action (action_group, "MediaPlayerSourceSync");
}
Exemplo n.º 4
0
static void
impl_constructed (GObject *object)
{
	RBAndroidSource *source;
	RBAndroidSourcePrivate *priv;
	RhythmDBEntryType *entry_type;
	RBShell *shell;
	char **output_formats;

	RB_CHAIN_GOBJECT_METHOD (rb_android_source_parent_class, constructed, object);
	source = RB_ANDROID_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_get (priv->device_info, "output-formats", &output_formats, NULL);
	if (output_formats != NULL) {
		GstEncodingTarget *target;
		int i;

		target = gst_encoding_target_new ("android-device", "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);

	g_object_unref (shell);
}
Exemplo n.º 5
0
static void
impl_constructed (GObject *object)
{
	RBButtonBar *bar;

	RB_CHAIN_GOBJECT_METHOD (rb_button_bar_parent_class, constructed, object);

	bar = RB_BUTTON_BAR (object);

	bar->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);

	bar->priv->handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);

	build_button_bar (bar);
}
Exemplo n.º 6
0
static void
impl_constructed (GObject *object)
{
	RBDisplayPageMenu *menu;

	RB_CHAIN_GOBJECT_METHOD (rb_display_page_menu_parent_class, constructed, object);

	menu = RB_DISPLAY_PAGE_MENU (object);

	g_signal_connect (menu->priv->real_model, "row-inserted", G_CALLBACK (row_inserted_cb), menu);
	g_signal_connect (menu->priv->real_model, "row-deleted", G_CALLBACK (row_deleted_cb), menu);
	g_signal_connect (menu->priv->real_model, "row-changed", G_CALLBACK (row_changed_cb), menu);
	g_signal_connect (menu->priv->real_model, "rows-reordered", G_CALLBACK (rows_reordered_cb), menu);

	rebuild_menu (menu);
}
Exemplo n.º 7
0
static void
impl_constructed (GObject *object)
{
	RBDisplayPageMenu *menu;
	GtkTreeModel *real_model;

	RB_CHAIN_GOBJECT_METHOD (rb_display_page_menu_parent_class, constructed, object);

	menu = RB_DISPLAY_PAGE_MENU (object);

	real_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (menu->priv->model));
	g_signal_connect (real_model, "row-inserted", G_CALLBACK (row_inserted_cb), menu);
	g_signal_connect (real_model, "row-deleted", G_CALLBACK (row_deleted_cb), menu);
	g_signal_connect (real_model, "row-changed", G_CALLBACK (row_changed_cb), menu);
	g_signal_connect (real_model, "rows-reordered", G_CALLBACK (rows_reordered_cb), menu);

	rebuild_menu (menu);
}
Exemplo n.º 8
0
static void
impl_constructed (GObject *object)
{
	RBPodcastMainSource *source;
	RBPodcastManager *podcast_mgr;
	GdkPixbuf *pixbuf;
	gint size;
	
	RB_CHAIN_GOBJECT_METHOD (rb_podcast_main_source_parent_class, constructed, object);
	source = RB_PODCAST_MAIN_SOURCE (object);

	g_object_get (source, "podcast-manager", &podcast_mgr, NULL);

	g_signal_connect_object (podcast_mgr,
	 		        "start_download",
			  	G_CALLBACK (start_download_cb),
			  	source, 0);

	g_signal_connect_object (podcast_mgr,
			  	"finish_download",
			  	G_CALLBACK (finish_download_cb),
			  	source, 0);

	g_signal_connect_object (podcast_mgr,
			  	"feed_updates_available",
 			  	G_CALLBACK (feed_updates_available_cb),
			  	source, 0);

	g_signal_connect_object (podcast_mgr,
			  	 "process_error",
			 	 G_CALLBACK (feed_error_cb),
			  	 source, 0);

	gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);
	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
					   RB_STOCK_PODCAST,
					   size,
					   0, NULL);

	if (pixbuf != NULL) {
		rb_source_set_pixbuf (RB_SOURCE (source), pixbuf);
		g_object_unref (pixbuf);
	}
}
static void
rb_removable_media_manager_constructed (GObject *object)
{
	RBRemovableMediaManager *mgr = RB_REMOVABLE_MEDIA_MANAGER (object);
	RBRemovableMediaManagerPrivate *priv = GET_PRIVATE (mgr);

	GApplication *app;
	GActionEntry actions[] = {
		{ "check-devices", check_devices_action_cb },
		{ "removable-media-eject", eject_action_cb }
	};

	RB_CHAIN_GOBJECT_METHOD (rb_removable_media_manager_parent_class, constructed, object);

	app = g_application_get_default ();
	g_action_map_add_action_entries (G_ACTION_MAP (app), actions, G_N_ELEMENTS (actions), mgr);

	priv->page_changed_id = g_signal_connect (priv->shell, "notify::selected-page", G_CALLBACK (page_changed_cb), mgr);
}
Exemplo n.º 10
0
static void
rb_mtp_source_constructed (GObject *object)
{
	RBMtpSource *source;
	RBEntryView *tracks;
	RBShell *shell;
	RBShellPlayer *shell_player;
	GObject *player_backend;

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

	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);
	g_object_get (shell, "shell-player", &shell_player, NULL);
	g_object_get (shell_player, "player", &player_backend, NULL);
	g_object_unref (shell_player);

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

	rb_display_page_set_icon_name (RB_DISPLAY_PAGE (source), "multimedia-player-symbolic");
}
Exemplo n.º 11
0
static void
rb_library_browser_constructed (GObject *object)
{
	RBLibraryBrowser *browser;
	RBLibraryBrowserPrivate *priv;
	int i;

	RB_CHAIN_GOBJECT_METHOD (rb_library_browser_parent_class, constructed, object);

	browser = RB_LIBRARY_BROWSER (object);
	priv = RB_LIBRARY_BROWSER_GET_PRIVATE (browser);

	for (i = 0; i < num_browser_properties; i++) {
		RBPropertyView *view;

		view = rb_property_view_new (priv->db,
					     browser_properties[i].type,
					     _(browser_properties[i].name));
		g_hash_table_insert (priv->property_views, (gpointer)(browser_properties[i].type), view);

		rb_property_view_set_selection_mode (view, GTK_SELECTION_MULTIPLE);
		g_signal_connect_object (G_OBJECT (view),
					 "properties-selected",
					 G_CALLBACK (view_property_selected_cb),
					 browser, 0);
		g_signal_connect_object (G_OBJECT (view),
					 "property-selection-reset",
					 G_CALLBACK (view_selection_reset_cb),
					 browser, 0);
		gtk_widget_show_all (GTK_WIDGET (view));
		gtk_widget_set_no_show_all (GTK_WIDGET (view), TRUE);
		gtk_box_pack_start (GTK_BOX (browser), GTK_WIDGET (view), TRUE, TRUE, 0);
	}

	update_browser_views_visibility (browser);
	priv->browser_view_notify_id =
		eel_gconf_notification_add (CONF_UI_BROWSER_VIEWS,
				(GConfClientNotifyFunc) rb_library_browser_views_changed, browser);
}
Exemplo n.º 12
0
static void
rb_media_player_source_constructed (GObject *object)
{
	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (object);
	RBShell *shell;
	GApplication *app;
	GActionEntry actions[] = {
		{ "media-player-sync", sync_action_cb },
		{ "media-player-properties", properties_action_cb }
	};

	RB_CHAIN_GOBJECT_METHOD (rb_media_player_source_parent_class, constructed, object);

	app = g_application_get_default ();
	g_object_get (object, "shell", &shell, NULL);
	_rb_add_display_page_actions (G_ACTION_MAP (app), G_OBJECT (shell), actions, G_N_ELEMENTS (actions));
	g_object_unref (shell);

	priv->sync_action = g_action_map_lookup_action (G_ACTION_MAP (app), "media-player-sync");
	priv->properties_action = g_action_map_lookup_action (G_ACTION_MAP (app), "media-player-properties");
	g_signal_connect (object, "notify::load-status", G_CALLBACK (load_status_changed_cb), NULL);
	update_actions (RB_MEDIA_PLAYER_SOURCE (object));
}
Exemplo n.º 13
0
static void
rb_playlist_source_constructed (GObject *object)
{
	GObject *shell_player;
	RBPlaylistSource *source;
	RBShell *shell;
	RhythmDB *db;
	RhythmDBQueryModel *query_model;
	GtkBuilder *builder;
	GSettings *settings;

	RB_CHAIN_GOBJECT_METHOD (rb_playlist_source_parent_class, constructed, object);
	source = RB_PLAYLIST_SOURCE (object);

	g_object_get (source, "shell", &shell, NULL);
	g_object_get (shell,
		      "db", &db,
		      "shell-player", &shell_player,
		      NULL);
	rb_playlist_source_set_db (source, db);
	g_object_unref (db);

	g_object_unref (shell);

	/* store playlist settings using the memory backend
	 * this means the settings path doesn't have to be consistent,
	 * it just has to be unique, so the address of the source object works.
	 * for local playlists, we write the settings into the playlist file on disk
	 * to make them persistent.
	 */
	g_object_get (source, "settings", &settings, NULL);
	if (settings == NULL) {
		char *path;
		path = g_strdup_printf ("/org/gnome/rhythmbox/playlist/%p/", source);
		settings = g_settings_new_with_backend_and_path ("org.gnome.rhythmbox.source",
								 playlist_settings_backend,
								 path);
		g_free (path);

		g_object_set (source, "settings", settings, NULL);
	}

	g_signal_connect (settings, "changed", G_CALLBACK (playlist_settings_changed_cb), source);
	g_object_unref (settings);

	builder = rb_builder_load ("playlist-popup.ui", NULL);
	source->priv->popup = G_MENU (gtk_builder_get_object (builder, "playlist-popup"));
	rb_application_link_shared_menus (RB_APPLICATION (g_application_get_default ()), source->priv->popup);
	g_object_ref (source->priv->popup);
	g_object_unref (builder);

	source->priv->entries = g_hash_table_new_full (rb_refstring_hash, rb_refstring_equal,
						       (GDestroyNotify)rb_refstring_unref, NULL);

	source->priv->songs = rb_entry_view_new (source->priv->db,
						 shell_player,
						 TRUE, TRUE);
	g_object_unref (shell_player);

	g_signal_connect_object (source->priv->songs,
				 "notify::sort-order",
				 G_CALLBACK (rb_playlist_source_songs_sort_order_changed_cb),
				 source, 0);

	query_model = rhythmdb_query_model_new_empty (source->priv->db);
	rb_playlist_source_set_query_model (source, query_model);
	g_object_unref (query_model);

	{
		const char *title = "";
		const char *strings[3] = {0};

		GtkTreeViewColumn *column = gtk_tree_view_column_new ();
		GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();

		g_object_set(renderer,
			     "style", PANGO_STYLE_OBLIQUE,
			     "weight", PANGO_WEIGHT_LIGHT,
			     "xalign", 1.0,
			     NULL);

		gtk_tree_view_column_pack_start (column, renderer, TRUE);

		gtk_tree_view_column_set_resizable (column, TRUE);
		gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);

		strings[0] = title;
		strings[1] = "9999";
		rb_entry_view_set_fixed_column_width (source->priv->songs, column, renderer,
						      strings);
		gtk_tree_view_column_set_cell_data_func (column, renderer,
							 (GtkTreeCellDataFunc)
							 rb_playlist_source_track_cell_data_func,
							 source, NULL);
		rb_entry_view_insert_column_custom (source->priv->songs, column, title,
						    "PlaylistTrack", NULL, 0, NULL, 0);
	}

	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TITLE, TRUE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_GENRE, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_COMPOSER, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_YEAR, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_DURATION, FALSE);
 	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_QUALITY, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_RATING, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_COMMENT, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LOCATION, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_FIRST_SEEN, FALSE);
	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_BPM, FALSE);
	rb_entry_view_set_columns_clickable (source->priv->songs, FALSE);

	rb_playlist_source_setup_entry_view (source, source->priv->songs);

	gtk_container_add (GTK_CONTAINER (source), GTK_WIDGET (source->priv->songs));

	gtk_widget_show_all (GTK_WIDGET (source));
}
static void
impl_constructed (GObject *object)
{
    RBObjectPropertyEditor *editor;
    GObjectClass *klass;
    int i;
    int row;

    RB_CHAIN_GOBJECT_METHOD (rb_object_property_editor_parent_class, constructed, object);

    editor = RB_OBJECT_PROPERTY_EDITOR (object);
    klass = G_OBJECT_GET_CLASS (editor->priv->object);

    editor->priv->notify_id = g_signal_connect (editor->priv->object, "notify", G_CALLBACK (notify_cb), editor);

    row = 0;
    for (i = 0; editor->priv->properties[i] != NULL; i++) {
        GParamSpec *pspec;
        GtkWidget *label;
        GtkWidget *control;
        GType prop_type;

        pspec = g_object_class_find_property (klass, editor->priv->properties[i]);
        if (pspec == NULL) {
            g_warning ("couldn't find property %s on object %s",
                       editor->priv->properties[i],
                       G_OBJECT_CLASS_NAME (klass));
            continue;
        }

        prop_type = G_PARAM_SPEC_TYPE (pspec);
        if (prop_type == G_TYPE_PARAM_BOOLEAN) {
            control = create_boolean_editor (editor, editor->priv->properties[i], pspec);
        } else if (prop_type == G_TYPE_PARAM_ENUM) {
            control = create_enum_editor (editor, editor->priv->properties[i], pspec);
        } else if (prop_type == G_TYPE_PARAM_INT) {
            control = create_int_editor (editor, editor->priv->properties[i], pspec);
        } else if (prop_type == G_TYPE_PARAM_FLOAT) {
            control = create_float_editor (editor, editor->priv->properties[i], pspec);
        } else if (prop_type == G_TYPE_PARAM_DOUBLE) {
            control = create_double_editor (editor, editor->priv->properties[i], pspec);
        } else {
            /* can't do this */
            g_warning ("don't know how to edit %s", g_type_name (prop_type));
            continue;
        }
        g_signal_connect (control, "focus-out-event", G_CALLBACK (focus_out_cb), editor);
        gtk_widget_set_hexpand (control, TRUE);

        label = gtk_label_new (g_param_spec_get_nick (pspec));
        gtk_widget_set_tooltip_text (label, g_param_spec_get_blurb (pspec));

        gtk_grid_attach (GTK_GRID (editor),
                         label,
                         0, row, 1, 1);
        gtk_grid_attach (GTK_GRID (editor),
                         control,
                         1, row, 1, 1);

        row++;
    }
}
static void
rb_iradio_source_constructed (GObject *object)
{
	RBIRadioSource *source;
	RBShell *shell;
	GtkAction *action;
	GSettings *settings;
	GtkUIManager *ui_manager;
	GtkWidget *grid;
	GtkWidget *paned;
	RBSourceToolbar *toolbar;
	gint size;
	GdkPixbuf *pixbuf;

	RB_CHAIN_GOBJECT_METHOD (rb_iradio_source_parent_class, constructed, object);
	source = RB_IRADIO_SOURCE (object);

	paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);

	g_object_get (source, "shell", &shell, NULL);
	g_object_get (shell,
		      "db", &source->priv->db,
		      "shell-player", &source->priv->player,
		      "ui-manager", &ui_manager,
		      NULL);
	g_object_unref (shell);

	gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);
	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
					   IRADIO_SOURCE_ICON,
					   size,
					   0, NULL);
	g_object_set (source, "pixbuf", pixbuf, NULL);
	if (pixbuf != NULL) {
		g_object_unref (pixbuf);
	}

	settings = g_settings_new ("org.gnome.rhythmbox.plugins.iradio");
	if (g_settings_get_boolean (settings, "initial-stations-loaded") == FALSE) {
		GObject *plugin;
		char *file;

		g_object_get (source, "plugin", &plugin, NULL);
		file = rb_find_plugin_data_file (plugin, "iradio-initial.xspf");
		if (file != NULL) {
			char *uri = g_filename_to_uri (file, NULL, NULL);
			if (uri != NULL) {
				rb_iradio_source_add_from_playlist (source, uri);
				g_free (uri);

				g_settings_set_boolean (settings, "initial-stations-loaded", TRUE);
			}
		}
		g_free (file);
		g_object_unref (plugin);
	}

	source->priv->action_group = _rb_display_page_register_action_group (RB_DISPLAY_PAGE (source),
									     "IRadioActions",
									     rb_iradio_source_actions,
									     G_N_ELEMENTS (rb_iradio_source_actions),
									     source);

	action = gtk_action_group_get_action (source->priv->action_group,
                                              "MusicNewInternetRadioStation");
        /* Translators: this is the toolbar button label for 
           New Internet Radio Station action. */
        g_object_set (action, "short-label", C_("Radio", "Add"), NULL);


	/* set up stations view */
	source->priv->stations = rb_entry_view_new (source->priv->db, G_OBJECT (source->priv->player),
						    FALSE, FALSE);

	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_TITLE, TRUE);
	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_GENRE, FALSE);
/* 	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_QUALITY, FALSE); */
	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_RATING, FALSE);
/*	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);*/
	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
	g_signal_connect_object (source->priv->stations,
				 "notify::sort-order",
				 G_CALLBACK (rb_iradio_source_songs_view_sort_order_changed_cb),
				 source, 0);

	/* set up drag and drop for the song tree view.
	 * we don't use RBEntryView's DnD support because it does too much.
	 * we just want to be able to drop stations in to add them.
	 */
	g_signal_connect_object (source->priv->stations,
				 "drag_data_received",
				 G_CALLBACK (stations_view_drag_data_received_cb),
				 source, 0);
	gtk_drag_dest_set (GTK_WIDGET (source->priv->stations),
			   GTK_DEST_DEFAULT_ALL,
			   stations_view_drag_types, 2,
			   GDK_ACTION_COPY | GDK_ACTION_MOVE);

	g_signal_connect_object (source->priv->stations, "show_popup",
				 G_CALLBACK (rb_iradio_source_songs_show_popup_cb), source, 0);

	/* set up genre entry view */
	source->priv->genres = rb_property_view_new (source->priv->db,
						     RHYTHMDB_PROP_GENRE,
						     _("Genre"));
	gtk_widget_show_all (GTK_WIDGET (source->priv->genres));
	gtk_widget_set_no_show_all (GTK_WIDGET (source->priv->genres), TRUE);
	g_signal_connect_object (source->priv->genres,
				 "property-selected",
				 G_CALLBACK (genre_selected_cb),
				 source, 0);
	g_signal_connect_object (source->priv->genres,
				 "property-selection-reset",
				 G_CALLBACK (genre_selection_reset_cb),
				 source, 0);

	g_object_set (source->priv->genres, "vscrollbar_policy",
		      GTK_POLICY_AUTOMATIC, NULL);

	gtk_paned_pack1 (GTK_PANED (paned), GTK_WIDGET (source->priv->genres), FALSE, FALSE);
	gtk_paned_pack2 (GTK_PANED (paned), GTK_WIDGET (source->priv->stations), TRUE, FALSE);

	/* set up toolbar */
	toolbar = rb_source_toolbar_new (RB_SOURCE (source), ui_manager);
	rb_source_toolbar_add_search_entry (toolbar, NULL, _("Search your internet radio stations"));

	grid = gtk_grid_new ();
	gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
	gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
	gtk_widget_set_margin_top (GTK_WIDGET (grid), 6);
	gtk_grid_attach (GTK_GRID (grid), GTK_WIDGET (toolbar), 0, 0, 1, 1);
	gtk_grid_attach (GTK_GRID (grid), paned, 0, 1, 1, 1);

	gtk_container_add (GTK_CONTAINER (source), grid);

	rb_source_bind_settings (RB_SOURCE (source),
				 GTK_WIDGET (source->priv->stations),
				 paned,
				 GTK_WIDGET (source->priv->genres));

	gtk_widget_show_all (GTK_WIDGET (source));

	g_signal_connect_object (source->priv->player, "playing-source-changed",
				 G_CALLBACK (playing_source_changed_cb),
				 source, 0);

	source->priv->default_search = rb_iradio_source_search_new ();

	rb_iradio_source_do_query (source);
}
Exemplo n.º 16
0
static void
impl_constructed (GObject *object)
{
	RBImportDialog *dialog;
	RhythmDBQuery *query;
	GtkBuilder *builder;
	GSettings *settings;
	char **locations;

	RB_CHAIN_GOBJECT_METHOD (rb_import_dialog_parent_class, constructed, object);
	dialog = RB_IMPORT_DIALOG (object);

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

	/* create entry types */
	dialog->priv->entry_type = g_object_new (rb_import_dialog_entry_type_get_type (),
						 "db", dialog->priv->db,
						 "name", "import-dialog",
						 NULL);
	dialog->priv->ignore_type = g_object_new (rb_import_dialog_ignore_type_get_type (),
						  "db", dialog->priv->db,
						  "name", "import-dialog-ignore",
						  NULL);
	rhythmdb_register_entry_type (dialog->priv->db, dialog->priv->entry_type);
	rhythmdb_register_entry_type (dialog->priv->db, dialog->priv->ignore_type);


	builder = rb_builder_load ("import-dialog.ui", NULL);

	dialog->priv->import_button = GTK_WIDGET (gtk_builder_get_object (builder, "import-button"));
	g_signal_connect_object (dialog->priv->import_button, "clicked", G_CALLBACK (import_clicked_cb), dialog, 0);
	gtk_widget_set_sensitive (dialog->priv->import_button, FALSE);

	dialog->priv->copy_check = GTK_WIDGET (gtk_builder_get_object (builder, "copy-check"));

	g_signal_connect (gtk_builder_get_object (builder, "close-button"),
			  "clicked",
			  G_CALLBACK (close_clicked_cb),
			  dialog);

	dialog->priv->file_chooser = GTK_WIDGET (gtk_builder_get_object (builder, "file-chooser-button"));
	
	/* select the first library location, since the default may be
	 * the user's home dir or / or something that will take forever to scan.
	 */
	settings = g_settings_new ("org.gnome.rhythmbox.rhythmdb");
	locations = g_settings_get_strv (settings, "locations");
	if (locations[0] != NULL) {
		dialog->priv->current_uri = g_strdup (locations[0]);
	} else {
		dialog->priv->current_uri = g_filename_to_uri (rb_music_dir (), NULL, NULL);
	}
	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog->priv->file_chooser),
						 dialog->priv->current_uri);
	g_strfreev (locations);
	g_object_unref (settings);

	g_signal_connect_object (dialog->priv->file_chooser, "selection-changed", G_CALLBACK (current_folder_changed_cb), dialog, 0);

	/* not sure why we have to set this, it should be the default */
	gtk_widget_set_vexpand (gtk_widget_get_parent (dialog->priv->file_chooser), FALSE);

	dialog->priv->info_bar_container = GTK_WIDGET (gtk_builder_get_object (builder, "info-bar-container"));

	/* set up entry view */
	dialog->priv->entry_view = rb_entry_view_new (dialog->priv->db, G_OBJECT (dialog->priv->shell_player), TRUE, FALSE);

	g_signal_connect (dialog->priv->entry_view, "entry-activated", G_CALLBACK (entry_activated_cb), dialog);
	g_signal_connect (dialog->priv->entry_view, "selection-changed", G_CALLBACK (selection_changed_cb), dialog);

	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_GENRE, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_YEAR, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_DURATION, FALSE);
 	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_QUALITY, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_BPM, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_COMMENT, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_LOCATION, FALSE);

	settings = g_settings_new ("org.gnome.rhythmbox.sources");
	g_settings_bind (settings, "visible-columns", dialog->priv->entry_view, "visible-columns", G_SETTINGS_BIND_DEFAULT);
	g_object_unref (settings);

	g_signal_connect (dialog->priv->entry_view,
			  "notify::sort-order",
			  G_CALLBACK (sort_changed_cb),
			  dialog);
	rb_entry_view_set_sorting_order (dialog->priv->entry_view, "Album", GTK_SORT_ASCENDING);

	gtk_container_add (GTK_CONTAINER (gtk_builder_get_object (builder, "entry-view-container")),
			   GTK_WIDGET (dialog->priv->entry_view));

	dialog->priv->query_model = rhythmdb_query_model_new_empty (dialog->priv->db);
	rb_entry_view_set_model (dialog->priv->entry_view, dialog->priv->query_model);
	query = rhythmdb_query_parse (dialog->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, dialog->priv->entry_type,
				      RHYTHMDB_QUERY_END);
	rhythmdb_do_full_query_async_parsed (dialog->priv->db, RHYTHMDB_QUERY_RESULTS (dialog->priv->query_model), query);
	rhythmdb_query_free (query);

	g_signal_connect (dialog->priv->query_model, "post-entry-delete", G_CALLBACK (entry_deleted_cb), dialog);
	g_signal_connect (dialog->priv->query_model, "row-inserted", G_CALLBACK (entry_inserted_cb), dialog);

	gtk_container_add (GTK_CONTAINER (dialog), GTK_WIDGET (gtk_builder_get_object (builder, "import-dialog")));

	gtk_widget_show_all (GTK_WIDGET (dialog));
	g_object_unref (builder);
}
Exemplo n.º 17
0
static void
rb_audiocd_source_constructed (GObject *object)
{
	RBAudioCdSourcePrivate *priv;
	RBAudioCdSource *source;
	RBEntryView *entry_view;
	GtkCellRenderer *renderer;
	GtkTreeViewColumn *extract;
	GtkWidget *widget;
	GtkAction *action;
	RhythmDB *db;
	RBPlugin *plugin;
	RBShell *shell;
	char *ui_file;
	int toggle_width;

	RB_CHAIN_GOBJECT_METHOD (rb_audiocd_source_parent_class, constructed, object);
	source = RB_AUDIOCD_SOURCE (object);
	priv = AUDIOCD_SOURCE_GET_PRIVATE (source);

	g_object_set (G_OBJECT (source), "name", "Unknown Audio", NULL);

	g_object_get (source, "shell", &shell, NULL);
	priv->action_group = _rb_source_register_action_group (RB_SOURCE (source),
							       "AudioCdActions",
							       NULL, 0, NULL);
	_rb_action_group_add_source_actions (priv->action_group,
					     G_OBJECT (shell),
					     rb_audiocd_source_actions,
					     G_N_ELEMENTS (rb_audiocd_source_actions));
	g_object_unref (shell);

	action = gtk_action_group_get_action (priv->action_group,
					      "AudioCdCopyTracks");
	/* Translators: this is the toolbar button label
	   for Copy to Library action. */
	g_object_set (action, "short-label", _("Extract"), NULL);

#if !defined(HAVE_SJ_METADATA_GETTER)
	action = gtk_action_group_get_action (priv->action_group, "AudioCdSourceReloadMetadata");
	g_object_set (action, "visible", FALSE, NULL);
#endif


	/* we want audio cds to sort by track# by default */
	entry_view = rb_source_get_entry_view (RB_SOURCE (source));
	rb_entry_view_set_sorting_order (entry_view, "Track", GTK_SORT_ASCENDING);

	/* enable in-place editing for titles, artists, and genres */
	rb_entry_view_set_column_editable (entry_view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
	rb_entry_view_set_column_editable (entry_view, RB_ENTRY_VIEW_COL_ARTIST, TRUE);
	rb_entry_view_set_column_editable (entry_view, RB_ENTRY_VIEW_COL_GENRE, TRUE);

	/* create the 'extract' column */
	renderer = gtk_cell_renderer_toggle_new ();
	extract = gtk_tree_view_column_new ();
	gtk_tree_view_column_pack_start (extract, renderer, FALSE);
	gtk_tree_view_column_set_cell_data_func (extract,
						 renderer,
						 (GtkTreeCellDataFunc) extract_cell_data_func,
						 source,
						 NULL);
	gtk_tree_view_column_set_clickable (extract, TRUE);
	widget = gtk_check_button_new ();
	g_object_set (widget, "active", TRUE, NULL);
	gtk_widget_show_all (widget);
	g_signal_connect_object (extract, "clicked", G_CALLBACK (extract_column_clicked_cb), source, 0);
	gtk_tree_view_column_set_widget (extract, widget);

	g_signal_connect_object (renderer, "toggled", G_CALLBACK (extract_toggled_cb), source, 0);

	/* set column width */
	gtk_cell_renderer_get_size (renderer, GTK_WIDGET (entry_view), NULL, NULL, NULL, &toggle_width, NULL);
	gtk_tree_view_column_set_sizing (extract, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_fixed_width (extract, toggle_width + 5);

	rb_entry_view_insert_column_custom (entry_view, extract, "", "Extract", NULL, NULL, NULL, 1);
	gtk_widget_set_tooltip_text (gtk_tree_view_column_get_widget (extract),
	                             _("Select tracks to be extracted"));

	/* hide the 'album' column */
	gtk_tree_view_column_set_visible (rb_entry_view_get_column (entry_view, RB_ENTRY_VIEW_COL_ALBUM), FALSE);

	/* handle extra metadata requests for album artist and album artist sortname */
	db = get_db_for_source (source);
	g_signal_connect_object (G_OBJECT (db), "entry-extra-metadata-request::" RHYTHMDB_PROP_ALBUM_ARTIST,
				 G_CALLBACK (album_artist_metadata_request_cb), source, 0);
	g_signal_connect_object (G_OBJECT (db), "entry-extra-metadata-request::" RHYTHMDB_PROP_ALBUM_ARTIST_SORTNAME,
				 G_CALLBACK (album_artist_sortname_metadata_request_cb), source, 0);
	g_signal_connect_object (G_OBJECT (db), "entry-extra-metadata-gather",
				 G_CALLBACK (metadata_gather_cb), source, 0);
	g_object_unref (db);

	/* set up the album info widgets */
	g_object_get (source, "plugin", &plugin, NULL);
	ui_file = rb_plugin_find_file (plugin, "album-info.ui");
	g_object_unref (plugin);

	if (ui_file == NULL) {
		g_warning ("couldn't find album-info.ui");
	} else {
		RBAudioCdSourcePrivate *priv;
		GtkWidget *table;
		GtkBuilder *builder;
#if defined(HAVE_SJ_METADATA_GETTER) && GTK_CHECK_VERSION(2,17,6)
		GtkWidget *box;
		char *message;
#endif

		priv = AUDIOCD_SOURCE_GET_PRIVATE (source);

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

		table = GTK_WIDGET (gtk_builder_get_object (builder, "album_info"));
		g_assert (table != NULL);

#if defined(HAVE_SJ_METADATA_GETTER) && GTK_CHECK_VERSION(2,17,6)
		/* Info bar for non-Musicbrainz data */
		priv->info_bar = gtk_info_bar_new_with_buttons (_("S_ubmit Album"), GTK_RESPONSE_OK,
								_("Hide"), GTK_RESPONSE_CANCEL,
								NULL);
		message = g_strdup_printf ("<b>%s</b>\n%s", _("Could not find this album on MusicBrainz."),
					   _("You can improve the MusicBrainz database by adding this album."));
		priv->info_bar_label = gtk_label_new (NULL);
		gtk_label_set_markup (GTK_LABEL (priv->info_bar_label), message);
		gtk_label_set_justify (GTK_LABEL (priv->info_bar_label), GTK_JUSTIFY_LEFT);
		g_free (message);
		box = gtk_info_bar_get_content_area (GTK_INFO_BAR (priv->info_bar));
		gtk_container_add (GTK_CONTAINER (box), priv->info_bar_label);
		gtk_widget_show_all (box);
		gtk_widget_set_no_show_all (priv->info_bar, TRUE);
		g_signal_connect (G_OBJECT (priv->info_bar), "response",
				  G_CALLBACK (info_bar_response_cb), source);
		gtk_table_attach_defaults (GTK_TABLE (table), priv->info_bar, 0, 2, 0, 1);
#endif

		priv->artist_entry = GTK_WIDGET (gtk_builder_get_object (builder, "artist_entry"));
		priv->artist_sort_entry = GTK_WIDGET (gtk_builder_get_object (builder, "artist_sort_entry"));
		priv->album_entry = GTK_WIDGET (gtk_builder_get_object (builder, "album_entry"));
		priv->year_entry = GTK_WIDGET (gtk_builder_get_object (builder, "year_entry"));
		priv->genre_entry = GTK_WIDGET (gtk_builder_get_object (builder, "genre_entry"));
		priv->disc_number_entry = GTK_WIDGET (gtk_builder_get_object (builder, "disc_number_entry"));

		g_signal_connect_object (priv->album_entry, "focus-out-event", G_CALLBACK (update_album_cb), source, 0);
		g_signal_connect_object (priv->genre_entry, "focus-out-event", G_CALLBACK (update_genre_cb), source, 0);
		g_signal_connect_object (priv->year_entry, "focus-out-event", G_CALLBACK (update_year_cb), source, 0);
		g_signal_connect_object (priv->disc_number_entry, "focus-out-event", G_CALLBACK (update_disc_number_cb), source, 0);

		gtk_box_pack_start (GTK_BOX (priv->box), table, FALSE, FALSE, 0);
		gtk_box_reorder_child (GTK_BOX (priv->box), table, 0);
		g_object_unref (builder);
	}

	g_object_ref (G_OBJECT (source));
	g_thread_create ((GThreadFunc)rb_audiocd_load_songs, source, FALSE, NULL);
}
Exemplo n.º 18
0
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);

}
Exemplo n.º 19
0
static void
rb_missing_files_source_constructed (GObject *object)
{
	GObject *shell_player;
	RBMissingFilesSource *source;
	RBShell *shell;
	GPtrArray *query;
	RhythmDBQueryModel *model;
	RhythmDBEntryType *entry_type;

	RB_CHAIN_GOBJECT_METHOD (rb_missing_files_source_parent_class, constructed, object);
	source = RB_MISSING_FILES_SOURCE (object);

	g_object_get (source,
		      "shell", &shell,
		      "entry-type", &entry_type,
		      NULL);
	g_object_get (shell, "db", &source->priv->db, NULL);
	shell_player = rb_shell_get_player (shell);
	g_object_unref (shell);

	/* construct real query */
	query = rhythmdb_query_parse (source->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      	RHYTHMDB_PROP_TYPE,
					entry_type,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      	RHYTHMDB_PROP_HIDDEN,
					TRUE,
				      RHYTHMDB_QUERY_END);
	g_object_unref (entry_type);

	model = rhythmdb_query_model_new (source->priv->db, query,
					  NULL, NULL, NULL, FALSE);

	rhythmdb_query_free (query);

	g_object_set (model, "show-hidden", TRUE, NULL);

	/* set up entry view */
	source->priv->view = rb_entry_view_new (source->priv->db, shell_player,
						NULL, FALSE, FALSE);

	rb_entry_view_set_model (source->priv->view, model);

	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
/*	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_GENRE, FALSE); */
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LOCATION, TRUE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LAST_SEEN, TRUE);

	rb_entry_view_set_columns_clickable (source->priv->view, TRUE);

	gtk_container_add (GTK_CONTAINER (source), GTK_WIDGET (source->priv->view));
	g_signal_connect_object (source->priv->view, "show_popup",
				 G_CALLBACK (rb_missing_files_source_songs_show_popup_cb), source, 0);
	g_signal_connect_object (source->priv->view, "sort-order-changed",
				 G_CALLBACK (rb_missing_files_source_songs_sort_order_changed_cb), source, 0);

	gtk_widget_show_all (GTK_WIDGET (source));

	g_object_set (source, "query-model", model, NULL);
	g_object_unref (model);
}
Exemplo n.º 20
0
static void
rb_static_playlist_source_constructed (GObject *object)
{
	RBStaticPlaylistSource *source;
	RBStaticPlaylistSourcePrivate *priv;
	RBPlaylistSource *psource;
	RBEntryView *songs;
	RBShell *shell;
	RhythmDBEntryType *entry_type;

	RB_CHAIN_GOBJECT_METHOD (rb_static_playlist_source_parent_class, constructed, object);

	source = RB_STATIC_PLAYLIST_SOURCE (object);
	priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source);
	psource = RB_PLAYLIST_SOURCE (source);

	priv->base_model = rb_playlist_source_get_query_model (RB_PLAYLIST_SOURCE (psource));
	g_object_set (priv->base_model, "show-hidden", TRUE, NULL);
	g_object_ref (priv->base_model);
	g_signal_connect_object (priv->base_model,
				 "filter-entry-drop",
				 G_CALLBACK (rb_static_playlist_source_filter_entry_drop),
				 source, 0);

	priv->paned = gtk_vpaned_new ();

	g_object_get (source, "shell", &shell, NULL);
	priv->action_group = _rb_display_page_register_action_group (RB_DISPLAY_PAGE (source),
								     "StaticPlaylistActions",
								     NULL, 0,
								     shell);
	if (gtk_action_group_get_action (priv->action_group,
					 rb_static_playlist_source_radio_actions[0].name) == NULL) {
		gtk_action_group_add_radio_actions (priv->action_group,
						    rb_static_playlist_source_radio_actions,
						    G_N_ELEMENTS (rb_static_playlist_source_radio_actions),
						    0,
						    NULL,
						    NULL);
		rb_source_search_basic_create_for_actions (priv->action_group,
							   rb_static_playlist_source_radio_actions,
							   G_N_ELEMENTS (rb_static_playlist_source_radio_actions));
	}
	priv->default_search = rb_source_search_basic_new (RHYTHMDB_PROP_SEARCH_MATCH);

	g_object_unref (shell);

	g_object_get (source, "entry-type", &entry_type, NULL);
	priv->browser = rb_library_browser_new (rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source)),
						entry_type);
	if (entry_type != NULL) {
		g_object_unref (entry_type);
	}

	gtk_paned_pack1 (GTK_PANED (priv->paned), GTK_WIDGET (priv->browser), TRUE, FALSE);
	g_signal_connect_object (priv->browser, "notify::output-model",
				 G_CALLBACK (rb_static_playlist_source_browser_changed_cb),
				 source, 0);

	rb_library_browser_set_model (priv->browser, priv->base_model, FALSE);
	rb_static_playlist_source_do_query (source);

	/* reparent the entry view */
	songs = rb_source_get_entry_view (RB_SOURCE (source));
	g_object_ref (songs);
	gtk_container_remove (GTK_CONTAINER (source), GTK_WIDGET (songs));
	gtk_paned_pack2 (GTK_PANED (priv->paned), GTK_WIDGET (songs), TRUE, FALSE);
	gtk_container_add (GTK_CONTAINER (source), priv->paned);

	rb_source_bind_settings (RB_SOURCE (source), GTK_WIDGET (songs), priv->paned, GTK_WIDGET (priv->browser));
	g_object_unref (songs);

	/* watch these to find out when things are dropped into the entry view */
	g_signal_connect_object (priv->base_model, "row-inserted",
				 G_CALLBACK (rb_static_playlist_source_row_inserted),
				 source, 0);
	g_signal_connect_object (priv->base_model, "non-entry-dropped",
				 G_CALLBACK (rb_static_playlist_source_non_entry_dropped),
				 source, 0);
	g_signal_connect_object (priv->base_model, "rows-reordered",
				 G_CALLBACK (rb_static_playlist_source_rows_reordered),
				 source, 0);

	gtk_widget_show_all (GTK_WIDGET (source));
}
Exemplo n.º 21
0
static void
impl_constructed (GObject *object)
{
	RBPodcastAddDialog *dialog;
	GtkBuilder *builder;
	GtkWidget *widget;
	GtkWidget *paned;
	GtkTreeViewColumn *column;
	GtkCellRenderer *renderer;
	RBEntryView *episodes;
	RBShellPlayer *shell_player;
	RhythmDBQuery *query;
	RhythmDBQueryModel *query_model;
	const char *episode_strings[3];

	RB_CHAIN_GOBJECT_METHOD (rb_podcast_add_dialog_parent_class, constructed, object);
	dialog = RB_PODCAST_ADD_DIALOG (object);

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

	builder = rb_builder_load ("podcast-add-dialog.ui", NULL);

	dialog->priv->info_bar_message = gtk_label_new ("");
	dialog->priv->info_bar = gtk_info_bar_new ();
	g_object_set (dialog->priv->info_bar, "spacing", 0, NULL);
	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (dialog->priv->info_bar))),
			   dialog->priv->info_bar_message);
	gtk_widget_set_no_show_all (dialog->priv->info_bar, TRUE);
	gtk_box_pack_start (GTK_BOX (dialog), dialog->priv->info_bar, FALSE, FALSE, 0);
	gtk_widget_show (dialog->priv->info_bar_message);

	dialog->priv->subscribe_button = GTK_WIDGET (gtk_builder_get_object (builder, "subscribe-button"));
	g_signal_connect_object (dialog->priv->subscribe_button, "clicked", G_CALLBACK (subscribe_clicked_cb), dialog, 0);
	gtk_widget_set_sensitive (dialog->priv->subscribe_button, FALSE);

	dialog->priv->feed_view = GTK_WIDGET (gtk_builder_get_object (builder, "feed-view"));
	g_signal_connect (dialog->priv->feed_view, "row-activated", G_CALLBACK (feed_activated_cb), dialog);
	g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->feed_view)),
			  "changed",
			  G_CALLBACK (feed_selection_changed_cb),
			  dialog);


	dialog->priv->search_entry = rb_search_entry_new (FALSE);
	gtk_widget_set_size_request (GTK_WIDGET (dialog->priv->search_entry), 400, -1);
	g_object_set (dialog->priv->search_entry,"explicit-mode", TRUE, NULL);
	g_signal_connect (dialog->priv->search_entry, "search", G_CALLBACK (search_cb), dialog);
	g_signal_connect (dialog->priv->search_entry, "activate", G_CALLBACK (search_cb), dialog);
	gtk_container_add (GTK_CONTAINER (gtk_builder_get_object (builder, "search-entry-box")),
			   GTK_WIDGET (dialog->priv->search_entry));

	g_signal_connect (gtk_builder_get_object (builder, "close-button"),
			  "clicked",
			  G_CALLBACK (close_clicked_cb),
			  dialog);

	dialog->priv->feed_model = gtk_list_store_new (7,
						       G_TYPE_STRING,	/* name */
						       G_TYPE_STRING,	/* author */
						       GDK_TYPE_PIXBUF, /* image */
						       G_TYPE_FILE,	/* image file */
						       G_TYPE_INT,	/* episode count */
						       G_TYPE_POINTER,	/* RBPodcastChannel */
						       G_TYPE_ULONG);	/* date */
	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->priv->feed_view), GTK_TREE_MODEL (dialog->priv->feed_model));

	column = gtk_tree_view_column_new_with_attributes (_("Title"), gtk_cell_renderer_pixbuf_new (), "pixbuf", FEED_COLUMN_IMAGE, NULL);
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_attributes (column, renderer, "text", FEED_COLUMN_TITLE, NULL);

	gtk_tree_view_column_set_expand (column, TRUE);
	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->priv->feed_view), column);

	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
	column = gtk_tree_view_column_new_with_attributes (_("Author"), renderer, "text", FEED_COLUMN_AUTHOR, NULL);
	gtk_tree_view_column_set_expand (column, TRUE);
	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->priv->feed_view), column);

	renderer = gtk_cell_renderer_text_new ();
	column = gtk_tree_view_column_new_with_attributes (_("Episodes"), renderer, NULL);
	gtk_tree_view_column_set_cell_data_func (column, renderer, episode_count_column_cell_data_func, NULL, NULL);
	episode_strings[0] = "0000";
	episode_strings[1] = _("Episodes");
	episode_strings[2] = NULL;
	rb_set_tree_view_column_fixed_width (dialog->priv->feed_view, column, renderer, episode_strings, 6);
	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->priv->feed_view), column);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "podcast-add-dialog"));
	gtk_box_pack_start (GTK_BOX (dialog), widget, TRUE, TRUE, 0);

	/* set up episode view */
	g_object_get (dialog->priv->shell, "shell-player", &shell_player, NULL);
	episodes = rb_entry_view_new (dialog->priv->db, G_OBJECT (shell_player), TRUE, FALSE);
	g_object_unref (shell_player);

	g_signal_connect (episodes, "entry-activated", G_CALLBACK (episode_entry_activated_cb), dialog);

	/* date column */
	column = gtk_tree_view_column_new ();
	renderer = gtk_cell_renderer_text_new();

	gtk_tree_view_column_pack_start (column, renderer, TRUE);

	gtk_tree_view_column_set_clickable (column, TRUE);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	{
		const char *sample_strings[3];
		sample_strings[0] = _("Date");
		sample_strings[1] = rb_entry_view_get_time_date_column_sample ();
		sample_strings[2] = NULL;
		rb_entry_view_set_fixed_column_width (episodes, column, renderer, sample_strings);
	}

	gtk_tree_view_column_set_cell_data_func (column, renderer,
						 (GtkTreeCellDataFunc) podcast_post_date_cell_data_func,
						 dialog, NULL);

	rb_entry_view_append_column_custom (episodes, column,
					    _("Date"), "Date",
					    (GCompareDataFunc) podcast_post_date_sort_func,
					    0, NULL);
	rb_entry_view_append_column (episodes, RB_ENTRY_VIEW_COL_TITLE, TRUE);
	rb_entry_view_append_column (episodes, RB_ENTRY_VIEW_COL_DURATION, TRUE);
	rb_entry_view_set_sorting_order (RB_ENTRY_VIEW (episodes), "Date", GTK_SORT_DESCENDING);
	g_signal_connect (episodes,
			  "notify::sort-order",
			  G_CALLBACK (episodes_sort_changed_cb),
			  dialog);

	query = rhythmdb_query_parse (dialog->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      RHYTHMDB_PROP_TYPE,
				      RHYTHMDB_ENTRY_TYPE_PODCAST_SEARCH,
				      RHYTHMDB_QUERY_END);
	query_model = rhythmdb_query_model_new_empty (dialog->priv->db);
	rb_entry_view_set_model (episodes, query_model);

	rhythmdb_do_full_query_async_parsed (dialog->priv->db, RHYTHMDB_QUERY_RESULTS (query_model), query);
	rhythmdb_query_free (query);

	g_object_unref (query_model);

	paned = GTK_WIDGET (gtk_builder_get_object (builder, "paned"));
	g_signal_connect (paned, "size-allocate", G_CALLBACK (paned_size_allocate_cb), dialog);
	gtk_paned_pack2 (GTK_PANED (paned),
			 GTK_WIDGET (episodes),
			 TRUE,
			 FALSE);

	gtk_widget_show_all (GTK_WIDGET (dialog));
	g_object_unref (builder);
}
Exemplo n.º 22
0
static void
rb_import_errors_source_constructed (GObject *object)
{
	GObject *shell_player;
	RBImportErrorsSource *source;
	RBShell *shell;
	GPtrArray *query;
	RhythmDBQueryModel *model;
	RhythmDBEntryType *entry_type;
	GtkWidget *box;
	GtkWidget *label;

	RB_CHAIN_GOBJECT_METHOD (rb_import_errors_source_parent_class, constructed, object);

	source = RB_IMPORT_ERRORS_SOURCE (object);

	g_object_get (source,
		      "shell", &shell,
		      "entry-type", &entry_type,
		      NULL);
	g_object_get (shell, "db", &source->priv->db, NULL);
	shell_player = rb_shell_get_player (shell);
	g_object_unref (shell);

	/* construct real query */
	query = rhythmdb_query_parse (source->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      	RHYTHMDB_PROP_TYPE,
					entry_type,
				      RHYTHMDB_QUERY_END);

	model = rhythmdb_query_model_new (source->priv->db, query,
					  (GCompareDataFunc) rhythmdb_query_model_string_sort_func,
					  GUINT_TO_POINTER (RHYTHMDB_PROP_LOCATION), NULL, FALSE);
	rhythmdb_query_free (query);

	/* set up entry view */
	source->priv->view = rb_entry_view_new (source->priv->db, shell_player,
						NULL, FALSE, FALSE);

	rb_entry_view_set_model (source->priv->view, model);

	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LOCATION, TRUE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ERROR, TRUE);

	g_signal_connect_object (source->priv->view, "show_popup",
				 G_CALLBACK (rb_import_errors_source_songs_show_popup_cb), source, 0);

	g_object_set (source, "query-model", model, NULL);
	g_object_unref (model);

	/* set up query model for tracking missing plugin information */
	query = rhythmdb_query_parse (source->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				        RHYTHMDB_PROP_TYPE,
					entry_type,
				      RHYTHMDB_QUERY_PROP_NOT_EQUAL,
				        RHYTHMDB_PROP_COMMENT,
					"",
				      RHYTHMDB_QUERY_END);

	source->priv->missing_plugin_model = rhythmdb_query_model_new_empty (source->priv->db);
	rhythmdb_do_full_query_async_parsed (source->priv->db,
					     RHYTHMDB_QUERY_RESULTS (source->priv->missing_plugin_model),
					     query);
	rhythmdb_query_free (query);

	/* set up info bar for triggering codec installation */
	source->priv->infobar = gtk_info_bar_new_with_buttons (_("Install Plugins"), GTK_RESPONSE_OK, NULL);
	g_signal_connect_object (source->priv->infobar,
				 "response",
				 G_CALLBACK (infobar_response_cb),
				 source, 0);

	label = gtk_label_new (_("Additional GStreamer plugins are required to play some of these files."));
	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (source->priv->infobar))),
			   label);

	g_object_unref (entry_type);

	box = gtk_vbox_new (FALSE, 6);
	gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (source->priv->view), TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (box), source->priv->infobar, FALSE, FALSE, 0);

	gtk_container_add (GTK_CONTAINER (source), box);
	gtk_widget_show_all (GTK_WIDGET (source));
	gtk_widget_hide (source->priv->infobar);

	/* show the info bar when there are missing plugin entries */
	g_signal_connect_object (source->priv->missing_plugin_model,
				 "row-inserted",
				 G_CALLBACK (missing_plugin_row_inserted_cb),
				 source, 0);
	g_signal_connect_object (source->priv->missing_plugin_model,
				 "row-deleted",
				 G_CALLBACK (missing_plugin_row_deleted_cb),
				 source, 0);
}
Exemplo n.º 23
0
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 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;
	char *label;
	char *fullname;
	char *name;

	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,
		      "name", &name,
		      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);


	priv->new_playlist_action_name = g_strdup_printf ("generic-player-%p-playlist-new", source);
	fullname = g_strdup_printf ("app.%s", priv->new_playlist_action_name);

	label = g_strdup_printf (_("New Playlist on %s"), name);

	rb_application_add_plugin_menu_item (RB_APPLICATION (g_application_get_default ()),
					     "display-page-add-playlist",
					     priv->new_playlist_action_name,
					     g_menu_item_new (label, fullname));
	g_free (fullname);
	g_free (label);
	g_free (name);

	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 ((priv->read_only == FALSE) && playlist_formats != NULL && g_strv_length (playlist_formats) > 0) {
		RBDisplayPageModel *model;
		GMenu *playlist_menu;
		GMenuModel *playlists;

		priv->new_playlist_action = g_simple_action_new (priv->new_playlist_action_name, NULL);
		g_signal_connect (priv->new_playlist_action, "activate", G_CALLBACK (new_playlist_action_cb), source);
		g_action_map_add_action (G_ACTION_MAP (g_application_get_default ()), G_ACTION (priv->new_playlist_action));

		g_object_get (shell, "display-page-model", &model, NULL);
		playlists = rb_display_page_menu_new (model,
						      RB_DISPLAY_PAGE (source),
						      RB_TYPE_GENERIC_PLAYER_PLAYLIST_SOURCE,
						      "app.playlist-add-to");
		g_object_unref (model);

		playlist_menu = g_menu_new ();
		g_menu_append (playlist_menu, _("Add to New Playlist"), priv->new_playlist_action_name);
		g_menu_append_section (playlist_menu, NULL, playlists);

		g_object_set (source, "playlist-menu", playlist_menu, 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);

	g_object_unref (shell);
}
Exemplo n.º 25
0
static void
rb_query_creator_constructed (GObject *object)
{
	RBQueryCreatorPrivate *priv;
	RBQueryCreator *creator;
	GtkWidget *mainbox;
	GtkWidget *content_area;
	GtkBuilder *builder;

	RB_CHAIN_GOBJECT_METHOD (rb_query_creator_parent_class, constructed, object);

	creator = RB_QUERY_CREATOR (object);
	priv = QUERY_CREATOR_GET_PRIVATE (creator);

	if (priv->creating) {
		gtk_dialog_add_button (GTK_DIALOG (creator),
				       _("_Cancel"),
				       GTK_RESPONSE_CLOSE);
		gtk_dialog_add_button (GTK_DIALOG (creator),
				       _("_New"),
				       GTK_RESPONSE_OK);
	} else {
		gtk_dialog_add_button (GTK_DIALOG (creator),
				       _("_Close"),
				       GTK_RESPONSE_CLOSE);
	}
	gtk_dialog_set_default_response (GTK_DIALOG (creator),
					 GTK_RESPONSE_CLOSE);

	priv->property_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
	priv->criteria_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
	priv->entry_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
	priv->button_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);

	if (priv->creating)
		gtk_window_set_title (GTK_WINDOW (creator), _("Create Automatic Playlist"));
	else
		gtk_window_set_title (GTK_WINDOW (creator), _("Edit Automatic Playlist"));

	content_area = gtk_dialog_get_content_area (GTK_DIALOG (creator));

	gtk_container_set_border_width (GTK_CONTAINER (creator), 5);
	gtk_box_set_spacing (GTK_BOX (content_area), 2);

	builder = rb_builder_load ("create-playlist.ui", creator);

	priv->disjunction_check = GTK_WIDGET (gtk_builder_get_object (builder, "disjunctionCheck"));
	priv->limit_check = GTK_WIDGET (gtk_builder_get_object (builder, "limitCheck"));
	priv->limit_entry = GTK_WIDGET (gtk_builder_get_object (builder, "limitEntry"));
	priv->limit_option = GTK_WIDGET (gtk_builder_get_object (builder, "limitOption"));
	priv->addbutton = GTK_WIDGET (gtk_builder_get_object (builder, "addButton"));
	priv->sort_label = GTK_WIDGET (gtk_builder_get_object (builder, "sortLabel"));
	priv->sort_menu = GTK_WIDGET (gtk_builder_get_object (builder, "sortMenu"));
	priv->sort_desc = GTK_WIDGET (gtk_builder_get_object (builder, "sortDesc"));

	gtk_combo_box_set_active (GTK_COMBO_BOX (priv->limit_option), 0);

	g_signal_connect_object (G_OBJECT (priv->limit_check), "toggled", G_CALLBACK (limit_toggled_cb),
				 creator, 0);
	limit_toggled_cb (priv->limit_check, creator);

	gtk_size_group_add_widget (priv->button_size_group, priv->addbutton);
	g_signal_connect_object (G_OBJECT (priv->addbutton), "clicked", G_CALLBACK (add_button_click_cb),
				 creator, 0);

	setup_sort_option_menu (creator, priv->sort_menu, sort_options, num_sort_options);

	priv->vbox = GTK_BOX (gtk_builder_get_object (builder, "sub_vbox"));
	if (priv->creating)
		append_row (creator);

	mainbox = GTK_WIDGET (gtk_builder_get_object (builder, "complex-playlist-creator"));
	gtk_box_pack_start (GTK_BOX (content_area), mainbox, FALSE, FALSE, 0);
	gtk_widget_show_all (GTK_WIDGET (creator));

	g_object_unref (builder);
}
static void
rb_grilo_source_constructed (GObject *object)
{
	RBGriloSource *source;
	RBShell *shell;
	RBShellPlayer *shell_player;
	const GList *source_keys;
	GtkTreeViewColumn *column;
	GtkCellRenderer *renderer;
	GtkTreeSelection *selection;
	GtkWidget *scrolled;
	GtkWidget *browserbox;
	GtkWidget *vbox;
	GtkWidget *mainbox;
	GtkAdjustment *adjustment;

	RB_CHAIN_GOBJECT_METHOD (rb_grilo_source_parent_class, constructed, object);
	source = RB_GRILO_SOURCE (object);

	g_object_get (source, "shell", &shell, NULL);
	g_object_get (shell,
		      "db", &source->priv->db,
		      "shell-player", &shell_player,
		      NULL);
	g_object_unref (shell);

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

	source->priv->entry_view = rb_entry_view_new (source->priv->db, G_OBJECT (shell_player), TRUE, FALSE);
	g_object_unref (shell_player);
	g_signal_connect (source->priv->entry_view,
			  "notify::sort-order",
			  G_CALLBACK (notify_sort_order_cb),
			  source);

	source_keys = grl_source_supported_keys (source->priv->grilo_source);

	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_TRACK_NUMBER))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_TRACK_NUMBER));
	}

	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_TITLE))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_TITLE));
	}

	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_GENRE))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_GENRE, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_GENRE));
	}
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_ARTIST))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_ARTIST));
	}
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_ALBUM))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_ALBUM));
	}
	/*
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_DATE))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_YEAR, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_DATE));
	}
	*/
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_DURATION))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_DURATION, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_DURATION));
	}

	source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_CHILDCOUNT));
	source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_URL));
	source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_THUMBNAIL));

	/* probably add an image column too? */
	source->priv->browser_model = gtk_tree_store_new (4, GRL_TYPE_MEDIA, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
	source->priv->browser_view = gtk_tree_view_new ();
	gtk_tree_view_set_model (GTK_TREE_VIEW (source->priv->browser_view), GTK_TREE_MODEL (source->priv->browser_model));

	column = gtk_tree_view_column_new ();
	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_set_title (column, _("Browse"));
	gtk_tree_view_column_pack_start (column, renderer, FALSE);
	gtk_tree_view_column_add_attribute (column, renderer, "text", 1);
	gtk_tree_view_column_set_expand (column, TRUE);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);

	gtk_tree_view_append_column (GTK_TREE_VIEW (source->priv->browser_view), column);
	gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (source->priv->browser_view), TRUE);
	gtk_tree_view_set_expander_column (GTK_TREE_VIEW (source->priv->browser_view), column);
	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (source->priv->browser_view), TRUE);
	gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (source->priv->browser_view), TRUE);

	g_signal_connect (source->priv->browser_view, "row-expanded", G_CALLBACK (browser_row_expanded_cb), source);
	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (source->priv->browser_view));
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);	/* should be multiple eventually */
	g_signal_connect (selection, "changed", G_CALLBACK (browser_selection_changed_cb), source);

	scrolled = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
	adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled));
	g_signal_connect (adjustment, "changed", G_CALLBACK (scroll_adjust_changed_cb), source);
	g_signal_connect (adjustment, "value-changed", G_CALLBACK (scroll_adjust_value_changed_cb), source);

	browserbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);

	/* search bar (if the source supports searching) */
	if (grl_source_supported_operations (source->priv->grilo_source) & GRL_OP_SEARCH) {
		source->priv->search_entry = rb_search_entry_new (FALSE);
		g_object_set (source->priv->search_entry, "explicit-mode", TRUE, NULL);
		g_signal_connect (source->priv->search_entry, "search", G_CALLBACK (search_cb), source);
		g_signal_connect (source->priv->search_entry, "activate", G_CALLBACK (search_cb), source);
		gtk_box_pack_start (GTK_BOX (browserbox), GTK_WIDGET (source->priv->search_entry), FALSE, FALSE, 6);
	}
	gtk_container_add (GTK_CONTAINER (scrolled), source->priv->browser_view);
	gtk_box_pack_start (GTK_BOX (browserbox), scrolled, TRUE, TRUE, 0);

	mainbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
	gtk_box_pack_start (GTK_BOX (source), mainbox, TRUE, TRUE, 0);

	/* info bar */
	source->priv->info_bar_label = gtk_label_new ("");
	source->priv->info_bar = gtk_info_bar_new ();
	gtk_info_bar_set_message_type (GTK_INFO_BAR (source->priv->info_bar), GTK_MESSAGE_INFO);
	gtk_info_bar_add_button (GTK_INFO_BAR (source->priv->info_bar), _("Fetch more tracks"), GTK_RESPONSE_OK);
	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (source->priv->info_bar))),
			   source->priv->info_bar_label);
	gtk_widget_show (GTK_WIDGET (source->priv->info_bar_label));
	gtk_widget_set_no_show_all (GTK_WIDGET (source->priv->info_bar), TRUE);
	g_signal_connect (source->priv->info_bar, "response", G_CALLBACK (fetch_more_cb), source);

	/* don't allow the browser to be hidden? */
	source->priv->paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
	rb_source_bind_settings (RB_SOURCE (source), GTK_WIDGET (source->priv->entry_view), source->priv->paned, NULL);
	gtk_paned_pack1 (GTK_PANED (source->priv->paned), browserbox, FALSE, FALSE);

	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
	gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (source->priv->entry_view), TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (vbox), source->priv->info_bar, FALSE, FALSE, 0);
	gtk_paned_pack2 (GTK_PANED (source->priv->paned), vbox, TRUE, FALSE);

	gtk_box_pack_start (GTK_BOX (mainbox), source->priv->paned, TRUE, TRUE, 0);

	gtk_widget_show_all (GTK_WIDGET (source));
}