/** * Copyright 2013 (c) Anna Schumaker. */ extern "C" { #include #include } #include class PlaylistQueue : public queue { public: void clear() { queue_clear(this); } unsigned int find_average_count() { struct db_entry *track, *next; unsigned int total = 0, count = 0; db_for_each(track, next, track_db_get()) { total += TRACK(track)->tr_count; count++; } if (count > 0) return total / count; return 0; } void dynamic_add(const std::string &name, struct track *track, unsigned int avg) { if ((name == "Unplayed") && (track->tr_count == 0)) queue_add(this, track); if ((name == "Most Played") && (track->tr_count > avg)) queue_add(this, track); if ((name == "Least Played") && (track->tr_count < avg) && (track->tr_count > 0)) queue_add(this, track); } void dynamic_fill(const std::string &name) { struct db_entry *track, *next; unsigned int avg = 0; if ((name == "Most Played") || (name == "Least Played")) avg = find_average_count(); clear(); queue_set_flag(this, Q_ADD_FRONT); db_for_each(track, next, track_db_get()) dynamic_add(name, TRACK(track), avg); queue_unset_flag(this, Q_ADD_FRONT); queue_resort(this); } }; static struct database playlist_db; static PlaylistQueue playlist_q; static std::string cur_plist; static inline bool __playlist_is_static(const gchar *name) { if (string_compare(name, "Favorites") == 0) return true; return string_compare(name, "Banned") == 0; } static inline bool __playlist_is_dynamic(const gchar *name) { if (string_compare(name, "Most Played") == 0) return true; if (string_compare(name, "Least Played") == 0) return true; return string_compare(name, "Unplayed") == 0; } static void __playlist_fill(const gchar *name, struct set *set) { struct set_iter it; queue_clear(&playlist_q); cur_plist = name; if (!set) return; queue_set_flag(&playlist_q, Q_ADD_FRONT); set_for_each(set, &it) queue_add(&playlist_q, track_get(it.it_val)); queue_unset_flag(&playlist_q, Q_ADD_FRONT); queue_resort(&playlist_q); } void playlist_init(struct queue_ops *ops) { struct set_iter it; queue_init(&playlist_q, Q_ENABLED | Q_REPEAT, ops); queue_sort(&playlist_q, COMPARE_ARTIST, true); queue_sort(&playlist_q, COMPARE_YEAR, false); queue_sort(&playlist_q, COMPARE_TRACK, false); queue_set_flag(&playlist_q, Q_NO_SORT); index_init(&playlist_db, "playlist.db", true); db_load(&playlist_db); index_entry *ent = playlist :: get_tracks("Banned"); if (!ent) return; set_for_each(&ent->ie_set, &it) queue_remove_all(collection_get_queue(), track_get(it.it_val)); } void playlist_deinit() { queue_deinit(&playlist_q); db_deinit(&playlist_db); } void playlist_add(const gchar *name, struct track *track) { if (!track || !name || !__playlist_is_static(name)) return; if (!playlist_has(name, track)) { index_insert(&playlist_db, name, track->tr_dbe.dbe_index); if (cur_plist == name) queue_add(&playlist_q, track); if (string_compare(name, "Banned") == 0) queue_remove_all(collection_get_queue(), track); } } void playlist_remove(const gchar *name, struct track *track) { if (!track || !name) return; if (playlist_has(name, track)) { index_remove(&playlist_db, name, track->tr_dbe.dbe_index); if (cur_plist == name) queue_remove_all(&playlist_q, track); if (string_compare(name, "Banned") == 0) queue_add(collection_get_queue(), track); } } bool playlist_has(const gchar *name, struct track *track) { if (!track || !name) return false; return index_has(&playlist_db, name, track->tr_dbe.dbe_index); } void playlist_select(const gchar *name) { struct index_entry *ent; if (!name) return; if (__playlist_is_static(name)) { ent = INDEX_ENTRY(db_get(&playlist_db, name)); __playlist_fill(name, ent ? &ent->ie_set : NULL); } else if (__playlist_is_dynamic(name)) { playlist_q.dynamic_fill(name); cur_plist = name; } } index_entry *playlist :: get_tracks(const std::string &name) { return INDEX_ENTRY(db_get(&playlist_db, name.c_str())); } struct queue *playlist_get_queue() { return &playlist_q; }