2012-03-20 08:30:00 -04:00
|
|
|
// Copyright (c) 2011 Bryan Schumaker
|
2012-08-30 13:58:46 -04:00
|
|
|
#include <libsaria/libsaria.h>
|
2012-03-20 08:30:00 -04:00
|
|
|
#include <libsaria/library.h>
|
2012-08-29 09:48:55 -04:00
|
|
|
#include <libsaria/format.h>
|
2012-03-26 20:02:33 -04:00
|
|
|
#include <libsaria/print.h>
|
2012-03-29 20:41:28 -04:00
|
|
|
#include <libsaria/deck.h>
|
2012-05-17 13:12:03 -04:00
|
|
|
#include <libsaria/ban.h>
|
2012-03-20 08:30:00 -04:00
|
|
|
|
2012-08-29 09:48:55 -04:00
|
|
|
#include <ocarina/ocarina.h>
|
|
|
|
|
2012-08-25 16:15:47 -04:00
|
|
|
#include <cstdio>
|
2012-08-29 09:48:55 -04:00
|
|
|
#include <sstream>
|
|
|
|
using namespace std;
|
2012-08-25 16:15:47 -04:00
|
|
|
|
2012-08-29 00:10:29 -04:00
|
|
|
struct PlaylistWidgets {
|
|
|
|
libsaria::Playlist *playlist;
|
|
|
|
GtkListStore *liststore;
|
2012-09-01 10:34:39 -04:00
|
|
|
GtkTreeView *treeview;
|
2012-08-29 00:10:29 -04:00
|
|
|
GtkTreeModel *filter;
|
|
|
|
GtkLabel *label;
|
2012-09-01 10:04:52 -04:00
|
|
|
GtkEntry *entry;
|
2012-08-29 00:10:29 -04:00
|
|
|
};
|
|
|
|
|
2012-09-01 10:18:46 -04:00
|
|
|
static PlaylistWidgets library_widgets;
|
|
|
|
static PlaylistWidgets recent_widgets;
|
|
|
|
static PlaylistWidgets banned_widgets;
|
2012-09-01 09:48:11 -04:00
|
|
|
static GtkWidget *focused_entry = NULL;
|
2012-08-29 00:10:29 -04:00
|
|
|
|
2012-09-01 09:59:17 -04:00
|
|
|
static string formatted(string str)
|
|
|
|
{
|
|
|
|
char *escaped = g_markup_escape_text(str.c_str(), -1);
|
|
|
|
string ret = escaped;
|
|
|
|
g_free(escaped);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct PlaylistWidgets *find_widgets(libsaria::Playlist *plist)
|
|
|
|
{
|
|
|
|
if (plist == library_widgets.playlist)
|
|
|
|
return &library_widgets;
|
|
|
|
else if (plist == recent_widgets.playlist)
|
|
|
|
return &recent_widgets;
|
|
|
|
else if (plist == banned_widgets.playlist)
|
|
|
|
return &banned_widgets;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-09-01 10:18:46 -04:00
|
|
|
static unsigned int tabs_size()
|
2012-09-01 09:59:17 -04:00
|
|
|
{
|
|
|
|
GtkNotebook *tabs = GTK_NOTEBOOK(get_widget("PlaylistTabs"));
|
2012-09-01 10:18:46 -04:00
|
|
|
return gtk_notebook_get_n_pages(tabs) - 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct PlaylistWidgets *find_nth_widgets(unsigned int n)
|
|
|
|
{
|
|
|
|
unsigned int size = tabs_size();
|
2012-09-01 09:59:17 -04:00
|
|
|
|
|
|
|
/* Dynamic playlists */
|
|
|
|
if (n < size)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
switch (n - size) {
|
|
|
|
case 0:
|
|
|
|
return &library_widgets;
|
|
|
|
case 1:
|
|
|
|
return &recent_widgets;
|
|
|
|
case 2:
|
|
|
|
return &banned_widgets;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct PlaylistWidgets *current_widgets()
|
|
|
|
{
|
|
|
|
GtkNotebook *tabs = GTK_NOTEBOOK(get_widget("PlaylistTabs"));
|
|
|
|
return find_nth_widgets(gtk_notebook_get_current_page(tabs));
|
|
|
|
}
|
|
|
|
|
|
|
|
static libsaria::Playlist *find_playlist(unsigned int n)
|
|
|
|
{
|
|
|
|
return find_nth_widgets(n)->playlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
static libsaria::Playlist *current_playlist()
|
|
|
|
{
|
|
|
|
return current_widgets()->playlist;
|
|
|
|
}
|
|
|
|
|
2012-09-01 10:18:46 -04:00
|
|
|
void playlist_switch_to(string &key)
|
|
|
|
{
|
|
|
|
GtkNotebook *tabs = GTK_NOTEBOOK(get_widget("PlaylistTabs"));
|
|
|
|
unsigned int size = tabs_size();
|
|
|
|
|
|
|
|
if (key == "l")
|
|
|
|
gtk_notebook_set_current_page(tabs, size);
|
|
|
|
else if (key == "r")
|
|
|
|
gtk_notebook_set_current_page(tabs, size + 1);
|
|
|
|
else if (key == "b")
|
|
|
|
gtk_notebook_set_current_page(tabs, size + 2);
|
|
|
|
}
|
|
|
|
|
2012-08-26 10:27:40 -04:00
|
|
|
static gboolean is_visible(GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
|
|
|
|
{
|
|
|
|
libsaria::Track *track;
|
|
|
|
libsaria::Playlist *plist = (libsaria::Playlist *)data;
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, iter, 0, &track, -1);
|
|
|
|
return plist->is_visible(track);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_filter(GtkWidget *entry, gpointer d)
|
|
|
|
{
|
|
|
|
string text = gtk_entry_get_text(GTK_ENTRY(entry));
|
|
|
|
libsaria::Playlist *plist = (libsaria::Playlist *)d;
|
|
|
|
plist->set_filter_text(text);
|
|
|
|
}
|
|
|
|
|
2012-09-01 09:48:11 -04:00
|
|
|
static gboolean on_focus_change(GtkWidget *entry, GdkEvent *event, gpointer data)
|
|
|
|
{
|
|
|
|
if (gtk_widget_is_focus(entry))
|
|
|
|
focused_entry = entry;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool playlist_entry_focused()
|
|
|
|
{
|
|
|
|
if (!focused_entry)
|
|
|
|
return false;
|
|
|
|
return gtk_widget_is_focus(focused_entry);
|
|
|
|
}
|
|
|
|
|
2012-09-01 10:04:52 -04:00
|
|
|
void playlist_focus_entry()
|
|
|
|
{
|
|
|
|
gtk_widget_grab_focus(GTK_WIDGET(current_widgets()->entry));
|
|
|
|
}
|
|
|
|
|
2012-09-01 10:34:39 -04:00
|
|
|
void playlist_focus_treeview()
|
|
|
|
{
|
|
|
|
gtk_widget_grab_focus(GTK_WIDGET(current_widgets()->treeview));
|
|
|
|
}
|
|
|
|
|
2012-08-26 09:31:38 -04:00
|
|
|
static void track_selected(GtkWidget *treeview, GtkTreePath *path,
|
|
|
|
GtkTreeViewColumn *col, gpointer data)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
libsaria::Track *track;
|
|
|
|
|
|
|
|
model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
|
|
|
|
gtk_tree_model_get_iter(model, &iter, path);
|
|
|
|
gtk_tree_model_get(model, &iter, 0, &track, -1);
|
|
|
|
track->load(true);
|
|
|
|
}
|
|
|
|
|
2012-08-29 09:59:46 -04:00
|
|
|
static void set_playlist_length(libsaria::Playlist *playlist)
|
|
|
|
{
|
|
|
|
stringstream stream;
|
|
|
|
unsigned int size = playlist->get_size();
|
|
|
|
stream << size << " song";
|
|
|
|
if (size != 1)
|
|
|
|
stream << "s";
|
|
|
|
if (size != 0)
|
|
|
|
stream << ": " << libsaria::length_string(playlist->get_length());
|
|
|
|
update_length_label(stream.str());
|
|
|
|
}
|
|
|
|
|
2012-08-30 09:57:31 -04:00
|
|
|
static void update_track(libsaria::Track *track, GtkListStore *liststore,
|
|
|
|
GtkTreeIter *iter)
|
2012-08-24 08:31:40 -04:00
|
|
|
{
|
2012-08-30 09:57:31 -04:00
|
|
|
gtk_list_store_set(liststore, iter,
|
2012-08-29 00:10:29 -04:00
|
|
|
0, track,
|
|
|
|
1, track->get_track(),
|
|
|
|
2, track->get_title().c_str(),
|
|
|
|
3, track->get_lenstr().c_str(),
|
|
|
|
4, track->get_artist().c_str(),
|
|
|
|
5, track->get_album().c_str(),
|
|
|
|
6, track->get_year(),
|
|
|
|
7, track->get_count(),
|
|
|
|
8, track->get_last_played().c_str(),
|
|
|
|
9, formatted(track->get_filepath()).c_str(),
|
|
|
|
-1);
|
2012-08-25 16:15:47 -04:00
|
|
|
}
|
2012-08-24 08:31:40 -04:00
|
|
|
|
2012-08-30 09:57:31 -04:00
|
|
|
static void playlist_add(libsaria::Playlist *plist, libsaria::Track *track,
|
|
|
|
unsigned int index)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
struct PlaylistWidgets *widgets = find_widgets(plist);
|
|
|
|
if (!widgets)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gtk_list_store_insert(widgets->liststore, &iter, index);
|
|
|
|
update_track(track, widgets->liststore, &iter);
|
|
|
|
}
|
|
|
|
|
2012-08-29 09:59:46 -04:00
|
|
|
static void playlist_rm(libsaria::Playlist *plist, unsigned int index)
|
2012-08-29 09:48:55 -04:00
|
|
|
{
|
2012-08-29 09:59:46 -04:00
|
|
|
GtkTreeIter iter;
|
|
|
|
PlaylistWidgets *widgets = find_widgets(plist);
|
|
|
|
gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(widgets->liststore), &iter, NULL, index);
|
|
|
|
gtk_list_store_remove(widgets->liststore, &iter);
|
|
|
|
if (plist == current_playlist())
|
|
|
|
set_playlist_length(plist);
|
2012-08-29 09:48:55 -04:00
|
|
|
}
|
|
|
|
|
2012-08-30 09:57:31 -04:00
|
|
|
static void playlist_update(libsaria::Playlist *plist, libsaria::Track *track,
|
|
|
|
unsigned int index)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
PlaylistWidgets *widgets = find_widgets(plist);
|
|
|
|
gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(widgets->liststore), &iter, NULL, index);
|
|
|
|
update_track(track, widgets->liststore, &iter);
|
|
|
|
}
|
|
|
|
|
2012-08-25 16:15:47 -04:00
|
|
|
static void set_playlist_size(libsaria::Playlist *plist)
|
|
|
|
{
|
|
|
|
char buf[11];
|
2012-08-29 00:10:29 -04:00
|
|
|
struct PlaylistWidgets *widgets = find_widgets(plist);
|
2012-08-29 09:48:55 -04:00
|
|
|
if (!widgets)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sprintf(buf, "%u", plist->get_size());
|
|
|
|
gtk_label_set_text(widgets->label, buf);
|
|
|
|
if (plist == current_playlist())
|
|
|
|
set_playlist_length(plist);
|
2012-08-24 08:31:40 -04:00
|
|
|
}
|
|
|
|
|
2012-08-26 10:27:40 -04:00
|
|
|
static void playlist_refilter(libsaria::Playlist *plist)
|
|
|
|
{
|
2012-08-29 00:10:29 -04:00
|
|
|
struct PlaylistWidgets *widgets = find_widgets(plist);
|
|
|
|
if (widgets)
|
|
|
|
gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(widgets->filter));
|
2012-08-26 10:27:40 -04:00
|
|
|
}
|
|
|
|
|
2012-08-24 08:31:40 -04:00
|
|
|
void update_playlist(notify_t event, libsaria::PlaylistNotification *data)
|
|
|
|
{
|
|
|
|
if (event == PLAYLIST_ADD)
|
|
|
|
playlist_add(data->plist, data->track, data->index);
|
2012-08-29 09:59:46 -04:00
|
|
|
else if (event == PLAYLIST_RM)
|
|
|
|
playlist_rm(data->plist, data->index);
|
2012-08-25 16:15:47 -04:00
|
|
|
else if (event == PLAYLIST_SIZE)
|
|
|
|
set_playlist_size(data->plist);
|
2012-08-26 10:27:40 -04:00
|
|
|
else if (event == PLAYLIST_FILTER)
|
|
|
|
playlist_refilter(data->plist);
|
2012-08-30 09:57:31 -04:00
|
|
|
else if (event == PLAYLIST_UPDATE)
|
|
|
|
playlist_update(data->plist, data->track, data->index);
|
2012-08-24 08:31:40 -04:00
|
|
|
}
|
2012-08-26 09:31:38 -04:00
|
|
|
|
2012-08-29 00:10:29 -04:00
|
|
|
static void init_playlist_tab(struct PlaylistWidgets *widgets,
|
|
|
|
libsaria::Playlist *playlist,
|
|
|
|
const string &list_name,
|
|
|
|
const string &view_name,
|
|
|
|
const string &label_name,
|
2012-08-26 15:42:04 -04:00
|
|
|
const string &entry_name)
|
2012-08-26 09:31:38 -04:00
|
|
|
{
|
2012-08-29 00:10:29 -04:00
|
|
|
widgets->playlist = playlist;
|
|
|
|
widgets->liststore = GTK_LIST_STORE(get_object(list_name));
|
2012-09-01 10:34:39 -04:00
|
|
|
widgets->treeview = GTK_TREE_VIEW(get_widget(view_name));
|
2012-08-29 00:10:29 -04:00
|
|
|
widgets->filter = gtk_tree_model_filter_new(
|
|
|
|
GTK_TREE_MODEL(widgets->liststore), NULL);
|
|
|
|
widgets->label = GTK_LABEL(get_widget(label_name));
|
2012-09-01 10:04:52 -04:00
|
|
|
widgets->entry = GTK_ENTRY(get_widget(entry_name));
|
2012-08-29 00:10:29 -04:00
|
|
|
|
2012-09-01 10:34:39 -04:00
|
|
|
gtk_tree_view_set_model(widgets->treeview, widgets->filter);
|
2012-08-29 00:10:29 -04:00
|
|
|
gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(widgets->filter),
|
|
|
|
is_visible, playlist, NULL);
|
2012-08-26 15:42:04 -04:00
|
|
|
|
|
|
|
connect_signal(view_name, "row-activated", G_CALLBACK(track_selected), NULL);
|
|
|
|
connect_signal(entry_name, "changed", G_CALLBACK(do_filter), playlist);
|
2012-09-01 09:48:11 -04:00
|
|
|
connect_signal(entry_name, "focus-in-event", G_CALLBACK(on_focus_change), NULL);
|
2012-08-26 15:42:04 -04:00
|
|
|
}
|
2012-08-26 10:27:40 -04:00
|
|
|
|
2012-08-29 09:48:55 -04:00
|
|
|
static void on_switch_page(GtkNotebook *tabs, gpointer page,
|
|
|
|
unsigned int page_num, gpointer data)
|
|
|
|
{
|
|
|
|
set_playlist_length(find_playlist(page_num));
|
|
|
|
}
|
|
|
|
|
2012-08-30 13:58:46 -04:00
|
|
|
static void on_click_open(GtkWidget *b, gpointer d)
|
|
|
|
{
|
|
|
|
string file = run_chooser("FileChooser");
|
|
|
|
if (file != "") {
|
|
|
|
println("Playing file: " + file);
|
|
|
|
libsaria::play_outside_song(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init_tab_action()
|
|
|
|
{
|
|
|
|
GtkWidget *box = gtk_vbox_new(FALSE, 0);
|
|
|
|
GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
|
|
|
|
GtkWidget *open = gtk_button_new();
|
|
|
|
|
|
|
|
gtk_button_set_image(GTK_BUTTON(open), img);
|
|
|
|
g_signal_connect(open, "clicked", G_CALLBACK(on_click_open), NULL);
|
|
|
|
|
|
|
|
gtk_box_pack_start(GTK_BOX(box), open, false, false, 0);
|
|
|
|
gtk_box_pack_start(GTK_BOX(box), get_widget("BanButton"), false, false, 0);
|
|
|
|
gtk_widget_show_all(box);
|
|
|
|
gtk_notebook_set_action_widget(GTK_NOTEBOOK(get_widget("PlaylistTabs")),
|
|
|
|
box, GTK_PACK_END);
|
|
|
|
}
|
|
|
|
|
2012-08-26 15:42:04 -04:00
|
|
|
void init_playlist()
|
|
|
|
{
|
2012-08-30 13:58:46 -04:00
|
|
|
init_tab_action();
|
2012-08-26 10:27:40 -04:00
|
|
|
|
2012-08-29 00:10:29 -04:00
|
|
|
init_playlist_tab(&library_widgets, libsaria::library::get_playlist(),
|
|
|
|
"LibraryPlist", "LibraryPlistView",
|
|
|
|
"LibrarySize", "LibraryEntry");
|
|
|
|
init_playlist_tab(&recent_widgets, libsaria::deck::get_recent_plist(),
|
|
|
|
"RecentPlist", "RecentView",
|
|
|
|
"RecentSize", "RecentEntry");
|
|
|
|
init_playlist_tab(&banned_widgets, libsaria::ban::get_banned_plist(),
|
|
|
|
"BannedPlist", "BannedView",
|
|
|
|
"BannedSize", "BannedEntry");
|
2012-08-29 09:48:55 -04:00
|
|
|
|
|
|
|
connect_signal("PlaylistTabs", "switch-page", G_CALLBACK(on_switch_page), NULL);
|
2012-08-26 09:31:38 -04:00
|
|
|
}
|