/* * Copyright 2016 (c) Anna Schumaker. */ #include #include #include static struct file sys_file = FILE_INIT("playlist.db", 0, 0); static struct queue sys_playlists[SYS_PL_NUM_PLAYLISTS]; static bool __sys_pl_remove(enum sys_playlist_t, struct track *); static enum sys_playlist_t __sys_pl_convert(const gchar *name) { if (string_match(name, "Favorites")) return SYS_PL_FAVORITES; else if (string_match(name, "Hidden") || string_match(name, "Banned")) return SYS_PL_HIDDEN; else if (string_match(name, "Unplayed")) return SYS_PL_UNPLAYED; return SYS_PL_NUM_PLAYLISTS; } static void __sys_pl_save() { if (!file_open(&sys_file, OPEN_WRITE)) return; file_writef(&sys_file, "%u\n 1 %s\n", 2, "Favorites"); queue_save_tracks(&sys_playlists[SYS_PL_FAVORITES], &sys_file); file_writef(&sys_file, "\n1 %s\n", "Banned"); queue_save_tracks(&sys_playlists[SYS_PL_HIDDEN], &sys_file); file_writef(&sys_file, "\n"); file_close(&sys_file); } static bool __sys_pl_load() { enum sys_playlist_t plist; unsigned int i, n; gchar *name; if (!file_open(&sys_file, OPEN_READ)) return true; file_readf(&sys_file, "%u\n", &n); for (i = 0; i < n; i++) { file_readf(&sys_file, "%*u %m[^\n]\n", &name); plist = __sys_pl_convert(name); queue_load_tracks(&sys_playlists[plist], &sys_file); g_free(name); } file_close(&sys_file); return true; } static bool __sys_pl_can_add(enum sys_playlist_t plist, struct track *track) { if (track->tr_count == 0) return plist == SYS_PL_UNPLAYED; return false; } static bool __sys_pl_add(enum sys_playlist_t plist, struct track *track) { if (plist != SYS_PL_FAVORITES && plist != SYS_PL_HIDDEN) { if (!__sys_pl_can_add(plist, track)) return false; if (queue_has(&sys_playlists[SYS_PL_HIDDEN], track)) return false; } if (queue_has(&sys_playlists[plist], track)) return false; queue_add(&sys_playlists[plist], track); switch (plist) { case SYS_PL_HIDDEN: __sys_pl_remove(SYS_PL_UNPLAYED, track); case SYS_PL_FAVORITES: __sys_pl_save(); default: break; } return true; } static bool __sys_pl_remove(enum sys_playlist_t plist, struct track *track) { if (!queue_remove_all(&sys_playlists[plist], track)) return false; switch (plist) { case SYS_PL_HIDDEN: __sys_pl_add(SYS_PL_UNPLAYED, track); case SYS_PL_FAVORITES: __sys_pl_save(); default: break; } return true; } static bool __sys_pl_update(enum sys_playlist_t plist) { struct db_entry *dbe, *next; db_for_each(dbe, next, track_db_get()) { if (TRACK(dbe)->tr_count == 0) __sys_pl_add(SYS_PL_UNPLAYED, TRACK(dbe)); else __sys_pl_remove(SYS_PL_UNPLAYED, TRACK(dbe)); } queue_unset_flag(&sys_playlists[plist], Q_ADD_FRONT); return true; } static struct queue *pl_system_get_queue(const gchar *name) { enum sys_playlist_t plist = __sys_pl_convert(name); if (plist == SYS_PL_NUM_PLAYLISTS) return NULL; return &sys_playlists[plist]; } static bool pl_system_add_track(const gchar *name, struct track *track) { enum sys_playlist_t plist = __sys_pl_convert(name); if (plist == SYS_PL_NUM_PLAYLISTS) return false; return __sys_pl_add(plist, track); } static bool pl_system_remove_track(const gchar *name, struct track *track) { enum sys_playlist_t plist = __sys_pl_convert(name); if (plist == SYS_PL_NUM_PLAYLISTS) return false; return __sys_pl_remove(plist, track); } static void pl_system_update(const gchar *name) { enum sys_playlist_t plist = __sys_pl_convert(name); if (plist != SYS_PL_FAVORITES && plist != SYS_PL_HIDDEN) idle_schedule(IDLE_SYNC, IDLE_FUNC(__sys_pl_update), GUINT_TO_POINTER(plist)); } struct playlist_type pl_system = { .pl_get_queue = pl_system_get_queue, .pl_add_track = pl_system_add_track, .pl_remove_track = pl_system_remove_track, .pl_update = pl_system_update, }; void pl_system_init(struct queue_ops *ops) { unsigned int i; for (i = 0; i < SYS_PL_NUM_PLAYLISTS; i++) { queue_init(&sys_playlists[i], Q_ENABLED | Q_REPEAT, ops); queue_sort(&sys_playlists[i], COMPARE_ARTIST, true); queue_sort(&sys_playlists[i], COMPARE_YEAR, false); queue_sort(&sys_playlists[i], COMPARE_TRACK, false); if (i >= SYS_PL_UNPLAYED) queue_set_flag(&sys_playlists[i], Q_ADD_FRONT); } idle_schedule(IDLE_SYNC, __sys_pl_load, NULL); pl_system_update("Unplayed"); } void pl_system_deinit() { unsigned int i; for (i = 0; i < SYS_PL_NUM_PLAYLISTS; i++) queue_deinit(&sys_playlists[i]); }