~ubuntu-branches/ubuntu/maverick/rhythmbox/maverick

« back to all changes in this revision

Viewing changes to shell/rb-shell.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-08-24 17:19:03 UTC
  • mfrom: (1.1.53 upstream)
  • Revision ID: james.westby@ubuntu.com-20100824171903-3ez8k8eexllnhurw
Tags: 0.13.0git20100819-0ubuntu1
* New git version, renamed patches specifics to ubuntu for easier review
* debian/patches/06_build_vala.patch,
  debian/patches/90_git_correct_playback_status.patch,
  debian/patches/91_git_new_mpris.patch:
  - dropped, those changes are in the new version
* debian/control.in:
  - build-depends on libdmapsharing-dev (lp: #609081)
* debian/rhythmbox-plugins.install:
  - install the daap code there (lp: #613617)
* debian/patches/20_pause_button.patch:
  - update by Bilal Akhtar to remove the play pause button label (lp: #620326)

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 * @short_description: holds the Rhythmbox main window and everything else
33
33
 *
34
34
 * RBShell is the main application class in Rhythmbox.  It creates and holds
35
 
 * references to the other main objects (#RBShellPlayer, #RhythmDB, #RBSourcelist),
 
35
 * references to the other main objects (#RBShellPlayer, #RhythmDB, #RBSourceList),
36
36
 * constructs the main window UI, and provides the basic DBus interface.
37
37
 */
38
38
 
137
137
static void source_activated_cb (RBSourceList *sourcelist,
138
138
                                 RBSource *source,
139
139
                                 RBShell *shell);
140
 
static void rb_shell_activate_source (RBShell *shell,
141
 
                                      RBSource *source);
 
140
static gboolean rb_shell_activate_source (RBShell *shell,
 
141
                                          RBSource *source,
 
142
                                          guint play,
 
143
                                          GError **error);
142
144
static void rb_shell_db_save_error_cb (RhythmDB *db,
143
145
                                       const char *uri, const GError *error,
144
146
                                       RBShell *shell);
145
 
static void rb_shell_db_entry_added_cb (RhythmDB *db,
146
 
                                        RhythmDBEntry *entry,
147
 
                                        RBShell *shell);
148
147
 
149
148
static void rb_shell_playlist_added_cb (RBPlaylistManager *mgr, RBSource *source, RBShell *shell);
150
149
static void rb_shell_playlist_created_cb (RBPlaylistManager *mgr, RBSource *source, RBShell *shell);
283
282
        REMOVABLE_MEDIA_SCAN_FINISHED,
284
283
        NOTIFY_PLAYING_ENTRY,
285
284
        NOTIFY_CUSTOM,
 
285
        DATABASE_LOAD_COMPLETE,
286
286
        LAST_SIGNAL
287
287
};
288
288
 
331
331
        char *playlists_file;
332
332
 
333
333
        RhythmDB *db;
334
 
        char *pending_entry;
335
334
 
336
335
        RBShellPlayer *player_shell;
337
336
        RBShellClipboard *clipboard_shell;
675
674
        /**
676
675
         * RBShell:sourcelist:
677
676
         *
678
 
         * The #RBSourcelist instance
 
677
         * The #RBSourceList instance
679
678
         */
680
679
        g_object_class_install_property (object_class,
681
680
                                         PROP_SOURCELIST,
682
681
                                         g_param_spec_object ("sourcelist",
683
682
                                                              "sourcelist",
684
 
                                                              "RBSourcelist",
 
683
                                                              "RBSourceList",
685
684
                                                              RB_TYPE_SOURCELIST,
686
685
                                                              G_PARAM_READABLE));
687
686
 
853
852
                              G_TYPE_NONE,
854
853
                              5,
855
854
                              G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN);
 
855
        /**
 
856
         * RBShell::database-load-complete:
 
857
         * @shell: the #RBShell
 
858
         *
 
859
         * Emitted when the database has been loaded.  This is intended to allow
 
860
         * DBus clients that start a new instance of the application to wait until
 
861
         * a reasonable amount of state has been loaded before making further requests.
 
862
         */
 
863
        rb_shell_signals[DATABASE_LOAD_COMPLETE] =
 
864
                g_signal_new ("database-load-complete",
 
865
                              G_OBJECT_CLASS_TYPE (object_class),
 
866
                              G_SIGNAL_RUN_LAST,
 
867
                              G_STRUCT_OFFSET (RBShellClass, database_load_complete),
 
868
                              NULL, NULL,
 
869
                              g_cclosure_marshal_VOID__VOID,
 
870
                              G_TYPE_NONE,
 
871
                              0);
856
872
 
857
873
        g_type_class_add_private (klass, sizeof (RBShellPrivate));
858
874
}
1161
1177
static GMountOperation *
1162
1178
rb_shell_create_mount_op_cb (RhythmDB *db, RBShell *shell)
1163
1179
{
1164
 
        return gtk_mount_operation_new (GTK_WINDOW (shell->priv->window));
 
1180
        /* we don't want the operation to be modal, so we don't associate it with the window. */
 
1181
        GMountOperation *op = gtk_mount_operation_new (NULL);
 
1182
        gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (op),
 
1183
                                        gtk_window_get_screen (GTK_WINDOW (shell->priv->window)));
 
1184
        return op;
1165
1185
}
1166
1186
 
1167
1187
static void
1584
1604
 
1585
1605
        g_signal_connect_object (G_OBJECT (shell->priv->db), "save-error",
1586
1606
                                 G_CALLBACK (rb_shell_db_save_error_cb), shell, 0);
1587
 
        g_signal_connect_object (G_OBJECT (shell->priv->db), "entry-added",
1588
 
                                 G_CALLBACK (rb_shell_db_entry_added_cb), shell, 0);
1589
1607
 
1590
1608
        construct_sources (shell);
1591
1609
 
1873
1891
{
1874
1892
        rb_debug ("source activated");
1875
1893
 
1876
 
        rb_shell_activate_source (shell, source);
 
1894
        rb_shell_activate_source (shell, source, 2, NULL);
1877
1895
}
1878
1896
 
1879
 
static void
1880
 
rb_shell_activate_source (RBShell *shell, RBSource *source)
 
1897
static gboolean
 
1898
rb_shell_activate_source (RBShell *shell, RBSource *source, guint play, GError **error)
1881
1899
{
 
1900
        RhythmDBEntry *entry;
1882
1901
        /* FIXME
1883
1902
         *
1884
1903
         * this doesn't work correctly yet, but it's still an improvement on the
1888
1907
         * doesn't start the new one.
1889
1908
         */
1890
1909
 
1891
 
        /* Select the new one, and start it playing */
 
1910
        /* Select the new one, and optionally start it playing */
1892
1911
        rb_shell_select_source (shell, source);
1893
 
        rb_shell_player_set_playing_source (shell->priv->player_shell, source);
1894
 
        /* Ignore error from here */
1895
 
        rb_shell_player_playpause (shell->priv->player_shell, FALSE, NULL);
 
1912
 
 
1913
        switch (play) {
 
1914
        case 0:
 
1915
                return TRUE;
 
1916
 
 
1917
        case 1:
 
1918
                entry = rb_shell_player_get_playing_entry (shell->priv->player_shell);
 
1919
                if (entry != NULL) {
 
1920
                        rhythmdb_entry_unref (entry);
 
1921
                        return TRUE;
 
1922
                }
 
1923
                /* fall through */
 
1924
        case 2:
 
1925
                rb_shell_player_set_playing_source (shell->priv->player_shell, source);
 
1926
                return rb_shell_player_playpause (shell->priv->player_shell, FALSE, error);
 
1927
 
 
1928
        default:
 
1929
                return FALSE;
 
1930
        }
1896
1931
}
1897
1932
 
1898
1933
static void
1905
1940
                         "%s", error->message);
1906
1941
}
1907
1942
 
1908
 
static void
1909
 
rb_shell_db_entry_added_cb (RhythmDB *db,
1910
 
                            RhythmDBEntry *entry,
1911
 
                            RBShell *shell)
1912
 
{
1913
 
        const char *loc;
1914
 
 
1915
 
        if (shell->priv->pending_entry == NULL)
1916
 
                return;
1917
 
 
1918
 
        loc = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
1919
 
        rb_debug ("got entry added for %s", loc);
1920
 
        if (strcmp (loc, shell->priv->pending_entry) == 0) {
1921
 
                rb_shell_play_entry (shell, entry);
1922
 
 
1923
 
                g_free (shell->priv->pending_entry);
1924
 
                shell->priv->pending_entry = NULL;
1925
 
        }
1926
 
}
1927
 
 
1928
1943
/**
1929
1944
 * rb_shell_get_source_by_entry_type:
1930
1945
 * @shell: the #RBShell
1937
1952
 */
1938
1953
RBSource *
1939
1954
rb_shell_get_source_by_entry_type (RBShell *shell,
1940
 
                                   RhythmDBEntryType type)
 
1955
                                   RhythmDBEntryType *type)
1941
1956
{
1942
1957
        return g_hash_table_lookup (shell->priv->sources_hash, type);
1943
1958
}
1956
1971
void
1957
1972
rb_shell_register_entry_type_for_source (RBShell *shell,
1958
1973
                                         RBSource *source,
1959
 
                                         RhythmDBEntryType type)
 
1974
                                         RhythmDBEntryType *type)
1960
1975
{
1961
1976
        if (shell->priv->sources_hash == NULL) {
1962
1977
                shell->priv->sources_hash = g_hash_table_new (g_direct_hash,
2027
2042
rb_shell_source_deleted_cb (RBSource *source,
2028
2043
                            RBShell *shell)
2029
2044
{
2030
 
        RhythmDBEntryType entry_type;
 
2045
        RhythmDBEntryType *entry_type;
2031
2046
 
2032
2047
        rb_debug ("source deleted");
2033
2048
 
2036
2051
        if (rb_shell_get_source_by_entry_type (shell, entry_type) == source) {
2037
2052
                g_hash_table_remove (shell->priv->sources_hash, entry_type);
2038
2053
        }
2039
 
        g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type);
 
2054
        g_object_unref (entry_type);
2040
2055
 
2041
2056
 
2042
2057
        if (source == rb_shell_player_get_playing_source (shell->priv->player_shell) ||
2084
2099
        } else {
2085
2100
                RBSource *source;
2086
2101
                RhythmDBEntry *entry;
2087
 
                RhythmDBEntryType entry_type;
 
2102
                RhythmDBEntryType *entry_type;
2088
2103
 
2089
2104
                /* if playing from the queue, show the playing entry as playing in the
2090
2105
                 * registered source for its type, so it makes sense when 'jump to current'
2609
2624
        shell->priv->load_complete = TRUE;
2610
2625
        shell->priv->save_playlist_id = g_timeout_add_seconds (10, (GSourceFunc) idle_save_playlist_manager, shell);
2611
2626
 
 
2627
        g_signal_emit (shell, rb_shell_signals[DATABASE_LOAD_COMPLETE], 0);
 
2628
 
2612
2629
        rhythmdb_start_action_thread (shell->priv->db);
2613
2630
 
2614
2631
        GDK_THREADS_LEAVE ();
2949
2966
        if ((source == RB_SOURCE (shell->priv->queue_source) &&
2950
2967
             shell->priv->queue_as_sidebar) ||
2951
2968
             source == NULL) {
2952
 
                RhythmDBEntryType entry_type;
 
2969
                RhythmDBEntryType *entry_type;
2953
2970
                entry_type = rhythmdb_entry_get_entry_type (entry);
2954
2971
                source = rb_shell_get_source_by_entry_type (shell, entry_type);
2955
2972
        }
3148
3165
                return FALSE;
3149
3166
        }
3150
3167
 
3151
 
        rb_source_add_uri (source, uri, title, genre);
 
3168
        rb_source_add_uri (source, uri, title, genre, NULL, NULL, NULL);
3152
3169
        return TRUE;
3153
3170
}
3154
3171
 
3190
3207
        }
3191
3208
}
3192
3209
 
 
3210
static void
 
3211
shell_load_uri_done (RBSource *source, const char *uri, RBShell *shell)
 
3212
{
 
3213
        RhythmDBEntry *entry;
 
3214
 
 
3215
        entry = rhythmdb_entry_lookup_by_location (shell->priv->db, uri);
 
3216
        if (entry) {
 
3217
                rb_shell_play_entry (shell, entry);
 
3218
        } else {
 
3219
                rb_debug ("unable to find entry for uri %s", uri);
 
3220
        }
 
3221
}
 
3222
 
3193
3223
/**
3194
3224
 * rb_shell_load_uri:
3195
3225
 * @shell: the #RBShell
3216
3246
                   GError **error)
3217
3247
{
3218
3248
        RhythmDBEntry *entry;
3219
 
        RBSource *playlist_source;
3220
 
 
3221
 
        entry = rhythmdb_entry_lookup_by_location (shell->priv->db, uri);
3222
 
        playlist_source = NULL;
 
3249
        RBSource *entry_source;
3223
3250
 
3224
3251
        /* If the URI points to a Podcast, pass it on to
3225
3252
         * the Podcast source */
3229
3256
                return TRUE;
3230
3257
        }
3231
3258
 
 
3259
        entry = rhythmdb_entry_lookup_by_location (shell->priv->db, uri);
 
3260
        entry_source = NULL;
 
3261
 
3232
3262
        if (entry == NULL) {
3233
3263
                TotemPlParser *parser;
3234
3264
                TotemPlParserResult result;
3257
3287
                if (result == TOTEM_PL_PARSER_RESULT_SUCCESS) {
3258
3288
                        if (data.can_use_playlist && data.playlist_source) {
3259
3289
                                rb_debug ("adding playlist %s to source", uri);
3260
 
                                rb_source_add_uri (data.playlist_source, uri, NULL, NULL);
 
3290
                                rb_source_add_uri (data.playlist_source, uri, NULL, NULL, NULL, NULL, NULL);
3261
3291
 
3262
3292
                                /* FIXME: We need some way to determine whether the URI as
3263
3293
                                 * given will appear in the db, or whether something else will.
3273
3303
                                                                     uri, error))
3274
3304
                                        return FALSE;
3275
3305
                        }
3276
 
                } else if ((result == TOTEM_PL_PARSER_RESULT_IGNORED && rb_uri_is_local (uri))
3277
 
                           || result == TOTEM_PL_PARSER_RESULT_UNHANDLED) {
3278
 
                        /* That happens for directories and unhandled schemes, such as CDDA */
3279
 
                        playlist_source = rb_shell_guess_source_for_uri (shell, uri);
3280
 
                        if (playlist_source == NULL || rb_source_uri_is_source (playlist_source, uri) == FALSE) {
3281
 
                                rb_debug ("%s doesn't have a source, adding", uri);
3282
 
                                if (!rb_shell_add_uri (shell, uri, NULL, NULL, error))
3283
 
                                        return FALSE;
3284
 
                        }
3285
3306
                } else {
3286
 
                        rb_debug ("%s didn't parse as a playlist", uri);
3287
 
                        if (!rb_shell_add_uri (shell, uri, NULL, NULL, error))
3288
 
                                return FALSE;
 
3307
                        RBSource *source;
 
3308
 
 
3309
                        source = rb_shell_guess_source_for_uri (shell, uri);
 
3310
                        if (source != NULL) {
 
3311
                                char *name;
 
3312
                                g_object_get (source, "name", &name, NULL);
 
3313
                                if (rb_source_uri_is_source (source, uri)) {
 
3314
                                        rb_debug ("%s identifies source %s", uri, name);
 
3315
                                        entry_source = source;
 
3316
                                } else if (play) {
 
3317
                                        rb_debug ("adding %s to source %s, will play it when it shows up", uri, name);
 
3318
                                        rb_source_add_uri (source, uri, NULL, NULL, (RBSourceAddCallback) shell_load_uri_done, g_object_ref (shell), g_object_unref);
 
3319
                                        play = FALSE;
 
3320
                                } else {
 
3321
                                        rb_debug ("just adding %s to source %s", uri, name);
 
3322
                                        rb_source_add_uri (source, uri, NULL, NULL, NULL, NULL, NULL);
 
3323
                                }
 
3324
                                g_free (name);
 
3325
                        } else {
 
3326
                                rb_debug ("couldn't find a source for %s, trying to add it anyway", uri);
 
3327
                                if (!rb_shell_add_uri (shell, uri, NULL, NULL, error)) {
 
3328
                                        rb_debug ("couldn't do it: %s", (*error)->message);
 
3329
                                        return FALSE;
 
3330
                                }
 
3331
                        }
3289
3332
                }
3290
3333
 
3291
3334
                if (data.source_is_entry != FALSE) {
3292
 
                        playlist_source = data.playlist_source;
 
3335
                        entry_source = data.playlist_source;
3293
3336
                } else if (data.playlist_source != NULL) {
3294
3337
                        g_object_unref (data.playlist_source);
3295
3338
                }
3296
3339
        }
3297
3340
 
3298
3341
        if (play) {
3299
 
                if (playlist_source != NULL) {
 
3342
                if (entry_source != NULL) {
3300
3343
                        char *name;
3301
 
 
3302
 
                        rb_shell_activate_source (shell, playlist_source);
3303
 
 
3304
 
                        g_object_get (playlist_source, "name", &name, NULL);
 
3344
                        int play_type = 0;
 
3345
                        if (entry == NULL) {
 
3346
                                /* we don't have a specific entry to play, so just play something */
 
3347
                                play_type = 2;
 
3348
                        }
 
3349
 
 
3350
                        if (rb_shell_activate_source (shell, entry_source, play_type, error) == FALSE) {
 
3351
                                return FALSE;
 
3352
                        }
 
3353
 
 
3354
                        g_object_get (entry_source, "name", &name, NULL);
3305
3355
                        rb_debug ("Activated source '%s' for uri %s", name, uri);
3306
3356
                        g_free (name);
3307
3357
 
3308
3358
                        return TRUE;
3309
3359
                }
3310
3360
 
3311
 
                if (entry == NULL)
3312
 
                        entry = rhythmdb_entry_lookup_by_location (shell->priv->db, uri);
3313
 
 
3314
3361
                if (entry) {
3315
3362
                        rb_shell_play_entry (shell, entry);
3316
 
                } else {
3317
 
                        /* wait for the entry to be added, and then play it */
3318
 
                        if (shell->priv->pending_entry)
3319
 
                                g_free (shell->priv->pending_entry);
3320
 
 
3321
 
                        shell->priv->pending_entry = g_strdup (uri);
3322
3363
                }
3323
3364
        }
3324
3365
 
3425
3466
                       const gchar *uri,
3426
3467
                       GError **error)
3427
3468
{
 
3469
        RhythmDBEntry *entry;
 
3470
 
 
3471
        entry = rhythmdb_entry_lookup_by_location (shell->priv->db, uri);
 
3472
        if (entry == NULL) {
 
3473
                RBSource *source;
 
3474
                source = rb_shell_guess_source_for_uri (shell, uri);
 
3475
                if (source != NULL) {
 
3476
                        rb_source_add_uri (source, uri, NULL, NULL, NULL, NULL, NULL);
 
3477
                } else {
 
3478
                        g_set_error (error,
 
3479
                                     RB_SHELL_ERROR,
 
3480
                                     RB_SHELL_ERROR_NO_SOURCE_FOR_URI,
 
3481
                                     _("No registered source can handle URI %s"),
 
3482
                                     uri);
 
3483
                        return FALSE;
 
3484
                }
 
3485
        }
3428
3486
        rb_static_playlist_source_add_location (RB_STATIC_PLAYLIST_SOURCE (shell->priv->queue_source),
3429
3487
                                                uri, -1);
3430
3488
        return TRUE;
3497
3555
}
3498
3556
 
3499
3557
/**
 
3558
 * rb_shell_activate_source_by_uri:
 
3559
 * @shell: the #RBShell
 
3560
 * @source_uri: URI for the source to activate
 
3561
 * @play: 0: select source, 1: play source if not playing, 2: play source
 
3562
 * @error: returns error information
 
3563
 *
 
3564
 * Searches for a source matching @source_uri and if found, selects it,
 
3565
 * and depending on the value of @play, may start playing from it.
 
3566
 * Device-based sources will match the device node or mount point URI.
 
3567
 * Other types of sources may have their own URI scheme or format.
 
3568
 * This is part of the DBus interface.
 
3569
 *
 
3570
 * Return value: %TRUE if successful
 
3571
 */
 
3572
gboolean
 
3573
rb_shell_activate_source_by_uri (RBShell *shell,
 
3574
                                 const char *source_uri,
 
3575
                                 guint play,
 
3576
                                 GError **error)
 
3577
{
 
3578
        GList *t;
 
3579
        GFile *f;
 
3580
        char *uri;
 
3581
 
 
3582
        /* ensure the argument is actually a URI */
 
3583
        f = g_file_new_for_commandline_arg (source_uri);
 
3584
        uri = g_file_get_uri (f);
 
3585
        g_object_unref (f);
 
3586
 
 
3587
        for (t = shell->priv->sources; t != NULL; t = t->next) {
 
3588
                RBSource *source;
 
3589
 
 
3590
                source = (RBSource *)t->data;
 
3591
                if (rb_source_uri_is_source (source, uri)) {
 
3592
                        rb_debug ("found source for uri %s", uri);
 
3593
                        g_free (uri);
 
3594
                        return rb_shell_activate_source (shell, source, play, error);
 
3595
                }
 
3596
        }
 
3597
 
 
3598
        g_set_error (error,
 
3599
                     RB_SHELL_ERROR,
 
3600
                     RB_SHELL_ERROR_NO_SOURCE_FOR_URI,
 
3601
                     _("No registered source matches URI %s"),
 
3602
                     uri);
 
3603
        g_free (uri);
 
3604
        return FALSE;
 
3605
}
 
3606
 
 
3607
/**
3500
3608
 * rb_shell_get_song_properties:
3501
3609
 * @shell: the #RBShell
3502
3610
 * @uri: the URI to query