diff --git a/package.json b/package.json index 82a7bc2..d40e6d8 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "messageKeys": [ "PKJS_READY", "IN_VANITY_LIST[2048]", - "IN_ID_LIST[2048]", + "IN_SEQ_ID_LIST[255]", "BIDIR_MENU_NAV_SCOPE", "OUT_MENU_NAV_SUBSCOPE", "OUT_PLAY_SEQ_ID", diff --git a/src/c/jellyPod.c b/src/c/jellyPod.c index a18ce2b..422e0fb 100644 --- a/src/c/jellyPod.c +++ b/src/c/jellyPod.c @@ -11,7 +11,8 @@ typedef enum { } NavScope; // constants -#define MAX_MENU_ITEMS 2048 +#define MAX_ARTISTS 2048 // TODO paginate or push as high as possible +#define MAX_TRACKS_PER_ALBUM 255 #define BAR_HEIGHT 20 #ifdef PBL_RECT #define MARGIN_X 4 @@ -36,8 +37,8 @@ static MenuLayer *s_menu_layer; // globals static bool s_pkjs_ready = false; static NavScope s_current_menu_scope = NAV_SCOPE_MAIN; -static const char *s_current_menu_vanity[MAX_MENU_ITEMS]; -// static uint16_t s_current_menu_seq_ids[MAX_MENU_ITEMS]; +static const char *s_current_menu_vanity[MAX_ARTISTS]; +static uint16_t s_current_menu_seq_ids[MAX_TRACKS_PER_ALBUM]; static uint16_t s_menu_items_count = 0; // resources @@ -60,7 +61,11 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) { // handle incoming menu list items Tuple *t_new_scope = dict_find(iter, MESSAGE_KEY_BIDIR_MENU_NAV_SCOPE); if (t_new_scope) { - for (uint16_t i = 0; i < MAX_MENU_ITEMS; i++) { + for (uint16_t i = 0; i < MAX_ARTISTS; i++) { + Tuple *t_seq_ids = dict_find(iter, MESSAGE_KEY_IN_SEQ_ID_LIST + i); + if (t_seq_ids) { + s_current_menu_seq_ids[i] = t_seq_ids->value->uint16; + } Tuple *t_vanity = dict_find(iter, MESSAGE_KEY_IN_VANITY_LIST + i); if (t_vanity) { s_current_menu_vanity[i] = t_vanity->value->cstring; @@ -133,10 +138,10 @@ static void menu_select_click(struct MenuLayer *menu_layer, MenuIndex *clicked_i } return; case NAV_SCOPE_SEARCH: - to_pkjs_scope_change(NAV_SCOPE_ARTISTS, &clicked_index->row); - break; case NAV_SCOPE_ARTISTS: case NAV_SCOPE_ALBUMS: + to_pkjs_scope_change(s_current_menu_scope + 1, &clicked_index->row); + break; case NAV_SCOPE_ALBUM_TRACKS: default: return; @@ -157,7 +162,6 @@ static void main_window_load() { s_menu_layer = menu_layer_create(s_menu_grect); menu_layer_set_callbacks(s_menu_layer, NULL, (MenuLayerCallbacks){.get_num_rows = menu_get_num_rows, .draw_row = menu_draw_row, .select_click = menu_select_click, .selection_changed = menu_selection_changed}); - menu_layer_pad_bottom_enable(s_menu_layer, false); menu_layer_set_click_config_onto_window(s_menu_layer, s_main_window); #ifdef PBL_ROUND menu_layer_set_center_focused(s_menu_layer, false); diff --git a/src/pkjs/index.js b/src/pkjs/index.js index a0bbd73..84693d2 100644 --- a/src/pkjs/index.js +++ b/src/pkjs/index.js @@ -13,6 +13,9 @@ var NavScope = Object.freeze({ var cfg = JSON.parse(localStorage.getItem('clay-settings')); var lookupMap = new Map(); +var jfIdToSeqIdMap = new Map(); +var allJfIds = []; +var currentArtist = null; Pebble.addEventListener("ready", function () { // store cache of library info from Jellyfin @@ -36,7 +39,9 @@ Pebble.addEventListener("ready", function () { // format response for jellyPod //// build lookupMap - let lastAlbumInfo = {AlbumArtist: "", AlbumName: "", AlbumYear: 0}; + let lastAlbumInfo = { AlbumArtist: "", AlbumName: "", AlbumYear: 0 }; + let currentSeqId = 0; + allJfIds = [] // ensure blank for (const track of libObj.Items) { if (!track.Name) continue; @@ -65,6 +70,9 @@ Pebble.addEventListener("ready", function () { TrackName: track.Name, JfId: track.Id }); + jfIdToSeqIdMap.set(track.Id, currentSeqId); + allJfIds.push(track.Id); + currentSeqId++; // consider the album to have changed if the album name OR artist changed if (lastAlbumInfo.AlbumArtist !== albumArtist || lastAlbumInfo.AlbumName !== albumName) { @@ -98,15 +106,17 @@ Pebble.addEventListener("appmessage", function (dict) { //console.log("expected NAV_SCOPE key", keys.BIDIR_MENU_NAV_SCOPE); const scope = payloadGet(dict.payload, "BIDIR_MENU_NAV_SCOPE"); + const subscope = payloadGet(dict.payload, "OUT_MENU_NAV_SUBSCOPE"); + if (scope) { let vanityList; + let seqIdList = []; switch (scope) { - case NavScope.NAV_SCOPE_SEARCH: { // search + case NavScope.NAV_SCOPE_SEARCH: { vanityList = Array.from(lookupMap.keys()); break; } - case NavScope.NAV_SCOPE_ARTISTS: { // artists - const subscope = payloadGet(dict.payload, "OUT_MENU_NAV_SUBSCOPE"); + case NavScope.NAV_SCOPE_ARTISTS: { if (subscope) { // allow filtering by starting character vanityList = Array.from(lookupMap.get(subscope).keys()); @@ -115,14 +125,32 @@ Pebble.addEventListener("appmessage", function (dict) { } break; } + case NavScope.NAV_SCOPE_ALBUMS: { + currentArtist = subscope; + const artistToAlbumsMap = lookupMap.get(Array.from(subscope)[0].toUpperCase()); + vanityList = Array.from(artistToAlbumsMap.get(subscope).keys()); + break; + } + case NavScope.NAV_SCOPE_ALBUM_TRACKS: { + const albumToTracksMap = lookupMap.get(Array.from(currentArtist)[0].toUpperCase()).get(currentArtist); + vanityList = albumToTracksMap.get(subscope).map((track) => track.TrackName); + const jfIdList = albumToTracksMap.get(subscope).map((track) => track.JfId); + for (const jfId of jfIdList) { + seqIdList.push(jfIdToSeqIdMap.get(jfId)); + } + break; + } default: return; } const outDict = {}; for (let i = 0; i < vanityList.length; i++) { outDict[keys.IN_VANITY_LIST + i] = vanityList[i]; - outDict[keys.BIDIR_MENU_NAV_SCOPE] = scope; + if (scope === NavScope.NAV_SCOPE_ALBUM_TRACKS) { + outDict[keys.IN_SEQ_ID_LIST + i] = seqIdList[i]; + } } + outDict[keys.BIDIR_MENU_NAV_SCOPE] = scope; Pebble.sendAppMessage(outDict); } });