~swem/totem/assignment

« back to all changes in this revision

Viewing changes to src/totem-playlist.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2010-01-27 09:40:18 UTC
  • mfrom: (1.4.2 upstream) (5.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20100127094018-q6rzt7va0y8ketwt
Tags: 2.29.4-1
* New upstream development release:
  + debian/patches/90_autotools.patch:
    - Refreshed for the new version.
  + debian/control.in:
    - Update build dependencies and dependencies.
    - Drop tracker plugin, it needs tracker 0.7.
  + debian/totem-mozilla.links:
    - Drop the complex plugin, it doesn't exist anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
131
131
enum {
132
132
        PLAYING_COL,
133
133
        FILENAME_COL,
 
134
        FILENAME_ESCAPED_COL,
134
135
        URI_COL,
135
136
        TITLE_CUSTOM_COL,
136
137
        SUBTITLE_URI_COL,
144
145
        TotemPlParserType type;
145
146
} PlaylistSaveType;
146
147
 
147
 
static PlaylistSaveType save_types [] = {
 
148
static const PlaylistSaveType save_types [] = {
148
149
        { NULL, NULL, -1 }, /* By extension entry */
149
150
        { N_("MP3 ShoutCast playlist"), "pls", TOTEM_PL_PARSER_PLS },
150
151
        { N_("MP3 audio (streamed)"), "m3u", TOTEM_PL_PARSER_M3U },
396
397
        gtk_widget_set_sensitive (button, state);
397
398
}
398
399
 
399
 
static void
400
 
totem_playlist_save_get_iter_func (GtkTreeModel *model,
401
 
                GtkTreeIter *iter, char **uri, char **title,
402
 
                gboolean *custom_title, gpointer user_data)
 
400
static gboolean
 
401
totem_playlist_save_iter_foreach (GtkTreeModel *model,
 
402
                                  GtkTreePath  *path,
 
403
                                  GtkTreeIter  *iter,
 
404
                                  gpointer      user_data)
403
405
{
 
406
        TotemPlPlaylist *playlist = user_data;
 
407
        TotemPlPlaylistIter pl_iter;
 
408
        gchar *uri, *title;
 
409
        gboolean custom_title;
 
410
 
404
411
        gtk_tree_model_get (model, iter,
405
 
                        URI_COL, uri,
406
 
                        FILENAME_COL, title,
407
 
                        TITLE_CUSTOM_COL, custom_title,
408
 
                        -1);
 
412
                            URI_COL, &uri,
 
413
                            FILENAME_COL, &title,
 
414
                            TITLE_CUSTOM_COL, &custom_title,
 
415
                            -1);
 
416
 
 
417
        totem_pl_playlist_append (playlist, &pl_iter);
 
418
        totem_pl_playlist_set (playlist, &pl_iter,
 
419
                               TOTEM_PL_PARSER_FIELD_URI, uri,
 
420
                               TOTEM_PL_PARSER_FIELD_TITLE, (custom_title) ? title : NULL,
 
421
                               NULL);
 
422
 
 
423
        g_free (uri);
 
424
        g_free (title);
 
425
 
 
426
        return FALSE;
409
427
}
410
428
 
411
429
void
417
435
void
418
436
totem_playlist_save_current_playlist_ext (TotemPlaylist *playlist, const char *output, TotemPlParserType type)
419
437
{
 
438
        TotemPlPlaylist *pl_playlist;
420
439
        GError *error = NULL;
 
440
        GFile *output_file;
421
441
        gboolean retval;
422
442
 
423
 
        retval = totem_pl_parser_write (playlist->priv->parser,
424
 
                        playlist->priv->model,
425
 
                        totem_playlist_save_get_iter_func,
426
 
                        output, type, NULL, &error);
 
443
        pl_playlist = totem_pl_playlist_new ();
 
444
        output_file = g_file_new_for_commandline_arg (output);
 
445
 
 
446
        gtk_tree_model_foreach (playlist->priv->model,
 
447
                                totem_playlist_save_iter_foreach,
 
448
                                pl_playlist);
 
449
 
 
450
        retval = totem_pl_parser_save (playlist->priv->parser,
 
451
                                       pl_playlist,
 
452
                                       output_file,
 
453
                                       NULL, type, &error);
427
454
 
428
455
        if (retval == FALSE)
429
456
        {
431
458
                                error->message, playlist);
432
459
                g_error_free (error);
433
460
        }
 
461
 
 
462
        g_object_unref (pl_playlist);
 
463
        g_object_unref (output_file);
434
464
}
435
465
 
436
466
static void
1303
1333
        }
1304
1334
}
1305
1335
 
 
1336
static gboolean
 
1337
search_equal_is_match (const gchar * s, const gchar * lc_key)
 
1338
{
 
1339
        gboolean match = FALSE;
 
1340
 
 
1341
        if (s != NULL) {
 
1342
                gchar *lc_s;
 
1343
 
 
1344
                /* maybe also normalize both strings? */
 
1345
                lc_s = g_utf8_strdown (s, -1);
 
1346
                match = (lc_s != NULL && strstr (lc_s, lc_key) != NULL);
 
1347
                g_free (lc_s);
 
1348
        }
 
1349
 
 
1350
        return match;
 
1351
}
 
1352
 
 
1353
static gboolean
 
1354
search_equal_func (GtkTreeModel *model, gint col, const gchar *key,
 
1355
                   GtkTreeIter *iter, gpointer userdata)
 
1356
{
 
1357
        gboolean match;
 
1358
        gchar *lc_key, *fn = NULL;
 
1359
 
 
1360
        lc_key = g_utf8_strdown (key, -1);
 
1361
 
 
1362
        /* type-ahead search: first check display filename / title, then URI */
 
1363
        gtk_tree_model_get (model, iter, FILENAME_COL, &fn, -1);
 
1364
        match = search_equal_is_match (fn, lc_key);
 
1365
        g_free (fn);
 
1366
 
 
1367
        if (!match) {
 
1368
                gchar *uri = NULL;
 
1369
 
 
1370
                gtk_tree_model_get (model, iter, URI_COL, &uri, -1);
 
1371
                fn = g_filename_from_uri (uri, NULL, NULL);
 
1372
                match = search_equal_is_match (fn, lc_key);
 
1373
                g_free (fn);
 
1374
                g_free (uri);
 
1375
        }
 
1376
 
 
1377
        g_free (lc_key);
 
1378
        return !match; /* needs to return FALSE if row matches */
 
1379
}
 
1380
 
1306
1381
static void
1307
1382
init_treeview (GtkWidget *treeview, TotemPlaylist *playlist)
1308
1383
{
1339
1414
 
1340
1415
        playlist->priv->selection = selection;
1341
1416
 
 
1417
        /* make type-ahead search work in the playlist */
 
1418
        gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (treeview),
 
1419
                                             search_equal_func, NULL, NULL);
 
1420
 
1342
1421
        gtk_widget_show (treeview);
1343
1422
}
1344
1423
 
1631
1710
 
1632
1711
        /* tooltips */
1633
1712
        gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(playlist->priv->treeview),
1634
 
                                         FILENAME_COL);
 
1713
                                         FILENAME_ESCAPED_COL);
1635
1714
 
1636
1715
        /* The configuration */
1637
1716
        init_config (playlist);
1654
1733
}
1655
1734
 
1656
1735
static gboolean
1657
 
totem_playlist_add_one_mrl (TotemPlaylist *playlist, const char *mrl,
1658
 
                const char *display_name)
 
1736
totem_playlist_add_one_mrl (TotemPlaylist *playlist,
 
1737
                            const char *mrl,
 
1738
                            const char *display_name)
1659
1739
{
1660
1740
        GtkListStore *store;
1661
1741
        GtkTreeIter iter;
1662
 
        char *filename_for_display, *uri;
 
1742
        char *filename_for_display, *uri, *escaped_filename;
1663
1743
        GtkTreeRowReference *ref;
1664
1744
        GFileMonitor *monitor;
1665
1745
        GFile *file;
1704
1784
                monitor = NULL;
1705
1785
        }
1706
1786
 
 
1787
        escaped_filename = g_markup_escape_text (filename_for_display, -1);
1707
1788
        gtk_list_store_insert_with_values (store, &iter, pos,
1708
1789
                        PLAYING_COL, TOTEM_PLAYLIST_STATUS_NONE,
1709
1790
                        FILENAME_COL, filename_for_display,
 
1791
                        FILENAME_ESCAPED_COL, escaped_filename,
1710
1792
                        URI_COL, uri ? uri : mrl,
1711
1793
                        TITLE_CUSTOM_COL, display_name ? TRUE : FALSE,
1712
1794
                        FILE_MONITOR_COL, monitor,
1713
1795
                        -1);
 
1796
        g_free (escaped_filename);
1714
1797
 
1715
1798
        g_signal_emit (playlist,
1716
1799
                       totem_playlist_table_signals[ITEM_ADDED],
1815
1898
        return TRUE;
1816
1899
}
1817
1900
 
 
1901
static int
 
1902
compare_removal (GtkTreeRowReference *ref, GtkTreePath *path)
 
1903
{
 
1904
        GtkTreePath *ref_path;
 
1905
        int ret = -1;
 
1906
 
 
1907
        ref_path = gtk_tree_row_reference_get_path (ref);
 
1908
        if (gtk_tree_path_compare (path, ref_path) == 0)
 
1909
                ret = 0;
 
1910
        gtk_tree_path_free (ref_path);
 
1911
        return ret;
 
1912
}
 
1913
 
 
1914
/* Whether the item in question will be removed */
 
1915
static gboolean
 
1916
totem_playlist_item_to_be_removed (TotemPlaylist *playlist,
 
1917
                                   GtkTreePath *path,
 
1918
                                   ClearComparisonFunc func)
 
1919
{
 
1920
        GList *ret;
 
1921
 
 
1922
        if (func == NULL) {
 
1923
                GtkTreeSelection *selection;
 
1924
 
 
1925
                selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (playlist->priv->treeview));
 
1926
                return gtk_tree_selection_path_is_selected (selection, path);
 
1927
        }
 
1928
 
 
1929
        ret = g_list_find_custom (playlist->priv->list, path, (GCompareFunc) compare_removal);
 
1930
        return (ret != NULL);
 
1931
}
 
1932
 
1818
1933
static void
1819
1934
totem_playlist_clear_with_compare (TotemPlaylist *playlist,
1820
1935
                                   ClearComparisonFunc func,
1821
1936
                                   gconstpointer data)
1822
1937
{
1823
1938
        GtkTreeRowReference *ref;
1824
 
        int next_pos;
 
1939
        GtkTreeRowReference *next;
1825
1940
 
1826
1941
        ref = NULL;
1827
 
        next_pos = -1;
 
1942
        next = NULL;
1828
1943
 
1829
1944
        if (func == NULL) {
1830
1945
                GtkTreeSelection *selection;
1861
1976
 
1862
1977
                                path = gtk_tree_path_new_from_indices (i, -1);
1863
1978
                                r = gtk_tree_row_reference_new (playlist->priv->model, path);
1864
 
                                if (playlist->priv->current != NULL) {
1865
 
                                        if (gtk_tree_path_compare (path, playlist->priv->current) == 0)
 
1979
                                if (playlist->priv->current_to_be_removed == FALSE && playlist->priv->current != NULL) {
 
1980
                                        if (gtk_tree_path_compare (path, playlist->priv->current) == 0) {
1866
1981
                                                playlist->priv->current_to_be_removed = TRUE;
 
1982
                                        }
1867
1983
                                }
1868
1984
                                playlist->priv->list = g_list_prepend (playlist->priv->list, r);
1869
1985
                                gtk_tree_path_free (path);
1876
1992
 
1877
1993
        /* If the current item is to change, we need to keep an static
1878
1994
         * reference to it, TreeIter and TreePath don't allow that */
1879
 
        if (playlist->priv->current != NULL) {
1880
 
                int *indices;
1881
 
 
 
1995
        if (playlist->priv->current_to_be_removed == FALSE &&
 
1996
            playlist->priv->current != NULL) {
1882
1997
                ref = gtk_tree_row_reference_new (playlist->priv->model,
1883
 
                                playlist->priv->current);
1884
 
                indices = gtk_tree_path_get_indices (playlist->priv->current);
1885
 
                next_pos = indices[0];
 
1998
                                                  playlist->priv->current);
 
1999
        } else if (playlist->priv->current != NULL) {
 
2000
                GtkTreePath *item;
1886
2001
 
 
2002
                item = gtk_tree_path_copy (playlist->priv->current);
 
2003
                gtk_tree_path_next (item);
 
2004
                next = gtk_tree_row_reference_new (playlist->priv->model, item);
 
2005
                while (next != NULL) {
 
2006
                        if (totem_playlist_item_to_be_removed (playlist, item, func) == FALSE) {
 
2007
                                /* Found the item after the current one that
 
2008
                                 * won't be removed, thus the new current */
 
2009
                                break;
 
2010
                        }
 
2011
                        gtk_tree_row_reference_free (next);
 
2012
                        gtk_tree_path_next (item);
 
2013
                        next = gtk_tree_row_reference_new (playlist->priv->model, item);
 
2014
                }
1887
2015
        }
1888
2016
 
1889
2017
        /* We destroy the items, one-by-one from the list built above */
1890
 
        while (playlist->priv->list != NULL)
1891
 
        {
 
2018
        while (playlist->priv->list != NULL) {
1892
2019
                GtkTreePath *path;
1893
2020
                GtkTreeIter iter;
1894
2021
 
1910
2037
 
1911
2038
        if (playlist->priv->current_to_be_removed != FALSE) {
1912
2039
                /* The current item was removed from the playlist */
1913
 
                if (next_pos != -1) {
1914
 
                        char *str;
1915
 
                        GtkTreeIter iter;
1916
 
                        GtkTreePath *cur;
1917
 
 
1918
 
                        str = g_strdup_printf ("%d", next_pos);
1919
 
                        cur = gtk_tree_path_new_from_string (str);
1920
 
 
1921
 
                        if (gtk_tree_model_get_iter (playlist->priv->model, &iter, cur) == FALSE) {
1922
 
                                playlist->priv->current = NULL;
1923
 
                                gtk_tree_path_free (cur);
1924
 
                        } else {
1925
 
                                playlist->priv->current = cur;
1926
 
                        }
1927
 
                        g_free (str);
 
2040
                if (next != NULL) {
 
2041
                        playlist->priv->current = gtk_tree_row_reference_get_path (next);
 
2042
                        gtk_tree_row_reference_free (next);
1928
2043
                } else {
1929
2044
                        playlist->priv->current = NULL;
1930
2045
                }
1939
2054
        } else {
1940
2055
                if (ref != NULL) {
1941
2056
                        /* The path to the current item changed */
1942
 
                        playlist->priv->current =
1943
 
                                gtk_tree_row_reference_get_path (ref);
1944
 
                        gtk_tree_row_reference_free (ref);
 
2057
                        playlist->priv->current = gtk_tree_row_reference_get_path (ref);
1945
2058
                }
1946
2059
 
1947
2060
                if (playlist->priv->shuffle)
1951
2064
                                totem_playlist_table_signals[CHANGED], 0,
1952
2065
                                NULL);
1953
2066
        }
 
2067
        if (ref != NULL)
 
2068
                gtk_tree_row_reference_free (ref);
1954
2069
        totem_playlist_update_save_button (playlist);
1955
2070
        gtk_tree_view_columns_autosize (GTK_TREE_VIEW (playlist->priv->treeview));
1956
2071
 
2139
2254
        GtkListStore *store;
2140
2255
        GtkTreeIter iter;
2141
2256
        gboolean custom_title;
 
2257
        char *escaped_title;
2142
2258
 
2143
2259
        g_return_val_if_fail (TOTEM_IS_PLAYLIST (playlist), FALSE);
2144
2260
 
2161
2277
                        return TRUE;
2162
2278
        }
2163
2279
 
 
2280
        escaped_title = g_markup_escape_text (title, -1);
2164
2281
        gtk_list_store_set (store, &iter,
2165
2282
                        FILENAME_COL, title,
 
2283
                        FILENAME_ESCAPED_COL, escaped_title,
2166
2284
                        TITLE_CUSTOM_COL, TRUE,
2167
2285
                        -1);
 
2286
        g_free (escaped_title);
2168
2287
 
2169
2288
        g_signal_emit (playlist,
2170
2289
                       totem_playlist_table_signals[ACTIVE_NAME_CHANGED], 0);
2283
2402
 
2284
2403
        g_return_if_fail (TOTEM_IS_PLAYLIST (playlist));
2285
2404
 
2286
 
        if (totem_playlist_has_next_mrl (playlist) == FALSE)
2287
 
        {
 
2405
        if (totem_playlist_has_next_mrl (playlist) == FALSE) {
2288
2406
                totem_playlist_set_at_start (playlist);
2289
2407
                return;
2290
2408
        }
2291
2409
 
2292
2410
        totem_playlist_unset_playing (playlist);
2293
2411
 
2294
 
        if (playlist->priv->shuffle == FALSE)
2295
 
        {
 
2412
        if (playlist->priv->shuffle == FALSE) {
2296
2413
                gtk_tree_model_get_iter (playlist->priv->model,
2297
 
                                &iter,
2298
 
                                playlist->priv->current);
 
2414
                                         &iter,
 
2415
                                         playlist->priv->current);
2299
2416
 
2300
2417
                gtk_tree_model_iter_next (playlist->priv->model, &iter);
2301
2418
                gtk_tree_path_free (playlist->priv->current);
2302
 
                playlist->priv->current = gtk_tree_model_get_path
2303
 
                        (playlist->priv->model, &iter);
 
2419
                playlist->priv->current = gtk_tree_model_get_path (playlist->priv->model, &iter);
2304
2420
        } else {
2305
2421
                int indice;
2306
2422