/*******************************************************************************
* Copyright (c) 2013 Jens Kristian Villadsen.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Jens Kristian Villadsen - Lead developer, owner and creator
******************************************************************************/
package org.dyndns.jkiddo.service.dacp.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.dyndns.jkiddo.NotImplementedException;
import org.dyndns.jkiddo.dmap.chunks.audio.extension.UnknownFR;
import org.dyndns.jkiddo.dmcp.chunks.media.MediaControlProtocolVersion;
import org.dyndns.jkiddo.dmcp.chunks.media.PlayingStatus;
import org.dyndns.jkiddo.dmcp.chunks.media.PropertyResponse;
import org.dyndns.jkiddo.dmcp.chunks.media.RelativeVolume;
import org.dyndns.jkiddo.dmcp.chunks.media.StatusRevision;
import org.dyndns.jkiddo.dmcp.chunks.media.UnknownIK;
import org.dyndns.jkiddo.dmcp.chunks.media.UnknownRL;
import org.dyndns.jkiddo.dmcp.chunks.media.UnknownSP;
import org.dyndns.jkiddo.dmcp.chunks.media.UnknownSV;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.AudioControlProtocolVersion;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.AvailableRepeatStates;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.AvailableShuffleStates;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.DataControlInt;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.FullScreenEnabled;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.FullscreenStatus;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.PlayStatus;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.RepeatStatus;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.ShuffleStatus;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.SpeakerActive;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.SpeakerList;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.UnknownOV;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.UnknownSS;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.UnknownSU;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.UnknownVD;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.VisualizerEnabled;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.VisualizerStatus;
import org.dyndns.jkiddo.dmcp.chunks.media.audio.VolumeControllable;
import org.dyndns.jkiddo.dmcp.chunks.media.extension.SavedGenius;
import org.dyndns.jkiddo.dmcp.chunks.media.extension.UnknownCESX;
import org.dyndns.jkiddo.dmcp.chunks.media.extension.UnknownQU;
import org.dyndns.jkiddo.dmp.chunks.media.Dictionary;
import org.dyndns.jkiddo.dmp.chunks.media.ItemId;
import org.dyndns.jkiddo.dmp.chunks.media.ItemName;
import org.dyndns.jkiddo.dmp.chunks.media.Listing;
import org.dyndns.jkiddo.dmp.chunks.media.ListingItem;
import org.dyndns.jkiddo.dmp.chunks.media.MachineAddress;
import org.dyndns.jkiddo.dmp.chunks.media.ReturnedCount;
import org.dyndns.jkiddo.dmp.chunks.media.SpecifiedTotalCount;
import org.dyndns.jkiddo.dmp.chunks.media.Status;
import org.dyndns.jkiddo.dmp.chunks.media.UpdateType;
import org.dyndns.jkiddo.dmp.util.DmapUtil;
import org.dyndns.jkiddo.service.dacp.client.IPairingDatabase;
import org.dyndns.jkiddo.service.dmap.MDNSResource;
import org.dyndns.jkiddo.service.dmap.Util;
import org.dyndns.jkiddo.zeroconf.IZeroconfManager;
@Singleton
public class TouchAbleServerResource extends MDNSResource implements ITouchAbleServerResource
{
public static final String DACP_SERVER_PORT_NAME = "DACP_SERVER_PORT_NAME";
private final String name;
private final String serviceGuid;
@Inject
public TouchAbleServerResource(final IZeroconfManager mDNS, @Named(DACP_SERVER_PORT_NAME) final Integer port, @Named(Util.APPLICATION_NAME) final String applicationName, final IPairingDatabase pairingDatabase ) throws IOException
{
super(mDNS, port);
this.name = applicationName;
this.serviceGuid = Util.toServiceGuid(applicationName);
this.register();
}
@Override
@GET
@Path("logout")
public Response logout(@QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/pause")
public Response pause(@QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/stop")
public Response stop(@QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/playpause")
public Response playpause(@QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/nextitem")
public Response nextitem(@QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/previtem")
public Response previtem(@QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/playlist")
public Response playlist(@QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/setproperty")
public Response setproperty(@Context final UriInfo uriInfo, @QueryParam("dmcp.volume") final String dmcpVolume, @QueryParam("dacp.playingtime") final String dacpPlayingtime, @QueryParam("dacp.shufflestate") final String dacpShufflestate, @QueryParam("dacp.repeatstate") final String dacpRepeatstate, @QueryParam("session-id") final long session_id)
{
final MultivaluedMap<String, String> map = uriInfo.getQueryParameters();
map.get("dmcp.volume");
map.get("dacp.playingtime");
map.get("dacp.shufflestate");
map.get("dacp.repeatstate");
map.get("dacp.userrating");
map.get("song-spec");
map.get("speaker-id");
map.get("include-speaker-id");
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/getproperty")
public Response getproperty(@Context final UriInfo uriInfo, @QueryParam("properties") final String properties, @QueryParam("session-id") final long session_id, @QueryParam("hsgid") final String hsgid) throws IOException
{
final MultivaluedMap<String, String> map = uriInfo.getQueryParameters();
map.get("properties");
final PropertyResponse response = new PropertyResponse();
response.add(new Status(200));
response.add(new RelativeVolume(100));//
return Util.buildResponse(response, "DAAP-Server", name);
}
@Override
@GET
@Path("ctrl-int/1/playstatusupdate")
public Response playstatusupdate(@QueryParam("revision-number") final long revisionNumber, @QueryParam("session-id") final long session_id, @QueryParam("hsgid") final String hsgid) throws IOException
{
if(revisionNumber == 0x24)
{
try
{
Thread.sleep(10000000);
}
catch(final InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
final PlayingStatus response = new PlayingStatus();
response.add(new Status(200));
response.add(new StatusRevision(0x24));//
response.add(new PlayStatus(2));//
response.add(new ShuffleStatus(0));
response.add(new RepeatStatus(0));
response.add(new FullscreenStatus(0));
response.add(new VisualizerStatus(0));
response.add(new VolumeControllable(0));
response.add(new AvailableShuffleStates(2));//
response.add(new AvailableRepeatStates(6));//
response.add(new FullScreenEnabled(0));
response.add(new VisualizerEnabled(0));
response.add(new UnknownSU(false));
response.add(new UnknownQU(0));
return Util.buildResponse(response, "DAAP-Server", name);
}
@Override
@GET
@Path("ctrl-int/1/cue")
public Response cue(@QueryParam("commmand") final String command, @QueryParam("query") final String query, @QueryParam("index") final String index, @QueryParam("sort") final String sort, @QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int/1/getspeakers")
public Response getspeakers(@QueryParam("session-id") final long session_id, @QueryParam("hsgid") final String hsgid) throws IOException
{
final SpeakerList response = new SpeakerList();
response.add(new Status(200));
final Dictionary dictionary = new Dictionary();
dictionary.add(new ItemName("My Compounter"));
dictionary.add(new RelativeVolume(100));
dictionary.add(new UnknownVD(true));
dictionary.add(new MachineAddress(new byte[]{0}));
dictionary.add(new SpeakerActive(true));
response.add(dictionary);
return Util.buildResponse(response, "DAAP-Server", name);
}
@Override
@GET
@Path("ctrl-int/1/setspeakers")
public Response setspeakers(@QueryParam("speaker-id") final String speaker_id, @QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("/ctrl-int/1/playspec")
public Response playspec(@QueryParam("container-item-spec") final String container_item_spec, @QueryParam("item-spec") final String item_spec, @QueryParam("container-spec") final String container_spec, @QueryParam("dacp.shufflestate") final String dacp_shufflestate, @QueryParam("database-spec") final String database_spec, @QueryParam("playlist-spec") final String playlist_spec, @QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("/ctrl-int/1/nowplayingartwork")
public Response nowplayingartwork(@QueryParam("mw") final String mw, @QueryParam("mh") final String mh, @QueryParam("session-id") final long session_id, @QueryParam("hsgid") final String hsgid)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("/ctrl-int/1/set-genius-seed")
public Response editGenius(@QueryParam("database-spec") final String database_spec, @QueryParam("item-spec") final String item_spec, @QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@Path("/databases/{databaseId}/edit")
@GET
public Response editPlaylist(@PathParam("databaseId") final long databaseId, @QueryParam("session-id") final long sessionId, @QueryParam("action") final String action, @QueryParam("edit-params") final String edit_params) throws IOException
{
throw new NotImplementedException();
}
@Override
protected IZeroconfManager.ServiceInfo getServiceInfoToRegister()
{
try
{
Util.toHex(hostname.getBytes("UTF-8"));
}
catch(final UnsupportedEncodingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
final HashMap<String, String> records = new HashMap<>();
records.put("Ver", DmapUtil.CONTROL_VERSION_205 +"");
records.put("CtlN", name);
records.put("OSsi", "0x1F5");
records.put("iV", "196620");
// records.put("DbId", hexedHostname);
records.put("DbId", DB_ID);
records.put("DvTy", "iTunes");
records.put("txtvers", "1");
records.put("iCSV", "65540");
records.put("DvSv", "3120");
// return new IZeroconfManager.ServiceInfo(TOUCH_ABLE_SERVER, serviceGuid, port, records);
return new IZeroconfManager.ServiceInfo(TOUCH_ABLE_SERVER, MID, port, records);
}
@Override
@GET
@Path("ctrl-int/1/playqueue-contents")
public Response playQueueContents(@QueryParam("span") final int span, @QueryParam("session-id") final long session_id)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("fp-setup")
public Response fpSetup(@QueryParam("session-id") final long session_id, @QueryParam("hsgid") final String hsgid, final InputStream is)
{
throw new NotImplementedException();
}
@Override
@GET
@Path("login")
public Response login(@QueryParam("pairing-guid") final String guid, @QueryParam("hasFP") final int value, @QueryParam("hsgid") final String hsgid) throws IOException
{
throw new NotImplementedException();
}
@Override
@Path("update")
@GET
public Response update(@QueryParam("session-id") final long sessionId, @QueryParam("revision-number") final long revisionNumber, @QueryParam("delta") final long delta, @QueryParam("daap-no-disconnect") final int daapNoDisconnect, @QueryParam("hsgid") final String hsgid) throws IOException
{
throw new NotImplementedException();
}
@Override
@GET
@Path("ctrl-int")
public Response ctrlInt(@Context final HttpServletRequest httpServletRequest, @Context final HttpServletResponse httpServletResponse, @QueryParam("hsgid") final String hsgid) throws IOException
{
final DataControlInt caci = new DataControlInt();
caci.add(new Status(200));
caci.add(new UpdateType(0));
caci.add(new SpecifiedTotalCount(4));//
caci.add(new ReturnedCount(1));//
final Listing listing = new Listing();
final ListingItem item = new ListingItem();
item.add(new ItemId(1));//
item.add(new UnknownIK(true));
item.add(new MediaControlProtocolVersion(0x20001));//
item.add(new AudioControlProtocolVersion(0x20003));//
item.add(new UnknownSP(true));
item.add(new UnknownFR(100));
item.add(new UnknownSV(true));
item.add(new UnknownSS(true));
item.add(new UnknownOV(true));
item.add(new UnknownSU(true));
item.add(new SavedGenius(true));
item.add(new UnknownRL(true));
item.add(new UnknownCESX(1));
listing.add(item);
caci.add(listing);
return Util.buildResponse(caci, "DAAP-Server", name);
}
// /ctrl-int/1/playqueue-edit?command=add&query='dmap.itemid:1024'&queuefilter=playlist:1&sort=name&mode=1&session-id=42
@Override
@GET
@Path("/ctrl-int/1/playqueue-edit")
public Response playQueueEdit(@Context final HttpServletRequest httpServletRequest, @Context final HttpServletResponse httpServletResponse, @QueryParam("commmand") final String command, @QueryParam("query") final String query, @QueryParam("queuefilter") final String index, @QueryParam("sort") final String sort, @QueryParam("session-id") final long session_id) throws Exception
{
return Util.buildEmptyResponse("DAAP-Server", name);
}
@Override
@GET
@Path("server-info")
public Response serverInfo(@QueryParam("hsgid") final String hsgid) throws IOException
{
// TODO Auto-generated method stub
return null;
}
@Override
@GET
@Path("home-share-verify")
public Response homeShareVerify(@QueryParam("session-id") final long session_id, @QueryParam("hsgid") final String hsgid, @QueryParam("hspid") final String hspid)
{
// TODO Auto-generated method stub
return null;
}
@Override
@Path("databases/{databaseId}/containers/{containerId}/items")
@GET
public Response containerItems(@PathParam("containerId") final long containerId, @PathParam("databaseId") final long databaseId, @QueryParam("session-id") final long sessionId, @QueryParam("revision-number") final long revisionNumber, @QueryParam("delta") final long delta, @QueryParam("meta") final String meta, @QueryParam("type") final String type, @QueryParam("group-type") final String group_type, @QueryParam("sort") final String sort, @QueryParam("include-sort-headers") final String include_sort_headers, @QueryParam("query") final String query, @QueryParam("index") final String index, @QueryParam("hsgid") final String hsgid) throws IOException
{
// TODO Auto-generated method stub
return null;
}
@Override
@Path("databases")
@GET
public Response databases(@QueryParam("session-id") final long sessionId, @QueryParam("revision-number") final long revisionNumber, @QueryParam("delta") final long delta, @QueryParam("hsgid") final String hsgid) throws IOException
{
// TODO Auto-generated method stub
return null;
}
@Override
@Path("databases/{databaseId}/containers")
@GET
public Response containers(@PathParam("databaseId") final long databaseId, @QueryParam("session-id") final long sessionId, @QueryParam("revision-number") final long revisionNumber, @QueryParam("delta") final long delta, @QueryParam("meta") final String meta, @QueryParam("hsgid") final String hsgid) throws IOException
{
// TODO Auto-generated method stub
return null;
}
@Override
@Path("databases/{databaseId}/groups")
@GET
public Response groups(@PathParam("databaseId") final long databaseId, @QueryParam("meta") final String meta, @QueryParam("type") final String type, @QueryParam("group-type") final String groupType, @QueryParam("sort") final String sort, @QueryParam("include-sort-headers") final long includeSortHeaders, @QueryParam("query") final String query, @QueryParam("session-id") final long sessionId, @QueryParam("hsgid") final String hsgid) throws IOException
{
// TODO Auto-generated method stub
return null;
}
@Override
public Response artwork(final long databaseId, final String mw, final String mh,
final long sessionId, final String groupType, final String hsgid) {
// TODO Auto-generated method stub
return null;
}
@Override
public Response artists(final long databaseId, final long sessionId,
final long includeSortHeaders, final String filter) {
// TODO Auto-generated method stub
return null;
}
}