[vlc-devel] [PATCH] Lua-SD: Adding a customized way to create Jamendo playlists for everyone to try

chrcnt7 at swift-mail.com chrcnt7 at swift-mail.com
Tue Aug 9 06:39:03 CEST 2016


>From c438748b969631aa89d184c933b00db8bbc4b075 Mon Sep 17 00:00:00 2001
From: Wilawar <chrcnt7 at swift.mail.org>
Date: Tue, 9 Aug 2016 04:22:04 +0200
Subject: [PATCH] lua/sd: add alternative services-discovery for Jamendo

Note that this is still unfinished and more of a proposal, although it should run just fine. For notes on the implementation, please refer to the comments at the beginning of the file, after the copyright notice.
---
 share/Makefile.am           |   4 +-
 share/lua/sd/jamendo-cj.lua | 349 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 352 insertions(+), 1 deletion(-)
 create mode 100644 share/lua/sd/jamendo-cj.lua

diff --git a/share/Makefile.am b/share/Makefile.am
index fbfa447..671d9a9 100644
--- a/share/Makefile.am
+++ b/share/Makefile.am
@@ -158,6 +158,7 @@ nobase_vlclib_DATA = \
 	lua/sd/icecast.luac \
 	lua/sd/icast.luac \
 	lua/sd/jamendo.luac \
+	lua/sd/jamendo-cj.luac \
 	$(NULL)
 
 nobase_doc_DATA = \
@@ -251,7 +252,8 @@ EXTRA_DIST += \
 	lua/sd/fmc.lua \
 	lua/sd/icecast.lua \
 	lua/sd/icast.lua \
-	lua/sd/jamendo.lua
+	lua/sd/jamendo.lua \
+	lua/sd/jamendo-cj.lua
 
 DIST_http_lua = \
 	lua/http/view.html \
diff --git a/share/lua/sd/jamendo-cj.lua b/share/lua/sd/jamendo-cj.lua
new file mode 100644
index 0000000..6fd1047
--- /dev/null
+++ b/share/lua/sd/jamendo-cj.lua
@@ -0,0 +1,354 @@
+--[[
+ $Id$
+
+ Copyright © 2016 VideoLAN and AUTHORS
+
+ Authors: Fabio Ritrovato <sephiroth87 at videolan dot org>
+          Rémi Duraffort  <ivoire at videolan dot org>
+          Gian Marco Sibilla <techos at jamendo dot com>
+          Some anonymous guy currently known as Wilawar on the IRC network
+            freenode and on trac <chrcnt7 at swift dash mail dot org>
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+--]]
+
+
+
+--[[ === Comments on this Script ===
+I realize the people at Jamendo probably want to see the playlists of featured tracks here the current
+(2016-08-09, version 2.2.4) default script provides. I’m not averse to integrating them, they just didn’t
+matter much to me. I will probably add them in a future version.
+The core parsing is done by code I made a parser generator for. I did already publish its source on pastebin.com,
+but people didn’t really like it (I’m not too much surprised by that, I wouldn’t call it beautiful myself). Part of that
+is because of Lua’s inherent limitations, part of it because I just didn’t clean it up or comment it for others to see.
+[Just note, there is a minor problem with code gen at the moment, the declaration of 'J' has to be moved out of
+the do-block. Else, it should work (but it should probably be changed to use string.find instead of loops, as this
+seems to be faster without LuaJIT despite the obvious overhead that is involved with it).]
+The parser gen. should really only have to be run once (and I already did that), I don’t expect Jamendo to change
+their response format anytime soon. It also relies on the specific ordering of fields and such (by design!) and would
+break if there were any strings with quotation marks in them (it’s just stripping the escape markers).
+
+For the future, I’d propose to use the XML backend I also wrote, which would have to be adapted a bit to the
+new code. It previously couldn’t work the way it should have because it was impossible to query for self-closing tags
+(the function had just been omitted). It’s been added by refp and should work in nightlies already, just the code
+doesn’t make use of it at the moment. However, it won’t ever work in any versions of VLC up to and including 2.2.4
+for this reason, therefore, I propose to keep this JSON edition as long as it’ll work for old versions.
+(I do like JSON way better than XML, but when I looked at the tools that were already there, VLC had libxml2 for XML
+parsing, which is a C library and should be fast, but only DKJSON for JSON parsing (which is written in Lua and ought
+to be slow for this reason). This and that the existing parser was already set for XML made me choose this format.*)
+
+Further improvements which could be made include those:
+1. On-demand loading of items (should be easy to do, according to refp), which would improve usability remarkably
+    and still probably saving Jamendo some bandwidth and server load
+2. Displaying tracks as soon as they are avialable (Done on purpose at the end for now; it can easily be changed by
+    shuffling around the lines in 'main'.)
+3. Updating the playlist entries automatically or at least on users’ request (This could get hard, but right now VLC has
+    to be closed and started again to get new lists, which is not exactly the user experience one would wish for.)
+4. Adding ways to customize the kinds of entries to be fetched, maybe even the queries and reimplementing the
+    merge function for multiple lists
+5. After the first one has been implemented: Prefetching those entries users frequently use themselves
+    (different people would probably use different entries)
+6. Adding more tracklist choices (also only really viable after on-demand loading is there) (more orderings, more sections)
+
+*It’s still verbose and ugly.
+=== End of the Comments on this Script ===]]
+
+
+
+--[[ === Example Query ===
+-- Comments --
+The line breaks are not present in the orignal answer (use 'format=jsonpretty' for that), they were added to enhance readability here.
+The API documentation can be had at [https://developer.jamendo.com/v3.0], the documentation for the 'tracks' 'method' specifically at
+[https://developer.jamendo.com/v3.0/tracks]. For trying stuff, use a limit like 10 or 5 or so, not 100. The client_id here is the one that
+was given out for testing and still worked 2016-08-09. You might have to get a new one (look at the documentation for the client_id
+request parameter, that’s where I usually found it). When I ran this query, for 100 tracks (still 2016-08-09), Firefox gave the page size
+in the JSON view as 12,258 bytes; I’ll have to assume that this is the compressed size, as some character counting tools gave me
+78,318 bytes for the size (and number of characters). Note that slashes are escaped for whichever reason and this has to be reversed.
+-- Query --
+https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&vocalinstrumental=instrumental&order=buzzrate_desc&limit=100&offset=300&type=single+albumtrack
+-- Response --
+{"headers":{"status":"success","code":0,"error_message":"","warnings":"","results_count":100},"results":[{"id":"716982","name":"Sunday Is Over",
+"duration":133,"artist_id":"366099", "artist_name":"Victoria Caff\u00e8","artist_idstr":"Victoria_Caffe","album_name":"Busy Days","album_id":"83642",
+"license_ccurl":"http:\/\/creativecommons.org\/licenses\/by-nc-nd\/2.0\/fr\/", "position":5,"releasedate":"2011-01-18","album_image":
+"https:\/\/imgjam1.jamendo.com\/albums\/s83\/83642\/covers\/1.200.jpg", "audio":"https:\/\/mp3l.jamendo.com\/?trackid=716982&format=mp31&from=app-56d30c95",
+"audiodownload":"https:\/\/mp3d.jamendo.com\/download\/track\/716982\/mp32\/", "prourl":"https:\/\/licensing.jamendo.com\/track\/716982","shorturl":
+"http:\/\/jamen.do\/t\/716982","shareurl":"http:\/\/www.jamendo.com\/track\/716982", "image":"https:\/\/imgjam1.jamendo.com\/albums\/s83\/83642\/covers\/1.200.jpg"},
+{"id":"1098631","name":"Shine (Orchestral Pop Rock Version)","duration":129,"artist_id":"361044", "artist_name":"Oursvince","artist_idstr":"Oursvince","album_name":"Shine",
+[…]}, {[…]}, {[…]}, {[…]}, […],
+{"id":"1075892","name":"Departure (Electro)","duration":295,"artist_id":"340768","artist_name":"Capashen","artist_idstr":"Capashen","album_name":"Departure",
+"album_id":"128151", "license_ccurl":"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/3.0\/","position":1,"releasedate":"2013-10-30","album_image":
+"https:\/\/imgjam1.jamendo.com\/albums\/s128\/128151\/covers\/1.200.jpg","audio":"https:\/\/mp3l.jamendo.com\/?trackid=1075892&format=mp31&from=app-56d30c95",
+"audiodownload":"https:\/\/mp3d.jamendo.com\/download\/track\/1075892\/mp32\/","prourl":"https:\/\/licensing.jamendo.com\/track\/1075892","shorturl":
+"http:\/\/jamen.do\/t\/1075892","shareurl":"http:\/\/www.jamendo.com\/track\/1075892","image":"https:\/\/imgjam1.jamendo.com\/albums\/s128\/128151\/covers\/1.200.jpg"}]}
+--=== Example End === ]]
+
+
+
+
+
+
+ --Those three functions have been carried over from the old script (I altered 'title', obviously)
+function descriptor()
+    return { title = "Custom Jamendo SD", capabilities = {} }
+end
+
+function activate()
+    main()
+end
+
+local function log( msg )
+    vlc.msg.dbg( "[JAMENDO] " .. msg )
+end
+
+--Hardening against maliciously constructed documents is not attempted.
+--This will read from a vlc.stream (it should yield a document in Jamendo’s JSON format!) and return
+--the contained tracks as tables ready to be passed to <node>:add_subitem
+local function ExtractingTheTrackInfo(OneJdoJsonTracklistQueryStream) --Returning the list of track infos and their count
+    local OJJTQResult, BytesRead = "", nil
+    --@ local BeforeReading, AfterReading_BeforeParsing, AfterParsing --For checking runtimes
+    --@ BeforeReading = os.clock()
+    while true do
+        BytesRead = OneJdoJsonTracklistQueryStream:read(131071) --Size of the example query: 78,318 bytes
+        if BytesRead == nil then --Should probably check for overly large documents, maybe over 1MiB.
+            break
+        end
+        OJJTQResult = OJJTQResult .. BytesRead --There shouldn’t be many iterations, so table.concat quite probably wouldn’t help
+    end
+    --@ AfterReading_BeforeParsing = os.clock()
+    local S = string.gsub(OJJTQResult, "\\", "") --Could indeed be the fastest way to do it in Lua (because Lua is a true misfit for this task)
+    OJJTQResult, BytesRead = nil, nil --The GC could take this as a hint to collect the memory, at least at some point (it might be paused)
+    --Using string.find instead of looping and checking for byte values in plain Lua code might be advantageous regarding speed
+    --(as I hadn’t benchmarked this and didn’t expect it to be so slow). On the other hand, the strides should be fairly short in every case,
+    --so maybe it’s not that bad
+-- The following line of code has been auto-generated
+    local StatusString,StatusCode,ErrorMsg,Warnings,ResCnt;local J=0;local TrackIds,TrackNames,Durations,ArtistIds,ArtistNames,ArtistIdstrs,AlbumNames,AlbumIds,LicenseCcUrls,NrsOnAlbums,Releasedates_IsoStr,AlbumImageUrls,StreamingUrls,DownloadUrls,ProUrls,ShortUrls,ShareUrls,ImageUrls={},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{};do local P=1;local A;local B=string.byte;local F=string.sub;P=22+P;A=P;while B(S,P)~=34 do P=1+P end;StatusString=F(S,A,P-1);P=9+P;A=P;while B(S,P)~=44 do P=1+P end;StatusCode=0;for C=A,P-1 do StatusCode=StatusCode*10+B(S,C)-48;end;P=18+P;A=P;while B(S,P)~=34 do P=1+P end;ErrorMsg=F(S,A,P-1);P=14+P;A=P;while B(S,P)~=34 do P=1+P end;Warnings=F(S,A,P-1);P=18+P;A=P;while B(S,P)~=125 do P=1+P end;ResCnt=0;for C=A,P-1 do ResCnt=ResCnt*10+B(S,C)-48;end;P=13+P;if B(S,P)==123 then P=1+P;repeat J=1+J;P=6+P;A=P;while B(S,P)~=34 do P=1+P end;TrackIds[J]=0;for C=A,P-1 do TrackIds[J]=TrackIds[J]*10+B(S,C)-48;end;P=10+P;A=P;while B(S,P)~=34 do P=1+P end;TrackNames[J]=F(S,A,P-1);P=13+P;A=P;while B(S,P)~=44 do P=1+P end;Durations[J]=0;for C=A,P-1 do Durations[J]=Durations[J]*10+B(S,C)-48;end;P=14+P;A=P;while B(S,P)~=34 do P=1+P end;ArtistIds[J]=0;for C=A,P-1 do ArtistIds[J]=ArtistIds[J]*10+B(S,C)-48;end;P=17+P;A=P;while B(S,P)~=34 do P=1+P end;ArtistNames[J]=F(S,A,P-1);P=18+P;A=P;while B(S,P)~=34 do P=1+P end;ArtistIdstrs[J]=F(S,A,P-1);P=16+P;A=P;while B(S,P)~=34 do P=1+P end;AlbumNames[J]=F(S,A,P-1);P=14+P;A=P;while B(S,P)~=34 do P=1+P end;AlbumIds[J]=0;for C=A,P-1 do AlbumIds[J]=AlbumIds[J]*10+B(S,C)-48;end;P=19+P;A=P;while B(S,P)~=34 do P=1+P end;LicenseCcUrls[J]=F(S,A,P-1);P=13+P;A=P;while B(S,P)~=44 do P=1+P end;NrsOnAlbums[J]=0;for C=A,P-1 do NrsOnAlbums[J]=NrsOnAlbums[J]*10+B(S,C)-48;end;P=16+P;A=P;while B(S,P)~=34 do P=1+P end;Releasedates_IsoStr[J]=F(S,A,P-1);P=17+P;A=P;while B(S,P)~=34 do P=1+P end;AlbumImageUrls[J]=F(S,A,P-1);P=11+P;A=P;while B(S,P)~=34 do P=1+P end;StreamingUrls[J]=F(S,A,P-1);P=19+P;A=P;while B(S,P)~=34 do P=1+P end;DownloadUrls[J]=F(S,A,P-1);P=12+P;A=P;while B(S,P)~=34 do P=1+P end;ProUrls[J]=F(S,A,P-1);P=14+P;A=P;while B(S,P)~=34 do P=1+P end;ShortUrls[J]=F(S,A,P-1);P=14+P;A=P;while B(S,P)~=34 do P=1+P end;ShareUrls[J]=F(S,A,P-1);P=11+P;A=P;while B(S,P)~=34 do P=1+P end;ImageUrls[J]=F(S,A,P-1);P=2+P;if B(S,P)==44 and B(S,P+1)==123 then P=2+P;else break;end;until false;end;P=1+P;end;
+-- The previous line of code has been auto-generated
+    --@ AfterParsing = os.clock()
+    --@ log("Reading took " .. tostring(AfterReading_BeforeParsing - BeforeReading) .. "ms, while parsing took " ..
+    --@	tostring(AfterParsing - AfterReading_BeforeParsing) .. "ms to complete.")
+    log("Status code: " .. StatusCode) --These four log items are optional debugging aids
+    log("Warnings: " .. Warnings)
+    log("Error messages: " .. ErrorMsg)
+    log("Results count: " .. ResCnt)
+    local TrackRes = {}
+    for TrackResNbr = 1, J do --J will hold the number of tracks that were encountered and hence the number of entries every table will have
+        TrackRes[TrackResNbr] = {["title"] = TrackNames[TrackResNbr], ["artist"] = ArtistNames[TrackResNbr], ["copyright"] = LicenseCcUrls[TrackResNbr],
+            ["album"] = AlbumNames[TrackResNbr], ["path"] = StreamingUrls[TrackResNbr], ["date"] = Releasedates_IsoStr[TrackResNbr],
+            ["arturl"] = ImageUrls[TrackResNbr], ["url"] = DownloadUrls[TrackResNbr], ["nowplaying"] = ShareUrls[TrackResNbr], ["duration"] = Durations[TrackResNbr],
+            ["tracknum"] = NrsOnAlbums[TrackResNbr], ["trackid"] = TrackIds[TrackResNbr]
+            --[=[, ["description"] = "Placement test: description", ["setting"] = "Placement test: setting",
+            ["rating"] = "Placement test: rating", ["name"] = "Placement test: name"--]=]}
+            --The parameter values for 'vocalinstrumental' and 'order' could be put into the field Genre
+    end
+    return TrackRes, J
+end
+
+--This function will add the tracks given in 'Tracklist' (as tables for use by add_subnode) and add a third of them each into every node it creates.
+--The nodes are created as subnodes of Bundle and will be named '<Prefix>:1/3', '<Prefix>:2/3', '<Prefix>:3/3'
+--TracklistItemCt is the highest index that will be used from Tracklist
+function AddingATracklistInThreeSlices(Bundle, Prefix, Tracklist, TracklistItemCt)
+    --Adding the three subnodes (inner bundles)
+    local LabelCarrier = {}
+    local FirstThird, SecondThird, ThirdThird
+    LabelCarrier["title"] = Prefix .. "::1/3"
+    FirstThird = Bundle:add_subnode(LabelCarrier)
+    LabelCarrier["title"] = Prefix .. "::2/3"
+    SecondThird = Bundle:add_subnode(LabelCarrier)
+    LabelCarrier["title"] = Prefix .. "::3/3"
+    ThirdThird = Bundle:add_subnode(LabelCarrier)
+    --Filling those bundles with the right tracks
+    local floor = math.floor
+    FirstToSecond = floor(TracklistItemCt / 3) --At which number to transition from the first to the second bundle
+        --(Should be an integer, really, but Lua 5.1 doesn’t have them anyways)
+    SecondToThird = floor(TracklistItemCt * 2 / 3) --And at which number the second bundle will be seen as filled and the third used for the remaining items
+    for TrackItemNbr = 1, FirstToSecond do
+        FirstThird:add_subitem(Tracklist[TrackItemNbr])
+    end
+    for TrackItemNbr = FirstToSecond + 1, SecondToThird do
+        SecondThird:add_subitem(Tracklist[TrackItemNbr])
+    end
+    for TrackItemNbr = SecondToThird + 1, TracklistItemCt do
+        ThirdThird:add_subitem(Tracklist[TrackItemNbr])
+    end
+end
+
+function main()
+    local OuterBundle = vlc.sd
+    local TopTracks_Buzzrate, TopTracks_PlyWeek, TopTracks_PlyMonth, TopTracks_TkId, TopInstTks_Buzzrate, TopInstTks_PlyWeek, TopInstTks_PlyMonth, TopInstTks_TkId
+    local LowTracks_Buzzrate, LowTracks_PlyWeek, LowTracks_PlyMonth, LowTracks_TkId, LowInstTks_Buzzrate, LowInstTks_PlyWeek, LowInstTks_PlyMonth, LowInstTks_TkId
+    local TopTracks_Buzzrate_Ct, TopTracks_PlyWeek_Ct, TopTracks_PlyMonth_Ct, TopTracks_TkId_Ct, TopInstTks_Buzzrate_Ct, TopInstTks_PlyWeek_Ct, TopInstTks_PlyMonth_Ct, TopInstTks_TkId_Ct
+    local LowTracks_Buzzrate_Ct, LowTracks_PlyWeek_Ct, LowTracks_PlyMonth_Ct, LowTracks_TkId_Ct, LowInstTks_Buzzrate_Ct, LowInstTks_PlyWeek_Ct, LowInstTks_PlyMonth_Ct, LowInstTks_TkId_Ct
+    TopTracks_PlyWeek, TopTracks_PlyWeek_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=popularity_week&limit=100"))
+    TopTracks_PlyMonth, TopTracks_PlyMonth_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=popularity_month&limit=100"))
+    TopTracks_TkId, TopTracks_TkId_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=id&limit=100"))
+    TopTracks_Buzzrate, TopTracks_Buzzrate_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=buzzrate_desc&limit=100"))
+    TopInstTks_PlyWeek, TopInstTks_PlyWeek_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=popularity_week&limit=100"))
+    TopInstTks_PlyMonth, TopInstTks_PlyMonth_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=popularity_month&limit=100"))
+    TopInstTks_TkId, TopInstTks_TkId_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=id&limit=100"))
+    TopInstTks_Buzzrate, TopInstTks_Buzzrate_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=buzzrate_desc&limit=100"))
+    LowTracks_PlyWeek, LowTracks_PlyWeek_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=popularity_week&limit=100&offset=300"))
+    LowTracks_PlyMonth, LowTracks_PlyMonth_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=popularity_month&limit=100&offset=300"))
+    LowTracks_TkId, LowTracks_TkId_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=id&limit=100&offset=300"))
+    LowTracks_Buzzrate, LowTracks_Buzzrate_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&order=buzzrate_desc&limit=100&offset=300"))
+    LowInstTks_PlyWeek, LowInstTks_PlyWeek_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=popularity_week&limit=100&offset=300"))
+    LowInstTks_PlyMonth, LowInstTks_PlyMonth_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=popularity_month&limit=100&offset=300"))
+    LowInstTks_TkId, LowInstTks_TkId_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=id&limit=100&offset=300"))
+    LowInstTks_Buzzrate, LowInstTks_Buzzrate_Ct = ExtractingTheTrackInfo(vlc.stream(
+        "https://api.jamendo.com/v3.0/tracks/?client_id=56d30c95&format=json&type=single+albumtrack&vocalinstrumental=instrumental&order=buzzrate_desc&limit=100&offset=300"))
+    --Adding the content to the playlist only at the end should make it painfully obvious how long it’s taking to fetch stuff right now.
+    --This could be much improved by loading only nodes that were requested by the user, time will tell when this will be implemented.
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Highest popularity for one week"}), "JATW", TopTracks_PlyWeek, TopTracks_PlyWeek_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Less popular for one week by 300 positions"}), "JAWL", LowTracks_PlyWeek, LowTracks_PlyWeek_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Highest popularity for one month"}), "JAMT", TopTracks_PlyMonth, TopTracks_PlyMonth_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "300 positions less popular for one month"}), "JAML", LowTracks_PlyMonth, LowTracks_PlyMonth_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Highest Track-IDs"}), "JANT", TopTracks_TkId, TopTracks_TkId_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Track-IDs 300 down from the top"}), "JANL", LowTracks_TkId, LowTracks_TkId_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Tracks with the highest buzzrate"}), "JABT", TopTracks_Buzzrate, TopTracks_Buzzrate_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Tracks which are 300 positions down on the buzzrate scale"}), "JABL", LowTracks_Buzzrate, LowTracks_Buzzrate_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Instrumental and highest popularity this week"}), "JIWT", TopInstTks_PlyWeek, TopInstTks_PlyWeek_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Instrumental and less popular this week by 300 positions"}), "JIWL", LowInstTks_PlyWeek, LowInstTks_PlyWeek_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Instrumental and Highest popularity this month"}), "JIMT", TopInstTks_PlyMonth, TopInstTks_PlyMonth_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Instrumental and 300 positions less popular this month"}), "JIML", LowInstTks_PlyMonth, LowInstTks_PlyMonth_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Highest Track-IDs | Instrumental"}), "JINT", TopInstTks_TkId, TopInstTks_TkId_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Track-IDs 300 down from the top | Instrumental"}), "JINL", LowInstTks_TkId, LowInstTks_TkId_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Instrumental | InstTks with the highest buzzrate"}), "JIBT", TopInstTks_Buzzrate, TopInstTks_Buzzrate_Ct)
+    AddingATracklistInThreeSlices(OuterBundle.add_node({["title"] = "Instrumental | InstTks which are 300 positions down on the buzzrate scale"}), "JIBL", LowInstTks_Buzzrate, LowInstTks_Buzzrate_Ct)
+    --Another format proposal "I: Tracks with the highest buzzrate (Instrumental)"
+end
+
+--[[ ==== For Playing with Layout Ideas =====
+I needed some independent source of song names, for which
+I used http://dfx.at/sets//Excitation/excitation%20016/tracklist.txt
+== V1 ==
+-- Top Tracks
+    -- Top: By popularity this week
+        -- JTW::1/3
+            -- Vicky Devine pres. Saphara - Eternal Dream (Ian Betts Remix)
+            -- NZK - Crop Circles
+            -- Fire & Ice - Para Siempre
+            -- Dmitri Federov - Falling Of Stars (Meridian Remix)
+        -- JTW::2/3
+            -- Ben Gold - Roll Cage (Aly & Fila Remix)
+            -- Mirco de Govia - Aura Indigo (Sequentia Remix)
+            -- Catching Dreams - Timeless (DJ Ray Remix)
+            -- Filo & Peri - Spectrum
+        -- JTW::3/3
+            -- Floyd - Any Given Day (Floyd Mix)
+            -- Syna - Do You Feel (Original Mix)
+            -- Dan Mangela - Constancy (About:Blank Mix)
+            -- Akretis - There's A Time (Photon Decay Dub Mix)
+    -- Top: By popularity this month
+        -- JTW::1/3
+            -- Ben Gold - Roll Cage (Aly & Fila Remix)
+            -- P.E.G. - Elite
+            -- NZK - Crop Circles
+            -- Akretis - There's A Time (Photon Decay Dub Mix)
+        -- JTW::2/3
+            -- Syna - Do You Feel (Original Mix)
+            -- A/B Project - Misconceptions (Ehren Stowers Remix)
+            -- Filo & Peri - Spectrum
+            -- Catching Dreams - Timeless (DJ Ray Remix)
+        -- JTW::3/3
+            -- Vicky Devine pres. Saphara - Eternal Dream (Ian Betts Remix)
+            -- Dmitri Federov - Falling Of Stars (Meridian Remix)
+            -- Kryztow de Fier - The Maze
+            -- Constant pres. Meyla - Snow Fall
+    -- Top: By TrackId
+        -- JTW::1/3
+            -- Rialdo Sheperd - Staring At My Own
+            -- Fire & Ice - Para Siempre
+            -- Mirco de Govia - Aura Indigo (Sequentia Remix)
+            -- Kryztow de Fier - The Maze
+        -- JTW::2/3
+            -- Airbase - One Tear Away
+            -- P.E.G. - Elite
+            -- NZK - Crop Circles
+            -- A/B Project - Misconceptions (Ehren Stowers Remix)
+        -- JTW::3/3
+            -- Ben Gold - Roll Cage (Aly & Fila Remix)
+            -- Constant pres. Meyla - Snow Fall
+            -- Floyd - Any Given Day (Floyd Mix)
+            -- Dan Mangela - Constancy (About:Blank Mix)
+-- Low Tracks
+    -- Low by popularity this week
+        -- JLW::1/3
+        -- JLW::2/3
+        -- JLW::3/3
+== V2 ==
+-- Top Tracks
+    -- Top: By popularity this week
+        -- JTW::1/3
+            -- Vicky Devine pres. Saphara - Eternal Dream (Ian Betts Remix)
+            -- NZK - Crop Circles
+            -- Fire & Ice - Para Siempre
+            -- Dmitri Federov - Falling Of Stars (Meridian Remix)
+        -- JTW::2/3
+            -- Ben Gold - Roll Cage (Aly & Fila Remix)
+            -- Mirco de Govia - Aura Indigo (Sequentia Remix)
+            -- Catching Dreams - Timeless (DJ Ray Remix)
+            -- Filo & Peri - Spectrum
+        -- JTW::3/3
+            -- Floyd - Any Given Day (Floyd Mix)
+            -- Syna - Do You Feel (Original Mix)
+            -- Dan Mangela - Constancy (About:Blank Mix)
+            -- Akretis - There's A Time (Photon Decay Dub Mix)
+    -- Top: By popularity this month
+        -- JTW::1/3
+            -- Ben Gold - Roll Cage (Aly & Fila Remix)
+            -- P.E.G. - Elite
+            -- NZK - Crop Circles
+            -- Akretis - There's A Time (Photon Decay Dub Mix)
+        -- JTW::2/3
+            -- Syna - Do You Feel (Original Mix)
+            -- A/B Project - Misconceptions (Ehren Stowers Remix)
+            -- Filo & Peri - Spectrum
+            -- Catching Dreams - Timeless (DJ Ray Remix)
+        -- JTW::3/3
+            -- Vicky Devine pres. Saphara - Eternal Dream (Ian Betts Remix)
+            -- Dmitri Federov - Falling Of Stars (Meridian Remix)
+            -- Kryztow de Fier - The Maze
+            -- Constant pres. Meyla - Snow Fall
+    -- Top: By TrackId
+        -- JTW::1/3
+            -- Rialdo Sheperd - Staring At My Own
+            -- Fire & Ice - Para Siempre
+            -- Mirco de Govia - Aura Indigo (Sequentia Remix)
+            -- Kryztow de Fier - The Maze
+        -- JTW::2/3
+            -- Airbase - One Tear Away
+            -- P.E.G. - Elite
+            -- NZK - Crop Circles
+            -- A/B Project - Misconceptions (Ehren Stowers Remix)
+        -- JTW::3/3
+            -- Ben Gold - Roll Cage (Aly & Fila Remix)
+            -- Constant pres. Meyla - Snow Fall
+            -- Floyd - Any Given Day (Floyd Mix)
+            -- Dan Mangela - Constancy (About:Blank Mix)
+=== - === ]]
+

-- 
http://www.fastmail.com - Or how I learned to stop worrying and
                          love email again



More information about the vlc-devel mailing list