Last active
May 10, 2023 04:00
-
-
Save mill1000/e07de721d3e76874db5c6bf5c6dda473 to your computer and use it in GitHub Desktop.
Custom Gerbera Import Scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Helper to access first element of an array if it exists | |
function get(item, fallback) { | |
return (item && item[0]) || fallback; | |
} | |
// Custom audio import script | |
function addAudioCustom(obj) { | |
var title = get(obj.metaData[M_TITLE], obj.title); | |
var artist = get(obj.metaData[M_ARTIST], "Unknown"); | |
var album = get(obj.metaData[M_ALBUM], "Unknown"); | |
var date = get(obj.metaData[M_DATE]); | |
var decade = "Unknown"; | |
if (/.*T.*/.test(date)) { | |
// Date appears to be a file modification time, ignore it | |
date = "Unknown" | |
} | |
else { | |
// Get year from full data | |
var year = getYear(date); | |
// Update metadata | |
obj.metaData[M_UPNP_DATE] = [year]; | |
// Compute decade | |
decade = date.substring(0, 3) + "0s" | |
} | |
// Update object title | |
obj.title = title; | |
const chain = { | |
// Container for all artists | |
artists: { title: "Artists", objectType: OBJECT_TYPE_CONTAINER, upnpclass: UPNP_CLASS_CONTAINER }, | |
// Container for each artist | |
artist: { searchable: true, title: artist, objectType: OBJECT_TYPE_CONTAINER, upnpclass: UPNP_CLASS_CONTAINER_MUSIC_ARTIST, metaData: {}, res: obj.res, aux: obj.aux, refID: obj.id }, | |
// Container for all albums | |
albums: { title: "Albums", objectType: OBJECT_TYPE_CONTAINER, upnpclass: UPNP_CLASS_CONTAINER }, | |
// Container for each album | |
album: { searchable: true, title: album, objectType: OBJECT_TYPE_CONTAINER, upnpclass: UPNP_CLASS_CONTAINER_MUSIC_ALBUM, metaData: {}, res: obj.res, aux: obj.aux, refID: obj.id }, | |
// Root container for decades | |
decades: { title: "Decades", objectType: OBJECT_TYPE_CONTAINER, upnpclass: UPNP_CLASS_CONTAINER }, | |
// Container for each decade | |
decade: { title: decade, objectType: OBJECT_TYPE_CONTAINER, upnpclass: UPNP_CLASS_CONTAINER }, | |
allTracks: { title: "All Tracks", objectType: OBJECT_TYPE_CONTAINER, upnpclass: UPNP_CLASS_CONTAINER }, | |
}; | |
// Set metadata on the album container | |
chain.album.metaData[M_ARTIST] = [artist]; | |
chain.album.metaData[M_CREATOR] = [artist]; | |
chain.album.metaData[M_ALBUMARTIST] = [artist]; | |
chain.album.metaData[M_DATE] = [date]; | |
chain.album.metaData[M_ALBUM] = [album]; | |
// Set metadata on the artist container | |
chain.artist.metaData[M_ARTIST] = [artist]; | |
chain.artist.metaData[M_ALBUMARTIST] = [artist]; | |
// Group by artist, then album | |
var container = addContainerTree([chain.artists, chain.artist, chain.album]); | |
addCdsObject(obj, container); | |
// Make the artist and album unsearchable so it only shows up once in results | |
chain.album.searchable = false; | |
chain.artist.searchable = false; | |
// Group by album | |
container = addContainerTree([chain.albums, chain.album]); | |
addCdsObject(obj, container); | |
// Group by decade, then album | |
container = addContainerTree([chain.decades, chain.decade, chain.album]); | |
addCdsObject(obj, container); | |
// All tracks | |
container = addContainerTree([chain.allTracks]); | |
addCdsObject(obj, container); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Custom Gerbera audio import script | |
if (getPlaylistType(orig.mimetype) === "") { | |
// Create a copy of the original object | |
var obj = orig; | |
// All virtual objects must reference an object in the PC-Directory | |
obj.refID = orig.id; | |
var mime = orig.mimetype.split("/")[0]; | |
if (mime === "video" && obj.onlineservice === ONLINE_SERVICE_APPLE_TRAILERS) { | |
mime = "trailer"; | |
} else if (orig.mimetype === "application/ogg") { | |
mime = (orig.theora === 1) ? "video" : "audio"; | |
} | |
var audioLayout = config["/import/scripting/virtual-layout/attribute::audio-layout"] || "Default"; | |
switch (mime) { | |
case "audio": | |
switch (audioLayout) { | |
case "Structured": | |
addAudioStructured(obj); | |
break; | |
case "Custom": | |
addAudioCustom(obj); | |
break; | |
default: | |
addAudio(obj); | |
break; | |
} | |
break; | |
default: | |
print("Ignored " + obj.location + " of type " + orig.mimetype); | |
break; | |
} | |
} |
Much appreciated. Looks like the trick was adding audio-layout="Custom"
. Cheers!
Awesome example!
Just been playing with this, and found that to make the "searchable" attribute work as intended in the above audio_custom.js:
// Make the artsit and album unsearchable so it only shows up once in results
chain.album.searchable = false;
chain.artist.searchable = false;
You need to add this to the SERVER section in your config.xml file
<upnp searchable-container-flag="yes" />
Otherwise, when you search for, say, an album called "Thriller" in your UPNP controller (e.g. BubbleUPnP), it will find it three times from:
- Albums / Thriller
- Artists / Michael Jackson / Thriller
- Decades / 1980s / Thiller
That's correct. Good catch. Perhaps I should add a snippet of my config.xml
for future reference.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This should be the relevant bit you need