An Java implementation of DMAP, DAAP, DPAP, DMCP, DACP and RAOP with Guice + Jetty - Essentially a iTunes share, iPhoto share and Airport Express emulation
A Java application/library implementation of the DMAP family (DAAP, DACP, DPAP) and RAOP with Guice + Jetty + Zeroconf/Bonojur (through jmDNS). The functionality is planned to resemble what is provided by eg. dmapd. It should however be thought of as an integration library, not a final application itself. jolivia is scoped to support the following proprietary protocols:
I'll just give you a brief introduction to how the DACP protocol works (you can read more on http://jsharkey.org/blog/2009/06/21/itunes-dacp-pairing-hash-is-broken/, http://dacp.jsharkey.org/, http://jinxidoru.blogspot.dk/2009/06/itunes-remote-pairing-code.html and http://www.awilco.net/doku/dacp).
The session is your 'remote control' instance. On a session you can do the remote control stuff or eg. traverse the library. See the following code example:
@Test
public void usage() throws Exception
{
// As soon as you have entered the pairing code '1337' in iTunes the
// registerNewSession will be invoked and the pairing will be stored in
// a local db file and in iTunes as well. Clear the pairing in iTunes by
// clearing all remotes in iTunes as usual. Clear the pairing in Jolivia
// by deleting the db
// file. Once paired every time you start iTunes this method will be
// called. Every time the iTunes instance is
// closed the tearDownSession will be invoked.
new Jolivia.JoliviaBuilder().clientSessionListener(new IClientSessionListener() {
private Session session;
@Override
public void tearDownSession(String server, int port)
{
// Maybe do some clean up?
try
{
session.logout();
}
catch(Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@SuppressWarnings("unused")
@Override
public void registerNewSession(Session session) throws Exception
{
// Showcase on some actions you can do on a session ...
// ////////////////////////////////////////
this.session = session;
// getUpdateBlocking blocks until an event happens in iTunes -
// eg. pressing play, pause, etc. ...
UpdateResponse response = this.session.getUpdateBlocking();
Database itunesDatabase = this.session.getDatabase();
// Get all playlists. For now the playlists only contains the
// master playlist. This is to be expanded
Collection<Container> playlists = itunesDatabase.getContainers();
// Traverse the library for eg. all tracks
for(SongArtist artist : this.session.getLibrary().getAllArtists().getBrowseArtistListing().getSongArtists())
{
System.out.println(artist.getValue());
}
long itemId = 0;
// Extract information from a generic listing
for(ListingItem item : this.session.getLibrary().getAllTracks().getListing().getListingItems())
{
System.out.println(item.getSpecificChunk(SongAlbum.class).getValue());
System.out.println(item.getSpecificChunk(SongArtist.class).getValue());
System.out.println(item.getSpecificChunk(SongTime.class).getValue());
System.out.println(item.getSpecificChunk(SongTrackNumber.class).getValue());
System.out.println(item.getSpecificChunk(SongUserRating.class).getValue());
System.out.println(item.getSpecificChunk(ItemName.class).getValue());
System.out.println(item.getSpecificChunk(ItemKind.class).getValue());
System.out.println(item.getSpecificChunk(ItemId.class).getValue());
itemId = item.getSpecificChunk(ItemId.class).getValue();
}
// Showcase on some actions you can do on speakers ...
// ////////////////////////////////////////
RemoteControl remoteControl = this.session.getRemoteControl();
// Set min volume
remoteControl.setVolume(0);
// Set max volume
remoteControl.setVolume(100);
remoteControl.setVolume(0);
// Get the master volume
remoteControl.getMasterVolume();
// Get all speakers visible to iTunes instance
Collection<Speaker> speakers = remoteControl.getSpeakers();
// Mark all speakers active meaning they are prepared for being
// used for the iTunes instance
for(Speaker s : speakers)
{
s.setActive(true);
}
// Assign all the active speakers to the iTunes instance. This
// means that all the speakers will now be used for output
remoteControl.setSpeakers(speakers);
// Change the volume individually on each speaker
speakers = remoteControl.getSpeakers();
for(Speaker s : speakers)
{
remoteControl.setSpeakerVolume(s.getId(), 60, 50, 40, 30, 100);
}
session.getLibrary().getAlbumArtwork(itemId, 320, 320);
session.getRemoteControl().fetchCover(320, 320);
}
}).build();
}
This project has found great inspiration in many projects and the people behind them, among those are the following:
This project is licensed under the license presented in the license.txt file. Anyone who uses Jolivia in any kind of software - being commercial or not must notify the author and submit a comment on this project site stating its usage and purpose.
Copyright 2013 Jens Kristian Villadsen.