Redesign Jellyfin API data operations
This commit is contained in:
1 parent
79045d8b4b
commit
f7b4805ba1
2 files changed
+48
-70
No files matched your search
+11
-26
@@ -4,13 +4,10 @@
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NAV_SCOPE_MAIN = 0,
|
NAV_SCOPE_MAIN = 0,
|
||||||
NAV_SCOPE_ALPHA = 1,
|
NAV_SCOPE_SEARCH = 1,
|
||||||
NAV_SCOPE_ARTISTS = 2,
|
NAV_SCOPE_ARTISTS = 2,
|
||||||
NAV_SCOPE_ALBUMS = 3,
|
NAV_SCOPE_ALBUMS = 3,
|
||||||
NAV_SCOPE_ALBUM_TRACKS = 4,
|
NAV_SCOPE_ALBUM_TRACKS = 4,
|
||||||
NAV_SCOPE_PLAYLISTS = 5,
|
|
||||||
NAV_SCOPE_PLAYLIST_TRACKS = 6,
|
|
||||||
NAV_SCOPE_NOW_PLAYING = 7
|
|
||||||
} NavScope;
|
} NavScope;
|
||||||
|
|
||||||
// layer-age
|
// layer-age
|
||||||
@@ -40,7 +37,7 @@ static GFont s_font_chicago;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
static const GRect s_menu_grect = GRect(MARGIN_X, BAR_HEIGHT + MARGIN_Y, PBL_DISPLAY_WIDTH - (MARGIN_X * 2), PBL_DISPLAY_HEIGHT - (MARGIN_Y * 2));
|
static const GRect s_menu_grect = GRect(MARGIN_X, BAR_HEIGHT + MARGIN_Y, PBL_DISPLAY_WIDTH - (MARGIN_X * 2), PBL_DISPLAY_HEIGHT - (MARGIN_Y * 2));
|
||||||
static const char *s_main_menu_options[3] = {"Artists", "Playlists", "Now Playing"};
|
static const char *s_main_menu_options[4] = {"Shuffle Songs", "Shuffle Artists", "> All Artists", "> Search Artists"};
|
||||||
|
|
||||||
////////////////////// PKJS //////////////////////
|
////////////////////// PKJS //////////////////////
|
||||||
|
|
||||||
@@ -52,7 +49,7 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_pkjs_scope_change(NavScope scope, const char *jfId, bool shuffleInScope) {
|
static void to_pkjs_scope_change(NavScope scope) {
|
||||||
if (!s_pkjs_ready) {
|
if (!s_pkjs_ready) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -65,16 +62,6 @@ static void to_pkjs_scope_change(NavScope scope, const char *jfId, bool shuffleI
|
|||||||
}
|
}
|
||||||
dict_write_uint8(out, MESSAGE_KEY_OUT_MENU_NAV_SCOPE, scope);
|
dict_write_uint8(out, MESSAGE_KEY_OUT_MENU_NAV_SCOPE, scope);
|
||||||
|
|
||||||
if (shuffleInScope) {
|
|
||||||
// tell PKJS to shuffle if a shuffle option was clicked
|
|
||||||
dict_write_uint8(out, MESSAGE_KEY_OUT_SHUFFLE_MODE, shuffleInScope); // if true, PKJS side shuffles IDs in scope and passes them to JF API
|
|
||||||
} else if (jfId) {
|
|
||||||
// otherwise, send the selected jfId, if present;
|
|
||||||
// for artists/albums/playlists, determines next data set returned to C;
|
|
||||||
// for tracks, starts sequential playback (sequential relative to entire library unless scope is playlist)
|
|
||||||
dict_write_cstring(out, MESSAGE_KEY_OUT_JFID, jfId);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = app_message_outbox_send();
|
result = app_message_outbox_send();
|
||||||
if (result != APP_MSG_OK) {
|
if (result != APP_MSG_OK) {
|
||||||
return;
|
return;
|
||||||
@@ -84,12 +71,11 @@ static void to_pkjs_scope_change(NavScope scope, const char *jfId, bool shuffleI
|
|||||||
static uint16_t menu_get_num_rows(MenuLayer *menu_layer, uint16_t section_index, void *context) {
|
static uint16_t menu_get_num_rows(MenuLayer *menu_layer, uint16_t section_index, void *context) {
|
||||||
switch (s_current_menu_scope) {
|
switch (s_current_menu_scope) {
|
||||||
case NAV_SCOPE_MAIN:
|
case NAV_SCOPE_MAIN:
|
||||||
return 3;
|
return 4;
|
||||||
case NAV_SCOPE_ALPHA:
|
case NAV_SCOPE_SEARCH:
|
||||||
case NAV_SCOPE_ARTISTS:
|
case NAV_SCOPE_ARTISTS:
|
||||||
case NAV_SCOPE_ALBUMS:
|
case NAV_SCOPE_ALBUMS:
|
||||||
case NAV_SCOPE_ALBUM_TRACKS:
|
case NAV_SCOPE_ALBUM_TRACKS:
|
||||||
case NAV_SCOPE_PLAYLISTS:
|
|
||||||
default:
|
default:
|
||||||
return 99;
|
return 99;
|
||||||
}
|
}
|
||||||
@@ -100,11 +86,10 @@ static void menu_draw_row(GContext *ctx, const Layer *cell_layer, MenuIndex *cel
|
|||||||
case NAV_SCOPE_MAIN:
|
case NAV_SCOPE_MAIN:
|
||||||
custom_menu_cell_title_draw(ctx, cell_layer, s_main_menu_options[cell_index->row], NULL, s_font_chicago, MARGIN_X);
|
custom_menu_cell_title_draw(ctx, cell_layer, s_main_menu_options[cell_index->row], NULL, s_font_chicago, MARGIN_X);
|
||||||
break;
|
break;
|
||||||
case NAV_SCOPE_ALPHA:
|
case NAV_SCOPE_SEARCH:
|
||||||
case NAV_SCOPE_ARTISTS:
|
case NAV_SCOPE_ARTISTS:
|
||||||
case NAV_SCOPE_ALBUMS:
|
case NAV_SCOPE_ALBUMS:
|
||||||
case NAV_SCOPE_ALBUM_TRACKS:
|
case NAV_SCOPE_ALBUM_TRACKS:
|
||||||
case NAV_SCOPE_PLAYLISTS:
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -115,20 +100,20 @@ static void menu_select_click(struct MenuLayer *menu_layer, MenuIndex *clicked_i
|
|||||||
case NAV_SCOPE_MAIN:
|
case NAV_SCOPE_MAIN:
|
||||||
switch (clicked_index->row) {
|
switch (clicked_index->row) {
|
||||||
case 0:
|
case 0:
|
||||||
to_pkjs_scope_change(NAV_SCOPE_ALPHA, NULL, false);
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
to_pkjs_scope_change(NAV_SCOPE_PLAYLISTS, NULL, false);
|
break;
|
||||||
|
case 2:
|
||||||
|
to_pkjs_scope_change(NAV_SCOPE_ARTISTS);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
to_pkjs_scope_change(NAV_SCOPE_NOW_PLAYING, NULL, false); // TODO
|
to_pkjs_scope_change(NAV_SCOPE_SEARCH);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case NAV_SCOPE_ALPHA:
|
case NAV_SCOPE_SEARCH:
|
||||||
case NAV_SCOPE_ARTISTS:
|
case NAV_SCOPE_ARTISTS:
|
||||||
case NAV_SCOPE_ALBUMS:
|
case NAV_SCOPE_ALBUMS:
|
||||||
case NAV_SCOPE_ALBUM_TRACKS:
|
case NAV_SCOPE_ALBUM_TRACKS:
|
||||||
case NAV_SCOPE_PLAYLISTS:
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-44
@@ -7,7 +7,7 @@ var cfg = JSON.parse(localStorage.getItem('clay-settings'));
|
|||||||
Pebble.addEventListener("ready", function () {
|
Pebble.addEventListener("ready", function () {
|
||||||
// store cache of library info from Jellyfin
|
// store cache of library info from Jellyfin
|
||||||
if (cfg.PRIV_BASE_URL && cfg.PRIV_API_KEY && cfg.PRIV_USERNAME) {
|
if (cfg.PRIV_BASE_URL && cfg.PRIV_API_KEY && cfg.PRIV_USERNAME) {
|
||||||
// get userId
|
// get userId from Jellyfin
|
||||||
callAPI("GET", cfg.PRIV_BASE_URL + "/Users", function (userIdResp) {
|
callAPI("GET", cfg.PRIV_BASE_URL + "/Users", function (userIdResp) {
|
||||||
if (userIdResp === null) { return; }
|
if (userIdResp === null) { return; }
|
||||||
const userIdObj = JSON.parse(userIdResp);
|
const userIdObj = JSON.parse(userIdResp);
|
||||||
@@ -19,63 +19,56 @@ Pebble.addEventListener("ready", function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get library
|
// get library response from Jellyfin
|
||||||
callAPI("GET", cfg.PRIV_BASE_URL + "/Items?userId=" + userId + "&recursive=true&includeItemTypes=Audio&sortBy=AlbumArtist,Artist,ProductionYear,Album,IndexNumber,Name'", function (libResp) {
|
callAPI("GET", cfg.PRIV_BASE_URL + "/Items?userId=" + userId + "&recursive=true&includeItemTypes=Audio&sortBy=AlbumArtist,Artist,ProductionYear,Album,IndexNumber,Name", function (libResp) {
|
||||||
if (libResp === null) { return; }
|
if (libResp === null) { return; }
|
||||||
const libObj = JSON.parse(libResp);
|
const libObj = JSON.parse(libResp);
|
||||||
// extraction output:
|
|
||||||
// a map of artists to arrays of albums
|
|
||||||
// a map of albums to arrays of contained tracks
|
|
||||||
|
|
||||||
// extract alphanumerical list of artists
|
// format response for jellyPod
|
||||||
let artists = [];
|
//// build tracks array and lookupMap (currently just binds alpha to artists)
|
||||||
let lastArtist = "";
|
let jpTracksArr = [];
|
||||||
let unknownFound = false;
|
const lookupMap = new Map();
|
||||||
|
let lastAlbumInfo = {AlbumArtist: "", AlbumName: "", AlbumYear: 0};
|
||||||
for (const track of libObj.Items) {
|
for (const track of libObj.Items) {
|
||||||
|
if (!track.Name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let albumArtist = "unknown artist";
|
||||||
if (track.AlbumArtist) {
|
if (track.AlbumArtist) {
|
||||||
if (track.AlbumArtist != lastArtist) {
|
albumArtist = track.AlbumArtist;
|
||||||
artists.push(track.AlbumArtist);
|
|
||||||
lastArtist = track.AlbumArtist;
|
|
||||||
}
|
|
||||||
} else if (track.Artists.length > 0) {
|
} else if (track.Artists.length > 0) {
|
||||||
if (track.Artists[0] != lastArtist) {
|
albumArtist = track.Artists[0]
|
||||||
artists.push(track.Artists[0]);
|
|
||||||
lastArtist = track.Artists[0];
|
|
||||||
}
|
}
|
||||||
} else if (!unknownFound) {
|
const albumName = track.Album ? track.Album : "unknown album";
|
||||||
unknownFound = true;
|
if (lastAlbumInfo.AlbumArtist != albumArtist) {
|
||||||
}
|
firstChar = Array.from(albumArtist)[0].toUpperCase();
|
||||||
}
|
if (!lookupMap.has(firstChar)) {
|
||||||
if (unknownFound) {
|
lookupMap.set(firstChar, [albumArtist]);
|
||||||
artists.push("unknown artist");
|
|
||||||
}
|
|
||||||
console.log(artists);
|
|
||||||
|
|
||||||
// sort artists into arrays mapped to first characters
|
|
||||||
const charMap = new Map();
|
|
||||||
let currentChar = "";
|
|
||||||
let currentArr = [];
|
|
||||||
for (const artistName of artists) {
|
|
||||||
char = Array.from(artistName)[0].toUpperCase();
|
|
||||||
if (currentChar == "") {
|
|
||||||
currentChar = char;
|
|
||||||
}
|
|
||||||
if (char == currentChar) {
|
|
||||||
currentArr.push(artistName);
|
|
||||||
} else {
|
} else {
|
||||||
charMap.set(currentChar, currentArr);
|
lookupMap.get(firstChar).push(albumArtist);
|
||||||
currentChar = char;
|
};
|
||||||
currentArr = [artistName];
|
if (lastAlbumInfo.AlbumName != albumName) {
|
||||||
|
lastAlbumInfo = {
|
||||||
|
AlbumArtist: albumArtist,
|
||||||
|
AlbumName: track.Album ? track.Album : "unknown album",
|
||||||
|
AlbumYear: track.ProductionYear ? track.ProductionYear : 1970
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentChar !== "") {
|
jpTracksArr.push({
|
||||||
charMap.set(currentChar, currentArr);
|
TrackName: track.Name,
|
||||||
}
|
JfId: track.Id,
|
||||||
console.log(...charMap);
|
AlbumInfo: lastAlbumInfo
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(jpTracksArr);
|
||||||
|
//console.log("Items:", libObj.Items.length, "Tracks:", jpTracksArr.length);
|
||||||
|
//console.log(...lookupMap);
|
||||||
|
|
||||||
Pebble.sendAppMessage({ PKJS_READY: 1 });
|
Pebble.sendAppMessage({ PKJS_READY: 1 });
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user