Media Device Syncing - One more time now .. (we have a volunteer)

Bart Cerneels bart.cerneels at kde.org
Wed May 26 09:55:56 CEST 2010


On Tue, May 25, 2010 at 23:55, Casey Link <unnamedrambler at gmail.com> wrote:
> He folks,
>
> Introducing Amitav here.. he has volunteered to work on iPod syncing
> for Summer of KDE.. something I've been trying to do and failing to do
> for awhile.
>
> As he is knew to the Amarok codebase I suggested he should work on the
> easiest task first, which AFAIK is extending parts podcast/playlist
> stuff to work on ipods. Bart, can you comment on what exactly needs to
> be done (with a few references to actually classes)?

For the regular playlists: implement UserPlaylistProvider and
iPodPlaylist class. Though I think this is already implemented
indirectly though MediaDevicePlaylistProvider, which is a problem I'll
describe below.

Podcasts on iPod are definitely not implemented yet and you'll be able
to do it similarly like I did for USB Mass Storage.
What is needed is a PodcastProvider and the Podcast classes:
PodcastChannel and PodcastEpisode for iPod. In practice the episodes
will be a proxy for the itunes-db tracks that are the episodes. You'll
probably have to generate the PodcastChannels based on the metadata of
these episodes. Again, UMS is the best inspiration.

Once the podcast provider is registered with
PlaylistManager::addProvider() it will automatically show up in the
podcast section.

In order to support copying playlists and adding podcast channels
you'll need to implement PlaylistProvider::addPlaylist() and
Playlist::addTrack(), Playlist::removeTrack(). This is all that is
needed to enable drag and drop copying in the browsers.

Both UserPlaylist and Podcasts share the same synchronization logic,
it uses the add and remove functions above to get playlists to the
same state meaning both the tracks and their order. Note that playlist
synchronization does not directly handle copying over the actual
tracks.

The steps of synchronization:
1) PlaylistProvider A is registered with PlaylistManager.
2) PlaylistProvider B is registered with PlaylistManager.
  * Playlists B.1 is to be synchronized with A.5.
  * Playlist A.5 and B.1 are added to a SyncedPlaylist
   - the synchronization logic iterates over all track positions of
A.5 and adds the track at that position in B.1 if it's not already
there. Once the end off A.5 is reached all tracks beyond that position
are removed from B.1.
(see http://gitorious.org/~Stecchino/amarok/stecchinos-amarok/blobs/playlist_sync/src/playlistmanager/SyncedPlaylist.cpp
)
This algorithm is optimized for situations where most of the time one
or a few tracks are inserted. It preforms badly when the playlist is
reordered because the playlist could double in length before the
second step removes the "down shifted" tracks. It does always ensure
that at least one copy of a track is present during the
synchronization, this is beneficial for track copying because never
will a track be completely removed only to be added again right after.

3) Now that the copies are in sync any changes to the playlist by the
user are applied to both by the SyncedPlaylist proxy.
4) Any event driven changes in one copy (like a podcast updating) are
applied to the other copies immediately.

>
> Alejandro, Bart, and Jeff: We had a conversation on IRC a few months
> back regarding the Media Device API and whether it was worth it to do
> things the "proper" way -- that is, writing all the code abstractly
> using Alejandro's media device API from the get go versus skipping
> that (like Bart did for UMS) and implementing on the device directly.
> What did we decide?
>
> I am trying to give Amitav here some pointers and guidance, but this
> is definitely not my area of expertise in Amarok.. as much as I would
> like it to be.
>
> Casey
>

The mediadevice framework has a good design goal: make it easier to
implement support for players by limiting the amount of code that
needs to be written. In practice though it has prevented me from
extending the playlist support to allow playlist synchronization and
podcast support on iPods. In fact, the only way I could make it work
on UMS is by sidestepping MD altogether.

It's not uncommon to have well meant API layers get in the way of
features. In fact, I would say most of my day job involves hacking
around the unflexible top-down design.
When implementing some framework from scratch I thus try to work
bottom up. This means the support needs to be implemented completely
at the user-level API. This does mean more coding work for the
implementer but by providing a lot of tools for common functions this
can be reduced to an absolute minimum. In practice the code is rarely
from scratch anyway, being able to copy previous implementations and
adapt in small ways.
This approach doesn't limit the flexibility of implementations and new
features are limited to one API level and if done right, without
impacting more code then required to introduce the feature.

I would define the API to be implemented by mediadevices to be:
Minimum: Collection, QueryMaker & Meta
If the player support copying: CollectionLocation (can't think of one
that doesn't in practice)
Player has playlist support: UserPlaylistProvider and
Playlists::Playlist (and this implies tracks added to a playlist are
also copied to the device)
Player has Podcast support: PodcastProvider and
Podcast(Channel|Episode). (If a player can download episodes itself,
like an iPhone, this can be triggered with an action).

Actually, the same is true for internet services and local collections
but in practice services also has an extra API and local is several
classes that use sqlStorage or file storage that can not be considered
one entity similar to a mediadevice plug-in.

Bart


More information about the Amarok-devel mailing list