Compare commits
58 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 | |
Anna Schumaker | e6fb772cad | |
Anna Schumaker | cce8666140 | |
Anna Schumaker | edcba6a353 | |
Anna Schumaker | 59506d45e7 | |
Anna Schumaker | e1f13a7ef4 | |
Anna Schumaker | 111fcd4e72 | |
Anna Schumaker | c5494811f4 | |
Anna Schumaker | 07f832ad26 | |
Anna Schumaker | 35d53855f5 | |
Anna Schumaker | a848d5d03c | |
Anna Schumaker | 0aaafcb5f7 | |
Anna Schumaker | 8f13765b08 | |
Anna Schumaker | 84a1022bdf | |
Anna Schumaker | 659aaff6a1 | |
Anna Schumaker | 3736b6cf3b | |
Anna Schumaker | 3fdf89c75e | |
Anna Schumaker | 22854b2f25 | |
Anna Schumaker | b6d45e666e | |
Anna Schumaker | 842547d735 | |
Anna Schumaker | 198fbf7f9b | |
Anna Schumaker | 82280edfa2 | |
Anna Schumaker | 48f79bdb49 | |
Anna Schumaker | d7d553b80f | |
Anna Schumaker | a2854ef31e | |
Anna Schumaker | d96e8ca1ca | |
Anna Schumaker | 1940a31a77 | |
Anna Schumaker | 07196a7cc8 | |
Anna Schumaker | 64e27c1221 | |
Anna Schumaker | 31cda0eebd | |
Anna Schumaker | 9b9be4e322 | |
Anna Schumaker | 1374a025e1 | |
Anna Schumaker | 21e1796b14 | |
Anna Schumaker | b4347d5a34 |
|
@ -10,7 +10,7 @@ option(CONFIG_TESTING_ARTWORK "Enable album artwork fetching tests" ON)
|
|||
# Configure settings
|
||||
set(CONFIG_MAJOR 6)
|
||||
set(CONFIG_MINOR 5)
|
||||
set(CONFIG_MICRO 7)
|
||||
set(CONFIG_MICRO 10)
|
||||
set(CONFIG_RC ON)
|
||||
|
||||
set(CONFIG_VERSION "${CONFIG_MAJOR}.${CONFIG_MINOR}.${CONFIG_MICRO}")
|
||||
|
|
2
PKGBUILD
2
PKGBUILD
|
@ -1,6 +1,6 @@
|
|||
# Maintainer: Anna Schumaker <anna@nowheycreamery.com>
|
||||
pkgname=ocarina
|
||||
pkgver=6.5.6
|
||||
pkgver=6.5.9
|
||||
pkgrel=1
|
||||
pkgdesc="A simple GTK+ and GStreamer based music player."
|
||||
url="http://www.nowheycreamery.com/"
|
||||
|
|
18
core/audio.c
18
core/audio.c
|
@ -13,7 +13,7 @@
|
|||
static const char *SETTINGS_TRACK = "core.audio.cur";
|
||||
static const char *SETTINGS_VOLUME = "core.audio.volume";
|
||||
|
||||
static struct file audio_file = FILE_INIT("cur_track", 0);
|
||||
static struct file audio_file = FILE_INIT_DATA("", "cur_track", 0);
|
||||
static struct track *audio_track = NULL;
|
||||
static int audio_pause_count = -1;
|
||||
|
||||
|
@ -45,7 +45,8 @@ static struct track *__audio_load(struct track *track, unsigned int flags)
|
|||
|
||||
audio_track = track;
|
||||
path = track_path(track);
|
||||
gst_element_set_state(audio_pipeline, GST_STATE_READY);
|
||||
if (audio_cur_state() != GST_STATE_NULL)
|
||||
gst_element_set_state(audio_pipeline, GST_STATE_READY);
|
||||
g_object_set(G_OBJECT(audio_source), "location", path, NULL);
|
||||
gst_element_set_state(audio_pipeline, flags & LOAD_PLAYING ?
|
||||
GST_STATE_PLAYING : GST_STATE_PAUSED);
|
||||
|
@ -131,7 +132,7 @@ static bool __audio_init_idle(void *data)
|
|||
track = settings_get(SETTINGS_TRACK);
|
||||
__audio_load(track_get(track), LOAD_HISTORY);
|
||||
} else if (file_open(&audio_file, OPEN_READ)) {
|
||||
file_readf(&audio_file, "%u", &track);
|
||||
track = file_readu(&audio_file);
|
||||
file_close(&audio_file);
|
||||
file_remove(&audio_file);
|
||||
__audio_load(track_get(track), LOAD_HISTORY);
|
||||
|
@ -304,13 +305,20 @@ struct track *audio_prev()
|
|||
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;
|
||||
if (audio_cb)
|
||||
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
|
||||
|
|
|
@ -36,10 +36,8 @@ static struct db_entry *__dbe_next(const struct database *db, unsigned int index
|
|||
static struct db_entry *__dbe_read(struct database *db, unsigned int index)
|
||||
{
|
||||
struct db_entry *dbe = NULL;
|
||||
int valid;
|
||||
|
||||
file_readf(&db->db_file, "%d", &valid);
|
||||
if (valid)
|
||||
if (file_readd(&db->db_file))
|
||||
dbe = db->db_ops->dbe_read(&db->db_file, index);
|
||||
|
||||
g_ptr_array_index(db->db_entries, index) = dbe;
|
||||
|
@ -76,7 +74,7 @@ void db_init(struct database *db, const char *filepath, bool autosave,
|
|||
db->db_autosave = autosave;
|
||||
db->db_entries = g_ptr_array_new();
|
||||
db->db_keys = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
file_init(&db->db_file, filepath, fmin);
|
||||
file_init_data(&db->db_file, "", filepath, fmin);
|
||||
}
|
||||
|
||||
void db_deinit(struct database *db)
|
||||
|
@ -118,7 +116,7 @@ void db_load(struct database *db)
|
|||
if (file_open(&db->db_file, OPEN_READ) == false)
|
||||
return;
|
||||
|
||||
file_readf(&db->db_file, "%u", &size);
|
||||
size = file_readu(&db->db_file);
|
||||
g_ptr_array_set_size(db->db_entries, size);
|
||||
for (unsigned int i = 0; i < size; i++) {
|
||||
if (__dbe_read(db, i))
|
||||
|
|
|
@ -26,14 +26,14 @@ void date_today(struct date *date)
|
|||
|
||||
void date_read(struct file *f, struct date *date)
|
||||
{
|
||||
file_readf(f, "%u %u %u", &date->d_year, &date->d_month, &date->d_day);
|
||||
date->d_year = file_readu(f);
|
||||
date->d_month = file_readu(f);
|
||||
date->d_day = file_readu(f);
|
||||
}
|
||||
|
||||
void date_read_stamp(struct file *f, struct date *date)
|
||||
{
|
||||
uint32_t stamp;
|
||||
file_readf(f, "%u", &stamp);
|
||||
date->d_stamp = be32toh(stamp);
|
||||
date->d_stamp = be32toh(file_readu(f));
|
||||
}
|
||||
|
||||
void date_write(struct file *f, struct date *date)
|
||||
|
|
257
core/file.c
257
core/file.c
|
@ -12,67 +12,43 @@
|
|||
g_printerr("%s (%s:%d): %s: %s\n", __func__, __FILE__, __LINE__, fname, error)
|
||||
#define REPORT_ERRNO(fname) REPORT_ERROR(fname, strerror(errno))
|
||||
|
||||
static gchar *__file_path(const gchar *base, const gchar *dir,
|
||||
const gchar *name)
|
||||
static void __file_init_common(struct file *file, const gchar *subdir,
|
||||
const gchar *name, unsigned int min,
|
||||
const gchar *(*user_dir)(void))
|
||||
{
|
||||
return g_build_filename(base, OCARINA_NAME, dir ? dir : "", name, NULL);
|
||||
file->f_file = NULL;
|
||||
file->f_name = name;
|
||||
file->f_subdir = subdir;
|
||||
file->f_mode = CLOSED;
|
||||
file->f_version = OCARINA_MINOR_VERSION;
|
||||
file->f_prev = 0;
|
||||
file->f_min = min;
|
||||
file->f_user_dir = user_dir;
|
||||
}
|
||||
|
||||
static gchar *__file_build_path(const gchar *base, const gchar *dir,
|
||||
const gchar *name)
|
||||
static bool __file_open(struct file *file, enum open_mode mode)
|
||||
{
|
||||
if (string_length(name) == 0)
|
||||
return g_strdup("");
|
||||
return __file_path(base, dir, name);
|
||||
}
|
||||
gchar *cmode, *path;
|
||||
|
||||
static gchar *__file_build_tmp(const gchar *base, const gchar *dir,
|
||||
const gchar *name)
|
||||
{
|
||||
gchar *tmp, *res;
|
||||
|
||||
if (string_length(name) == 0)
|
||||
return g_strdup("");
|
||||
|
||||
tmp = g_strdup_printf(".%s.tmp", name);
|
||||
res = __file_path(base, dir, tmp);
|
||||
g_free(tmp);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool __file_exists(gchar *path)
|
||||
{
|
||||
bool ret = g_file_test(path, G_FILE_TEST_EXISTS);
|
||||
g_free(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static FILE *__file_open(gchar *path, const gchar *mode)
|
||||
{
|
||||
FILE *ret = g_fopen(path, mode);
|
||||
|
||||
if (!ret)
|
||||
REPORT_ERRNO(path);
|
||||
g_free(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __file_close(FILE *file, gchar *path, gchar *tmp)
|
||||
{
|
||||
if (file) {
|
||||
fclose(file);
|
||||
if (path && tmp)
|
||||
g_rename(tmp, path);
|
||||
if (mode == OPEN_READ || mode == OPEN_READ_BINARY) {
|
||||
cmode = "r";
|
||||
path = file_path(file);
|
||||
} else {
|
||||
cmode = "w";
|
||||
path = file_write_path(file);
|
||||
}
|
||||
|
||||
file->f_file = g_fopen(path, cmode);
|
||||
if (!file->f_file)
|
||||
REPORT_ERRNO(path);
|
||||
g_free(path);
|
||||
g_free(tmp);
|
||||
return file->f_file != NULL;
|
||||
}
|
||||
|
||||
static bool __file_mkdir(const gchar *basedir, const gchar *subdir)
|
||||
static bool __file_mkdir(struct file *file)
|
||||
{
|
||||
gchar *dir = __file_path(basedir, subdir, NULL);
|
||||
gchar *dir = g_build_filename(file->f_user_dir(), OCARINA_NAME,
|
||||
file->f_subdir, NULL);
|
||||
int ret = g_mkdir_with_parents(dir, 0755);
|
||||
|
||||
if (ret != 0)
|
||||
|
@ -94,43 +70,38 @@ static bool __file_can_write(struct file *file)
|
|||
}
|
||||
|
||||
|
||||
void file_init(struct file *file, const gchar *name, unsigned int min)
|
||||
void file_init_data(struct file *file, const gchar *subdir,
|
||||
const gchar *name, unsigned int min)
|
||||
{
|
||||
file->f_mode = OPEN_READ;
|
||||
file->f_version = OCARINA_MINOR_VERSION;
|
||||
file->f_prev = 0;
|
||||
file->f_min = min;
|
||||
file->f_file = NULL;
|
||||
file->f_name = name;
|
||||
__file_init_common(file, subdir, name, min, g_get_user_data_dir);
|
||||
}
|
||||
|
||||
void cache_file_init(struct cache_file *file, gchar *subdir, gchar *name)
|
||||
void file_init_cache(struct file *file, const gchar *subdir, const gchar *name)
|
||||
{
|
||||
file->cf_file = NULL;
|
||||
file->cf_name = name;
|
||||
file->cf_subdir = subdir;
|
||||
__file_init_common(file, subdir, name, 0, g_get_user_cache_dir);
|
||||
}
|
||||
|
||||
gchar *file_path(struct file *file)
|
||||
{
|
||||
return __file_build_path(g_get_user_data_dir(), NULL, file->f_name);
|
||||
}
|
||||
|
||||
gchar *cache_file_path(struct cache_file *file)
|
||||
{
|
||||
return __file_build_path(g_get_user_cache_dir(), file->cf_subdir,
|
||||
file->cf_name);
|
||||
if (string_length(file->f_name) == 0)
|
||||
return g_strdup("");
|
||||
return g_build_filename(file->f_user_dir(), OCARINA_NAME,
|
||||
file->f_subdir, file->f_name, NULL);
|
||||
}
|
||||
|
||||
gchar *file_write_path(struct file *file)
|
||||
{
|
||||
return __file_build_tmp(g_get_user_data_dir(), NULL, file->f_name);
|
||||
}
|
||||
gchar *tmp, *res;
|
||||
|
||||
gchar *cache_file_write_path(struct cache_file *file)
|
||||
{
|
||||
return __file_build_tmp(g_get_user_cache_dir(), file->cf_subdir,
|
||||
file->cf_name);
|
||||
if (string_length(file->f_name) == 0)
|
||||
return g_strdup("");
|
||||
|
||||
tmp = g_strdup_printf(".%s.tmp", file->f_name);
|
||||
res = g_build_filename(file->f_user_dir(), OCARINA_NAME,
|
||||
file->f_subdir, tmp, NULL);
|
||||
g_free(tmp);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const unsigned int file_version(struct file *file)
|
||||
|
@ -142,26 +113,24 @@ const unsigned int file_version(struct file *file)
|
|||
|
||||
bool file_exists(struct file *file)
|
||||
{
|
||||
return __file_exists(file_path(file));
|
||||
gchar *path = file_path(file);
|
||||
bool ret = g_file_test(path, G_FILE_TEST_EXISTS);
|
||||
g_free(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool cache_file_exists(struct cache_file *file)
|
||||
{
|
||||
return __file_exists(cache_file_path(file));
|
||||
}
|
||||
|
||||
static bool __file_open_read(struct file *file)
|
||||
static bool __file_open_read(struct file *file, enum open_mode mode)
|
||||
{
|
||||
if (!file_exists(file))
|
||||
return false;
|
||||
|
||||
file->f_file = __file_open(file_path(file), "r");
|
||||
if (!file->f_file)
|
||||
if (!__file_open(file, mode))
|
||||
return false;
|
||||
|
||||
file->f_mode = OPEN_READ;
|
||||
if (file_readf(file, "%u\n", &file->f_prev) != 1)
|
||||
return false;
|
||||
file->f_mode = mode;
|
||||
if (mode == OPEN_READ_BINARY)
|
||||
return true;
|
||||
|
||||
file->f_prev = file_readu(file);
|
||||
if (file->f_prev < file->f_min) {
|
||||
REPORT_ERROR(file->f_name, "File too old to be upgraded.");
|
||||
file_close(file);
|
||||
|
@ -175,18 +144,18 @@ static bool __file_open_read(struct file *file)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool __file_open_write(struct file *file)
|
||||
static bool __file_open_write(struct file *file, enum open_mode mode)
|
||||
{
|
||||
if (!__file_mkdir(g_get_user_data_dir(), NULL))
|
||||
if (!__file_mkdir(file))
|
||||
return false;
|
||||
if (!__file_can_write(file))
|
||||
return false;
|
||||
|
||||
file->f_file = __file_open(file_write_path(file), "w");
|
||||
if (!file->f_file)
|
||||
if (!__file_open(file, OPEN_WRITE))
|
||||
return false;
|
||||
|
||||
file->f_mode = OPEN_WRITE;
|
||||
file->f_mode = mode;
|
||||
if (mode == OPEN_WRITE_BINARY)
|
||||
return true;
|
||||
return file_writef(file, "%d\n", file->f_version) > 0;
|
||||
}
|
||||
|
||||
|
@ -194,62 +163,49 @@ bool file_open(struct file *file, enum open_mode mode)
|
|||
{
|
||||
if ((string_length(file->f_name) == 0) || (file->f_file != NULL))
|
||||
return false;
|
||||
|
||||
if (mode == OPEN_READ)
|
||||
return __file_open_read(file);
|
||||
return __file_open_write(file);
|
||||
}
|
||||
|
||||
bool cache_file_open(struct cache_file *file, enum open_mode mode)
|
||||
{
|
||||
if (mode == OPEN_READ)
|
||||
return false;
|
||||
if ((string_length(file->cf_name) == 0) || (file->cf_file != NULL))
|
||||
return false;
|
||||
if (!__file_mkdir(g_get_user_cache_dir(), file->cf_subdir))
|
||||
if (mode == CLOSED)
|
||||
return false;
|
||||
|
||||
file->cf_file = __file_open(cache_file_write_path(file), "wb");
|
||||
return file->cf_file != NULL;
|
||||
if (mode == OPEN_READ || mode == OPEN_READ_BINARY)
|
||||
return __file_open_read(file, mode);
|
||||
return __file_open_write(file, mode);
|
||||
}
|
||||
|
||||
void file_close(struct file *file)
|
||||
{
|
||||
__file_close(file->f_file,
|
||||
file->f_mode == OPEN_WRITE ? file_path(file) : NULL,
|
||||
file->f_mode == OPEN_WRITE ? file_write_path(file) : NULL);
|
||||
gchar *path = file_path(file);
|
||||
gchar *tmp = file_write_path(file);
|
||||
|
||||
if (file->f_file) {
|
||||
fclose(file->f_file);
|
||||
if (file->f_mode == OPEN_WRITE || file->f_mode == OPEN_WRITE_BINARY)
|
||||
g_rename(tmp, path);
|
||||
}
|
||||
|
||||
file->f_file = NULL;
|
||||
file->f_mode = CLOSED;
|
||||
|
||||
g_free(path);
|
||||
g_free(tmp);
|
||||
}
|
||||
|
||||
void cache_file_close(struct cache_file *file)
|
||||
gchar *file_readw(struct file *file)
|
||||
{
|
||||
__file_close(file->cf_file,
|
||||
cache_file_path(file),
|
||||
cache_file_write_path(file));
|
||||
file->cf_file = NULL;
|
||||
}
|
||||
|
||||
int file_readf(struct file *file, const char *fmt, ...)
|
||||
{
|
||||
va_list argp;
|
||||
int ret;
|
||||
|
||||
va_start(argp, fmt);
|
||||
ret = vfscanf(file->f_file, fmt, argp);
|
||||
va_end(argp);
|
||||
|
||||
return ret;
|
||||
gchar *s;
|
||||
return fscanf(file->f_file, "%ms%*c", &s) ? s : g_strdup("");
|
||||
}
|
||||
|
||||
gchar *file_readl(struct file *file)
|
||||
{
|
||||
gchar *res;
|
||||
gchar *s = NULL;
|
||||
size_t len = 0;
|
||||
return getline(&s, &len, file->f_file) ? g_strchomp(s) : g_strdup("");
|
||||
}
|
||||
|
||||
if (file_readf(file, "%m[^\n]\n", &res) == 0)
|
||||
return g_strdup("");
|
||||
|
||||
g_strstrip(res);
|
||||
return res;
|
||||
unsigned int file_readu(struct file *file)
|
||||
{
|
||||
unsigned int u;
|
||||
return fscanf(file->f_file, "%u%*c", &u) ? u : 0;
|
||||
}
|
||||
|
||||
int file_writef(struct file *file, const char *fmt, ...)
|
||||
|
@ -266,36 +222,57 @@ int file_writef(struct file *file, const char *fmt, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int cache_file_write(struct cache_file *file, const void *data, size_t len)
|
||||
gchar *file_read(struct file *file)
|
||||
{
|
||||
if (fwrite(data, len, 1, file->cf_file) == 1)
|
||||
int fd = fileno(file->f_file);
|
||||
struct stat st;
|
||||
gchar *buf;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return NULL;
|
||||
|
||||
buf = g_malloc0(st.st_size + 1);
|
||||
if (fread(buf, st.st_size, 1, file->f_file) == 1)
|
||||
return buf;
|
||||
|
||||
g_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int file_write(struct file *file, const void *data, size_t len)
|
||||
{
|
||||
if (fwrite(data, len, 1, file->f_file) == 1)
|
||||
return len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool cache_file_import(struct cache_file *file, const gchar *srcpath)
|
||||
bool file_import(struct file *file, const gchar *srcpath)
|
||||
{
|
||||
gchar *contents = NULL;
|
||||
gsize length = 0;
|
||||
|
||||
if (!file->cf_file || !srcpath)
|
||||
if (!file->f_file || !srcpath)
|
||||
return false;
|
||||
if (!g_file_get_contents(srcpath, &contents, &length, NULL))
|
||||
return false;
|
||||
|
||||
cache_file_write(file, contents, length);
|
||||
file_write(file, contents, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool file_remove(struct file *file)
|
||||
{
|
||||
gchar *path, *dir;
|
||||
int ret = -1;
|
||||
gchar *path;
|
||||
|
||||
if (!file->f_file) {
|
||||
path = file_path(file);
|
||||
ret = g_unlink(path);
|
||||
dir = g_path_get_dirname(path);
|
||||
if (string_length(file->f_subdir) > 0)
|
||||
g_rmdir(dir);
|
||||
g_free(path);
|
||||
g_free(dir);
|
||||
}
|
||||
|
||||
return ret == 0;
|
||||
|
|
|
@ -208,6 +208,20 @@ bool playlist_sort(struct playlist *playlist, enum compare_t sort)
|
|||
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)
|
||||
{
|
||||
gchar **tokens = NULL;
|
||||
|
|
|
@ -5,19 +5,21 @@
|
|||
#include <core/playlists/artist.h>
|
||||
#include <core/string.h>
|
||||
|
||||
static struct file artist_file = FILE_INIT("playlist.artist", 0);
|
||||
static struct file artist_file = FILE_INIT_DATA("", "playlist.artist", 0);
|
||||
|
||||
static struct playlist_ops pl_artist_ops = {
|
||||
.pl_can_select = playlist_generic_can_select,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
static struct playlist *__artist_pl_alloc(struct artist *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)
|
||||
|
@ -50,7 +52,7 @@ static bool __artist_pl_load(void *data)
|
|||
if (!file_open(&artist_file, OPEN_READ))
|
||||
return true;
|
||||
|
||||
file_readf(&artist_file, "%u\n", &n);
|
||||
n = file_readu(&artist_file);
|
||||
for (i = 0; i < n; i++) {
|
||||
name = file_readl(&artist_file);
|
||||
playlist = __artist_pl_lookup(name);
|
||||
|
|
|
@ -38,26 +38,32 @@ void playlist_generic_set_callbacks(struct playlist_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) {
|
||||
g_queue_init(&playlist->pl_tracks);
|
||||
playlist->pl_length = 0;
|
||||
playlist->pl_random = false;
|
||||
playlist->pl_current = NULL;
|
||||
playlist->pl_sort = NULL;
|
||||
playlist->pl_search = NULL;
|
||||
}
|
||||
unsigned int i;
|
||||
|
||||
if (!playlist)
|
||||
return;
|
||||
|
||||
g_queue_init(&playlist->pl_tracks);
|
||||
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) {
|
||||
playlist_generic_init(playlist);
|
||||
playlist_generic_sort(playlist, COMPARE_ARTIST);
|
||||
playlist_generic_sort(playlist, COMPARE_YEAR);
|
||||
playlist_generic_sort(playlist, COMPARE_TRACK);
|
||||
}
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, nargs);
|
||||
__playlist_generic_vinit(playlist, nargs, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
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,
|
||||
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));
|
||||
va_list argp;
|
||||
|
||||
playlist->pl_name = name;
|
||||
playlist->pl_type = type;
|
||||
playlist->pl_id = id;
|
||||
playlist->pl_ops = ops;
|
||||
|
||||
playlist_generic_init_sorted(playlist);
|
||||
va_start(argp, nargs);
|
||||
__playlist_generic_vinit(playlist, nargs, argp);
|
||||
if (callbacks)
|
||||
callbacks->pl_cb_alloc(playlist);
|
||||
va_end(argp);
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
||||
|
@ -134,39 +145,34 @@ void playlist_generic_load(struct playlist *playlist, struct file *file,
|
|||
{
|
||||
unsigned int f, n, i, t, it = 0;
|
||||
int field, ascending;
|
||||
gchar *line;
|
||||
|
||||
if (!playlist)
|
||||
return;
|
||||
|
||||
if (flags & PL_SAVE_ITER)
|
||||
file_readf(file, "%u", &it);
|
||||
it = file_readu(file);
|
||||
|
||||
if (flags & PL_SAVE_FLAGS) {
|
||||
file_readf(file, "%u %u", &f, &n);
|
||||
f = file_readu(file);
|
||||
n = file_readu(file);
|
||||
playlist_clear_sort(playlist);
|
||||
for (i = 0; i < n; i++) {
|
||||
file_readf(file, "%u %d", &field, &ascending);
|
||||
field += 1;
|
||||
field = file_readu(file) + 1;
|
||||
ascending = file_readd(file);
|
||||
if (!ascending)
|
||||
field = -field;
|
||||
playlist->pl_sort = g_slist_append(playlist->pl_sort,
|
||||
GINT_TO_POINTER(field));
|
||||
}
|
||||
playlist_generic_resort(playlist);
|
||||
|
||||
if (file_readf(file, "%m\n", &line))
|
||||
g_free(line);
|
||||
}
|
||||
|
||||
if (flags & PL_SAVE_TRACKS) {
|
||||
file_readf(file, "%u ", &n);
|
||||
n = file_readu(file);
|
||||
for (i = 0; i < n; i++) {
|
||||
file_readf(file, "%u", &t);
|
||||
t = file_readu(file);
|
||||
playlist_generic_add(playlist, track_get(t));
|
||||
}
|
||||
if (file_readf(file, "%m\n", &line))
|
||||
g_free(line);
|
||||
}
|
||||
|
||||
playlist_generic_set_random(playlist, f == PL_RANDOM);
|
||||
|
@ -274,6 +280,22 @@ void playlist_generic_resort(struct playlist *playlist)
|
|||
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)
|
||||
{
|
||||
unsigned int pos, size = playlist_size(playlist);
|
||||
|
|
|
@ -14,7 +14,7 @@ struct scan_data {
|
|||
};
|
||||
|
||||
static bool __lib_pl_scan_dir(void *);
|
||||
static struct file lib_file = FILE_INIT("playlist.library", 0);
|
||||
static struct file lib_file = FILE_INIT_DATA("", "playlist.library", 0);
|
||||
|
||||
static struct playlist_ops pl_library_ops;
|
||||
|
||||
|
@ -22,7 +22,9 @@ static struct playlist_ops pl_library_ops;
|
|||
static struct playlist *__lib_pl_alloc(struct library *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)
|
||||
|
@ -55,7 +57,7 @@ static bool __lib_pl_load(void *data)
|
|||
if (!file_open(&lib_file, OPEN_READ))
|
||||
return true;
|
||||
|
||||
file_readf(&lib_file, "%u\n", &n);
|
||||
n = file_readu(&lib_file);
|
||||
for (i = 0; i < n; i++) {
|
||||
name = file_readl(&lib_file);
|
||||
playlist = __lib_pl_lookup(name);
|
||||
|
@ -179,6 +181,7 @@ static struct playlist_ops pl_library_ops = {
|
|||
.pl_delete = pl_library_delete,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@ static struct playlist *pl_system_lookup(const gchar *);
|
|||
static struct playlist *pl_system_get(unsigned int);
|
||||
static void pl_system_save();
|
||||
|
||||
static struct file sys_file = FILE_INIT("playlist.db", 0);
|
||||
static struct file sys_deck_f = FILE_INIT("deck", 1);
|
||||
static struct file sys_collection_f = FILE_INIT("library.q", 0);
|
||||
static struct file sys_pl_file = FILE_INIT("playlist.system", 0);
|
||||
static struct file sys_file = FILE_INIT_DATA("", "playlist.db", 0);
|
||||
static struct file sys_deck_f = FILE_INIT_DATA("", "deck", 1);
|
||||
static struct file sys_collection_f = FILE_INIT_DATA("", "library.q", 0);
|
||||
static struct file sys_pl_file = FILE_INIT_DATA("", "playlist.system", 0);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -82,6 +82,7 @@ static struct playlist_ops favorites_ops = {
|
|||
.pl_remove = playlist_generic_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.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_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
@ -146,9 +148,9 @@ static bool sys_pl_queued_load()
|
|||
if (!file_open(&sys_deck_f, OPEN_READ))
|
||||
return true;
|
||||
|
||||
file_readf(&sys_deck_f, "%u", &num);
|
||||
num = file_readu(&sys_deck_f);
|
||||
for (i = 0; i < num; i++) {
|
||||
file_readf(&sys_deck_f, "%u", &flags);
|
||||
flags = file_readu(&sys_deck_f);
|
||||
flags &= PL_RANDOM;
|
||||
if (i == 0)
|
||||
playlist_generic_set_random(playlist,
|
||||
|
@ -183,6 +185,7 @@ static struct playlist_ops queued_ops = {
|
|||
.pl_remove = sys_pl_queued_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.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_set_random = playlist_generic_set_random,
|
||||
.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_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
@ -264,9 +269,10 @@ static bool __sys_pl_load()
|
|||
if (!file_open(&sys_file, OPEN_READ))
|
||||
return true;
|
||||
|
||||
file_readf(&sys_file, "%u\n", &n);
|
||||
n = file_readu(&sys_file);
|
||||
for (i = 0; i < n; i++) {
|
||||
file_readf(&sys_file, "%*u %m[^\n]\n", &name);
|
||||
file_readu(&sys_file);
|
||||
name = file_readl(&sys_file);
|
||||
if (string_match(name, "Banned")) {
|
||||
g_free(name);
|
||||
name = g_strdup("Hidden");
|
||||
|
@ -297,7 +303,7 @@ static bool __sys_pl_load_new()
|
|||
return true;
|
||||
}
|
||||
|
||||
file_readf(&sys_pl_file, "%u\n", &n);
|
||||
n = file_readu(&sys_pl_file);
|
||||
for (i = 0; i < n; i++) {
|
||||
load = PL_SAVE_METADATA;
|
||||
name = file_readl(&sys_pl_file);
|
||||
|
@ -413,7 +419,7 @@ void pl_system_init(void)
|
|||
switch (i) {
|
||||
case SYS_PL_QUEUED:
|
||||
case SYS_PL_HISTORY:
|
||||
playlist_generic_init(playlist);
|
||||
playlist_generic_init(playlist, 0);
|
||||
break;
|
||||
case SYS_PL_COLLECTION:
|
||||
case SYS_PL_UNPLAYED:
|
||||
|
@ -422,7 +428,8 @@ void pl_system_init(void)
|
|||
sys_pl_update(playlist);
|
||||
case SYS_PL_FAVORITES:
|
||||
case SYS_PL_HIDDEN:
|
||||
playlist_generic_init_sorted(playlist);
|
||||
playlist_generic_init(playlist, 4, COMPARE_ARTIST,
|
||||
COMPARE_YEAR, COMPARE_ALBUM, COMPARE_TRACK);
|
||||
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_id = index;
|
||||
playlist->pl_playlist.pl_ops = &user_ops;
|
||||
playlist_generic_init_sorted(&playlist->pl_playlist);
|
||||
playlist_generic_init(&playlist->pl_playlist, 0);
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ static struct playlist_ops user_ops = {
|
|||
.pl_remove = playlist_generic_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <core/settings.h>
|
||||
|
||||
static GHashTable *gui_settings = NULL;
|
||||
static struct file gui_settings_file = FILE_INIT("settings", 0);
|
||||
static struct file gui_settings_file = FILE_INIT_DATA("", "settings", 0);
|
||||
|
||||
|
||||
static void __settings_save_item(gpointer key, gpointer value, gpointer data)
|
||||
|
@ -29,9 +29,11 @@ static void __settings_read()
|
|||
unsigned int num, i, value;
|
||||
gchar *key;
|
||||
|
||||
file_readf(&gui_settings_file, "%u\n", &num);
|
||||
num = file_readu(&gui_settings_file);
|
||||
for (i = 0; i < num; i++) {
|
||||
file_readf(&gui_settings_file, "%m[^ ] %u\n", &key, &value);
|
||||
key = file_readw(&gui_settings_file);
|
||||
value = file_readu(&gui_settings_file);
|
||||
|
||||
g_hash_table_insert(gui_settings, key, GUINT_TO_POINTER(value));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,24 +19,35 @@
|
|||
static struct database album_db;
|
||||
static bool album_db_upgraded = false;
|
||||
|
||||
struct album_cache_file {
|
||||
struct file ac_file;
|
||||
gchar *ac_subdir;
|
||||
gchar *ac_name;
|
||||
};
|
||||
|
||||
static inline void __album_init_file(struct album *al, struct cache_file *f)
|
||||
struct album_cache_file *__album_alloc_file(struct album *al)
|
||||
{
|
||||
struct album_cache_file *ret = g_malloc(sizeof(struct album_cache_file));
|
||||
gchar *name = g_uri_escape_string(al->al_name, " ", true);
|
||||
cache_file_init(f, g_strdup_printf("%d", al->al_year),
|
||||
g_strdup_printf("%s.jpg", name));
|
||||
|
||||
ret->ac_subdir = g_strdup_printf("%d", al->al_year);
|
||||
ret->ac_name = g_strdup_printf("%s.jpg", name);
|
||||
file_init_cache(&ret->ac_file, ret->ac_subdir, ret->ac_name);
|
||||
|
||||
g_free(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void __album_deinit_file(struct cache_file *f)
|
||||
static inline void __album_free_file(struct album_cache_file *acf)
|
||||
{
|
||||
g_free(f->cf_subdir);
|
||||
g_free(f->cf_name);
|
||||
g_free(acf->ac_subdir);
|
||||
g_free(acf->ac_name);
|
||||
g_free(acf);
|
||||
}
|
||||
|
||||
static bool __album_fetch_cover(struct album *album, gchar *releaseid)
|
||||
{
|
||||
struct cache_file file;
|
||||
struct album_cache_file *file;
|
||||
CaaImageData image;
|
||||
CaaCoverArt *caa;
|
||||
gchar error[256];
|
||||
|
@ -52,13 +63,13 @@ static bool __album_fetch_cover(struct album *album, gchar *releaseid)
|
|||
goto out;
|
||||
}
|
||||
|
||||
__album_init_file(album, &file);
|
||||
if (cache_file_open(&file, OPEN_WRITE)) {
|
||||
cache_file_write(&file, caa_imagedata_data(image),
|
||||
caa_imagedata_size(image));
|
||||
cache_file_close(&file);
|
||||
file = __album_alloc_file(album);
|
||||
if (file_open(&file->ac_file, OPEN_WRITE_BINARY)) {
|
||||
file_write(&file->ac_file, caa_imagedata_data(image),
|
||||
caa_imagedata_size(image));
|
||||
file_close(&file->ac_file);
|
||||
}
|
||||
__album_deinit_file(&file);
|
||||
__album_free_file(file);
|
||||
|
||||
caa_imagedata_delete(image);
|
||||
out:
|
||||
|
@ -127,7 +138,8 @@ static bool __album_query_artist(struct album *album, struct artist *al_artist,
|
|||
gchar *release, *artist, *year;
|
||||
bool found = false;
|
||||
|
||||
if (!al_artist || strcmp(al_artist->ar_tokens[0], "various") == 0)
|
||||
if (!al_artist || !string_length(al_artist->ar_name) ||
|
||||
strcmp(al_artist->ar_tokens[0], "various") == 0)
|
||||
return false;
|
||||
|
||||
release = g_strdup_printf("release:\"%s\"~", lower);
|
||||
|
@ -351,40 +363,40 @@ bool album_match_token(struct album *album, const gchar *string)
|
|||
|
||||
bool album_artwork_exists(struct album *album)
|
||||
{
|
||||
struct cache_file file;
|
||||
struct album_cache_file *file;
|
||||
bool ret;
|
||||
|
||||
__album_init_file(album, &file);
|
||||
ret = cache_file_exists(&file);
|
||||
__album_deinit_file(&file);
|
||||
file = __album_alloc_file(album);
|
||||
ret = file_exists(&file->ac_file);
|
||||
__album_free_file(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gchar *album_artwork_path(struct album *album)
|
||||
{
|
||||
struct cache_file file;
|
||||
struct album_cache_file *file;
|
||||
gchar *ret = NULL;
|
||||
|
||||
__album_init_file(album, &file);
|
||||
if (cache_file_exists(&file))
|
||||
ret = cache_file_path(&file);
|
||||
__album_deinit_file(&file);
|
||||
file = __album_alloc_file(album);
|
||||
if (file_exists(&file->ac_file))
|
||||
ret = file_path(&file->ac_file);
|
||||
__album_free_file(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool album_artwork_import(struct album *album, gchar *path)
|
||||
{
|
||||
struct cache_file file;
|
||||
struct album_cache_file *file;
|
||||
bool ret = false;
|
||||
|
||||
__album_init_file(album, &file);
|
||||
if (path && cache_file_open(&file, OPEN_WRITE)) {
|
||||
ret = cache_file_import(&file, path);
|
||||
cache_file_close(&file);
|
||||
file = __album_alloc_file(album);
|
||||
if (path && file_open(&file->ac_file, OPEN_WRITE_BINARY)) {
|
||||
ret = file_import(&file->ac_file, path);
|
||||
file_close(&file->ac_file);
|
||||
}
|
||||
__album_deinit_file(&file);
|
||||
__album_free_file(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -35,13 +35,13 @@ static gchar *library_key(struct db_entry *dbe)
|
|||
|
||||
static struct db_entry *library_read(struct file *file, unsigned int index)
|
||||
{
|
||||
int enabled;
|
||||
gchar *path;
|
||||
|
||||
/* Old "enabled" flag */
|
||||
if (file_version(file) == 0)
|
||||
file_readf(file, "%d", &enabled);
|
||||
file_readd(file);
|
||||
|
||||
file_readf(file, " %m[^\n]", &path);
|
||||
path = file_readl(file);
|
||||
return &__library_alloc(path)->li_dbe;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,19 +128,13 @@ static gchar *track_key(struct db_entry *dbe)
|
|||
|
||||
static void track_read_v0(struct file *file, struct track *track)
|
||||
{
|
||||
unsigned int artist_id, album_id, genre_id;
|
||||
struct artist *artist;
|
||||
struct genre *genre;
|
||||
struct album *album;
|
||||
struct artist *artist = artist_get(file_readu(file));
|
||||
struct album *album = album_get( file_readu(file));
|
||||
struct genre *genre = genre_get( file_readu(file));
|
||||
|
||||
file_readf(file, "%u %u %u %hu", &artist_id, &album_id, &genre_id,
|
||||
&track->tr_track);
|
||||
track->tr_track = file_readhu(file);
|
||||
date_read(file, &track->tr_date);
|
||||
|
||||
album = album_get(album_id);
|
||||
artist = artist_get(artist_id);
|
||||
genre = genre_get(genre_id);
|
||||
|
||||
if (album->al_artist != artist || album->al_genre != genre)
|
||||
album = album_find(artist, genre, album->al_name, album->al_year);
|
||||
|
||||
|
@ -150,20 +144,19 @@ static void track_read_v0(struct file *file, struct track *track)
|
|||
static struct db_entry *track_read(struct file *file, unsigned int index)
|
||||
{
|
||||
struct track *track = __track_alloc();
|
||||
unsigned int library_id, album_id;
|
||||
|
||||
file_readf(file, "%u", &library_id);
|
||||
track->tr_library = library_get(library_id);
|
||||
track->tr_library = library_get(file_readu(file));
|
||||
|
||||
if (file_version(file) == 0)
|
||||
track_read_v0(file, track);
|
||||
else {
|
||||
file_readf(file, "%u %hu", &album_id, &track->tr_track);
|
||||
track->tr_album = album_get(album_id);
|
||||
track->tr_album = album_get(file_readu(file));
|
||||
track->tr_track = file_readhu(file);
|
||||
date_read_stamp(file, &track->tr_date);
|
||||
}
|
||||
|
||||
file_readf(file, "%hu %hu", &track->tr_count, &track->tr_length);
|
||||
track->tr_count = file_readhu(file);
|
||||
track->tr_length = file_readhu(file);
|
||||
|
||||
play_count += track->tr_count;
|
||||
if (track->tr_count == 0)
|
||||
|
|
100
gui/audio.c
100
gui/audio.c
|
@ -9,7 +9,8 @@
|
|||
#include <gui/treeview.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,
|
||||
const gchar *size,
|
||||
|
@ -42,16 +43,40 @@ static void __gui_audio_load(struct track *track)
|
|||
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)
|
||||
{
|
||||
bool playing = (state == GST_STATE_PLAYING);
|
||||
gtk_widget_set_visible(GTK_WIDGET(gui_play_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)
|
||||
{
|
||||
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,
|
||||
|
@ -98,6 +182,8 @@ void gui_audio_init()
|
|||
void gui_audio_deinit()
|
||||
{
|
||||
g_source_remove(audio_timeout);
|
||||
if (popover_timeout > 0)
|
||||
g_source_remove(popover_timeout);
|
||||
}
|
||||
|
||||
int gui_audio_timeout(gpointer data)
|
||||
|
@ -111,3 +197,9 @@ int gui_audio_timeout(gpointer data)
|
|||
g_free(position);
|
||||
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);
|
||||
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,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
return GTK_TREE_MODEL_LIST_ONLY;
|
||||
|
@ -169,6 +175,27 @@ static gboolean __gui_model_iter_parent(GtkTreeModel *model, GtkTreeIter *iter,
|
|||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.class_size = sizeof(GuiModelClass),
|
||||
.base_init = NULL,
|
||||
|
@ -221,6 +254,12 @@ static const GInterfaceInfo gui_tree_model = {
|
|||
.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)
|
||||
{
|
||||
|
@ -229,6 +268,9 @@ void gui_model_init(void)
|
|||
(GTypeFlags)0);
|
||||
g_type_add_interface_static(gui_model_type, GTK_TYPE_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);
|
||||
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)
|
||||
{
|
||||
gui_model_add(playlist, track);
|
||||
gui_filter_refilter(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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
struct playlist *playlist = playlist_current();
|
||||
|
|
155
gui/sidebar.c
155
gui/sidebar.c
|
@ -117,15 +117,12 @@ static gboolean __gui_sidebar_can_select(GtkTreeSelection *selection,
|
|||
|
||||
void __gui_sidebar_selection_changed(GtkTreeSelection *selection, gpointer data)
|
||||
{
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(gui_sidebar_filter());
|
||||
bool active = false, sensitive = false;
|
||||
struct playlist *playlist = NULL;
|
||||
GtkTreeIter iter, child;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
|
||||
__gui_sidebar_filter_iter_convert(&iter, &child);
|
||||
|
||||
playlist = gui_sidebar_iter_playlist(&child);
|
||||
if (gui_sidebar_iter_current(&iter)) {
|
||||
playlist = gui_sidebar_iter_playlist(&iter);
|
||||
active = playlist->pl_random;
|
||||
sensitive = (playlist->pl_ops->pl_set_random != NULL);
|
||||
}
|
||||
|
@ -135,47 +132,108 @@ void __gui_sidebar_selection_changed(GtkTreeSelection *selection, gpointer data)
|
|||
gtk_widget_set_sensitive(GTK_WIDGET(gui_random_button()), sensitive);
|
||||
}
|
||||
|
||||
static void __gui_sidebar_do_rename(GtkTreePath *path)
|
||||
{
|
||||
GtkTreeView *treeview = gui_sidebar_treeview();
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
|
||||
GtkTreeViewColumn *column = gtk_tree_view_get_column(treeview, SB_NAME);
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
if (!gtk_tree_model_get_iter(model, &iter, path))
|
||||
return;
|
||||
|
||||
__gui_sidebar_filter_iter_convert(&iter, &child);
|
||||
gui_sidebar_iter_set_editable(&child, true);
|
||||
gtk_tree_view_set_cursor(treeview, path, column, true);
|
||||
}
|
||||
|
||||
static GtkTreePath *__gui_sidebar_current_path(void)
|
||||
{
|
||||
GtkTreeView *treeview = gui_sidebar_treeview();
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||
return NULL;
|
||||
return gtk_tree_model_get_path(model, &iter);
|
||||
}
|
||||
|
||||
bool __gui_sidebar_rename(GtkMenuItem *item, gpointer data)
|
||||
{
|
||||
GtkTreePath *path = __gui_sidebar_current_path();
|
||||
if (path) {
|
||||
__gui_sidebar_do_rename(path);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
return path != NULL;
|
||||
}
|
||||
|
||||
bool __gui_sidebar_select(GtkMenuItem *item, gpointer data)
|
||||
{
|
||||
GtkTreeView *treeview = gui_sidebar_treeview();
|
||||
GtkTreePath *path = __gui_sidebar_current_path();
|
||||
|
||||
if (path) {
|
||||
gtk_tree_view_row_activated(treeview, path, NULL);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
return path != NULL;
|
||||
}
|
||||
|
||||
bool __gui_sidebar_delete(GtkMenuItem *item, gpointer data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!gui_sidebar_iter_current(&iter))
|
||||
return false;
|
||||
if (playlist_delete(gui_model_get_playlist()))
|
||||
gtk_tree_store_remove(gui_sidebar_store(), &iter);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool __gui_sidebar_keypress(GtkTreeView *treeview, GdkEventKey *event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
|
||||
struct playlist *playlist = gui_model_get_playlist();
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(gui_sidebar_filter());
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
if (!playlist || event->keyval != GDK_KEY_Delete)
|
||||
switch (event->keyval) {
|
||||
case GDK_KEY_BackSpace:
|
||||
return __gui_sidebar_rename(NULL, NULL);
|
||||
case GDK_KEY_Return:
|
||||
return __gui_sidebar_select(NULL, NULL);
|
||||
case GDK_KEY_Delete:
|
||||
return __gui_sidebar_delete(NULL, NULL);
|
||||
default:
|
||||
return false;
|
||||
if (!gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||
return false;
|
||||
|
||||
__gui_sidebar_filter_iter_convert(&iter, &child);
|
||||
if (playlist_delete(playlist))
|
||||
gtk_tree_store_remove(gui_sidebar_store(), &child);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool __gui_sidebar_button_press(GtkTreeView *treeview, GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
|
||||
GtkTreeViewColumn *column = gtk_tree_view_get_column(treeview, SB_NAME);
|
||||
GtkTreeIter iter, child;
|
||||
enum playlist_type_t type = PL_MAX_TYPE;
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
bool ret = true;
|
||||
|
||||
if (event->type != GDK_2BUTTON_PRESS ||
|
||||
event->button != GDK_BUTTON_MIDDLE)
|
||||
return false;
|
||||
if (!gtk_tree_view_get_path_at_pos(treeview, event->x, event->y,
|
||||
&path, NULL, NULL, NULL))
|
||||
return true;
|
||||
if (!gtk_tree_model_get_iter(model, &iter, path))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
if (event->button == GDK_BUTTON_SECONDARY) {
|
||||
gtk_tree_view_set_cursor(treeview, path, NULL, false);
|
||||
if (gui_sidebar_iter_current(&iter))
|
||||
type = gui_sidebar_iter_type(&iter);
|
||||
gtk_widget_set_visible(gui_builder_widget("rc_sidebar_rename"),
|
||||
type == PL_USER);
|
||||
gtk_menu_popup_at_pointer(gui_sidebar_menu(), (GdkEvent *)event);
|
||||
} else if (event->type == GDK_2BUTTON_PRESS &&
|
||||
event->button == GDK_BUTTON_MIDDLE) {
|
||||
__gui_sidebar_do_rename(path);
|
||||
} else
|
||||
ret = false;
|
||||
|
||||
__gui_sidebar_filter_iter_convert(&iter, &child);
|
||||
gui_sidebar_iter_set_editable(&child, true);
|
||||
gtk_tree_view_set_cursor(treeview, path, column, true);
|
||||
gtk_tree_path_free(path);
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __gui_sidebar_resized(GtkPaned *pane, GParamSpec *pspec, gpointer data)
|
||||
|
@ -198,6 +256,10 @@ void gui_sidebar_init()
|
|||
GtkTreeSelection *selection;
|
||||
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)) {
|
||||
__gui_sidebar_add_header(&iter, "Playlists", "emblem-documents");
|
||||
__gui_sidebar_add_header(&iter, "Dynamic", "emblem-generic");
|
||||
|
@ -216,6 +278,19 @@ void gui_sidebar_init()
|
|||
gtk_paned_set_position(gui_sidebar(), pos);
|
||||
}
|
||||
|
||||
gboolean gui_sidebar_iter_current(GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreeView *treeview = gui_sidebar_treeview();
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(gui_sidebar_filter());
|
||||
GtkTreeIter it;
|
||||
|
||||
if (!gtk_tree_selection_get_selected(selection, &model, &it))
|
||||
return false;
|
||||
__gui_sidebar_filter_iter_convert(&it, iter);
|
||||
return true;
|
||||
}
|
||||
|
||||
gboolean gui_sidebar_iter_first(GtkTreeIter *iter)
|
||||
{
|
||||
return gtk_tree_model_get_iter_first(gui_sidebar_model(), iter);
|
||||
|
@ -415,3 +490,19 @@ gboolean gui_sidebar_iter_from_string(const gchar *path, GtkTreeIter *child)
|
|||
__gui_sidebar_filter_iter_convert(&iter, child);
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
GtkTreeViewColumn *col;
|
||||
|
@ -167,6 +204,12 @@ void gui_treeview_init()
|
|||
|
||||
gtk_tree_view_set_model(gui_treeview(),
|
||||
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++) {
|
||||
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)
|
||||
{
|
||||
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,
|
||||
&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);
|
||||
}
|
||||
}
|
||||
|
||||
GList *gui_treeview_list_selected_tracks(void)
|
||||
{
|
||||
GList *rows, *cur, *list = NULL;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection(gui_treeview());
|
||||
rows = gtk_tree_selection_get_selected_rows(selection, NULL);
|
||||
cur = g_list_first(rows);
|
||||
GtkTreeSelection *selection = gui_treeview_selection();
|
||||
GList *rows = gtk_tree_selection_get_selected_rows(selection, NULL);
|
||||
GList *cur = g_list_first(rows);
|
||||
GList *list = NULL;
|
||||
|
||||
while (cur) {
|
||||
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. */
|
||||
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
|
||||
void test_audio_eos();
|
||||
|
|
|
@ -78,7 +78,7 @@ struct database {
|
|||
{ \
|
||||
.db_size = 0, \
|
||||
.db_autosave = autosave, \
|
||||
.db_file = FILE_INIT(fname, fmin), \
|
||||
.db_file = FILE_INIT_DATA("", fname, fmin), \
|
||||
.db_entries = g_ptr_array_new(), \
|
||||
.db_keys = g_hash_table_new(g_str_hash, g_str_equal), \
|
||||
.db_ops = ops, \
|
||||
|
|
|
@ -30,105 +30,100 @@
|
|||
|
||||
|
||||
enum open_mode {
|
||||
OPEN_READ,
|
||||
OPEN_WRITE,
|
||||
CLOSED, /* File is not open. */
|
||||
OPEN_READ, /* File is open for reading text. */
|
||||
OPEN_READ_BINARY, /* File is open for reading binary data. */
|
||||
OPEN_WRITE, /* File is open for writing text. */
|
||||
OPEN_WRITE_BINARY, /* File is open for writing binary data. */
|
||||
};
|
||||
|
||||
struct file {
|
||||
FILE *f_file; /* The file's IO stream. */
|
||||
const gchar *f_name; /* The file's basename. */
|
||||
const gchar *f_subdir; /* The file's subdirectory. */
|
||||
|
||||
enum open_mode f_mode; /* The file's current open mode. */
|
||||
unsigned int f_version; /* The file's current data version. */
|
||||
unsigned int f_prev; /* The file's on-disk data version. */
|
||||
unsigned int f_min; /* The file's minimum data version. */
|
||||
FILE *f_file; /* The file's IO stream. */
|
||||
const gchar *f_name; /* The file's basename. */
|
||||
|
||||
const gchar *(*f_user_dir)(void); /* The file's user directory. */
|
||||
};
|
||||
|
||||
#define FILE_INIT(fname, min) \
|
||||
{ \
|
||||
.f_mode = OPEN_READ, \
|
||||
.f_version = OCARINA_MINOR_VERSION, \
|
||||
.f_prev = 0, \
|
||||
.f_min = min, \
|
||||
.f_file = NULL, \
|
||||
.f_name = fname, \
|
||||
#define FILE_INIT_DATA(fdir, fname, min) \
|
||||
{ \
|
||||
.f_file = NULL, \
|
||||
.f_name = fname, \
|
||||
.f_subdir = fdir, \
|
||||
.f_mode = CLOSED, \
|
||||
.f_version = OCARINA_MINOR_VERSION, \
|
||||
.f_prev = 0, \
|
||||
.f_min = min, \
|
||||
.f_user_dir = g_get_user_data_dir, \
|
||||
}
|
||||
|
||||
|
||||
struct cache_file {
|
||||
FILE *cf_file; /* The cache file's IO stream. */
|
||||
gchar *cf_name; /* The cache file's basename. */
|
||||
gchar *cf_subdir; /* The cache file's subdirectory. */
|
||||
};
|
||||
|
||||
#define CACHE_FILE_INIT(cfsubdir, cfname) \
|
||||
{ \
|
||||
.cf_file = NULL, \
|
||||
.cf_subdir = cfsubdir, \
|
||||
.cf_name = cfname, \
|
||||
}
|
||||
|
||||
/* Initialize a new file object. */
|
||||
void file_init(struct file *, const gchar *, unsigned int);
|
||||
void cache_file_init(struct cache_file *, gchar *, gchar *);
|
||||
/* Initialize a file object. */
|
||||
void file_init_data(struct file *, const gchar *, const gchar *, unsigned int);
|
||||
void file_init_cache(struct file *, const gchar *, const gchar *);
|
||||
|
||||
/*
|
||||
* Returns the full path of the file or an empty string if filename is not set.
|
||||
* These functions allocates a new string that MUST be freed with g_free().
|
||||
* NOTE: This function allocates a new string that MUST be freed with g_free().
|
||||
*/
|
||||
gchar *file_path(struct file *);
|
||||
gchar *cache_file_path(struct cache_file *);
|
||||
|
||||
/*
|
||||
* Returns the path to the temporary file used for writes.
|
||||
* This function allocates a new string that MUST be freed with g_free().
|
||||
* NOTE: This function allocates a new string that MUST be freed with g_free().
|
||||
*/
|
||||
gchar *file_write_path(struct file *);
|
||||
gchar *cache_file_write_path(struct cache_file *);
|
||||
|
||||
/* Returns the version number of the file. */
|
||||
const unsigned int file_version(struct file *);
|
||||
|
||||
/* Returns true if the file exists on disk and false otherwise. */
|
||||
bool file_exists(struct file *);
|
||||
bool cache_file_exists(struct cache_file *);
|
||||
|
||||
/*
|
||||
* Call to open a file for either reading or writing. Callers
|
||||
* are expected to call file_close() when IO is completed.
|
||||
*
|
||||
* When opening a file for reading (OPEN_READ):
|
||||
* - Check if the file exists.
|
||||
* - Read in file->_prev_version from the start of the file.
|
||||
* When opening a file for reading (OPEN_READ / OPEN_READ_BINARY):
|
||||
* - Check if the file exists
|
||||
* - If open for reading text (OPEN_READ):
|
||||
* - Read in file->_prev_version from the start of the file.
|
||||
*
|
||||
* When opening a file for writing (OPEN_WRITE):
|
||||
* When opening a file for writing (OPEN_WRITE / OPEN_WRITE_BINARY):
|
||||
* - Create missing directories as needed.
|
||||
* - Open a temporary file to protect data if Ocarina crashes.
|
||||
* - Write file->_version to the start of the file (data files only).
|
||||
* - If open for writing text (OPEN_WRITE):
|
||||
* - Write file->_version to the start of the file (data files only).
|
||||
*
|
||||
* Returns true if the open was successful and false otherwise.
|
||||
* Oening a cache file with OPEN_READ is currently unsupported.
|
||||
*/
|
||||
bool file_open(struct file *, enum open_mode);
|
||||
bool cache_file_open(struct cache_file *, enum open_mode);
|
||||
|
||||
/*
|
||||
* Closes an open file, setting file->{f|cf}_file to NULL. If the file was opened
|
||||
* with OPEN_WRITE, then rename the temporary file to file_path().
|
||||
* Closes an open file, setting file->f_file to NULL and file->f_mode
|
||||
* to CLOSED. If the file was opened for writing, then rename the
|
||||
* temporary file to file_path().
|
||||
*/
|
||||
void file_close(struct file *);
|
||||
void cache_file_close(struct cache_file *);
|
||||
|
||||
/*
|
||||
* Read an entire line from the file and return it to the caller.
|
||||
* This function allocates a new string that MUST be freed with g_free().
|
||||
* Called to read an unsigned int, signed int, single word, or entire
|
||||
* line from the file.
|
||||
* NOTE: file_readw() and file_readl() both return a new string that
|
||||
* MUST be freed with g_free()
|
||||
*/
|
||||
gchar *file_readw(struct file *);
|
||||
gchar *file_readl(struct file *);
|
||||
|
||||
/*
|
||||
* Read from a file with an fscanf(3) style format string.
|
||||
* Returns the number of items matched.
|
||||
*/
|
||||
int file_readf(struct file *, const char *, ...);
|
||||
unsigned int file_readu(struct file *);
|
||||
static inline int file_readd(struct file *file)
|
||||
{ return (int)file_readu(file); }
|
||||
static inline unsigned short int file_readhu(struct file *file)
|
||||
{ return (unsigned short int)file_readu(file); }
|
||||
|
||||
/*
|
||||
* Write to a file with an fprintf(3) style format string.
|
||||
|
@ -137,13 +132,19 @@ int file_readf(struct file *, const char *, ...);
|
|||
int file_writef(struct file *, const char *, ...);
|
||||
|
||||
/*
|
||||
* Write binary data to a cache file similar to fwrite(3).
|
||||
* Reads the contents of a file as binary data.
|
||||
* NOTE: This function returns a new string which MUST be freed with g_free().
|
||||
*/
|
||||
gchar *file_read(struct file *);
|
||||
|
||||
/*
|
||||
* Write binary data a cache file, similar to fwrite(3).
|
||||
* Returns the number of bytes successfully written.
|
||||
*/
|
||||
int cache_file_write(struct cache_file *, const void *, size_t);
|
||||
int file_write(struct file *, const void *, size_t);
|
||||
|
||||
/* Import a file into the cache. */
|
||||
bool cache_file_import(struct cache_file *, const gchar *);
|
||||
bool file_import(struct file *, const gchar *);
|
||||
|
||||
/* Removes a closed file from disk. */
|
||||
bool file_remove(struct file *);
|
||||
|
|
|
@ -71,6 +71,9 @@ void playlist_set_random(struct playlist *, bool);
|
|||
/* Called to change the sort order of the playlist. */
|
||||
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 */
|
||||
void playlist_set_search(struct playlist *, const gchar *);
|
||||
|
|
|
@ -40,15 +40,15 @@ struct playlist_callbacks {
|
|||
void playlist_generic_set_callbacks(struct playlist_callbacks *);
|
||||
|
||||
/* Generic playlist init functions. */
|
||||
void playlist_generic_init(struct playlist *);
|
||||
void playlist_generic_init_sorted(struct playlist *);
|
||||
void playlist_generic_init(struct playlist *, unsigned int, ...);
|
||||
|
||||
/* Generic playlist deinit function. */
|
||||
void playlist_generic_deinit(struct playlist *);
|
||||
|
||||
/* Generic playlist alloc function. */
|
||||
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. */
|
||||
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_resort(struct playlist *);
|
||||
|
||||
/* Generic playlist rearranging operation. */
|
||||
bool playlist_generic_rearrange(struct playlist *, unsigned int, unsigned int);
|
||||
|
||||
/* Generic playlist next track operation. */
|
||||
struct track *playlist_generic_next(struct playlist *);
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ struct playlist_ops {
|
|||
|
||||
/* Called to sort the playlist. */
|
||||
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. */
|
||||
int gui_audio_timeout();
|
||||
int gui_audio_popover_timeout();
|
||||
|
||||
/* Called to get the label displaying the album tag. */
|
||||
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"));
|
||||
}
|
||||
|
||||
/* Called to get the pause-fater combobox. */
|
||||
static inline GtkComboBoxText *gui_pause_after(void)
|
||||
/* Called to get the pause-after widgets. */
|
||||
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. */
|
||||
|
|
|
@ -38,6 +38,9 @@ unsigned int gui_filter_path_get_index(GtkTreePath *);
|
|||
/* Called to convert a playlist iterator index into a path. */
|
||||
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. */
|
||||
static inline GtkSearchEntry *gui_filter_search(void)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,15 @@ struct gui_model_class {
|
|||
};
|
||||
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 */
|
||||
void gui_model_init(void);
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
/* Called to initialize the sidebar. */
|
||||
void gui_sidebar_init();
|
||||
|
||||
/* Called to set an iterator to the currently displayed playlist. */
|
||||
gboolean gui_sidebar_iter_current(GtkTreeIter *);
|
||||
|
||||
/* Called to set an iterator to the first playlist. */
|
||||
gboolean gui_sidebar_iter_first(GtkTreeIter *);
|
||||
|
||||
|
@ -73,6 +76,9 @@ gboolean gui_sidebar_iter_find(GtkTreeIter *, const gchar *,
|
|||
/* Called to set the a GtkTreeIter to the row at path string */
|
||||
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. */
|
||||
static inline GtkPaned *gui_sidebar()
|
||||
{
|
||||
|
@ -103,6 +109,12 @@ static inline GtkTreeView *gui_sidebar_treeview()
|
|||
return GTK_TREE_VIEW(gui_builder_widget("sidebar_treeview"));
|
||||
}
|
||||
|
||||
/* Called to get the sidebar right-click menu. */
|
||||
static inline GtkMenu *gui_sidebar_menu()
|
||||
{
|
||||
return GTK_MENU(gui_builder_widget("rc_sidebar"));
|
||||
}
|
||||
|
||||
/* Called to get the random button. */
|
||||
static inline GtkToggleButton *gui_random_button()
|
||||
{
|
||||
|
|
|
@ -32,6 +32,12 @@ static inline GtkTreeView *gui_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. */
|
||||
static inline GtkLabel *gui_sorting()
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<!-- Generated with glade 3.20.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
|
@ -88,6 +88,58 @@
|
|||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="image25">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">dialog-ok</property>
|
||||
<property name="icon_size">1</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image26">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">edit-delete</property>
|
||||
<property name="icon_size">1</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image27">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">document-edit</property>
|
||||
<property name="icon_size">1</property>
|
||||
</object>
|
||||
<object class="GtkMenu" id="rc_sidebar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem">
|
||||
<property name="label" translatable="yes">Select Playlist</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image25</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="__gui_sidebar_select" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="rc_sidebar_rename">
|
||||
<property name="label" translatable="yes">Rename Playlist</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image27</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="__gui_sidebar_rename" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem">
|
||||
<property name="label" translatable="yes">Delete Playlist</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="image">image26</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="__gui_sidebar_delete" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="image3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
|
@ -214,7 +266,7 @@
|
|||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<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>
|
||||
<object class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
|
@ -480,7 +532,6 @@ audio-volume-medium</property>
|
|||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -546,132 +597,83 @@ audio-volume-medium</property>
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<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">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="active">0</property>
|
||||
<items>
|
||||
<item translatable="yes">(disabled)</item>
|
||||
<item translatable="yes">this track</item>
|
||||
<item translatable="yes">next track</item>
|
||||
<item translatable="yes">2 tracks</item>
|
||||
<item translatable="yes">3 tracks</item>
|
||||
<item translatable="yes">4 tracks</item>
|
||||
<item translatable="yes">5 tracks</item>
|
||||
<item translatable="yes">6 tracks</item>
|
||||
<item translatable="yes">7 tracks</item>
|
||||
<item translatable="yes">8 tracks</item>
|
||||
<item translatable="yes">9 tracks</item>
|
||||
<item translatable="yes">10 tracks</item>
|
||||
<item translatable="yes">11 tracks</item>
|
||||
<item translatable="yes">12 tracks</item>
|
||||
<item translatable="yes">13 tracks</item>
|
||||
<item translatable="yes">14 tracks</item>
|
||||
<item translatable="yes">15 tracks</item>
|
||||
<item translatable="yes">16 tracks</item>
|
||||
<item translatable="yes">17 tracks</item>
|
||||
<item translatable="yes">18 tracks</item>
|
||||
<item translatable="yes">19 tracks</item>
|
||||
<item translatable="yes">20 tracks</item>
|
||||
<item translatable="yes">21 tracks</item>
|
||||
<item translatable="yes">22 tracks</item>
|
||||
<item translatable="yes">23 tracks</item>
|
||||
<item translatable="yes">24 tracks</item>
|
||||
<item translatable="yes">25 tracks</item>
|
||||
<item translatable="yes">26 tracks</item>
|
||||
<item translatable="yes">27 tracks</item>
|
||||
<item translatable="yes">28 tracks</item>
|
||||
<item translatable="yes">29 tracks</item>
|
||||
<item translatable="yes">30 tracks</item>
|
||||
<item translatable="yes">31 tracks</item>
|
||||
<item translatable="yes">32 tracks</item>
|
||||
<item translatable="yes">33 tracks</item>
|
||||
<item translatable="yes">34 tracks</item>
|
||||
<item translatable="yes">35 tracks</item>
|
||||
<item translatable="yes">36 tracks</item>
|
||||
<item translatable="yes">37 tracks</item>
|
||||
<item translatable="yes">38 tracks</item>
|
||||
<item translatable="yes">39 tracks</item>
|
||||
<item translatable="yes">40 tracks</item>
|
||||
<item translatable="yes">41 tracks</item>
|
||||
<item translatable="yes">42 tracks</item>
|
||||
<item translatable="yes">43 tracks</item>
|
||||
<item translatable="yes">44 tracks</item>
|
||||
<item translatable="yes">45 tracks</item>
|
||||
<item translatable="yes">46 tracks</item>
|
||||
<item translatable="yes">47 tracks</item>
|
||||
<item translatable="yes">48 tracks</item>
|
||||
<item translatable="yes">49 tracks</item>
|
||||
<item translatable="yes">50 tracks</item>
|
||||
<item translatable="yes">51 tracks</item>
|
||||
<item translatable="yes">52 tracks</item>
|
||||
<item translatable="yes">53 tracks</item>
|
||||
<item translatable="yes">54 tracks</item>
|
||||
<item translatable="yes">55 tracks</item>
|
||||
<item translatable="yes">56 tracks</item>
|
||||
<item translatable="yes">57 tracks</item>
|
||||
<item translatable="yes">58 tracks</item>
|
||||
<item translatable="yes">59 tracks</item>
|
||||
<item translatable="yes">60 tracks</item>
|
||||
<item translatable="yes">61 tracks</item>
|
||||
<item translatable="yes">62 tracks</item>
|
||||
<item translatable="yes">63 tracks</item>
|
||||
<item translatable="yes">64 tracks</item>
|
||||
<item translatable="yes">65 tracks</item>
|
||||
<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"/>
|
||||
<child>
|
||||
<object class="GtkEntry" id="pause_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="text" translatable="yes">Paused</property>
|
||||
<signal name="activate" handler="__gui_audio_pause_change_text" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="pause_down">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="can-activate-accel" handler="__gui_audio_can_accel" swapped="no"/>
|
||||
<signal name="clicked" handler="__gui_audio_pause_dec" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">list-remove-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<accelerator key="minus" signal="clicked"/>
|
||||
<accelerator key="KP_Subtract" signal="clicked"/>
|
||||
<style>
|
||||
<class name="down"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="pause_up">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="can-activate-accel" handler="__gui_audio_can_accel" swapped="no"/>
|
||||
<signal name="clicked" handler="__gui_audio_pause_inc" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<accelerator key="plus" signal="clicked"/>
|
||||
<accelerator key="KP_Add" signal="clicked"/>
|
||||
<style>
|
||||
<class name="up"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="height">2</property>
|
||||
</packing>
|
||||
|
@ -766,6 +768,8 @@ audio-volume-medium</property>
|
|||
<property name="search_column">1</property>
|
||||
<property name="enable_tree_lines">True</property>
|
||||
<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="row-activated" handler="__gui_playlist_row_activated" swapped="no"/>
|
||||
<signal name="row-collapsed" handler="__gui_playlist_row_collapsed" swapped="no"/>
|
||||
|
@ -830,7 +834,7 @@ audio-volume-medium</property>
|
|||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -910,6 +914,8 @@ audio-volume-medium</property>
|
|||
<property name="rubber_banding">True</property>
|
||||
<property name="tooltip_column">9</property>
|
||||
<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="row-activated" handler="__gui_treeview_row_activated" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
|
@ -1115,7 +1121,7 @@ audio-volume-medium</property>
|
|||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="width">5</property>
|
||||
<property name="width">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -1141,4 +1147,55 @@ audio-volume-medium</property>
|
|||
<widget name="filter_how"/>
|
||||
</widgets>
|
||||
</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>
|
||||
|
|
|
@ -62,6 +62,7 @@ static void test_init()
|
|||
g_assert_cmpuint(audio_get_volume(), ==, 100);
|
||||
g_assert_null(audio_cur_track());
|
||||
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(state_count, ==, 0);
|
||||
|
||||
|
@ -201,20 +202,32 @@ void test_autopause()
|
|||
struct playlist *history = playlist_lookup(PL_SYSTEM, "History");
|
||||
int i;
|
||||
|
||||
audio_pause_after(3);
|
||||
g_assert_cmpuint(pause_count, ==, 3);
|
||||
g_assert_true(audio_pause_after(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;
|
||||
audio_pause_after(3);
|
||||
g_assert_cmpuint(pause_count, ==, 0);
|
||||
g_assert_false(audio_pause_after(3));
|
||||
g_assert_cmpint(pause_count, ==, 0);
|
||||
g_assert_cmpint(audio_get_pause_count(), ==, 3);
|
||||
|
||||
audio_pause_after(5);
|
||||
g_assert_cmpuint(pause_count, ==, 5);
|
||||
g_assert_true(audio_pause_after(-1));
|
||||
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;
|
||||
for (i = 4; i > -1; i--) {
|
||||
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(playlist_at(history, 0) == audio_cur_track());
|
||||
}
|
||||
|
@ -223,6 +236,7 @@ void test_autopause()
|
|||
test_audio_eos();
|
||||
while (idle_run_task()) {}
|
||||
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(test_wait_state(), ==, 6);
|
||||
|
||||
|
|
|
@ -46,9 +46,7 @@ static gchar *int_key(struct db_entry *dbe)
|
|||
|
||||
static struct db_entry *int_read(struct file *f, unsigned int index)
|
||||
{
|
||||
unsigned int val;
|
||||
file_readf(f, "%u", &val);
|
||||
return &__int_alloc(val)->ie_dbe;
|
||||
return &__int_alloc(file_readu(f))->ie_dbe;
|
||||
}
|
||||
|
||||
static void int_write(struct file *file, struct db_entry *dbe)
|
||||
|
@ -67,8 +65,8 @@ static const struct db_ops int_ops = {
|
|||
|
||||
static void test_db_entry()
|
||||
{
|
||||
struct file f = FILE_INIT_DATA("", "test_db_entry", 0);
|
||||
struct int_entry *ent;
|
||||
struct file f;
|
||||
|
||||
ent = INT_ENTRY(int_ops.dbe_alloc("1", 0));
|
||||
g_assert_cmpuint(ent->ie_dbe.dbe_index, ==, 0);
|
||||
|
@ -76,7 +74,6 @@ static void test_db_entry()
|
|||
g_assert_cmpuint(ent->ie_val, ==, 1);
|
||||
g_assert_cmpstr_free(int_ops.dbe_key(&ent->ie_dbe), ==, "1");
|
||||
|
||||
file_init(&f, "test_db_entry", 0);
|
||||
file_open(&f, OPEN_WRITE);
|
||||
int_ops.dbe_write(&f, &ent->ie_dbe);
|
||||
file_close(&f);
|
||||
|
|
|
@ -16,7 +16,7 @@ void test_date()
|
|||
.d_month = 0,
|
||||
.d_day = 0,
|
||||
};
|
||||
struct file f = FILE_INIT("date", 0);
|
||||
struct file f = FILE_INIT_DATA("", "date", 0);
|
||||
|
||||
date_today(NULL);
|
||||
date_set(NULL, 0, 0, 0);
|
||||
|
|
|
@ -11,7 +11,7 @@ static void test_verify_constructor(struct file *file, gchar *fpath, gchar *ftmp
|
|||
{
|
||||
g_assert_null(file->f_file);
|
||||
g_assert_cmpuint(file_version(file), ==, OCARINA_MINOR_VERSION);
|
||||
g_assert_cmpuint(file->f_mode, ==, OPEN_READ);
|
||||
g_assert_cmpuint(file->f_mode, ==, CLOSED);
|
||||
g_assert_cmpstr_free(file_path(file), ==, fpath);
|
||||
g_assert_cmpstr_free(file_write_path(file), ==, ftmp);
|
||||
}
|
||||
|
@ -20,21 +20,21 @@ static void test_invalid_file(gconstpointer path)
|
|||
{
|
||||
struct file file;
|
||||
|
||||
file_init(&file, (gchar *)path, 0);
|
||||
file_init_data(&file, "", (gchar *)path, 0);
|
||||
test_verify_constructor(&file, "", "");
|
||||
|
||||
g_assert_false(file_open(&file, OPEN_READ));
|
||||
g_assert_null(file.f_file);
|
||||
g_assert_false(file_open(&file, OPEN_WRITE));
|
||||
g_assert_null(file.f_file);
|
||||
g_assert_cmpuint(file.f_mode, ==, OPEN_READ);
|
||||
g_assert_cmpuint(file.f_mode, ==, CLOSED);
|
||||
|
||||
g_assert_false(file_exists(&file));
|
||||
}
|
||||
|
||||
static void __test_file_subprocess()
|
||||
{
|
||||
struct file file = FILE_INIT("file.txt", 0);
|
||||
struct file file = FILE_INIT_DATA("", "file.txt", 0);
|
||||
gchar *basepath, *filepath, *realpath;
|
||||
|
||||
basepath = g_strjoin("/", g_get_user_data_dir(), OCARINA_NAME, NULL);
|
||||
|
@ -45,7 +45,8 @@ static void __test_file_subprocess()
|
|||
g_assert_false(file_exists(&file));
|
||||
|
||||
g_assert_false(file_open(&file, OPEN_READ));
|
||||
g_assert_true(file_open(&file, OPEN_WRITE));
|
||||
g_assert_false(file_open(&file, CLOSED));
|
||||
g_assert_true( file_open(&file, OPEN_WRITE));
|
||||
g_assert_nonnull(file.f_file);
|
||||
g_assert_cmpuint(file.f_mode, ==, OPEN_WRITE);
|
||||
g_assert_false(file_open(&file, OPEN_WRITE));
|
||||
|
@ -53,7 +54,7 @@ static void __test_file_subprocess()
|
|||
g_assert_false(file_exists(&file));
|
||||
file_close(&file);
|
||||
g_assert_null(file.f_file);
|
||||
g_assert_cmpuint(file.f_mode, ==, OPEN_WRITE);
|
||||
g_assert_cmpuint(file.f_mode, ==, CLOSED);
|
||||
g_assert_true(file_exists(&file));
|
||||
|
||||
g_chmod(filepath, 0444);
|
||||
|
@ -61,6 +62,7 @@ static void __test_file_subprocess()
|
|||
g_chmod(filepath, 0200);
|
||||
g_assert_false(file_open(&file, OPEN_READ));
|
||||
g_chmod(filepath, 0644);
|
||||
g_assert_false(file_open(&file, CLOSED));
|
||||
|
||||
g_assert_true(file_open(&file, OPEN_READ));
|
||||
g_assert_nonnull(file.f_file);
|
||||
|
@ -70,6 +72,7 @@ static void __test_file_subprocess()
|
|||
g_assert_false(file_remove(&file));
|
||||
g_assert_true(file_exists(&file));
|
||||
file_close(&file);
|
||||
g_assert_cmpuint(file.f_mode, ==, CLOSED);
|
||||
g_assert_true(file_remove(&file));
|
||||
g_assert_false(file_exists(&file));
|
||||
|
||||
|
@ -90,10 +93,8 @@ static void test_file()
|
|||
|
||||
static void test_io()
|
||||
{
|
||||
struct file fout = FILE_INIT("file.txt", 0);
|
||||
struct file fin = FILE_INIT("file.txt", 1);
|
||||
char *res = NULL;
|
||||
unsigned int i;
|
||||
struct file fout = FILE_INIT_DATA("", "file.txt", 0);
|
||||
struct file fin = FILE_INIT_DATA("", "file.txt", 1);
|
||||
|
||||
fout.f_version = 1;
|
||||
g_assert_true(file_open(&fout, OPEN_WRITE));
|
||||
|
@ -101,28 +102,28 @@ static void test_io()
|
|||
file_writef(&fout, "2 FGHIJ KLMNO\n");
|
||||
file_writef(&fout, "3 \n");
|
||||
file_writef(&fout, "4 5 PQRST\n");
|
||||
file_writef(&fout, "-6 UV WX YZ\n");
|
||||
file_close(&fout);
|
||||
g_assert_true(file_exists(&fout));
|
||||
|
||||
g_assert_true(file_open(&fin, OPEN_READ));
|
||||
g_assert_cmpuint(file_version(&fin), ==, 1);
|
||||
|
||||
g_assert_cmpuint(file_readf(&fin, "%u %ms\n", &i, &res), ==, 2);
|
||||
g_assert_cmpuint(i, ==, 1);
|
||||
g_assert_cmpstr_free(res, ==, "ABCDE");
|
||||
g_assert_cmpuint( file_readu(&fin), ==, 1);
|
||||
g_assert_cmpstr_free(file_readl(&fin), ==, "ABCDE");
|
||||
|
||||
g_assert_cmpuint(file_readf(&fin, "%u %m[^\n]\n", &i, &res), ==, 2);
|
||||
g_assert_cmpuint(i, ==, 2);
|
||||
g_assert_cmpstr_free(res, ==, "FGHIJ KLMNO");
|
||||
g_assert_cmpuint( file_readu(&fin), ==, 2);
|
||||
g_assert_cmpstr_free(file_readl(&fin), ==, "FGHIJ KLMNO");
|
||||
|
||||
g_assert_cmpuint(file_readf(&fin, "%u", &i), ==, 1);
|
||||
res = file_readl(&fin);
|
||||
g_assert_cmpuint(i, ==, 3);
|
||||
g_assert_cmpstr_free(res, ==, "");
|
||||
g_assert_cmpuint( file_readu(&fin), ==, 3);
|
||||
g_assert_cmpstr_free(file_readl(&fin), ==, "");
|
||||
|
||||
g_assert_cmpuint(file_readf(&fin, "%u %m[^\n]", &i, &res), ==, 2);
|
||||
g_assert_cmpuint(i, ==, 4);
|
||||
g_assert_cmpstr_free(res, ==, "5 PQRST");
|
||||
g_assert_cmpuint( file_readu(&fin), ==, 4);
|
||||
g_assert_cmpstr_free(file_readl(&fin), ==, "5 PQRST");
|
||||
|
||||
g_assert_cmpint( file_readd(&fin), ==, -6);
|
||||
g_assert_cmpstr_free(file_readw(&fin), ==, "UV");
|
||||
g_assert_cmpstr_free(file_readl(&fin), ==, "WX YZ");
|
||||
|
||||
file_close(&fin);
|
||||
g_assert_cmpuint(file_version(&fin), ==, OCARINA_MINOR_VERSION);
|
||||
|
@ -130,8 +131,8 @@ static void test_io()
|
|||
|
||||
static void __test_versioning_subprocess(unsigned int out, unsigned int in)
|
||||
{
|
||||
struct file fout = FILE_INIT("file.txt", out);
|
||||
struct file fin = FILE_INIT("file.txt", in);
|
||||
struct file fout = FILE_INIT_DATA("", "file.txt", out);
|
||||
struct file fin = FILE_INIT_DATA("", "file.txt", in);
|
||||
|
||||
fout.f_version = out;
|
||||
fin.f_version = in;
|
||||
|
@ -171,44 +172,67 @@ static void test_versioning_new()
|
|||
|
||||
static void test_cache()
|
||||
{
|
||||
struct cache_file file = CACHE_FILE_INIT("dir", "file.txt");
|
||||
struct cache_file copy = CACHE_FILE_INIT("dir", "copy.txt");
|
||||
gchar *basepath, *filepath, *writepath;
|
||||
struct file file, copy;
|
||||
|
||||
basepath = g_strjoin("/", g_get_user_cache_dir(), OCARINA_NAME, NULL);
|
||||
filepath = g_strjoin("/", basepath, "dir", "file.txt", NULL);
|
||||
writepath = g_strjoin("/", basepath, "dir", ".file.txt.tmp", NULL);
|
||||
file_init_cache(&file, "dir", "file.txt");
|
||||
file_init_cache(©, "dir", "copy.txt");
|
||||
|
||||
g_assert_null(file.cf_file);
|
||||
g_assert_cmpstr(file.cf_name, ==, "file.txt");
|
||||
g_assert_cmpstr(file.cf_subdir, ==, "dir");
|
||||
basepath = g_strjoin("/", g_get_user_cache_dir(), OCARINA_NAME, "dir", NULL);
|
||||
filepath = g_strjoin("/", basepath, "file.txt", NULL);
|
||||
writepath = g_strjoin("/", basepath, ".file.txt.tmp", NULL);
|
||||
|
||||
g_assert_cmpstr_free(cache_file_path(&file), ==, filepath);
|
||||
g_assert_cmpstr_free(cache_file_write_path(&file), ==, writepath);
|
||||
g_assert_null(file.f_file);
|
||||
g_assert_cmpstr(file.f_name, ==, "file.txt");
|
||||
g_assert_cmpstr(file.f_subdir, ==, "dir");
|
||||
g_assert_cmpuint(file.f_mode, ==, CLOSED);
|
||||
|
||||
g_assert_cmpstr_free(file_path(&file), ==, filepath);
|
||||
g_assert_cmpstr_free(file_write_path(&file), ==, writepath);
|
||||
|
||||
/* Test writing data to a cache file. */
|
||||
g_assert_false(cache_file_exists(&file));
|
||||
g_assert_false(cache_file_open(&file, OPEN_READ));
|
||||
g_assert_true(cache_file_open(&file, OPEN_WRITE));
|
||||
g_assert_nonnull(file.cf_file);
|
||||
g_assert_false(cache_file_open(&file, OPEN_WRITE));
|
||||
g_assert_false(file_exists(&file));
|
||||
g_assert_false(file_open(&file, OPEN_READ_BINARY));
|
||||
g_assert_false(file_open(&file, CLOSED));
|
||||
g_assert_true( file_open(&file, OPEN_WRITE_BINARY));
|
||||
g_assert_nonnull(file.f_file);
|
||||
g_assert_cmpuint(file.f_mode, ==, OPEN_WRITE_BINARY);
|
||||
g_assert_false(file_open(&file, OPEN_WRITE_BINARY));
|
||||
|
||||
g_assert_false(cache_file_exists(&file));
|
||||
g_assert_cmpuint(cache_file_write(&file, "abcde", 5), ==, 5);
|
||||
cache_file_close(&file);
|
||||
g_assert_null(file.cf_file);
|
||||
g_assert_true(cache_file_exists(&file));
|
||||
g_assert_false(file_exists(&file));
|
||||
g_assert_cmpuint(file_write(&file, "abcde", 5), ==, 5);
|
||||
file_close(&file);
|
||||
g_assert_null(file.f_file);
|
||||
g_assert_cmpuint(file.f_mode, ==, CLOSED);
|
||||
g_assert_true(file_exists(&file));
|
||||
|
||||
g_assert_true(file_open(&file, OPEN_READ_BINARY));
|
||||
g_assert_cmpuint(file.f_mode, ==, OPEN_READ_BINARY);
|
||||
g_assert_cmpuint(file.f_version, ==, OCARINA_MINOR_VERSION);
|
||||
g_assert_cmpuint(file.f_prev, ==, 0);
|
||||
g_assert_cmpstr_free(file_read(&file), ==, "abcde");
|
||||
file_close(&file);
|
||||
|
||||
/* Test importing a file into the cache. */
|
||||
g_assert_false(cache_file_exists(©));
|
||||
g_assert_false(cache_file_import(©, filepath));
|
||||
g_assert_false(cache_file_exists(©));
|
||||
g_assert_true(cache_file_open(©, OPEN_WRITE));
|
||||
g_assert_false(cache_file_import(©, NULL));
|
||||
g_assert_true(cache_file_import(©, filepath));
|
||||
g_assert_false(cache_file_exists(©));
|
||||
cache_file_close(©);
|
||||
g_assert_true(cache_file_exists(©));
|
||||
g_assert_false(file_exists(©));
|
||||
g_assert_false(file_import(©, filepath));
|
||||
g_assert_false(file_exists(©));
|
||||
g_assert_true( file_open(©, OPEN_WRITE_BINARY));
|
||||
g_assert_false(file_import(©, NULL));
|
||||
g_assert_true( file_import(©, filepath));
|
||||
g_assert_false(file_exists(©));
|
||||
file_close(©);
|
||||
g_assert_true(file_exists(©));
|
||||
|
||||
/* Test removing cache files. */
|
||||
g_assert_true(file_remove(©));
|
||||
g_assert_false(file_exists(©));
|
||||
g_assert_true(file_exists(&file));
|
||||
g_assert_true(g_file_test(basepath, G_FILE_TEST_EXISTS));
|
||||
|
||||
g_assert_true(file_remove(&file));
|
||||
g_assert_false(file_exists(&file));
|
||||
g_assert_false(g_file_test(basepath, G_FILE_TEST_EXISTS));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
|
|
@ -34,6 +34,7 @@ static struct playlist_ops test_ops = {
|
|||
.pl_remove = playlist_generic_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
static struct playlist_callbacks test_cb = {
|
||||
.pl_cb_alloc = test_pl_alloc,
|
||||
|
@ -49,8 +50,7 @@ static void test_null()
|
|||
g_assert_false(playlist_delete(NULL));
|
||||
playlist_generic_free(NULL);
|
||||
|
||||
playlist_generic_init(NULL);
|
||||
playlist_generic_init_sorted(NULL);
|
||||
playlist_generic_init(NULL, 0);
|
||||
playlist_generic_deinit(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));
|
||||
playlist_generic_resort(NULL);
|
||||
playlist_clear_sort(NULL);
|
||||
g_assert_false(playlist_rearrange(NULL, 0, 0));
|
||||
|
||||
playlist_set_search(NULL, NULL);
|
||||
|
||||
|
@ -110,9 +111,10 @@ static void test_playlist()
|
|||
int i;
|
||||
|
||||
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(p.pl_length, ==, 0);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||
|
||||
for (i = 0; i < 13; i++) {
|
||||
ex_length += track_get(i)->tr_length;
|
||||
|
@ -202,8 +204,9 @@ static void test_sorting()
|
|||
struct track *track;
|
||||
unsigned int i;
|
||||
|
||||
playlist_generic_init_sorted(&p);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 3);
|
||||
playlist_generic_init(&p, 4, COMPARE_ARTIST, COMPARE_YEAR,
|
||||
COMPARE_ALBUM, COMPARE_TRACK);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||
playlist_clear_sort(&p);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||
|
||||
|
@ -279,6 +282,43 @@ static void test_sorting()
|
|||
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()
|
||||
{
|
||||
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
|
||||
|
@ -286,7 +326,7 @@ static void test_next()
|
|||
unsigned int i;
|
||||
|
||||
g_random_set_seed(0);
|
||||
playlist_generic_init(&p);
|
||||
playlist_generic_init(&p, 0);
|
||||
|
||||
for (i = 0; i < 13; i++)
|
||||
playlist_generic_add(&p, track_get(i));
|
||||
|
@ -329,7 +369,7 @@ static void test_save_load()
|
|||
struct playlist q = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test 2", 0, NULL);
|
||||
struct playlist r = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
|
||||
struct playlist s = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test 2", 0, NULL);
|
||||
struct file f = FILE_INIT("test.playlist", 0);
|
||||
struct file f = FILE_INIT_DATA("", "test.playlist", 0);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 13; 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/Playlists/General", test_playlist);
|
||||
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/Playlist/Save and Load", test_save_load);
|
||||
ret = g_test_run();
|
||||
|
|
|
@ -75,8 +75,8 @@ void test_library()
|
|||
playlist_set_random(playlist, false);
|
||||
g_assert_false(playlist->pl_random);
|
||||
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 3);
|
||||
playlist_clear_sort(playlist);
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 4);
|
||||
g_assert_true(playlist_rearrange(playlist, 15, 20));
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
||||
g_assert_true(playlist_sort(playlist, COMPARE_ARTIST));
|
||||
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) {
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
||||
} 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. */
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
static void test_settings()
|
||||
{
|
||||
struct file f = FILE_INIT("settings", 0);
|
||||
struct file f = FILE_INIT_DATA("", "settings", 0);
|
||||
|
||||
settings_set(NULL, 0);
|
||||
g_assert_cmpuint(settings_get(NULL), ==, 0);
|
||||
|
|
|
@ -46,7 +46,7 @@ static void test_album()
|
|||
struct album *album;
|
||||
struct artist *koji;
|
||||
struct genre *genre;
|
||||
struct file f;
|
||||
struct file f = FILE_INIT_DATA("", "album_tag", 1);
|
||||
|
||||
idle_init(IDLE_SYNC);
|
||||
|
||||
|
@ -58,7 +58,6 @@ static void test_album()
|
|||
g_assert_true( album_match_token(album, "symphony"));
|
||||
g_assert_false(album_match_token(album, "skyward"));
|
||||
|
||||
file_init(&f, "album_tag", 1);
|
||||
file_open(&f, OPEN_WRITE);
|
||||
file_writef(&f, "0 0 0 \n");
|
||||
album_ops->dbe_write(&f, &album->al_dbe);
|
||||
|
|
|
@ -28,10 +28,9 @@ static void test_verify_koji(struct artist *artist)
|
|||
|
||||
static void test_artist()
|
||||
{
|
||||
struct file f = FILE_INIT_DATA("", "artist_tag", 0);
|
||||
const struct db_ops *artist_ops = test_artist_ops();
|
||||
struct artist *artist;
|
||||
unsigned int i;
|
||||
struct file f;
|
||||
|
||||
artist = ARTIST(artist_ops->dbe_alloc("Koji Kondo", 0));
|
||||
|
||||
|
@ -40,7 +39,6 @@ static void test_artist()
|
|||
g_assert_true( artist_match_token(artist, "kondo"));
|
||||
g_assert_false(artist_match_token(artist, "hajime"));
|
||||
|
||||
file_init(&f, "artist_tag", 0);
|
||||
file_open(&f, OPEN_WRITE);
|
||||
file_writef(&f, "1 \n2 ");
|
||||
artist_ops->dbe_write(&f, &artist->ar_dbe);
|
||||
|
@ -49,13 +47,13 @@ static void test_artist()
|
|||
artist_ops->dbe_free(&artist->ar_dbe);
|
||||
|
||||
file_open(&f, OPEN_READ);
|
||||
file_readf(&f, "%u", &i);
|
||||
file_readu(&f);
|
||||
artist = ARTIST(artist_ops->dbe_read(&f, 0));
|
||||
test_verify_empty(artist);
|
||||
g_free(artist->ar_name);
|
||||
artist_ops->dbe_free(&artist->ar_dbe);
|
||||
|
||||
file_readf(&f, "%u", &i);
|
||||
file_readu(&f);
|
||||
artist = ARTIST(artist_ops->dbe_read(&f, 0));
|
||||
file_close(&f);
|
||||
test_verify_koji(artist);
|
||||
|
|
|
@ -27,10 +27,9 @@ static void test_verify_vg(struct genre *genre)
|
|||
|
||||
static void test_genre()
|
||||
{
|
||||
struct file f = FILE_INIT_DATA("", "genre_tag", 0);
|
||||
const struct db_ops *genre_ops = test_genre_ops();
|
||||
struct genre *genre;
|
||||
unsigned int i;
|
||||
struct file f;
|
||||
|
||||
genre = GENRE(genre_ops->dbe_alloc("Video Game Music", 0));
|
||||
test_verify_vg(genre);
|
||||
|
@ -38,7 +37,6 @@ static void test_genre()
|
|||
g_assert_true( genre_match_token(genre, "music"));
|
||||
g_assert_false(genre_match_token(genre, "rock"));
|
||||
|
||||
file_init(&f, "genre_tag", 0);
|
||||
file_open(&f, OPEN_WRITE);
|
||||
file_writef(&f, "1 \n1 ");
|
||||
genre_ops->dbe_write(&f, &genre->ge_dbe);
|
||||
|
@ -47,13 +45,13 @@ static void test_genre()
|
|||
genre_ops->dbe_free(&genre->ge_dbe);
|
||||
|
||||
file_open(&f, OPEN_READ);
|
||||
file_readf(&f, "%u", &i);
|
||||
file_readu(&f);
|
||||
genre = GENRE(genre_ops->dbe_read(&f, 0));
|
||||
test_verify_empty(genre);
|
||||
g_free(genre->ge_name);
|
||||
genre_ops->dbe_free(&genre->ge_dbe);
|
||||
|
||||
file_readf(&f, "%u", &i);
|
||||
file_readu(&f);
|
||||
genre = GENRE(genre_ops->dbe_read(&f, 0));
|
||||
file_close(&f);
|
||||
test_verify_vg(genre);
|
||||
|
|
|
@ -20,9 +20,9 @@ static void test_verify_link(struct library *library)
|
|||
|
||||
static void test_library()
|
||||
{
|
||||
struct file f = FILE_INIT_DATA("", "library_tag", 0);
|
||||
const struct db_ops *library_ops = test_library_ops();
|
||||
struct library *link, *zelda, *library;
|
||||
struct file f;
|
||||
|
||||
link = LIBRARY(library_ops->dbe_alloc("/home/Link/Music", 0));
|
||||
zelda = LIBRARY(library_ops->dbe_alloc("/home/Zelda/Music", 0));
|
||||
|
@ -30,7 +30,6 @@ static void test_library()
|
|||
test_verify_link(link);
|
||||
test_verify_zelda(zelda);
|
||||
|
||||
file_init(&f, "library_tag", 0);
|
||||
file_open(&f, OPEN_WRITE);
|
||||
library_ops->dbe_write(&f, &link->li_dbe);
|
||||
file_writef(&f, "\n");
|
||||
|
|
|
@ -83,10 +83,9 @@ static void test_track()
|
|||
time_t rawtime = time(NULL);
|
||||
struct tm *now = localtime(&rawtime);
|
||||
struct track *track;
|
||||
struct file f;
|
||||
struct file f = FILE_INIT_DATA("", "track_tag", 1);
|
||||
gchar *date;
|
||||
|
||||
file_init(&f, "track_tag", 1);
|
||||
g_assert_nonnull(library_find("tests/Music"));
|
||||
date = string_tm2str(now);
|
||||
|
||||
|
|
|
@ -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_position()), ==, "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()),
|
||||
==, "(disabled)");
|
||||
g_assert_cmpuint(gtk_combo_box_get_active(
|
||||
GTK_COMBO_BOX(gui_pause_after())), ==, 0);
|
||||
g_assert_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Paused");
|
||||
g_assert_true(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_up())));
|
||||
g_assert_false(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||
g_assert_cmpfloat(gtk_scale_button_get_value(gui_volume_button()),
|
||||
==, 100);
|
||||
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_popover())));
|
||||
}
|
||||
|
||||
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_position()), ==, "0:00");
|
||||
|
||||
test_main_loop();
|
||||
test_main_loop();
|
||||
g_assert_false(gtk_widget_is_visible(GTK_WIDGET(gui_play_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_true( gtk_widget_is_visible(GTK_WIDGET(gui_play_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());
|
||||
test_main_loop();
|
||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
||||
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_cmpstr(gtk_entry_get_text(gui_pause_entry()), ==, "Keep playing");
|
||||
|
||||
gtk_button_clicked(gui_next_button());
|
||||
if (track_get(0)->tr_track == 1)
|
||||
|
@ -79,16 +84,72 @@ static void test_audio_buttons()
|
|||
gtk_button_clicked(gui_prev_button());
|
||||
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();
|
||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
|
||||
g_assert_cmpuint(gtk_combo_box_get_active(
|
||||
GTK_COMBO_BOX(gui_pause_after())), ==, 1);
|
||||
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())));
|
||||
|
||||
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();
|
||||
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
|
||||
g_assert_cmpuint(gtk_combo_box_get_active(
|
||||
GTK_COMBO_BOX(gui_pause_after())), ==, 0);
|
||||
g_assert_false(gtk_widget_get_sensitive(GTK_WIDGET(gui_pause_down())));
|
||||
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);
|
||||
g_assert_cmpuint(audio_get_volume(), ==, 50);
|
||||
|
|
|
@ -102,9 +102,9 @@ static void test_sidebar_selection()
|
|||
struct playlist *collection;
|
||||
GtkTreeSelection *selection;
|
||||
GtkToggleButton *random;
|
||||
GtkTreeIter iter, cur;
|
||||
GtkTreeModel *filter;
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
unsigned int i, n;
|
||||
|
||||
collection = playlist_lookup(PL_SYSTEM, "Collection");
|
||||
|
@ -136,6 +136,10 @@ static void test_sidebar_selection()
|
|||
g_assert_true(gtk_widget_get_sensitive(
|
||||
GTK_WIDGET(random)));
|
||||
|
||||
g_assert_true(gui_sidebar_iter_current(&cur));
|
||||
g_assert_true(gui_sidebar_iter_playlist(&cur) ==
|
||||
collection);
|
||||
|
||||
gtk_toggle_button_set_active(random, false);
|
||||
g_assert_false(collection->pl_random);
|
||||
gtk_toggle_button_set_active(random, true);
|
||||
|
@ -143,6 +147,11 @@ static void test_sidebar_selection()
|
|||
} else if (i == 1) {
|
||||
g_assert(gui_model_get_playlist() ==
|
||||
playlist_lookup(PL_SYSTEM, "History"));
|
||||
|
||||
g_assert_true(gui_sidebar_iter_current(&cur));
|
||||
g_assert_true(gui_sidebar_iter_playlist(&cur) ==
|
||||
playlist_lookup(PL_SYSTEM, "History"));
|
||||
|
||||
g_assert_false(gtk_toggle_button_get_active(random));
|
||||
g_assert_false(gtk_widget_get_sensitive(
|
||||
GTK_WIDGET(random)));
|
||||
|
|
|
@ -65,7 +65,7 @@ void test_treeview_select()
|
|||
GList *list;
|
||||
unsigned int i;
|
||||
|
||||
selection = gtk_tree_view_get_selection(gui_treeview());
|
||||
selection = gui_treeview_selection();
|
||||
|
||||
gui_treeview_set_playlist(playlist_lookup(PL_SYSTEM, "Collection"));
|
||||
g_assert(gui_model_get_playlist() ==
|
||||
|
@ -112,6 +112,7 @@ void test_treeview_sort()
|
|||
break;
|
||||
case GUI_MODEL_ARTIST:
|
||||
case GUI_MODEL_YEAR:
|
||||
case GUI_MODEL_ALBUM:
|
||||
case GUI_MODEL_TRACK_NR:
|
||||
g_assert_true(
|
||||
gtk_tree_view_column_get_sort_indicator(col));
|
||||
|
|
Loading…
Reference in New Issue