diff src/audacious/ui_playlist_widget.c @ 4728:ab79ddbdcf42

introduce new playlist widget
author Tomasz Mon <desowin@gmail.com>
date Thu, 17 Jul 2008 00:18:16 +0200
parents
children 5e70c200eb8d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audacious/ui_playlist_widget.c	Thu Jul 17 00:18:16 2008 +0200
@@ -0,0 +1,284 @@
+/*  Audacious - Cross-platform multimedia player
+ *  Copyright (C) 2008 Tomasz Moń <desowin@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; under version 3 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses>.
+ *
+ *  The Audacious team does not consider modular code linking to
+ *  Audacious or using our public API to be a derived work.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include "playlist.h"
+#include "playback.h"
+#include "strings.h"
+
+enum {
+    COLUMN_NUM = 0,
+    COLUMN_TEXT,
+    COLUMN_TIME,
+    COLUMN_WEIGHT,
+    N_COLUMNS
+};
+
+static void
+ui_playlist_widget_change_song(guint pos)
+{
+    playlist_set_position(playlist_get_active(), pos);
+
+    if (!playback_get_playing())
+        playback_initiate();
+}
+
+void
+ui_playlist_widget_set_current(GtkWidget *treeview, gint pos)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    gchar *p;
+
+    model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
+
+    gint old_pos = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(treeview), "current"));
+
+    if (old_pos != -1) {
+        p = g_strdup_printf("%d", old_pos);
+        path = gtk_tree_path_new_from_string(p);
+        gtk_tree_model_get_iter(model, &iter, path);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 3, PANGO_WEIGHT_NORMAL, -1);
+        g_free(p);
+        gtk_tree_path_free(path);
+    }
+
+    if (pos != -1) {
+        p = g_strdup_printf("%d", pos);
+        path = gtk_tree_path_new_from_string(p);
+        gtk_tree_model_get_iter(model, &iter, path);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 3, PANGO_WEIGHT_BOLD, -1);
+        g_free(p);
+        gtk_tree_path_free(path);
+    }
+
+    g_object_set_data(G_OBJECT(treeview), "current", GINT_TO_POINTER(pos));
+}
+
+static void
+ui_playlist_widget_jump(GtkTreeView * treeview, gpointer data)
+{
+    GtkTreeModel *model;
+    GtkTreeSelection *selection;
+    GtkTreeIter iter;
+    guint pos;
+
+    model = gtk_tree_view_get_model(treeview);
+    selection = gtk_tree_view_get_selection(treeview);
+
+    if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
+        return;
+
+    gtk_tree_model_get(model, &iter, 0, &pos, -1);
+
+    ui_playlist_widget_change_song(pos - 1);
+
+    ui_playlist_widget_set_current(GTK_WIDGET(treeview), pos);
+}
+
+static gboolean
+ui_playlist_widget_keypress_cb(GtkWidget * widget,
+                            GdkEventKey * event,
+                            gpointer data)
+{
+    switch (event->keyval) {
+    case GDK_KP_Enter:
+        ui_playlist_widget_jump(GTK_TREE_VIEW(widget), NULL);
+        return TRUE;
+    default:
+        return FALSE;
+    };
+}
+
+void
+ui_playlist_widget_update(GtkWidget *widget)
+{
+    guint row;
+    gboolean valid;
+
+    GList *playlist_glist;
+    gchar *desc_buf = NULL;
+    gchar *length = NULL;
+    GtkTreeIter iter;
+    Playlist *playlist;
+    GtkTreeModel *store;
+    GtkTreeView *tree = GTK_TREE_VIEW(widget);
+
+    store = gtk_tree_view_get_model(tree);
+    valid = gtk_tree_model_get_iter_first(store, &iter);
+
+    row = 1;
+    playlist = playlist_get_active();
+
+    for (playlist_glist = playlist->entries; playlist_glist;
+         playlist_glist = g_list_next(playlist_glist)) {
+        PlaylistEntry *entry = PLAYLIST_ENTRY(playlist_glist->data);
+
+        if (entry->title)
+            desc_buf = g_strdup(entry->title);
+        else {
+            gchar *realfn = NULL;
+            realfn = g_filename_from_uri(entry->filename, NULL, NULL);
+            if (strchr(realfn ? realfn : entry->filename, '/'))
+                desc_buf = str_assert_utf8(strrchr(realfn ? realfn : entry->filename, '/') + 1);
+            else
+                desc_buf = str_assert_utf8(realfn ? realfn : entry->filename);
+            g_free(realfn); realfn = NULL;
+        }
+
+        if (entry->length != -1) {
+            length = g_strdup_printf("%d:%-2.2d", entry->length / 60000, (entry->length / 1000) % 60);
+        }
+
+        if (!valid)
+            gtk_list_store_append(GTK_LIST_STORE(store), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(store), &iter,
+                           COLUMN_NUM, row, COLUMN_TEXT, desc_buf,
+                           COLUMN_TIME, length,
+                           COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL, -1);
+        row++;
+
+        g_free(desc_buf);
+        desc_buf = NULL;
+
+        if (length) g_free(length);
+        length = NULL;
+
+        valid = gtk_tree_model_iter_next(store, &iter);
+    }
+
+    /* remove additional rows */
+    while (valid) {
+        valid = gtk_list_store_remove(GTK_LIST_STORE(store), &iter);
+    }
+
+    ui_playlist_widget_set_current(widget, playlist_get_position(playlist));
+}
+
+static gboolean
+ui_playlist_widget_fill(gpointer treeview)
+{
+    GList *playlist_glist;
+    Playlist *playlist;
+    gchar *desc_buf = NULL;
+    gchar *length = NULL;
+    guint row;
+    GtkTreeIter iter;
+    GtkListStore *store = (GtkListStore*)gtk_tree_view_get_model( GTK_TREE_VIEW(treeview) );
+
+    /* detach model from treeview before fill */
+    g_object_ref(store);
+    gtk_tree_view_set_model( GTK_TREE_VIEW(treeview), NULL );
+
+    gtk_list_store_clear(store);
+
+    row = 1;
+    playlist = playlist_get_active();
+
+    PLAYLIST_LOCK(playlist);
+    for (playlist_glist = playlist->entries; playlist_glist;
+         playlist_glist = g_list_next(playlist_glist)) {
+
+        PlaylistEntry *entry = PLAYLIST_ENTRY(playlist_glist->data);
+
+        if (entry->title)
+            desc_buf = g_strdup(entry->title);
+        else {
+            gchar *realfn = NULL;
+            realfn = g_filename_from_uri(entry->filename, NULL, NULL);
+            if (strchr(realfn ? realfn : entry->filename, '/'))
+                desc_buf = str_assert_utf8(strrchr(realfn ? realfn : entry->filename, '/') + 1);
+            else
+                desc_buf = str_assert_utf8(realfn ? realfn : entry->filename);
+            g_free(realfn); realfn = NULL;
+        }
+
+        if (entry->length != -1) {
+            length = g_strdup_printf("%d:%-2.2d", entry->length / 60000, (entry->length / 1000) % 60);
+        }
+
+        gtk_list_store_append(GTK_LIST_STORE(store), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(store), &iter,
+                           COLUMN_NUM, row, COLUMN_TEXT, desc_buf,
+                           COLUMN_TIME, length,
+                           COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL, -1);
+        row++;
+
+        g_free(desc_buf);
+        desc_buf = NULL;
+
+        if (length) g_free(length);
+        length = NULL;
+    }
+    PLAYLIST_UNLOCK(playlist);
+
+    /* attach liststore to treeview */
+    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
+    g_object_unref(store);
+
+    return FALSE;
+}
+
+GtkWidget *
+ui_playlist_widget_new(void)
+{
+    GtkWidget *treeview;
+    GtkListStore *store;
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+
+    store = gtk_list_store_new(N_COLUMNS, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, PANGO_TYPE_WEIGHT);
+    treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+    g_object_unref(store);
+
+    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
+
+    column = gtk_tree_view_column_new();
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
+    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+    gtk_tree_view_column_set_spacing(column, 4);
+
+    renderer = gtk_cell_renderer_text_new();
+    gtk_tree_view_column_pack_start(column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes(column, renderer, "text", COLUMN_NUM, NULL);
+
+    renderer = gtk_cell_renderer_text_new();
+    gtk_tree_view_column_pack_start(column, renderer, TRUE);
+    gtk_tree_view_column_set_attributes(column, renderer, "text", COLUMN_TEXT, "weight", COLUMN_WEIGHT, NULL);
+
+    renderer = gtk_cell_renderer_text_new();
+    gtk_tree_view_column_pack_start(column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes(column, renderer, "text", COLUMN_TIME, NULL);
+
+    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+    g_signal_connect(treeview, "row-activated",
+                     G_CALLBACK(ui_playlist_widget_jump), NULL);
+
+    g_signal_connect(treeview, "key-press-event",
+                     G_CALLBACK(ui_playlist_widget_keypress_cb), NULL);
+
+    ui_playlist_widget_fill(treeview);
+
+    g_object_set_data(G_OBJECT(treeview), "current", GINT_TO_POINTER(-1));
+
+    return treeview;
+}