GSoC:2008 Collections 2.0 Querying concept - nesciens/xmms2-wiki GitHub Wiki
The client developer provides a collection structure resulting in a medialist to the daemon. The daemon then queries the metadata from the sqlite-database, so that there is one row for every entry of the medialist and the rows are in the same order as the medialist.
Informal signature:
query_medialist (coll, fetch)
The client developer provides a collection structure to the daemon, then metadata is queried for groups of ids aka clusters.
The developer also specifies a list of things the ids in a cluster should have in common, for instance genre, artist or album. The daemon then queries the metadata from the sqlite-database, so that there is one row per cluster. If no things to have in common are specified all ids in the collection will be in one cluster.
Informal signature:
query_clustered (coll, cluster, fetch, order, start, length)
As this is gets you a value-key dict you can use this for entry_format.
query_medialist (
reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
dict ( // fetch-argument
"artist" = "artist",
"album" = "album",
"tracknr" = "tracknr",
"title" = "title"
"duration" = "duration"
)
list (
dict (
"artist" = "Something Corporate",
"album" = "Leaving through the window",
"tracknr" = "10",
"title" = "Good News",
"duration" = "232280"
),
...,
dict (
"artist" = "Something Corporate",
"album" = "Leaving through the window",
"tracknr" = "16",
"title" = "Globes and Maps",
"duration" = "287933"
)
)
As this is gets you a value-key dict you can use this for entry_format.
query_medialist (
reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
dict (
"id" = "id"
"data" = dict ( "field" = list ( "artist", "album", "tracknr", "title", "duration" ) )
)
)
list (
dict (
"id" = 767
"data" = dict (
"artist" = "Something Corporate",
"album" = "Leaving through the window",
"tracknr" = "10",
"title" = "Good News",
"duration" = "232280"
)
),
...,
dict (
"id" = 766
"data" = dict (
"artist" = "Something Corporate",
"album" = "Leaving through the window",
"tracknr" = "16",
"title" = "Globes and Maps",
"duration" = "287933"
)
)
)
query_medialist (
reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
dict (
"data" = dict ( "get" = list ( "key", "source", "value" ), "source-preference" = "All" )
)
)
list (
dict (
"data" => dict (
"artist" = dict (
"plugin/id3v2" = "Something Corporate"
),
...,
"size" = dict (
"plugin/file" = "6126427"
"plugin/id3v2" = "6125413"
),
...,
"url" = dict (
"server" = "
file:///home/erik/muziek/Something+Corporate+-+Leaving+Through+the+Window+-+Good+News.mp3
"
)
)
),
...
)
query_medialist (
reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
dict (
"data" = dict ( "get" = list ( "key", "value" ) )
)
)
list (
dict (
"data" => dict (
"artist" = "Something Corporate",
...,
"size" = "6126427",
...,
"url" = "
file:///home/erik/muziek/Something+Corporate+-+Leaving+Through+the+Window+-+Good+News.mp3
"
)
),
...
)
query_clustered (
coll, // coll argument: the collection
NULL, // cluster argument: all songs go into 1 cluster
dict (
"fields" = "field",
"aggregate" = "list"
), // fetch argument: get the fields
NULL, 0, 0 // order, start, length arguments: who cares?
)
list (
dict ("fields" = list ( "added", "album", "artist", ...) )
)
query_clustered (
coll, // coll argument: the collection
NULL, // cluster argument: all songs go into 1 cluster
dict ("count" = "count"), // fetch argument: get the number of songs in this cluster
NULL, 0, 0 // order, start, length arguments: who cares?
)
list (
dict = ("count" = 10)
)
query_clustered (
coll,
dict ("artist", "artist"),
dict (
"artist" = "cluster",
"albums" = dict ("field" = "album", "aggregate" = "list")
),
NULL, 0, 0
)
list (
dict (
"artist" = "The Clash",
"albums" = list (
"London Calling"
)
),
...,
dict (
"artist" = "Sonata Arctica",
"albums" = list (
"Broken",
"Ecliptica",
"For The Sake Of Revenge"
)
)
)
query_clustered (
coll,
dict ("album" = "album"),
dict (
"album" = "cluster",
"number" = "count",
"duration" = dict ("field" = "duration", "aggregate" = "sum"),
)
NULL, 0, 0
)
list (
dict = (
"album" = "The Devil And God Are Raging Inside Me",
"number" = 12,
"duration" = 3541123
),
...,
dict (
"album" = "MTV Unplugged in New York",
"number" = 1,
"duration" = 175943
)
)
query_clustered (
coll, // coll argument: the collection
dict ("album" = "album"), // cluster argument: 1 cluster for every album
dict (
"album" = "cluster",
"ids" = "ids",
"metadata" = dict (
"field" = list ("tracknr", "title"),
"get" = list ("id", "field", "value")
)
),
NULL, 0, 0 // order, start, length arguments: who cares?
)
list (
dict (
"album" = "The Devil And God Are Raging Inside Me",
"ids" = list (59, ..., 70),
"metadata" = dict (
"59" = dict (
"tracknr" = "4",
"title" = "Degausser"
),
...,
"70" = dict (
"tracknr" = "6",
"title" = "You won't know"
)
)
),
...,
dict (
"album" = "MTV Unplugged in New York",
"ids" = 630,
"metadata" = dict (
"tracknr" = "12",
"title" = "Lake of Fire"
)
)
)
This is an informal description of the datatype used in the fetch, cluster, and order arguments below.
dict (
"type" = < "id" | "count" | "random" | "cluster" | "metadata" >
)
Note: "type" = "cluster" is only allowed in order and fetch arguments.
Default values:
"type" = "metadata"
"id" => dict ( "type" = "id" )
"ids" => dict ( "type" = "id", "aggregate" = "list" )
"count" => dict ( "type" = "count" )
"random" => dict ( "type" = "random" )
"cluster" => dict ( "type" = "cluster", label =
) // (only in fetch argument)
"fields" => dict ( "get" = list ("field"), "aggregate" = "list" )
"sources" => dict ( "get" = list ("source"), "aggregate" = "list")
=> dict ( "field" =
)
Note: Everywhere where a list is used below a string can also be used, which is converted to a list of one element:
=> list (
)
=== "type" = "cluster" === Additional fields:
"label" =
,
"get" = list (
list of one or more of "field", "id", "value", "source".
)
Default values:
"get" = list ( "value" )
=== "type" = "id" === Additional fields:
"aggregate" = < "first" | "sum" | "min" | "max" | "list" >
Default values:
"aggregate" = "first"
=== "type" = "metadata" === Additional fields:
"get" = list (
list of one or more of "field", "id", "value", "source".
)
"aggregate" = < "first" | "sum" | "min" | "max" | "list" >
"source-preference" = < "All" | "Default" >
Default values:
"get" = list ("value")
"aggregate" = "first"
"source-preference" = "Default"
Optional fields:
"id" = list (...)
"field" = list (...)
"value" = list (...)
"source" = list (...)
These are yet to be updated.
The client developer provides a collection structure to the daemon. The daemon then queries the metadata from the sqlite-database, so that there is one row for every id of the resulting collection. The result is ordered ascending by id.
coll: reference[reference=Gothic Metal,namespace=Playlists]
fetch: {{ spec={ type=id, arguments={} }, label=id },
{ spec={ type=value, arguments={field=artist} }, label=artist },
{ spec={ type=value, arguments={field=album} }, label=album },
{ spec={ type=value, arguments={field=title} }, label=title },
{ spec={ type=source_value_dict, arguments={field=size} }, label=datasize }}
result: {{ id=113, artist=Evanescence, album=Anywhere But Home, title=Thoughtless, datasize={plugin/id3v2=8286281, plugin/file=8314880} },
{ id=141, artist=Evanescence, album=Not For Your Ears, title=Taking Over Me (Long), datasize={plugin/id3v2=5304040, plugin/file=5326558} },
{ id=1092, artist=Within Temptation, album=Mother Earth, title=Mother Earth, datasize={plugin/id3v2=8947303, plugin/file=8947840} }}
The client developer provides a collection structure to the daemon and an optional list of things ids in a group should have in common, for instance genre, artist or album (the groupby-argument). The daemon then queries the metadata from the sqlite-database, so that there are zero or more rows per group, showing all permutations of the "free" (not used for grouping) properties. If no groupby-list is supplied all requested properties are used for grouping.
coll: reference[reference=Gothic Metal,namespace=Playlists]
group-by: {artist}
fetch: {id, artist, album, title, size}
result: {{ id=113, artist=Evanescence, album=Anywhere But Home, title=Thoughtless, size=8286281 },
{ id=1092, artist=Within Temptation, album=Mother Earth, title=Mother Earth, size=8947303 }}
coll: reference[reference=Gothic Metal,namespace=Playlists]
group-by: {}
fetch: {id, artist, album, title, size}
result: {{ id=113, artist=Evanescence, album=Anywhere But Home, title=Thoughtless, size=8286281 },
{ id=113, artist=Evanescence, album=Anywhere But Home, title=Thoughtless, size=8314880 },
{ id=141, artist=Evanescence, album=Not For Your Ears, title=Taking Over Me (Long), size=5304040 },
{ id=141, artist=Evanescence, album=Not For Your Ears, title=Taking Over Me (Long), size=5326558 },
{ id=1092, artist=Within Temptation, album=Mother Earth, title=Mother Earth, size=8947303 },
{ id=1092, artist=Within Temptation, album=Mother Earth, title=Mother Earth, size=8947840 }}