/* * Copyright 2016 (c) Anna Schumaker. */ #include #include #include static struct playlist_callbacks *callbacks = NULL; static int __playlist_generic_find_sort(gconstpointer a, gconstpointer b) { return abs(GPOINTER_TO_INT(a)) - abs(GPOINTER_TO_INT(b)); } void playlist_generic_set_callbacks(struct playlist_callbacks *cb) { callbacks = cb; } void playlist_generic_init(struct playlist *playlist, unsigned int flags, struct queue_ops *ops) { queue_init(&playlist->pl_queue, flags, ops, playlist); playlist_generic_sort(playlist, COMPARE_ARTIST); playlist_generic_sort(playlist, COMPARE_YEAR); playlist_generic_sort(playlist, COMPARE_TRACK); playlist->pl_private = NULL; } void playlist_generic_save(struct playlist *playlist, struct file *file, unsigned int flags) { struct queue_iter it; GSList *sort; int field; if (!playlist) return; if (flags & PL_SAVE_ITER) file_writef(file, "%u ", playlist->pl_queue.q_cur.it_pos); if (flags & PL_SAVE_FLAGS) { sort = playlist->pl_queue.q_sort; file_writef(file, "%u ", playlist->pl_queue.q_flags); file_writef(file, "%u", g_slist_length(sort)); while (sort) { field = GPOINTER_TO_INT(sort->data); file_writef(file, " %u %d", abs(field) - 1, field > 0); sort = g_slist_next(sort); } file_writef(file, "\n"); } if (flags & PL_SAVE_TRACKS) { file_writef(file, "%u", queue_size(&playlist->pl_queue)); queue_for_each(&playlist->pl_queue, &it) file_writef(file, " %u", track_index(queue_iter_val(&it))); file_writef(file, "\n"); } } void playlist_generic_load(struct playlist *playlist, struct file *file, unsigned int flags) { unsigned int f, n, i, t, it = 0; int field, ascending; GSList *sort = NULL; gchar *line; if (!playlist) return; if (flags & PL_SAVE_ITER) file_readf(file, "%u", &it); if (flags & PL_SAVE_FLAGS) { file_readf(file, "%u %u", &f, &n); for (i = 0; i < n; i++) { file_readf(file, "%u %d", &field, &ascending); field += 1; if (!ascending) field = -field; sort = g_slist_append(sort, GINT_TO_POINTER(field)); } playlist_clear_sort(playlist); playlist->pl_queue.q_sort = sort; queue_resort(&playlist->pl_queue); if (file_readf(file, "%m\n", &line)) g_free(line); } if (flags & PL_SAVE_TRACKS) { file_readf(file, "%u ", &n); for (i = 0; i < n; i++) { file_readf(file, "%u", &t); queue_add(&playlist->pl_queue, track_get(t)); } if (file_readf(file, "%m\n", &line)) g_free(line); } playlist->pl_queue.q_flags |= (f & Q_VALID_FLAGS); queue_iter_set(&playlist->pl_queue, &playlist->pl_queue.q_cur, it); } bool playlist_generic_can_select(struct playlist *playlist) { return queue_size(&playlist->pl_queue) > 0; } void playlist_generic_clear(struct playlist *playlist) { queue_clear(&playlist->pl_queue); } bool playlist_generic_add_track(struct playlist *playlist, struct track *track) { if (queue_has(&playlist->pl_queue, track)) return false; queue_add(&playlist->pl_queue, track); return true; } bool playlist_generic_add_track_front(struct playlist *playlist, struct track *track) { if (queue_has(&playlist->pl_queue, track)) return false; queue_add_front(&playlist->pl_queue, track); return true; } bool playlist_generic_remove_track(struct playlist *playlist, struct track *track) { return queue_remove_all(&playlist->pl_queue, track); } void playlist_generic_set_flag(struct playlist *playlist, enum queue_flags flag, bool enabled) { if (enabled) return queue_set_flag(&playlist->pl_queue, flag); return queue_unset_flag(&playlist->pl_queue, flag); } void playlist_generic_sort(struct playlist *playlist, enum compare_t sort) { GSList *found = g_slist_find_custom(playlist->pl_queue.q_sort, GINT_TO_POINTER(sort), __playlist_generic_find_sort); if (found) found->data = GINT_TO_POINTER(-GPOINTER_TO_INT(found->data)); else playlist->pl_queue.q_sort = g_slist_append(playlist->pl_queue.q_sort, GINT_TO_POINTER(sort)); queue_resort(&playlist->pl_queue); } struct track *playlist_generic_next(struct playlist *playlist) { return queue_next(&playlist->pl_queue); }