144
145
TotemPlParserType type;
145
146
} PlaylistSaveType;
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);
400
totem_playlist_save_get_iter_func (GtkTreeModel *model,
401
GtkTreeIter *iter, char **uri, char **title,
402
gboolean *custom_title, gpointer user_data)
401
totem_playlist_save_iter_foreach (GtkTreeModel *model,
406
TotemPlPlaylist *playlist = user_data;
407
TotemPlPlaylistIter pl_iter;
409
gboolean custom_title;
404
411
gtk_tree_model_get (model, iter,
407
TITLE_CUSTOM_COL, custom_title,
413
FILENAME_COL, &title,
414
TITLE_CUSTOM_COL, &custom_title,
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,
418
436
totem_playlist_save_current_playlist_ext (TotemPlaylist *playlist, const char *output, TotemPlParserType type)
438
TotemPlPlaylist *pl_playlist;
420
439
GError *error = NULL;
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);
446
gtk_tree_model_foreach (playlist->priv->model,
447
totem_playlist_save_iter_foreach,
450
retval = totem_pl_parser_save (playlist->priv->parser,
428
455
if (retval == FALSE)
1337
search_equal_is_match (const gchar * s, const gchar * lc_key)
1339
gboolean match = FALSE;
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);
1354
search_equal_func (GtkTreeModel *model, gint col, const gchar *key,
1355
GtkTreeIter *iter, gpointer userdata)
1358
gchar *lc_key, *fn = NULL;
1360
lc_key = g_utf8_strdown (key, -1);
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);
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);
1378
return !match; /* needs to return FALSE if row matches */
1307
1382
init_treeview (GtkWidget *treeview, TotemPlaylist *playlist)
1340
1415
playlist->priv->selection = selection;
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);
1342
1421
gtk_widget_show (treeview);
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,
1738
const char *display_name)
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;
1704
1784
monitor = NULL;
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,
1796
g_free (escaped_filename);
1715
1798
g_signal_emit (playlist,
1716
1799
totem_playlist_table_signals[ITEM_ADDED],
1902
compare_removal (GtkTreeRowReference *ref, GtkTreePath *path)
1904
GtkTreePath *ref_path;
1907
ref_path = gtk_tree_row_reference_get_path (ref);
1908
if (gtk_tree_path_compare (path, ref_path) == 0)
1910
gtk_tree_path_free (ref_path);
1914
/* Whether the item in question will be removed */
1916
totem_playlist_item_to_be_removed (TotemPlaylist *playlist,
1918
ClearComparisonFunc func)
1923
GtkTreeSelection *selection;
1925
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (playlist->priv->treeview));
1926
return gtk_tree_selection_path_is_selected (selection, path);
1929
ret = g_list_find_custom (playlist->priv->list, path, (GCompareFunc) compare_removal);
1930
return (ret != NULL);
1819
1934
totem_playlist_clear_with_compare (TotemPlaylist *playlist,
1820
1935
ClearComparisonFunc func,
1821
1936
gconstpointer data)
1823
1938
GtkTreeRowReference *ref;
1939
GtkTreeRowReference *next;
1829
1944
if (func == NULL) {
1830
1945
GtkTreeSelection *selection;
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;
1868
1984
playlist->priv->list = g_list_prepend (playlist->priv->list, r);
1869
1985
gtk_tree_path_free (path);
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) {
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) {
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 */
2011
gtk_tree_row_reference_free (next);
2012
gtk_tree_path_next (item);
2013
next = gtk_tree_row_reference_new (playlist->priv->model, item);
1889
2017
/* We destroy the items, one-by-one from the list built above */
1890
while (playlist->priv->list != NULL)
2018
while (playlist->priv->list != NULL) {
1892
2019
GtkTreePath *path;
1893
2020
GtkTreeIter iter;
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) {
1918
str = g_strdup_printf ("%d", next_pos);
1919
cur = gtk_tree_path_new_from_string (str);
1921
if (gtk_tree_model_get_iter (playlist->priv->model, &iter, cur) == FALSE) {
1922
playlist->priv->current = NULL;
1923
gtk_tree_path_free (cur);
1925
playlist->priv->current = cur;
2041
playlist->priv->current = gtk_tree_row_reference_get_path (next);
2042
gtk_tree_row_reference_free (next);
1929
2044
playlist->priv->current = NULL;
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);
1947
2060
if (playlist->priv->shuffle)
1951
2064
totem_playlist_table_signals[CHANGED], 0,
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));
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,
2286
g_free (escaped_title);
2169
2288
g_signal_emit (playlist,
2170
2289
totem_playlist_table_signals[ACTIVE_NAME_CHANGED], 0);
2284
2403
g_return_if_fail (TOTEM_IS_PLAYLIST (playlist));
2286
if (totem_playlist_has_next_mrl (playlist) == FALSE)
2405
if (totem_playlist_has_next_mrl (playlist) == FALSE) {
2288
2406
totem_playlist_set_at_start (playlist);
2292
2410
totem_playlist_unset_playing (playlist);
2294
if (playlist->priv->shuffle == FALSE)
2412
if (playlist->priv->shuffle == FALSE) {
2296
2413
gtk_tree_model_get_iter (playlist->priv->model,
2298
playlist->priv->current);
2415
playlist->priv->current);
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);