To implement part of a forthcoming Really Neat Idea(tm), I would need
an enhancement to the Collections concept.  I am, of course, willing to
develop a patch for this concept, but as the Collections concept itself
required a ton of discussion, I feel that just making a patch and
trying to get it upstream with no prior discussion disrespects all of
you who spent so much time engineering the concept, so I'll pitch it
with words before I do it with code.

DISCLAIMER: I haven't done a thorough audit of the existing code.  Some
of the ideas expressed may make me sound like an idiot.  That isn't a
new thing for me, so don't hesitate to let me know. ;)  Oh, and sorry
about the length.

== Definition

Atomic media (I'm open to suggestions for the name as well as
everything else) is an ordered set of media which behaves like a single
article of media in every way.  This means:

* The atomic media (AM) is identified by a single mediaid.
* The AM has properties that are visible to filter operators.

In addition, AM are subject to the following restrictions, which make
implementing them worlds easier:

* AM can not be saved.
* AM must be split before they can be played.

== Uhh... why?

My undying love of whole albums, of course.

To be more specific: an AM can make certain kinds of excruciatingly
complicated DAGs - and in fact some DAGs not before possible without
resorting to complicated, client-side-sorted idlists - remarkably
simple.  

=== Example time!

"Party shuffle of whole albums by Pinback, Menomena, or Radiohead with
running time greater than 42 minutes (2520000 msec) and an average
rating of four, which I've listened to an average of at least three
times, sorted by number of tracks."

It's possible to construct this list by manually manipulating idlists
with client code, but it would be a complicated operation involving
many queries.  The alternative is to do the following (expressed using
something similar to cli collections syntax - it should be clear how
this would translate into real code).

----

1. Query: artist:Pinback OR artist:Menomena OR artist:Radiohead album

    Returns: idlist.  Contents obvious.

2. Fuse: key:album sum:duration max:tracks avg:rating,timesplayed

    Returns: idlist.  Each mediaid is a virtual id (explained later).
    It should be noted that all of the values specified above would be
    done that way by default; they were manually specified for clarity.

3. Query: duration>2520000 rating>=4 timesplayed>=3

    Returns: idlist.  Each mediaid is still a virtual id.

4. Party shuffle.

    Returns: idlist.  Each mediaid is still a virtual id.

5. Split: limit:1

    Returns: idlist.  The top mediaids are the real mediaids of the
    individual tracks in the first album on the list.  The remaining
    ones are still virtual mediaids representing whole albums.

----

This example - for use in a party shuffle playlist - is the ugliest
example I could come up with, because of the fact that party shuffle
does duplicate some of this functionality.  I have many more
use-cases, as well as ideas regarding ways of expressing the concept of
AM to the user in a familiar and usable way, that helped when designing
the concept, but for brevity's sake I'm excluding those for now.

=== How this is better

It adds a unified method for performing selections on aggregate
statistics, and a straightforward (and client-side-logic-free) method
for computing said statistics.  This has several benefits:

* You can operate on things like albums without ever leaving the
  collections context.  It's possible to achieve some of these things
  manually, but it is disruptive because it must be accomplished 
  programmatically instead of as operations on a DAG.
* Consistent behavior for these features across clients.
* Implementation of more complex random algorithms - tournament
  selection, weighted selection - and sorting on album-wide properties
  becomes essentially free.

In the description for the aforementioned Really Neat Idea(tm), it
should become clear how easily this new functionality can be exposed to
the user.  It might help my case to cite the quote that actually
started this train of thought:

13:37 < anders> Fill my mp3player with random songs, but I prefer
                synth, and make sure the latest added albums are there,
                exept this really crappy album, and btw, the most played
                metal-albums would be nice too. And Hey! I just want
                full albums, don't splitt them, except these songs,
                which are the only good ones on their albums.

The fact that we can express this set of music in natural language much
easier than in Collections notation indicates that there is room for
improvement.  I believe that AM can greatly enhance the ability of a
Collection query to achieve the expressiveness of natural language.


== OK, hot-shot, so how you gonna implement the thing?

I propose the following changes.  Obviously these are very pseudocode,
the names etc. are designed for readability not direct implementation.

* The medialib is given the following new method: 

add_virtual_mediaid ( proplist )
-> int mediaid

Adds the virtual mediaid with the given list of properties to a
temporary table.  Returns a previously unassigned mediaid from the top
of the range of int32.  Some form of garbage collection or flushing
should be considered; I need to work on this aspect a little bit more.

It should be noted that this wouldn't break existing clients or require
further modifications to the code.  Simply exclude virtual mediaids
from the 'universe' collection.


* Two new Collections filters are created:

FUSE
FIELD: yes.i.know.this.is.gross.and.it.needs.work.i.am.still.thinking
VALUE: "key:property [sort:property] min:property[,property]..."

Takes a collection.  Sorts it by key, then by sort - let's say Album,
then Track - and fuses media with the same unique key into one virtual
mediaid.  Property x of the virtual mediaid is determined by an
operation on the values of that property from the real mediaids it
comprises.  Let v be the list of values of the given properties, and vn
being the list of values of the given properties with mathematical
nulls (non-numerical strings, empty strings, missing values) removed.

min: min(vn)
max: max(vn)
sum: sum(vn)
avg: sum(vn) / len(vn)
realavg: sum(vn) / len(v)
concat: '\n'.join(v)

More may be added as I think of them.  They'd be pretty trivial to
implement, of course.

Additionally, the property 'metamediaid' (better named) would be added,
containing the ordered list of mediaids in the virtual mediaid.


SPLIT
FIELD: [property, usually mediaid]
VALUE: [as normal]

Takes the (probably ordered) collection, splits the virtual ids that
match the property/value pair, and returns the new collection.

=== Pros of this desgin

It's a simple design, backwards-compatible*, and easily implemented.
What more could you want?

* If the default is, for instance, "title" to be concatenated with a
newline, a client will properly render the track title of an album in a
playlist/queue/whatever as a list of the individual track titles.
Similar sensible behavior would be available for all properties for
clients that chose not to become aware of AMs.

=== Items that need to be addressed

First and foremost, the FUSE filter's parameter passing is uggggggly.
The syntax isn't bad, but it's a misuse of the FIELD and VALUE
parameters.  Some alternatives spring to mind but none strike me as
elegant.  Any thoughts would be much appreciated.

Saving and loading playlists (and other medialists) with AMs would also
require an extra step, though a simple one: if a program is doing
an album view, put a SPLIT on the end of the chain when you save the
playlist, and a FUSE when you load it.  This saves much complexity from
having to deal with saving and garbage-collecting virtual mediaids, but
it still is an extra step.




*ducks under desk, covers back of neck with hands*

All right, flame away.
Steven

OH CRAP THAT DRILL IS FOR TORNAD^@

Attachment: signature.asc
Description: PGP signature

--
_______________________________________________
Xmms2-devel mailing list
Xmms2-devel@lists.xmms.se
http://lists.xmms.se/cgi-bin/mailman/listinfo/xmms2-devel

Reply via email to