Compare commits
25 Commits
Author | SHA1 | Date |
---|---|---|
Anna Schumaker | 45d2422be3 | |
Anna Schumaker | 54138d8814 | |
Anna Schumaker | 6ab3cff28f | |
Anna Schumaker | 0972e027ed | |
Anna Schumaker | 77efa0c631 | |
Anna Schumaker | a9970c455f | |
Anna Schumaker | fc5e6eb043 | |
Anna Schumaker | a41652ab28 | |
Anna Schumaker | eca857cb3b | |
Anna Schumaker | d7fb67ed51 | |
Anna Schumaker | 7df129d533 | |
Anna Schumaker | a4cdac7f22 | |
Anna Schumaker | d5b0752497 | |
Anna Schumaker | 5fb46dc663 | |
Anna Schumaker | d149289e00 | |
Anna Schumaker | f167f968ba | |
Anna Schumaker | 94f3a7f387 | |
Anna Schumaker | 60e6e2a9eb | |
Anna Schumaker | 1836104f40 | |
Anna Schumaker | cd7364300e | |
Anna Schumaker | 994234caf2 | |
Anna Schumaker | af5bafb03e | |
Anna Schumaker | fd68cdf70a | |
Anna Schumaker | 8a2c631a9b | |
Anna Schumaker | e6ab06cf2b |
|
@ -10,8 +10,8 @@ option(CONFIG_TESTING_ARTWORK "Enable album artwork fetching tests" ON)
|
||||||
# Configure settings
|
# Configure settings
|
||||||
set(CONFIG_MAJOR 6)
|
set(CONFIG_MAJOR 6)
|
||||||
set(CONFIG_MINOR 5)
|
set(CONFIG_MINOR 5)
|
||||||
set(CONFIG_MICRO 8)
|
set(CONFIG_MICRO 10)
|
||||||
set(CONFIG_RC OFF)
|
set(CONFIG_RC ON)
|
||||||
|
|
||||||
set(CONFIG_VERSION "${CONFIG_MAJOR}.${CONFIG_MINOR}.${CONFIG_MICRO}")
|
set(CONFIG_VERSION "${CONFIG_MAJOR}.${CONFIG_MINOR}.${CONFIG_MICRO}")
|
||||||
|
|
||||||
|
|
2
PKGBUILD
2
PKGBUILD
|
@ -1,6 +1,6 @@
|
||||||
# Maintainer: Anna Schumaker <anna@nowheycreamery.com>
|
# Maintainer: Anna Schumaker <anna@nowheycreamery.com>
|
||||||
pkgname=ocarina
|
pkgname=ocarina
|
||||||
pkgver=6.5.8
|
pkgver=6.5.9
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="A simple GTK+ and GStreamer based music player."
|
pkgdesc="A simple GTK+ and GStreamer based music player."
|
||||||
url="http://www.nowheycreamery.com/"
|
url="http://www.nowheycreamery.com/"
|
||||||
|
|
11
core/audio.c
11
core/audio.c
|
@ -305,13 +305,20 @@ struct track *audio_prev()
|
||||||
return __audio_load(playlist_prev(), LOAD_PLAYING);
|
return __audio_load(playlist_prev(), LOAD_PLAYING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_pause_after(int n)
|
bool audio_pause_after(int n)
|
||||||
{
|
{
|
||||||
if (n != audio_pause_count) {
|
if (n >= -1 && n != audio_pause_count) {
|
||||||
audio_pause_count = n;
|
audio_pause_count = n;
|
||||||
if (audio_cb)
|
if (audio_cb)
|
||||||
audio_cb->audio_cb_config_pause(audio_pause_count);
|
audio_cb->audio_cb_config_pause(audio_pause_count);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int audio_get_pause_count(void)
|
||||||
|
{
|
||||||
|
return audio_pause_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING
|
#ifdef CONFIG_TESTING
|
||||||
|
|
|
@ -208,6 +208,20 @@ bool playlist_sort(struct playlist *playlist, enum compare_t sort)
|
||||||
return g_slist_length(playlist->pl_sort) > 0;
|
return g_slist_length(playlist->pl_sort) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool playlist_rearrange(struct playlist *playlist, unsigned int old_pos,
|
||||||
|
unsigned int new_pos)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
if (!playlist || !playlist->pl_ops->pl_rearrange)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ret = playlist->pl_ops->pl_rearrange(playlist, old_pos, new_pos);
|
||||||
|
if (ret && playlist->pl_type < PL_MAX_TYPE)
|
||||||
|
playlist_types[playlist->pl_type]->pl_save();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void playlist_set_search(struct playlist *playlist, const gchar *text)
|
void playlist_set_search(struct playlist *playlist, const gchar *text)
|
||||||
{
|
{
|
||||||
gchar **tokens = NULL;
|
gchar **tokens = NULL;
|
||||||
|
|
|
@ -11,13 +11,15 @@ static struct playlist_ops pl_artist_ops = {
|
||||||
.pl_can_select = playlist_generic_can_select,
|
.pl_can_select = playlist_generic_can_select,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct playlist *__artist_pl_alloc(struct artist *artist)
|
static struct playlist *__artist_pl_alloc(struct artist *artist)
|
||||||
{
|
{
|
||||||
return playlist_generic_alloc(artist->ar_name, PL_ARTIST,
|
return playlist_generic_alloc(artist->ar_name, PL_ARTIST,
|
||||||
artist_index(artist), &pl_artist_ops);
|
artist_index(artist), &pl_artist_ops,
|
||||||
|
3, COMPARE_YEAR, COMPARE_ALBUM, COMPARE_TRACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __artist_pl_add(void *data)
|
static bool __artist_pl_add(void *data)
|
||||||
|
|
|
@ -38,26 +38,32 @@ void playlist_generic_set_callbacks(struct playlist_callbacks *cb)
|
||||||
callbacks = cb;
|
callbacks = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void playlist_generic_init(struct playlist *playlist)
|
static void __playlist_generic_vinit(struct playlist *playlist,
|
||||||
|
unsigned int nargs, va_list argp)
|
||||||
{
|
{
|
||||||
if (playlist) {
|
unsigned int i;
|
||||||
g_queue_init(&playlist->pl_tracks);
|
|
||||||
playlist->pl_length = 0;
|
if (!playlist)
|
||||||
playlist->pl_random = false;
|
return;
|
||||||
playlist->pl_current = NULL;
|
|
||||||
playlist->pl_sort = NULL;
|
g_queue_init(&playlist->pl_tracks);
|
||||||
playlist->pl_search = NULL;
|
playlist->pl_length = 0;
|
||||||
}
|
playlist->pl_random = false;
|
||||||
|
playlist->pl_current = NULL;
|
||||||
|
playlist->pl_sort = NULL;
|
||||||
|
playlist->pl_search = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < nargs; i++)
|
||||||
|
playlist_generic_sort(playlist, va_arg(argp, unsigned int));
|
||||||
}
|
}
|
||||||
|
|
||||||
void playlist_generic_init_sorted(struct playlist *playlist)
|
void playlist_generic_init(struct playlist *playlist, unsigned int nargs, ...)
|
||||||
{
|
{
|
||||||
if (playlist) {
|
va_list argp;
|
||||||
playlist_generic_init(playlist);
|
|
||||||
playlist_generic_sort(playlist, COMPARE_ARTIST);
|
va_start(argp, nargs);
|
||||||
playlist_generic_sort(playlist, COMPARE_YEAR);
|
__playlist_generic_vinit(playlist, nargs, argp);
|
||||||
playlist_generic_sort(playlist, COMPARE_TRACK);
|
va_end(argp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void playlist_generic_deinit(struct playlist *playlist)
|
void playlist_generic_deinit(struct playlist *playlist)
|
||||||
|
@ -72,18 +78,23 @@ void playlist_generic_deinit(struct playlist *playlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct playlist *playlist_generic_alloc(gchar *name, enum playlist_type_t type,
|
struct playlist *playlist_generic_alloc(gchar *name, enum playlist_type_t type,
|
||||||
unsigned int id, struct playlist_ops *ops)
|
unsigned int id, struct playlist_ops *ops,
|
||||||
|
unsigned int nargs, ...)
|
||||||
{
|
{
|
||||||
struct playlist *playlist = g_malloc(sizeof(struct playlist));
|
struct playlist *playlist = g_malloc(sizeof(struct playlist));
|
||||||
|
va_list argp;
|
||||||
|
|
||||||
playlist->pl_name = name;
|
playlist->pl_name = name;
|
||||||
playlist->pl_type = type;
|
playlist->pl_type = type;
|
||||||
playlist->pl_id = id;
|
playlist->pl_id = id;
|
||||||
playlist->pl_ops = ops;
|
playlist->pl_ops = ops;
|
||||||
|
|
||||||
playlist_generic_init_sorted(playlist);
|
va_start(argp, nargs);
|
||||||
|
__playlist_generic_vinit(playlist, nargs, argp);
|
||||||
if (callbacks)
|
if (callbacks)
|
||||||
callbacks->pl_cb_alloc(playlist);
|
callbacks->pl_cb_alloc(playlist);
|
||||||
|
va_end(argp);
|
||||||
|
|
||||||
return playlist;
|
return playlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +280,22 @@ void playlist_generic_resort(struct playlist *playlist)
|
||||||
playlist_generic_update(playlist, NULL);
|
playlist_generic_update(playlist, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool playlist_generic_rearrange(struct playlist *playlist, unsigned int old_pos,
|
||||||
|
unsigned int new_pos)
|
||||||
|
{
|
||||||
|
GList *nth;
|
||||||
|
|
||||||
|
if (old_pos == new_pos || old_pos >= playlist_size(playlist) ||
|
||||||
|
new_pos > playlist_size(playlist))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
playlist_clear_sort(playlist);
|
||||||
|
nth = g_queue_pop_nth_link(&playlist->pl_tracks, old_pos);
|
||||||
|
g_queue_push_nth_link(&playlist->pl_tracks, new_pos, nth);
|
||||||
|
playlist_generic_update(playlist, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
struct track *playlist_generic_next(struct playlist *playlist)
|
struct track *playlist_generic_next(struct playlist *playlist)
|
||||||
{
|
{
|
||||||
unsigned int pos, size = playlist_size(playlist);
|
unsigned int pos, size = playlist_size(playlist);
|
||||||
|
|
|
@ -22,7 +22,9 @@ static struct playlist_ops pl_library_ops;
|
||||||
static struct playlist *__lib_pl_alloc(struct library *library)
|
static struct playlist *__lib_pl_alloc(struct library *library)
|
||||||
{
|
{
|
||||||
return playlist_generic_alloc(library->li_path, PL_LIBRARY,
|
return playlist_generic_alloc(library->li_path, PL_LIBRARY,
|
||||||
library_index(library), &pl_library_ops);
|
library_index(library), &pl_library_ops,
|
||||||
|
4, COMPARE_ARTIST, COMPARE_YEAR,
|
||||||
|
COMPARE_ALBUM, COMPARE_TRACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __lib_pl_add(void *data)
|
static bool __lib_pl_add(void *data)
|
||||||
|
@ -179,6 +181,7 @@ static struct playlist_ops pl_library_ops = {
|
||||||
.pl_delete = pl_library_delete,
|
.pl_delete = pl_library_delete,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ static struct playlist_ops favorites_ops = {
|
||||||
.pl_remove = playlist_generic_remove,
|
.pl_remove = playlist_generic_remove,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,6 +133,7 @@ static struct playlist_ops hidden_ops = {
|
||||||
.pl_remove = sys_pl_hidden_remove,
|
.pl_remove = sys_pl_hidden_remove,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -183,6 +185,7 @@ static struct playlist_ops queued_ops = {
|
||||||
.pl_remove = sys_pl_queued_remove,
|
.pl_remove = sys_pl_queued_remove,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,6 +210,7 @@ static struct playlist_ops collection_ops = {
|
||||||
.pl_remove = sys_pl_hidden_add,
|
.pl_remove = sys_pl_hidden_add,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,6 +236,7 @@ static struct playlist_ops dynamic_ops = {
|
||||||
.pl_can_select = playlist_generic_can_select,
|
.pl_can_select = playlist_generic_can_select,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -414,7 +419,7 @@ void pl_system_init(void)
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case SYS_PL_QUEUED:
|
case SYS_PL_QUEUED:
|
||||||
case SYS_PL_HISTORY:
|
case SYS_PL_HISTORY:
|
||||||
playlist_generic_init(playlist);
|
playlist_generic_init(playlist, 0);
|
||||||
break;
|
break;
|
||||||
case SYS_PL_COLLECTION:
|
case SYS_PL_COLLECTION:
|
||||||
case SYS_PL_UNPLAYED:
|
case SYS_PL_UNPLAYED:
|
||||||
|
@ -423,7 +428,8 @@ void pl_system_init(void)
|
||||||
sys_pl_update(playlist);
|
sys_pl_update(playlist);
|
||||||
case SYS_PL_FAVORITES:
|
case SYS_PL_FAVORITES:
|
||||||
case SYS_PL_HIDDEN:
|
case SYS_PL_HIDDEN:
|
||||||
playlist_generic_init_sorted(playlist);
|
playlist_generic_init(playlist, 4, COMPARE_ARTIST,
|
||||||
|
COMPARE_YEAR, COMPARE_ALBUM, COMPARE_TRACK);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ static struct user_playlist *__user_db_alloc(gchar *name, unsigned int index)
|
||||||
playlist->pl_playlist.pl_type = PL_USER;
|
playlist->pl_playlist.pl_type = PL_USER;
|
||||||
playlist->pl_playlist.pl_id = index;
|
playlist->pl_playlist.pl_id = index;
|
||||||
playlist->pl_playlist.pl_ops = &user_ops;
|
playlist->pl_playlist.pl_ops = &user_ops;
|
||||||
playlist_generic_init_sorted(&playlist->pl_playlist);
|
playlist_generic_init(&playlist->pl_playlist, 0);
|
||||||
|
|
||||||
return playlist;
|
return playlist;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ static struct playlist_ops user_ops = {
|
||||||
.pl_remove = playlist_generic_remove,
|
.pl_remove = playlist_generic_remove,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
100
gui/audio.c
100
gui/audio.c
|
@ -9,7 +9,8 @@
|
||||||
#include <gui/treeview.h>
|
#include <gui/treeview.h>
|
||||||
#include <gui/window.h>
|
#include <gui/window.h>
|
||||||
|
|
||||||
static guint audio_timeout = 0;
|
static guint audio_timeout = 0;
|
||||||
|
static guint popover_timeout = 0;
|
||||||
|
|
||||||
static inline void __gui_audio_set_label_markup(GtkLabel *label,
|
static inline void __gui_audio_set_label_markup(GtkLabel *label,
|
||||||
const gchar *size,
|
const gchar *size,
|
||||||
|
@ -42,16 +43,40 @@ static void __gui_audio_load(struct track *track)
|
||||||
g_free(duration);
|
g_free(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __gui_audio_set_pause_text(int n, GstState state)
|
||||||
|
{
|
||||||
|
bool sensitive = true;
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
if (n == -1) {
|
||||||
|
sensitive = false;
|
||||||
|
if (state == GST_STATE_PLAYING)
|
||||||
|
text = g_strdup("Keep playing");
|
||||||
|
else
|
||||||
|
text = g_strdup("Paused");
|
||||||
|
} else if (n == 0)
|
||||||
|
text = g_strdup("Pause after this track");
|
||||||
|
else if (n == 1)
|
||||||
|
text = g_strdup("Pause after next track");
|
||||||
|
else
|
||||||
|
text = g_strdup_printf("Pause after %d tracks", n);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive(GTK_WIDGET(gui_pause_down()), sensitive);
|
||||||
|
gtk_entry_set_text(gui_pause_entry(), text);
|
||||||
|
g_free(text);
|
||||||
|
}
|
||||||
|
|
||||||
static void __gui_audio_change_state(GstState state)
|
static void __gui_audio_change_state(GstState state)
|
||||||
{
|
{
|
||||||
bool playing = (state == GST_STATE_PLAYING);
|
bool playing = (state == GST_STATE_PLAYING);
|
||||||
gtk_widget_set_visible(GTK_WIDGET(gui_play_button()), !playing);
|
gtk_widget_set_visible(GTK_WIDGET(gui_play_button()), !playing);
|
||||||
gtk_widget_set_visible(GTK_WIDGET(gui_pause_button()), playing);
|
gtk_widget_set_visible(GTK_WIDGET(gui_pause_button()), playing);
|
||||||
|
__gui_audio_set_pause_text(audio_get_pause_count(), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __gui_audio_config_pause(int n)
|
static void __gui_audio_config_pause(int n)
|
||||||
{
|
{
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(gui_pause_after()), n + 1);
|
__gui_audio_set_pause_text(n, audio_cur_state());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,9 +87,68 @@ struct audio_callbacks audio_cb = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void __gui_audio_pause_changed(GtkComboBox *combo, gpointer data)
|
void __gui_audio_pause(GtkButton *button, gpointer data)
|
||||||
{
|
{
|
||||||
audio_pause_after(gtk_combo_box_get_active(combo) - 1);
|
audio_pause();
|
||||||
|
if (audio_get_pause_count() > -1) {
|
||||||
|
gtk_popover_popup(gui_pause_popover());
|
||||||
|
popover_timeout = g_timeout_add_seconds(10,
|
||||||
|
gui_audio_popover_timeout, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __gui_audio_pause_change_text(GtkEntry *entry, gpointer data)
|
||||||
|
{
|
||||||
|
const gchar *text = gtk_entry_get_text(entry);
|
||||||
|
int n = audio_get_pause_count();
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (g_str_match_string("Keep", text, true))
|
||||||
|
n = -1;
|
||||||
|
else if (g_str_match_string("This", text, true))
|
||||||
|
n = 0;
|
||||||
|
else if (g_str_match_string("Next", text, true))
|
||||||
|
n = 1;
|
||||||
|
else {
|
||||||
|
for (i = 0; text[i] != '\0'; i++) {
|
||||||
|
if (!g_ascii_isdigit(text[i]))
|
||||||
|
continue;
|
||||||
|
if (i > 0 && text[i-1] == '-')
|
||||||
|
i -= 1;
|
||||||
|
n = g_strtod(text + i, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!audio_pause_after(n))
|
||||||
|
__gui_audio_set_pause_text(audio_get_pause_count(), audio_cur_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
void __gui_audio_pause_inc(GtkButton *button, gpointer data)
|
||||||
|
{
|
||||||
|
audio_pause_after(audio_get_pause_count() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __gui_audio_pause_dec(GtkButton *button, gpointer data)
|
||||||
|
{
|
||||||
|
audio_pause_after(audio_get_pause_count() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __gui_audio_pause_popover_popdown(GtkButton *button, gpointer data)
|
||||||
|
{
|
||||||
|
gtk_popover_popdown(gui_pause_popover());
|
||||||
|
#ifdef CONFIG_TESTING
|
||||||
|
gtk_widget_hide(GTK_WIDGET(gui_pause_popover()));
|
||||||
|
#endif /* CONFIG_TESTING */
|
||||||
|
|
||||||
|
g_source_remove(popover_timeout);
|
||||||
|
popover_timeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __gui_audio_pause_popover_clear(GtkButton *button, gpointer data)
|
||||||
|
{
|
||||||
|
audio_pause_after(-1);
|
||||||
|
__gui_audio_pause_popover_popdown(button, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __gui_audio_seek(GtkRange *range, GtkScrollType type,
|
void __gui_audio_seek(GtkRange *range, GtkScrollType type,
|
||||||
|
@ -98,6 +182,8 @@ void gui_audio_init()
|
||||||
void gui_audio_deinit()
|
void gui_audio_deinit()
|
||||||
{
|
{
|
||||||
g_source_remove(audio_timeout);
|
g_source_remove(audio_timeout);
|
||||||
|
if (popover_timeout > 0)
|
||||||
|
g_source_remove(popover_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
int gui_audio_timeout(gpointer data)
|
int gui_audio_timeout(gpointer data)
|
||||||
|
@ -111,3 +197,9 @@ int gui_audio_timeout(gpointer data)
|
||||||
g_free(position);
|
g_free(position);
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gui_audio_popover_timeout(gpointer data)
|
||||||
|
{
|
||||||
|
__gui_audio_pause_popover_popdown(NULL, data);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
|
@ -134,3 +134,9 @@ GtkTreePath *gui_filter_path_from_index(unsigned int index)
|
||||||
gtk_tree_path_free(real);
|
gtk_tree_path_free(real);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gui_filter_refilter(struct playlist *playlist)
|
||||||
|
{
|
||||||
|
if (!playlist || playlist == gui_model_get_playlist())
|
||||||
|
gtk_tree_model_filter_refilter(gui_filter_get());
|
||||||
|
}
|
||||||
|
|
42
gui/model.c
42
gui/model.c
|
@ -28,6 +28,12 @@ static GType gui_model_columns[GUI_MODEL_N_COLUMNS] = {
|
||||||
[GUI_MODEL_FONT] = G_TYPE_STRING,
|
[GUI_MODEL_FONT] = G_TYPE_STRING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const GtkTargetEntry gui_model_drag_targets[] = {
|
||||||
|
{ GUI_DRAG_DATA, GTK_TARGET_SAME_APP, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned int gui_model_n_targets = G_N_ELEMENTS(gui_model_drag_targets);
|
||||||
|
|
||||||
static GtkTreeModelFlags __gui_model_get_flags(GtkTreeModel *model)
|
static GtkTreeModelFlags __gui_model_get_flags(GtkTreeModel *model)
|
||||||
{
|
{
|
||||||
return GTK_TREE_MODEL_LIST_ONLY;
|
return GTK_TREE_MODEL_LIST_ONLY;
|
||||||
|
@ -169,6 +175,27 @@ static gboolean __gui_model_iter_parent(GtkTreeModel *model, GtkTreeIter *iter,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean __gui_model_drag_data_get(GtkTreeDragSource *drag_source,
|
||||||
|
GtkTreePath *path,
|
||||||
|
GtkSelectionData *selection_data)
|
||||||
|
{
|
||||||
|
struct gui_model_drag_data *data = g_malloc(sizeof(*data));
|
||||||
|
|
||||||
|
data->drag_row = gtk_tree_path_get_indices(path)[0];
|
||||||
|
data->drag_track = gui_model_path_get_track(path);
|
||||||
|
|
||||||
|
gtk_selection_data_set(selection_data, gdk_atom_intern(GUI_DRAG_DATA, false),
|
||||||
|
8 /* bytes */, (void *)data, sizeof(*data));
|
||||||
|
g_free(data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean __gui_model_drag_data_delete(GtkTreeDragSource *drag_source,
|
||||||
|
GtkTreePath *path)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void __gui_model_init(GuiModel *model)
|
static void __gui_model_init(GuiModel *model)
|
||||||
{
|
{
|
||||||
model->gm_stamp = g_random_int();
|
model->gm_stamp = g_random_int();
|
||||||
|
@ -203,6 +230,12 @@ static void __gui_tree_model_init(GtkTreeModelIface *iface)
|
||||||
iface->iter_parent = __gui_model_iter_parent;
|
iface->iter_parent = __gui_model_iter_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __gui_drag_source_init(GtkTreeDragSourceIface *iface)
|
||||||
|
{
|
||||||
|
iface->drag_data_get = __gui_model_drag_data_get;
|
||||||
|
iface->drag_data_delete = __gui_model_drag_data_delete;
|
||||||
|
}
|
||||||
|
|
||||||
static const GTypeInfo gui_model_type_info = {
|
static const GTypeInfo gui_model_type_info = {
|
||||||
.class_size = sizeof(GuiModelClass),
|
.class_size = sizeof(GuiModelClass),
|
||||||
.base_init = NULL,
|
.base_init = NULL,
|
||||||
|
@ -221,6 +254,12 @@ static const GInterfaceInfo gui_tree_model = {
|
||||||
.interface_data = NULL,
|
.interface_data = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const GInterfaceInfo gui_drag_source = {
|
||||||
|
.interface_init = (GInterfaceInitFunc)__gui_drag_source_init,
|
||||||
|
.interface_finalize = NULL,
|
||||||
|
.interface_data = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void gui_model_init(void)
|
void gui_model_init(void)
|
||||||
{
|
{
|
||||||
|
@ -229,6 +268,9 @@ void gui_model_init(void)
|
||||||
(GTypeFlags)0);
|
(GTypeFlags)0);
|
||||||
g_type_add_interface_static(gui_model_type, GTK_TYPE_TREE_MODEL,
|
g_type_add_interface_static(gui_model_type, GTK_TYPE_TREE_MODEL,
|
||||||
&gui_tree_model);
|
&gui_tree_model);
|
||||||
|
g_type_add_interface_static(gui_model_type, GTK_TYPE_TREE_DRAG_SOURCE,
|
||||||
|
&gui_drag_source);
|
||||||
|
|
||||||
|
|
||||||
gui_model = g_object_new(gui_model_type, NULL);
|
gui_model = g_object_new(gui_model_type, NULL);
|
||||||
g_assert(gui_model != NULL);
|
g_assert(gui_model != NULL);
|
||||||
|
|
|
@ -37,6 +37,7 @@ static void __gui_playlist_alloc(struct playlist *playlist)
|
||||||
static void __gui_playlist_added(struct playlist *playlist, struct track *track)
|
static void __gui_playlist_added(struct playlist *playlist, struct track *track)
|
||||||
{
|
{
|
||||||
gui_model_add(playlist, track);
|
gui_model_add(playlist, track);
|
||||||
|
gui_filter_refilter(playlist);
|
||||||
__gui_playlist_update_size(playlist);
|
__gui_playlist_update_size(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +208,31 @@ void __gui_playlist_row_expanded(GtkTreeView *treeview, GtkTreeIter *iter,
|
||||||
gui_sidebar_filter_row_expanded(iter, true);
|
gui_sidebar_filter_row_expanded(iter, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __gui_playlist_drag_data_received(GtkTreeView *treeview, GdkDragContext *context,
|
||||||
|
gint x, gint y, GtkSelectionData *data,
|
||||||
|
guint info, guint time, gpointer user_data)
|
||||||
|
{
|
||||||
|
struct playlist *playlist;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
if (gui_sidebar_iter_from_xy(x, y, &iter))
|
||||||
|
playlist = gui_sidebar_iter_playlist(&iter);
|
||||||
|
if (!playlist)
|
||||||
|
playlist = gui_pl_user_add_dialog();
|
||||||
|
if (!playlist)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (playlist == playlist_lookup(PL_SYSTEM, "Collection") &&
|
||||||
|
gui_model_get_playlist() == playlist_lookup(PL_SYSTEM, "Hidden"))
|
||||||
|
__gui_playlist_delete(NULL, NULL);
|
||||||
|
else if (playlist != playlist_lookup(PL_SYSTEM, "History"))
|
||||||
|
__gui_playlist_add_selected_to(playlist);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_signal_stop_emission_by_name(treeview, "drag_data_received");
|
||||||
|
gtk_drag_finish(context, true, true, time);
|
||||||
|
}
|
||||||
|
|
||||||
bool __gui_playlist_init_idle()
|
bool __gui_playlist_init_idle()
|
||||||
{
|
{
|
||||||
struct playlist *playlist = playlist_current();
|
struct playlist *playlist = playlist_current();
|
||||||
|
|
|
@ -256,6 +256,10 @@ void gui_sidebar_init()
|
||||||
GtkTreeSelection *selection;
|
GtkTreeSelection *selection;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
gtk_tree_view_enable_model_drag_dest(gui_sidebar_treeview(),
|
||||||
|
gui_model_drag_targets, gui_model_n_targets,
|
||||||
|
GDK_ACTION_MOVE);
|
||||||
|
|
||||||
if (!gui_sidebar_iter_first(&iter)) {
|
if (!gui_sidebar_iter_first(&iter)) {
|
||||||
__gui_sidebar_add_header(&iter, "Playlists", "emblem-documents");
|
__gui_sidebar_add_header(&iter, "Playlists", "emblem-documents");
|
||||||
__gui_sidebar_add_header(&iter, "Dynamic", "emblem-generic");
|
__gui_sidebar_add_header(&iter, "Dynamic", "emblem-generic");
|
||||||
|
@ -486,3 +490,19 @@ gboolean gui_sidebar_iter_from_string(const gchar *path, GtkTreeIter *child)
|
||||||
__gui_sidebar_filter_iter_convert(&iter, child);
|
__gui_sidebar_filter_iter_convert(&iter, child);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean gui_sidebar_iter_from_xy(gint x, gint y, GtkTreeIter *child)
|
||||||
|
{
|
||||||
|
GtkTreeModel *model = GTK_TREE_MODEL(gui_sidebar_filter());
|
||||||
|
GtkTreePath *path;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
if (!gtk_tree_view_get_path_at_pos(gui_sidebar_treeview(), x, y,
|
||||||
|
&path, NULL, NULL, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
gtk_tree_model_get_iter(model, &iter, path);
|
||||||
|
__gui_sidebar_filter_iter_convert(&iter, child);
|
||||||
|
gtk_tree_path_free(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -160,6 +160,43 @@ void __gui_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path,
|
||||||
can_scroll = true;
|
can_scroll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __gui_treeview_drag_data_received(GtkTreeView *treeview, GdkDragContext *context,
|
||||||
|
gint x, gint y, GtkSelectionData *data,
|
||||||
|
guint info, guint time, gpointer user_data)
|
||||||
|
{
|
||||||
|
struct gui_model_drag_data *drag_data;
|
||||||
|
unsigned int to, from;
|
||||||
|
GtkTreePath *path;
|
||||||
|
|
||||||
|
drag_data = (void *)gtk_selection_data_get_data(data);
|
||||||
|
if (gtk_tree_view_get_path_at_pos(gui_treeview(), x, y,
|
||||||
|
&path, NULL, NULL, NULL))
|
||||||
|
gtk_tree_path_prev(path);
|
||||||
|
else if (!gtk_tree_view_get_visible_range(gui_treeview(), NULL, &path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
from = drag_data->drag_row;
|
||||||
|
to = gui_filter_path_get_index(path);
|
||||||
|
|
||||||
|
if (playlist_rearrange(gui_model_get_playlist(), from, to)) {
|
||||||
|
gtk_tree_selection_unselect_all(gui_treeview_selection());
|
||||||
|
gtk_tree_selection_select_path(gui_treeview_selection(), path);
|
||||||
|
__gui_treeview_set_sort_indicators();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_stop_emission_by_name(treeview, "drag_data_received");
|
||||||
|
gtk_drag_finish(context, true, true, time);
|
||||||
|
gtk_tree_path_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __gui_treeview_drag_drop(GtkTreeView *treeview, GdkDragContext *context,
|
||||||
|
gint x, gint y, guint time, gpointer user_data)
|
||||||
|
{
|
||||||
|
gtk_drag_get_data(GTK_WIDGET(treeview), context,
|
||||||
|
gdk_atom_intern(GUI_DRAG_DATA, false), time);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void gui_treeview_init()
|
void gui_treeview_init()
|
||||||
{
|
{
|
||||||
GtkTreeViewColumn *col;
|
GtkTreeViewColumn *col;
|
||||||
|
@ -167,6 +204,12 @@ void gui_treeview_init()
|
||||||
|
|
||||||
gtk_tree_view_set_model(gui_treeview(),
|
gtk_tree_view_set_model(gui_treeview(),
|
||||||
GTK_TREE_MODEL(gui_filter_get()));
|
GTK_TREE_MODEL(gui_filter_get()));
|
||||||
|
gtk_tree_view_enable_model_drag_source(gui_treeview(), GDK_BUTTON1_MASK,
|
||||||
|
gui_model_drag_targets, gui_model_n_targets,
|
||||||
|
GDK_ACTION_MOVE);
|
||||||
|
gtk_tree_view_enable_model_drag_dest(gui_treeview(),
|
||||||
|
gui_model_drag_targets, gui_model_n_targets,
|
||||||
|
GDK_ACTION_MOVE);
|
||||||
|
|
||||||
for (i = 0; i < GUI_MODEL_N_COLUMNS; i++) {
|
for (i = 0; i < GUI_MODEL_N_COLUMNS; i++) {
|
||||||
col = gtk_tree_view_get_column(gui_treeview(), i);
|
col = gtk_tree_view_get_column(gui_treeview(), i);
|
||||||
|
@ -218,26 +261,22 @@ void gui_treeview_scroll()
|
||||||
|
|
||||||
void gui_treeview_select_path_at_pos(unsigned int x, unsigned int y)
|
void gui_treeview_select_path_at_pos(unsigned int x, unsigned int y)
|
||||||
{
|
{
|
||||||
GtkTreeSelection *selection;
|
GtkTreePath *path;
|
||||||
GtkTreePath *path;
|
|
||||||
|
|
||||||
selection = gtk_tree_view_get_selection(gui_treeview());
|
|
||||||
if (gtk_tree_view_get_path_at_pos(gui_treeview(), x, y,
|
if (gtk_tree_view_get_path_at_pos(gui_treeview(), x, y,
|
||||||
&path, NULL, NULL, NULL))
|
&path, NULL, NULL, NULL))
|
||||||
{
|
{
|
||||||
gtk_tree_selection_select_path(selection, path);
|
gtk_tree_selection_select_path(gui_treeview_selection(), path);
|
||||||
gtk_tree_path_free(path);
|
gtk_tree_path_free(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *gui_treeview_list_selected_tracks(void)
|
GList *gui_treeview_list_selected_tracks(void)
|
||||||
{
|
{
|
||||||
GList *rows, *cur, *list = NULL;
|
GtkTreeSelection *selection = gui_treeview_selection();
|
||||||
GtkTreeSelection *selection;
|
GList *rows = gtk_tree_selection_get_selected_rows(selection, NULL);
|
||||||
|
GList *cur = g_list_first(rows);
|
||||||
selection = gtk_tree_view_get_selection(gui_treeview());
|
GList *list = NULL;
|
||||||
rows = gtk_tree_selection_get_selected_rows(selection, NULL);
|
|
||||||
cur = g_list_first(rows);
|
|
||||||
|
|
||||||
while (cur) {
|
while (cur) {
|
||||||
list = g_list_append(list, gui_filter_path_get_track(cur->data));
|
list = g_list_append(list, gui_filter_path_get_track(cur->data));
|
||||||
|
|
|
@ -73,8 +73,12 @@ struct track *audio_next();
|
||||||
/* Called to load the previous track. */
|
/* Called to load the previous track. */
|
||||||
struct track *audio_prev();
|
struct track *audio_prev();
|
||||||
|
|
||||||
/* Called to configure automatic pausing. */
|
/*
|
||||||
void audio_pause_after(int);
|
* Called to configure automatic pausing.
|
||||||
|
* Returns true if the value has been changed.
|
||||||
|
*/
|
||||||
|
bool audio_pause_after(int);
|
||||||
|
int audio_get_pause_count(void);
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING
|
#ifdef CONFIG_TESTING
|
||||||
void test_audio_eos();
|
void test_audio_eos();
|
||||||
|
|
|
@ -71,6 +71,9 @@ void playlist_set_random(struct playlist *, bool);
|
||||||
/* Called to change the sort order of the playlist. */
|
/* Called to change the sort order of the playlist. */
|
||||||
bool playlist_sort(struct playlist *, enum compare_t);
|
bool playlist_sort(struct playlist *, enum compare_t);
|
||||||
|
|
||||||
|
/* Called to manually rearrange the order of the playlist. */
|
||||||
|
bool playlist_rearrange(struct playlist *, unsigned int, unsigned int);
|
||||||
|
|
||||||
|
|
||||||
/* Called to set the playlist's search text */
|
/* Called to set the playlist's search text */
|
||||||
void playlist_set_search(struct playlist *, const gchar *);
|
void playlist_set_search(struct playlist *, const gchar *);
|
||||||
|
|
|
@ -40,15 +40,15 @@ struct playlist_callbacks {
|
||||||
void playlist_generic_set_callbacks(struct playlist_callbacks *);
|
void playlist_generic_set_callbacks(struct playlist_callbacks *);
|
||||||
|
|
||||||
/* Generic playlist init functions. */
|
/* Generic playlist init functions. */
|
||||||
void playlist_generic_init(struct playlist *);
|
void playlist_generic_init(struct playlist *, unsigned int, ...);
|
||||||
void playlist_generic_init_sorted(struct playlist *);
|
|
||||||
|
|
||||||
/* Generic playlist deinit function. */
|
/* Generic playlist deinit function. */
|
||||||
void playlist_generic_deinit(struct playlist *);
|
void playlist_generic_deinit(struct playlist *);
|
||||||
|
|
||||||
/* Generic playlist alloc function. */
|
/* Generic playlist alloc function. */
|
||||||
struct playlist *playlist_generic_alloc(gchar *, enum playlist_type_t,
|
struct playlist *playlist_generic_alloc(gchar *, enum playlist_type_t,
|
||||||
unsigned int, struct playlist_ops *);
|
unsigned int, struct playlist_ops *,
|
||||||
|
unsigned int, ...);
|
||||||
|
|
||||||
/* Generic playlist free function. */
|
/* Generic playlist free function. */
|
||||||
void playlist_generic_free(struct playlist *);
|
void playlist_generic_free(struct playlist *);
|
||||||
|
@ -82,6 +82,9 @@ void playlist_generic_set_random(struct playlist *, bool);
|
||||||
void playlist_generic_sort(struct playlist *, enum compare_t);
|
void playlist_generic_sort(struct playlist *, enum compare_t);
|
||||||
void playlist_generic_resort(struct playlist *);
|
void playlist_generic_resort(struct playlist *);
|
||||||
|
|
||||||
|
/* Generic playlist rearranging operation. */
|
||||||
|
bool playlist_generic_rearrange(struct playlist *, unsigned int, unsigned int);
|
||||||
|
|
||||||
/* Generic playlist next track operation. */
|
/* Generic playlist next track operation. */
|
||||||
struct track *playlist_generic_next(struct playlist *);
|
struct track *playlist_generic_next(struct playlist *);
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,9 @@ struct playlist_ops {
|
||||||
|
|
||||||
/* Called to sort the playlist. */
|
/* Called to sort the playlist. */
|
||||||
void (*pl_sort)(struct playlist *, enum compare_t);
|
void (*pl_sort)(struct playlist *, enum compare_t);
|
||||||
|
|
||||||
|
/* Called to rearrange the playlist. */
|
||||||
|
bool (*pl_rearrange)(struct playlist *, unsigned int, unsigned int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ void gui_audio_deinit();
|
||||||
|
|
||||||
/* Called to update the current track position. */
|
/* Called to update the current track position. */
|
||||||
int gui_audio_timeout();
|
int gui_audio_timeout();
|
||||||
|
int gui_audio_popover_timeout();
|
||||||
|
|
||||||
/* Called to get the label displaying the album tag. */
|
/* Called to get the label displaying the album tag. */
|
||||||
static inline GtkLabel *gui_album_tag(void)
|
static inline GtkLabel *gui_album_tag(void)
|
||||||
|
@ -72,10 +73,25 @@ static inline GtkButton *gui_next_button(void)
|
||||||
return GTK_BUTTON(gui_builder_widget("next_button"));
|
return GTK_BUTTON(gui_builder_widget("next_button"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called to get the pause-fater combobox. */
|
/* Called to get the pause-after widgets. */
|
||||||
static inline GtkComboBoxText *gui_pause_after(void)
|
static inline GtkEntry *gui_pause_entry(void)
|
||||||
{
|
{
|
||||||
return GTK_COMBO_BOX_TEXT(gui_builder_widget("pause_after"));
|
return GTK_ENTRY(gui_builder_widget("pause_entry"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GtkButton *gui_pause_down(void)
|
||||||
|
{
|
||||||
|
return GTK_BUTTON(gui_builder_widget("pause_down"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GtkButton *gui_pause_up(void)
|
||||||
|
{
|
||||||
|
return GTK_BUTTON(gui_builder_widget("pause_up"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GtkPopover *gui_pause_popover(void)
|
||||||
|
{
|
||||||
|
return GTK_POPOVER(gui_builder_widget("pause_popover"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called to get the seeking GtkAdjustment. */
|
/* Called to get the seeking GtkAdjustment. */
|
||||||
|
|
|
@ -38,6 +38,9 @@ unsigned int gui_filter_path_get_index(GtkTreePath *);
|
||||||
/* Called to convert a playlist iterator index into a path. */
|
/* Called to convert a playlist iterator index into a path. */
|
||||||
GtkTreePath *gui_filter_path_from_index(unsigned int);
|
GtkTreePath *gui_filter_path_from_index(unsigned int);
|
||||||
|
|
||||||
|
/* Called to refilter a playlist. Pass NULL to refilter the current playlist */
|
||||||
|
void gui_filter_refilter(struct playlist *);
|
||||||
|
|
||||||
/* Called to access the filter search-entry. */
|
/* Called to access the filter search-entry. */
|
||||||
static inline GtkSearchEntry *gui_filter_search(void)
|
static inline GtkSearchEntry *gui_filter_search(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,15 @@ struct gui_model_class {
|
||||||
};
|
};
|
||||||
typedef struct gui_model_class GuiModelClass;
|
typedef struct gui_model_class GuiModelClass;
|
||||||
|
|
||||||
|
struct gui_model_drag_data {
|
||||||
|
unsigned int drag_row;
|
||||||
|
struct track *drag_track;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GUI_DRAG_DATA "GUI_DRAG_DATA"
|
||||||
|
|
||||||
|
extern const GtkTargetEntry gui_model_drag_targets[];
|
||||||
|
extern const unsigned int gui_model_n_targets;
|
||||||
|
|
||||||
/* Called to initialize the GuiModel */
|
/* Called to initialize the GuiModel */
|
||||||
void gui_model_init(void);
|
void gui_model_init(void);
|
||||||
|
|
|
@ -76,6 +76,9 @@ gboolean gui_sidebar_iter_find(GtkTreeIter *, const gchar *,
|
||||||
/* Called to set the a GtkTreeIter to the row at path string */
|
/* Called to set the a GtkTreeIter to the row at path string */
|
||||||
gboolean gui_sidebar_iter_from_string(const gchar *, GtkTreeIter *);
|
gboolean gui_sidebar_iter_from_string(const gchar *, GtkTreeIter *);
|
||||||
|
|
||||||
|
/* Called to set the GtkTreeIter to the row at (x, y) */
|
||||||
|
gboolean gui_sidebar_iter_from_xy(gint, gint, GtkTreeIter *);
|
||||||
|
|
||||||
/* Called to get the sidebar widget. */
|
/* Called to get the sidebar widget. */
|
||||||
static inline GtkPaned *gui_sidebar()
|
static inline GtkPaned *gui_sidebar()
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,12 @@ static inline GtkTreeView *gui_treeview()
|
||||||
return GTK_TREE_VIEW(gui_builder_widget("treeview"));
|
return GTK_TREE_VIEW(gui_builder_widget("treeview"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called to access the treview selection. */
|
||||||
|
static inline GtkTreeSelection *gui_treeview_selection()
|
||||||
|
{
|
||||||
|
return gtk_tree_view_get_selection(gui_treeview());
|
||||||
|
}
|
||||||
|
|
||||||
/* Called to access the sorting display widget. */
|
/* Called to access the sorting display widget. */
|
||||||
static inline GtkLabel *gui_sorting()
|
static inline GtkLabel *gui_sorting()
|
||||||
{
|
{
|
||||||
|
|
|
@ -266,7 +266,7 @@
|
||||||
<property name="halign">center</property>
|
<property name="halign">center</property>
|
||||||
<property name="valign">center</property>
|
<property name="valign">center</property>
|
||||||
<signal name="can-activate-accel" handler="__gui_audio_can_accel" swapped="no"/>
|
<signal name="can-activate-accel" handler="__gui_audio_can_accel" swapped="no"/>
|
||||||
<signal name="clicked" handler="audio_pause" swapped="no"/>
|
<signal name="clicked" handler="__gui_audio_pause" swapped="no"/>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="image2">
|
<object class="GtkImage" id="image2">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -532,7 +532,6 @@ audio-volume-medium</property>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">3</property>
|
<property name="left_attach">3</property>
|
||||||
<property name="top_attach">0</property>
|
<property name="top_attach">0</property>
|
||||||
<property name="width">2</property>
|
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -598,132 +597,83 @@ audio-volume-medium</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">end</property>
|
|
||||||
<property name="label" translatable="yes">Pause after</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">3</property>
|
|
||||||
<property name="top_attach">1</property>
|
|
||||||
<property name="height">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkComboBoxText" id="pause_after">
|
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">end</property>
|
<property name="halign">end</property>
|
||||||
<property name="valign">center</property>
|
<property name="valign">center</property>
|
||||||
<property name="active">0</property>
|
<child>
|
||||||
<items>
|
<object class="GtkEntry" id="pause_entry">
|
||||||
<item translatable="yes">(disabled)</item>
|
<property name="visible">True</property>
|
||||||
<item translatable="yes">this track</item>
|
<property name="can_focus">True</property>
|
||||||
<item translatable="yes">next track</item>
|
<property name="text" translatable="yes">Paused</property>
|
||||||
<item translatable="yes">2 tracks</item>
|
<signal name="activate" handler="__gui_audio_pause_change_text" swapped="no"/>
|
||||||
<item translatable="yes">3 tracks</item>
|
</object>
|
||||||
<item translatable="yes">4 tracks</item>
|
<packing>
|
||||||
<item translatable="yes">5 tracks</item>
|
<property name="expand">False</property>
|
||||||
<item translatable="yes">6 tracks</item>
|
<property name="fill">True</property>
|
||||||
<item translatable="yes">7 tracks</item>
|
<property name="position">0</property>
|
||||||
<item translatable="yes">8 tracks</item>
|
</packing>
|
||||||
<item translatable="yes">9 tracks</item>
|
</child>
|
||||||
<item translatable="yes">10 tracks</item>
|
<child>
|
||||||
<item translatable="yes">11 tracks</item>
|
<object class="GtkButton" id="pause_down">
|
||||||
<item translatable="yes">12 tracks</item>
|
<property name="visible">True</property>
|
||||||
<item translatable="yes">13 tracks</item>
|
<property name="sensitive">False</property>
|
||||||
<item translatable="yes">14 tracks</item>
|
<property name="can_focus">False</property>
|
||||||
<item translatable="yes">15 tracks</item>
|
<property name="receives_default">True</property>
|
||||||
<item translatable="yes">16 tracks</item>
|
<signal name="can-activate-accel" handler="__gui_audio_can_accel" swapped="no"/>
|
||||||
<item translatable="yes">17 tracks</item>
|
<signal name="clicked" handler="__gui_audio_pause_dec" swapped="no"/>
|
||||||
<item translatable="yes">18 tracks</item>
|
<child>
|
||||||
<item translatable="yes">19 tracks</item>
|
<object class="GtkImage">
|
||||||
<item translatable="yes">20 tracks</item>
|
<property name="visible">True</property>
|
||||||
<item translatable="yes">21 tracks</item>
|
<property name="can_focus">False</property>
|
||||||
<item translatable="yes">22 tracks</item>
|
<property name="icon_name">list-remove-symbolic</property>
|
||||||
<item translatable="yes">23 tracks</item>
|
</object>
|
||||||
<item translatable="yes">24 tracks</item>
|
</child>
|
||||||
<item translatable="yes">25 tracks</item>
|
<accelerator key="minus" signal="clicked"/>
|
||||||
<item translatable="yes">26 tracks</item>
|
<accelerator key="KP_Subtract" signal="clicked"/>
|
||||||
<item translatable="yes">27 tracks</item>
|
<style>
|
||||||
<item translatable="yes">28 tracks</item>
|
<class name="down"/>
|
||||||
<item translatable="yes">29 tracks</item>
|
</style>
|
||||||
<item translatable="yes">30 tracks</item>
|
</object>
|
||||||
<item translatable="yes">31 tracks</item>
|
<packing>
|
||||||
<item translatable="yes">32 tracks</item>
|
<property name="expand">False</property>
|
||||||
<item translatable="yes">33 tracks</item>
|
<property name="fill">True</property>
|
||||||
<item translatable="yes">34 tracks</item>
|
<property name="position">1</property>
|
||||||
<item translatable="yes">35 tracks</item>
|
</packing>
|
||||||
<item translatable="yes">36 tracks</item>
|
</child>
|
||||||
<item translatable="yes">37 tracks</item>
|
<child>
|
||||||
<item translatable="yes">38 tracks</item>
|
<object class="GtkButton" id="pause_up">
|
||||||
<item translatable="yes">39 tracks</item>
|
<property name="visible">True</property>
|
||||||
<item translatable="yes">40 tracks</item>
|
<property name="can_focus">False</property>
|
||||||
<item translatable="yes">41 tracks</item>
|
<property name="receives_default">True</property>
|
||||||
<item translatable="yes">42 tracks</item>
|
<signal name="can-activate-accel" handler="__gui_audio_can_accel" swapped="no"/>
|
||||||
<item translatable="yes">43 tracks</item>
|
<signal name="clicked" handler="__gui_audio_pause_inc" swapped="no"/>
|
||||||
<item translatable="yes">44 tracks</item>
|
<child>
|
||||||
<item translatable="yes">45 tracks</item>
|
<object class="GtkImage">
|
||||||
<item translatable="yes">46 tracks</item>
|
<property name="visible">True</property>
|
||||||
<item translatable="yes">47 tracks</item>
|
<property name="can_focus">False</property>
|
||||||
<item translatable="yes">48 tracks</item>
|
<property name="icon_name">list-add-symbolic</property>
|
||||||
<item translatable="yes">49 tracks</item>
|
</object>
|
||||||
<item translatable="yes">50 tracks</item>
|
</child>
|
||||||
<item translatable="yes">51 tracks</item>
|
<accelerator key="plus" signal="clicked"/>
|
||||||
<item translatable="yes">52 tracks</item>
|
<accelerator key="KP_Add" signal="clicked"/>
|
||||||
<item translatable="yes">53 tracks</item>
|
<style>
|
||||||
<item translatable="yes">54 tracks</item>
|
<class name="up"/>
|
||||||
<item translatable="yes">55 tracks</item>
|
</style>
|
||||||
<item translatable="yes">56 tracks</item>
|
</object>
|
||||||
<item translatable="yes">57 tracks</item>
|
<packing>
|
||||||
<item translatable="yes">58 tracks</item>
|
<property name="expand">False</property>
|
||||||
<item translatable="yes">59 tracks</item>
|
<property name="fill">True</property>
|
||||||
<item translatable="yes">60 tracks</item>
|
<property name="position">2</property>
|
||||||
<item translatable="yes">61 tracks</item>
|
</packing>
|
||||||
<item translatable="yes">62 tracks</item>
|
</child>
|
||||||
<item translatable="yes">63 tracks</item>
|
<style>
|
||||||
<item translatable="yes">64 tracks</item>
|
<class name="linked"/>
|
||||||
<item translatable="yes">65 tracks</item>
|
</style>
|
||||||
<item translatable="yes">66 tracks</item>
|
|
||||||
<item translatable="yes">67 tracks</item>
|
|
||||||
<item translatable="yes">68 tracks</item>
|
|
||||||
<item translatable="yes">69 tracks</item>
|
|
||||||
<item translatable="yes">70 tracks</item>
|
|
||||||
<item translatable="yes">71 tracks</item>
|
|
||||||
<item translatable="yes">72 tracks</item>
|
|
||||||
<item translatable="yes">73 tracks</item>
|
|
||||||
<item translatable="yes">74 tracks</item>
|
|
||||||
<item translatable="yes">75 tracks</item>
|
|
||||||
<item translatable="yes">76 tracks</item>
|
|
||||||
<item translatable="yes">77 tracks</item>
|
|
||||||
<item translatable="yes">78 tracks</item>
|
|
||||||
<item translatable="yes">79 tracks</item>
|
|
||||||
<item translatable="yes">80 tracks</item>
|
|
||||||
<item translatable="yes">81 tracks</item>
|
|
||||||
<item translatable="yes">82 tracks</item>
|
|
||||||
<item translatable="yes">83 tracks</item>
|
|
||||||
<item translatable="yes">84 tracks</item>
|
|
||||||
<item translatable="yes">85 tracks</item>
|
|
||||||
<item translatable="yes">86 tracks</item>
|
|
||||||
<item translatable="yes">87 tracks</item>
|
|
||||||
<item translatable="yes">88 tracks</item>
|
|
||||||
<item translatable="yes">89 tracks</item>
|
|
||||||
<item translatable="yes">90 tracks</item>
|
|
||||||
<item translatable="yes">91 tracks</item>
|
|
||||||
<item translatable="yes">92 tracks</item>
|
|
||||||
<item translatable="yes">93 tracks</item>
|
|
||||||
<item translatable="yes">94 tracks</item>
|
|
||||||
<item translatable="yes">95 tracks</item>
|
|
||||||
<item translatable="yes">96 tracks</item>
|
|
||||||
<item translatable="yes">97 tracks</item>
|
|
||||||
<item translatable="yes">98 tracks</item>
|
|
||||||
<item translatable="yes">99 tracks</item>
|
|
||||||
</items>
|
|
||||||
<signal name="changed" handler="__gui_audio_pause_changed" swapped="no"/>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">4</property>
|
<property name="left_attach">3</property>
|
||||||
<property name="top_attach">1</property>
|
<property name="top_attach">1</property>
|
||||||
<property name="height">2</property>
|
<property name="height">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
|
@ -818,6 +768,8 @@ audio-volume-medium</property>
|
||||||
<property name="search_column">1</property>
|
<property name="search_column">1</property>
|
||||||
<property name="enable_tree_lines">True</property>
|
<property name="enable_tree_lines">True</property>
|
||||||
<signal name="button-press-event" handler="__gui_sidebar_button_press" swapped="no"/>
|
<signal name="button-press-event" handler="__gui_sidebar_button_press" swapped="no"/>
|
||||||
|
<signal name="drag-data-received" handler="__gui_playlist_drag_data_received" swapped="no"/>
|
||||||
|
<signal name="drag-drop" handler="__gui_treeview_drag_drop" swapped="no"/>
|
||||||
<signal name="key-press-event" handler="__gui_sidebar_keypress" swapped="no"/>
|
<signal name="key-press-event" handler="__gui_sidebar_keypress" swapped="no"/>
|
||||||
<signal name="row-activated" handler="__gui_playlist_row_activated" swapped="no"/>
|
<signal name="row-activated" handler="__gui_playlist_row_activated" swapped="no"/>
|
||||||
<signal name="row-collapsed" handler="__gui_playlist_row_collapsed" swapped="no"/>
|
<signal name="row-collapsed" handler="__gui_playlist_row_collapsed" swapped="no"/>
|
||||||
|
@ -962,6 +914,8 @@ audio-volume-medium</property>
|
||||||
<property name="rubber_banding">True</property>
|
<property name="rubber_banding">True</property>
|
||||||
<property name="tooltip_column">9</property>
|
<property name="tooltip_column">9</property>
|
||||||
<signal name="button-press-event" handler="__gui_playlist_button_press" swapped="no"/>
|
<signal name="button-press-event" handler="__gui_playlist_button_press" swapped="no"/>
|
||||||
|
<signal name="drag-data-received" handler="__gui_treeview_drag_data_received" swapped="no"/>
|
||||||
|
<signal name="drag-drop" handler="__gui_treeview_drag_drop" swapped="no"/>
|
||||||
<signal name="key-press-event" handler="__gui_playlist_keypress" swapped="no"/>
|
<signal name="key-press-event" handler="__gui_playlist_keypress" swapped="no"/>
|
||||||
<signal name="row-activated" handler="__gui_treeview_row_activated" swapped="no"/>
|
<signal name="row-activated" handler="__gui_treeview_row_activated" swapped="no"/>
|
||||||
<child internal-child="selection">
|
<child internal-child="selection">
|
||||||
|
@ -1167,7 +1121,7 @@ audio-volume-medium</property>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">0</property>
|
<property name="left_attach">0</property>
|
||||||
<property name="top_attach">3</property>
|
<property name="top_attach">3</property>
|
||||||
<property name="width">5</property>
|
<property name="width">4</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
@ -1193,4 +1147,55 @@ audio-volume-medium</property>
|
||||||
<widget name="filter_how"/>
|
<widget name="filter_how"/>
|
||||||
</widgets>
|
</widgets>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="GtkPopover" id="pause_popover">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="relative_to">play_button</property>
|
||||||
|
<property name="position">bottom</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="row_homogeneous">True</property>
|
||||||
|
<property name="column_homogeneous">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Cancel "pause after" configuration?</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="pause_popover_no">
|
||||||
|
<property name="label" translatable="yes">No</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="clicked" handler="__gui_audio_pause_popover_popdown" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="pause_popover_yes">
|
||||||
|
<property name="label" translatable="yes">Yes</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="clicked" handler="__gui_audio_pause_popover_clear" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
@ -62,6 +62,7 @@ static void test_init()
|
||||||
g_assert_cmpuint(audio_get_volume(), ==, 100);
|
g_assert_cmpuint(audio_get_volume(), ==, 100);
|
||||||
g_assert_null(audio_cur_track());
|
g_assert_null(audio_cur_track());
|
||||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_NULL);
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_NULL);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, -1);
|
||||||
g_assert_cmpuint(load_count, ==, 0);
|
g_assert_cmpuint(load_count, ==, 0);
|
||||||
g_assert_cmpuint(state_count, ==, 0);
|
g_assert_cmpuint(state_count, ==, 0);
|
||||||
|
|
||||||
|
@ -201,20 +202,32 @@ void test_autopause()
|
||||||
struct playlist *history = playlist_lookup(PL_SYSTEM, "History");
|
struct playlist *history = playlist_lookup(PL_SYSTEM, "History");
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
audio_pause_after(3);
|
g_assert_true(audio_pause_after(3));
|
||||||
g_assert_cmpuint(pause_count, ==, 3);
|
g_assert_cmpint(pause_count, ==, 3);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 3);
|
||||||
|
|
||||||
|
g_assert_false(audio_pause_after(-2));
|
||||||
|
g_assert_cmpint(pause_count, ==, 3);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 3);
|
||||||
|
|
||||||
pause_count = 0;
|
pause_count = 0;
|
||||||
audio_pause_after(3);
|
g_assert_false(audio_pause_after(3));
|
||||||
g_assert_cmpuint(pause_count, ==, 0);
|
g_assert_cmpint(pause_count, ==, 0);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 3);
|
||||||
|
|
||||||
audio_pause_after(5);
|
g_assert_true(audio_pause_after(-1));
|
||||||
g_assert_cmpuint(pause_count, ==, 5);
|
g_assert_cmpint(pause_count, ==, -1);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, -1);
|
||||||
|
|
||||||
|
g_assert_true(audio_pause_after(5));
|
||||||
|
g_assert_cmpint(pause_count, ==, 5);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 5);
|
||||||
|
|
||||||
state_count = 0;
|
state_count = 0;
|
||||||
for (i = 4; i > -1; i--) {
|
for (i = 4; i > -1; i--) {
|
||||||
test_audio_eos();
|
test_audio_eos();
|
||||||
g_assert_cmpuint(pause_count, ==, i);
|
g_assert_cmpint(pause_count, ==, i);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, i);
|
||||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
||||||
g_assert(playlist_at(history, 0) == audio_cur_track());
|
g_assert(playlist_at(history, 0) == audio_cur_track());
|
||||||
}
|
}
|
||||||
|
@ -223,6 +236,7 @@ void test_autopause()
|
||||||
test_audio_eos();
|
test_audio_eos();
|
||||||
while (idle_run_task()) {}
|
while (idle_run_task()) {}
|
||||||
g_assert_cmpint(pause_count, ==, -1);
|
g_assert_cmpint(pause_count, ==, -1);
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, -1);
|
||||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
||||||
g_assert_cmpuint(test_wait_state(), ==, 6);
|
g_assert_cmpuint(test_wait_state(), ==, 6);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ static struct playlist_ops test_ops = {
|
||||||
.pl_remove = playlist_generic_remove,
|
.pl_remove = playlist_generic_remove,
|
||||||
.pl_set_random = playlist_generic_set_random,
|
.pl_set_random = playlist_generic_set_random,
|
||||||
.pl_sort = playlist_generic_sort,
|
.pl_sort = playlist_generic_sort,
|
||||||
|
.pl_rearrange = playlist_generic_rearrange,
|
||||||
};
|
};
|
||||||
static struct playlist_callbacks test_cb = {
|
static struct playlist_callbacks test_cb = {
|
||||||
.pl_cb_alloc = test_pl_alloc,
|
.pl_cb_alloc = test_pl_alloc,
|
||||||
|
@ -49,8 +50,7 @@ static void test_null()
|
||||||
g_assert_false(playlist_delete(NULL));
|
g_assert_false(playlist_delete(NULL));
|
||||||
playlist_generic_free(NULL);
|
playlist_generic_free(NULL);
|
||||||
|
|
||||||
playlist_generic_init(NULL);
|
playlist_generic_init(NULL, 0);
|
||||||
playlist_generic_init_sorted(NULL);
|
|
||||||
playlist_generic_deinit(NULL);
|
playlist_generic_deinit(NULL);
|
||||||
|
|
||||||
g_assert_null(playlist_lookup(PL_MAX_TYPE, "NULL"));
|
g_assert_null(playlist_lookup(PL_MAX_TYPE, "NULL"));
|
||||||
|
@ -77,6 +77,7 @@ static void test_null()
|
||||||
g_assert_false(playlist_sort(NULL, COMPARE_TRACK));
|
g_assert_false(playlist_sort(NULL, COMPARE_TRACK));
|
||||||
playlist_generic_resort(NULL);
|
playlist_generic_resort(NULL);
|
||||||
playlist_clear_sort(NULL);
|
playlist_clear_sort(NULL);
|
||||||
|
g_assert_false(playlist_rearrange(NULL, 0, 0));
|
||||||
|
|
||||||
playlist_set_search(NULL, NULL);
|
playlist_set_search(NULL, NULL);
|
||||||
|
|
||||||
|
@ -110,9 +111,10 @@ static void test_playlist()
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_assert_cmpuint(playlist_size(&p), ==, 0);
|
g_assert_cmpuint(playlist_size(&p), ==, 0);
|
||||||
playlist_generic_init(&p);
|
playlist_generic_init(&p, 0);
|
||||||
g_assert_cmpuint(playlist_size(&p), ==, 0);
|
g_assert_cmpuint(playlist_size(&p), ==, 0);
|
||||||
g_assert_cmpuint(p.pl_length, ==, 0);
|
g_assert_cmpuint(p.pl_length, ==, 0);
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||||
|
|
||||||
for (i = 0; i < 13; i++) {
|
for (i = 0; i < 13; i++) {
|
||||||
ex_length += track_get(i)->tr_length;
|
ex_length += track_get(i)->tr_length;
|
||||||
|
@ -202,8 +204,9 @@ static void test_sorting()
|
||||||
struct track *track;
|
struct track *track;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
playlist_generic_init_sorted(&p);
|
playlist_generic_init(&p, 4, COMPARE_ARTIST, COMPARE_YEAR,
|
||||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 3);
|
COMPARE_ALBUM, COMPARE_TRACK);
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||||
playlist_clear_sort(&p);
|
playlist_clear_sort(&p);
|
||||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||||
|
|
||||||
|
@ -279,6 +282,43 @@ static void test_sorting()
|
||||||
g_assert_null(p.pl_sort);
|
g_assert_null(p.pl_sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_rearranging()
|
||||||
|
{
|
||||||
|
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
|
||||||
|
struct track *track;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
playlist_generic_init(&p, 4, COMPARE_ARTIST, COMPARE_YEAR,
|
||||||
|
COMPARE_ALBUM, COMPARE_TRACK);
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||||
|
|
||||||
|
for (i = 0; i < 13; i++)
|
||||||
|
playlist_add(&p, track_get(i));
|
||||||
|
|
||||||
|
g_assert_false(playlist_rearrange(&p, 42, 4));
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||||
|
g_assert_false(playlist_rearrange(&p, 4, 42));
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||||
|
g_assert_false(playlist_rearrange(&p, 4, 4));
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||||
|
g_assert_true(playlist_rearrange(&p, 12, 0));
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||||
|
g_assert_true(playlist_rearrange(&p, 1, 12));
|
||||||
|
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < 13; i++) {
|
||||||
|
track = playlist_at(&p, i);
|
||||||
|
if (i == 0)
|
||||||
|
g_assert_cmpuint(track->tr_track, ==, 13);
|
||||||
|
else if (i == 12)
|
||||||
|
g_assert_cmpuint(track->tr_track, ==, 1);
|
||||||
|
else
|
||||||
|
g_assert_cmpuint(track->tr_track, ==, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
playlist_generic_deinit(&p);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_next()
|
static void test_next()
|
||||||
{
|
{
|
||||||
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
|
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
|
||||||
|
@ -286,7 +326,7 @@ static void test_next()
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
g_random_set_seed(0);
|
g_random_set_seed(0);
|
||||||
playlist_generic_init(&p);
|
playlist_generic_init(&p, 0);
|
||||||
|
|
||||||
for (i = 0; i < 13; i++)
|
for (i = 0; i < 13; i++)
|
||||||
playlist_generic_add(&p, track_get(i));
|
playlist_generic_add(&p, track_get(i));
|
||||||
|
@ -403,6 +443,7 @@ int main(int argc, char **argv)
|
||||||
g_test_add_func("/Core/Playlist/NULL", test_null);
|
g_test_add_func("/Core/Playlist/NULL", test_null);
|
||||||
g_test_add_func("/Core/Playlists/General", test_playlist);
|
g_test_add_func("/Core/Playlists/General", test_playlist);
|
||||||
g_test_add_func("/Core/Playlists/Sorting", test_sorting);
|
g_test_add_func("/Core/Playlists/Sorting", test_sorting);
|
||||||
|
g_test_add_func("/Core/Playlists/Rearranging", test_rearranging);
|
||||||
g_test_add_func("/Core/Playlists/Next Track", test_next);
|
g_test_add_func("/Core/Playlists/Next Track", test_next);
|
||||||
g_test_add_func("/Core/Playlist/Save and Load", test_save_load);
|
g_test_add_func("/Core/Playlist/Save and Load", test_save_load);
|
||||||
ret = g_test_run();
|
ret = g_test_run();
|
||||||
|
|
|
@ -75,8 +75,8 @@ void test_library()
|
||||||
playlist_set_random(playlist, false);
|
playlist_set_random(playlist, false);
|
||||||
g_assert_false(playlist->pl_random);
|
g_assert_false(playlist->pl_random);
|
||||||
|
|
||||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 3);
|
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 4);
|
||||||
playlist_clear_sort(playlist);
|
g_assert_true(playlist_rearrange(playlist, 15, 20));
|
||||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
||||||
g_assert_true(playlist_sort(playlist, COMPARE_ARTIST));
|
g_assert_true(playlist_sort(playlist, COMPARE_ARTIST));
|
||||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 1);
|
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 1);
|
||||||
|
|
|
@ -44,7 +44,7 @@ static void test_init()
|
||||||
if (i == SYS_PL_QUEUED || i == SYS_PL_HISTORY) {
|
if (i == SYS_PL_QUEUED || i == SYS_PL_HISTORY) {
|
||||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
||||||
} else
|
} else
|
||||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 3);
|
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add tracks to the collection. */
|
/* Add tracks to the collection. */
|
||||||
|
|
|
@ -21,14 +21,14 @@ static void test_audio_init()
|
||||||
g_assert_cmpstr(gtk_label_get_text(gui_title_tag()), ==, " ");
|
g_assert_cmpstr(gtk_label_get_text(gui_title_tag()), ==, " ");
|
||||||
g_assert_cmpstr(gtk_label_get_text(gui_position()), ==, "0:00");
|
g_assert_cmpstr(gtk_label_get_text(gui_position()), ==, "0:00");
|
||||||
g_assert_cmpstr(gtk_label_get_text(gui_duration()), ==, "0:00");
|
g_assert_cmpstr(gtk_label_get_text(gui_duration()), ==, "0:00");
|
||||||
g_assert_cmpstr(gtk_combo_box_text_get_active_text(gui_pause_after()),
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Paused");
|
||||||
==, "(disabled)");
|
g_assert_true(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_up())));
|
||||||
g_assert_cmpuint(gtk_combo_box_get_active(
|
g_assert_false(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
GTK_COMBO_BOX(gui_pause_after())), ==, 0);
|
|
||||||
g_assert_cmpfloat(gtk_scale_button_get_value(gui_volume_button()),
|
g_assert_cmpfloat(gtk_scale_button_get_value(gui_volume_button()),
|
||||||
==, 100);
|
==, 100);
|
||||||
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
||||||
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
||||||
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_audio_load()
|
static void test_audio_load()
|
||||||
|
@ -46,6 +46,7 @@ static void test_audio_load()
|
||||||
g_assert_cmpstr(gtk_label_get_text(gui_duration()), ==, length);
|
g_assert_cmpstr(gtk_label_get_text(gui_duration()), ==, length);
|
||||||
g_assert_cmpstr(gtk_label_get_text(gui_position()), ==, "0:00");
|
g_assert_cmpstr(gtk_label_get_text(gui_position()), ==, "0:00");
|
||||||
|
|
||||||
|
test_main_loop();
|
||||||
test_main_loop();
|
test_main_loop();
|
||||||
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
||||||
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
||||||
|
@ -64,12 +65,16 @@ static void test_audio_buttons()
|
||||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
||||||
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
||||||
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Paused");
|
||||||
|
g_assert_false(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
|
|
||||||
gtk_button_clicked(gui_play_button());
|
gtk_button_clicked(gui_play_button());
|
||||||
test_main_loop();
|
test_main_loop();
|
||||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
||||||
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_play_button())));
|
||||||
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
g_assert_true( gtk_widget_is_visible(GTK_WIDGET(gui_pause_button())));
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Keep playing");
|
||||||
|
|
||||||
gtk_button_clicked(gui_next_button());
|
gtk_button_clicked(gui_next_button());
|
||||||
if (track_get(0)->tr_track == 1)
|
if (track_get(0)->tr_track == 1)
|
||||||
|
@ -79,16 +84,72 @@ static void test_audio_buttons()
|
||||||
gtk_button_clicked(gui_prev_button());
|
gtk_button_clicked(gui_prev_button());
|
||||||
g_assert(audio_cur_track() == track_get(0));
|
g_assert(audio_cur_track() == track_get(0));
|
||||||
|
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(gui_pause_after()), 2);
|
g_assert_cmpint(audio_get_pause_count(), ==, -1);
|
||||||
|
gtk_button_clicked(gui_pause_up());
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 0);
|
||||||
|
gtk_button_clicked(gui_pause_up());
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 1);
|
||||||
|
gtk_button_clicked(gui_pause_down());
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 0);
|
||||||
|
gtk_button_clicked(gui_pause_down());
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, -1);
|
||||||
|
|
||||||
|
gtk_entry_set_text(gui_pause_entry(), "2 tracks");
|
||||||
|
gtk_widget_activate(GTK_WIDGET(gui_pause_entry()));
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 2);
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Pause after 2 tracks");
|
||||||
|
g_assert_true(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
|
|
||||||
test_audio_eos();
|
test_audio_eos();
|
||||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
||||||
g_assert_cmpuint(gtk_combo_box_get_active(
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Pause after next track");
|
||||||
GTK_COMBO_BOX(gui_pause_after())), ==, 1);
|
g_assert_true(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
|
|
||||||
|
gtk_button_clicked(gui_pause_button());
|
||||||
|
test_main_loop();
|
||||||
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Pause after next track");
|
||||||
|
g_assert_true(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
|
g_assert_true(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
|
|
||||||
|
gtk_button_clicked(GTK_BUTTON(gui_builder_widget("pause_popover_yes")));
|
||||||
|
test_main_loop();
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, -1);
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Paused");
|
||||||
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
|
|
||||||
|
gtk_button_clicked(gui_play_button());
|
||||||
|
gtk_button_clicked(gui_pause_up());
|
||||||
|
gtk_button_clicked(gui_pause_up());
|
||||||
|
gtk_button_clicked(gui_pause_button());
|
||||||
|
g_assert_true(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
|
|
||||||
|
gtk_button_clicked(GTK_BUTTON(gui_builder_widget("pause_popover_no")));
|
||||||
|
g_assert_cmpint(audio_get_pause_count(), ==, 1);
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Pause after next track");
|
||||||
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
|
|
||||||
|
gtk_button_clicked(gui_pause_button());
|
||||||
|
g_assert_true(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
|
g_assert_cmpint(gui_audio_popover_timeout(), ==, G_SOURCE_REMOVE);
|
||||||
|
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_pause_popover())));
|
||||||
|
|
||||||
|
gtk_button_clicked(gui_play_button());
|
||||||
|
test_main_loop();
|
||||||
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Pause after next track");
|
||||||
|
g_assert_true(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
|
|
||||||
|
test_audio_eos();
|
||||||
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Pause after this track");
|
||||||
|
g_assert_true(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
|
|
||||||
test_audio_eos();
|
test_audio_eos();
|
||||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
||||||
g_assert_cmpuint(gtk_combo_box_get_active(
|
g_assert_false(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||||
GTK_COMBO_BOX(gui_pause_after())), ==, 0);
|
test_main_loop(); /* Give the text entry time to update */
|
||||||
|
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Paused");
|
||||||
|
|
||||||
gtk_scale_button_set_value(gui_volume_button(), 50);
|
gtk_scale_button_set_value(gui_volume_button(), 50);
|
||||||
g_assert_cmpuint(audio_get_volume(), ==, 50);
|
g_assert_cmpuint(audio_get_volume(), ==, 50);
|
||||||
|
|
|
@ -65,7 +65,7 @@ void test_treeview_select()
|
||||||
GList *list;
|
GList *list;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
selection = gtk_tree_view_get_selection(gui_treeview());
|
selection = gui_treeview_selection();
|
||||||
|
|
||||||
gui_treeview_set_playlist(playlist_lookup(PL_SYSTEM, "Collection"));
|
gui_treeview_set_playlist(playlist_lookup(PL_SYSTEM, "Collection"));
|
||||||
g_assert(gui_model_get_playlist() ==
|
g_assert(gui_model_get_playlist() ==
|
||||||
|
@ -112,6 +112,7 @@ void test_treeview_sort()
|
||||||
break;
|
break;
|
||||||
case GUI_MODEL_ARTIST:
|
case GUI_MODEL_ARTIST:
|
||||||
case GUI_MODEL_YEAR:
|
case GUI_MODEL_YEAR:
|
||||||
|
case GUI_MODEL_ALBUM:
|
||||||
case GUI_MODEL_TRACK_NR:
|
case GUI_MODEL_TRACK_NR:
|
||||||
g_assert_true(
|
g_assert_true(
|
||||||
gtk_tree_view_column_get_sort_indicator(col));
|
gtk_tree_view_column_get_sort_indicator(col));
|
||||||
|
|
Loading…
Reference in New Issue