diff deps/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,1035 @@
+/*****************************************************************
+|
+|   Platinum - AV Media Controller (Media Renderer Control Point)
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaController.h"
+#include "PltDidl.h"
+#include "PltDeviceData.h"
+#include "PltXmlHelper.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.renderer.controller")
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::PLT_MediaController
++---------------------------------------------------------------------*/
+PLT_MediaController::PLT_MediaController(PLT_CtrlPointReference&      ctrl_point, 
+                                         PLT_MediaControllerDelegate* delegate /* = NULL */) :
+    m_CtrlPoint(ctrl_point),
+    m_Delegate(delegate)
+{
+    m_CtrlPoint->AddListener(this);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::~PLT_MediaController
++---------------------------------------------------------------------*/
+PLT_MediaController::~PLT_MediaController()
+{
+    m_CtrlPoint->RemoveListener(this);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnDeviceAdded
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnDeviceAdded(PLT_DeviceDataReference& device)
+{
+    PLT_DeviceDataReference data;
+    NPT_String uuid = device->GetUUID();
+    // is it a new device?
+    if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), data))) {
+        NPT_LOG_FINE_1("Device (%s) is already in our list!", (const char*)uuid);
+        return NPT_FAILURE;
+    }
+
+    NPT_LOG_FINE("Device Found:");
+    device->ToLog(NPT_LOG_LEVEL_FINE);
+
+    // verify the device implements the function we need
+    PLT_Service* serviceAVT;
+    PLT_Service* serviceCMR;
+    NPT_String type;
+    
+    type = "urn:schemas-upnp-org:service:AVTransport:1";
+    if (NPT_FAILED(device->FindServiceByType(type, serviceAVT))) {
+        NPT_LOG_FINE_1("Service %s not found", (const char*)type);
+        return NPT_FAILURE;
+    }
+    
+    type = "urn:schemas-upnp-org:service:ConnectionManager:1";
+    if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) {
+        NPT_LOG_FINE_1("Service %s not found", (const char*)type);
+        return NPT_FAILURE;
+    }
+
+    m_MediaRenderers.Add(device);
+    
+    if (m_Delegate && m_Delegate->OnMRAdded(device)) {
+        // subscribe to AVT eventing if delegate wants it
+        m_CtrlPoint->Subscribe(serviceAVT);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnDeviceRemoved
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::OnDeviceRemoved(PLT_DeviceDataReference& device)
+{
+    // only release if we have kept it around
+    PLT_DeviceDataReference data;
+    NPT_String uuid = device->GetUUID();
+    // is it a new device?
+    if (NPT_FAILED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), data))) {
+        NPT_LOG_FINE_1("Device (%s) not found in our list!", (const char*)uuid);
+        return NPT_FAILURE;
+    }
+
+    NPT_LOG_FINE("Device Removed:");
+    device->ToLog(NPT_LOG_LEVEL_FINE);
+
+    if (m_Delegate) {
+        m_Delegate->OnMRRemoved(device);
+    }
+    
+    m_MediaRenderers.Remove(device);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::FindActionDesc
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::FindActionDesc(PLT_DeviceDataReference& device, 
+                                    const char*              service_type,
+                                    const char*              action_name,
+                                    PLT_ActionDesc*&         action_desc)
+{
+    // look for the service
+    PLT_Service* service;
+    if (NPT_FAILED(device->FindServiceByType(service_type, service))) {
+        NPT_LOG_FINE_1("Service %s not found", (const char*)service_type);
+        return NPT_FAILURE;
+    }
+
+    action_desc = service->FindActionDesc(action_name);
+    if (action_desc == NULL) {
+        NPT_LOG_FINE_1("Action %s not found in service", action_name);
+        return NPT_FAILURE;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::CreateAction
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::CreateAction(PLT_DeviceDataReference& device, 
+                                  const char*              service_type,
+                                  const char*              action_name,
+                                  PLT_ActionReference&     action)
+{
+    PLT_ActionDesc* action_desc;
+    NPT_CHECK_SEVERE(FindActionDesc(device, service_type, action_name, action_desc));
+    action = new PLT_Action(action_desc);
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::CallAVTransportAction
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::CallAVTransportAction(PLT_ActionReference& action,
+                                           NPT_UInt32           instance_id,
+                                           void*                userdata)
+{
+    // Set the object id
+    NPT_CHECK_SEVERE(action->SetArgumentValue("InstanceID", 
+        NPT_String::FromInteger(instance_id)));
+
+    // set the arguments on the action, this will check the argument values
+    return m_CtrlPoint->InvokeAction(action, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetCurrentTransportActions
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetCurrentTransportActions(PLT_DeviceDataReference& device, 
+                                                NPT_UInt32               instance_id,
+                                                void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetCurrentTransportActions", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetDeviceCapabilities
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetDeviceCapabilities(PLT_DeviceDataReference& device, 
+                                           NPT_UInt32               instance_id,
+                                           void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetDeviceCapabilities", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetMediaInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetMediaInfo(PLT_DeviceDataReference& device, 
+                                  NPT_UInt32               instance_id,
+                                  void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetMediaInfo", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetPositionInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetPositionInfo(PLT_DeviceDataReference& device, 
+                                     NPT_UInt32               instance_id,
+                                     void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetPositionInfo", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetTransportInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetTransportInfo(PLT_DeviceDataReference& device, 
+                                      NPT_UInt32               instance_id,
+                                      void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetTransportInfo", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetTransportSettings
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetTransportSettings(PLT_DeviceDataReference&  device, 
+                                          NPT_UInt32                instance_id,
+                                          void*                     userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "GetTransportSettings", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Next
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Next(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Next", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Pause
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Pause(PLT_DeviceDataReference& device, 
+                           NPT_UInt32               instance_id,
+                           void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Pause", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Play
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Play(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          NPT_String               speed,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Play", 
+        action));
+
+    // Set the speed
+    if (NPT_FAILED(action->SetArgumentValue("Speed", speed))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Previous
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Previous(PLT_DeviceDataReference& device, 
+                              NPT_UInt32               instance_id,
+                              void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Previous", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Seek
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Seek(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          NPT_String               unit,
+                          NPT_String               target,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Seek", 
+        action));
+
+    // Set the unit
+    if (NPT_FAILED(action->SetArgumentValue("Unit", unit))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // Set the target
+    if (NPT_FAILED(action->SetArgumentValue("Target", target))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::SetAVTransportURI
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::SetAVTransportURI(PLT_DeviceDataReference& device, 
+                                       NPT_UInt32               instance_id, 
+                                       const char*              uri,
+                                       const char*              metadata,
+                                       void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "SetAVTransportURI", 
+        action));
+
+    // set the uri
+    if (NPT_FAILED(action->SetArgumentValue("CurrentURI", uri))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the uri metadata
+    if (NPT_FAILED(action->SetArgumentValue("CurrentURIMetaData", metadata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::SetPlayMode
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::SetPlayMode(PLT_DeviceDataReference& device, 
+                                 NPT_UInt32               instance_id,
+                                 NPT_String               new_play_mode,
+                                 void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "SetPlayMode", 
+        action));
+
+    // set the New PlayMode
+    if (NPT_FAILED(action->SetArgumentValue("NewPlayMode", new_play_mode))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::Stop
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::Stop(PLT_DeviceDataReference& device, 
+                          NPT_UInt32               instance_id,
+                          void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:AVTransport:1", 
+        "Stop", 
+        action));
+    return CallAVTransportAction(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetCurrentConnectionIDs
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetCurrentConnectionIDs(PLT_DeviceDataReference& device, 
+                                             void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:ConnectionManager:1", 
+        "GetCurrentConnectionIDs", 
+        action));
+
+    // set the arguments on the action, this will check the argument values
+    if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetCurrentConnectionInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetCurrentConnectionInfo(PLT_DeviceDataReference& device, 
+                                              NPT_UInt32               connection_id,
+                                              void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:ConnectionManager:1", 
+        "GetCurrentConnectionInfo", 
+        action));
+
+    // set the New PlayMode
+    if (NPT_FAILED(action->SetArgumentValue("ConnectionID", NPT_String::FromInteger(connection_id)))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    // set the arguments on the action, this will check the argument values
+    if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::GetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_MediaController::GetProtocolInfo(PLT_DeviceDataReference& device, 
+                                     void*                    userdata)
+{
+    PLT_ActionReference action;
+    NPT_CHECK_SEVERE(CreateAction(device, 
+        "urn:schemas-upnp-org:service:ConnectionManager:1", 
+        "GetProtocolInfo", 
+        action));
+
+    // set the arguments on the action, this will check the argument values
+    if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+        return NPT_ERROR_INVALID_PARAMETERS;
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnActionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata)
+{
+    if (m_Delegate == NULL) return NPT_SUCCESS;
+
+    /* make sure device is a renderer we've previously found */
+    PLT_DeviceDataReference device;
+    NPT_String uuid = action->GetActionDesc()->GetService()->GetDevice()->GetUUID();
+    if (NPT_FAILED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), device))) {
+        NPT_LOG_FINE_1("Device (%s) not found in our list of renderers", (const char*)uuid);
+        res = NPT_FAILURE;
+    }
+       
+    /* extract action name */
+    NPT_String actionName = action->GetActionDesc()->GetName();
+
+    /* AVTransport response ? */
+    if (actionName.Compare("GetCurrentTransportActions", true) == 0) {
+        return OnGetCurrentTransportActionsResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetDeviceCapabilities", true) == 0) {
+        return OnGetDeviceCapabilitiesResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetMediaInfo", true) == 0) {
+        return OnGetMediaInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetPositionInfo", true) == 0) {
+        return OnGetPositionInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetTransportInfo", true) == 0) {
+        return OnGetTransportInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetTransportSettings", true) == 0) {
+        return OnGetTransportSettingsResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("Next", true) == 0) {
+        m_Delegate->OnNextResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Pause", true) == 0) {
+        m_Delegate->OnPauseResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Play", true) == 0) {
+        m_Delegate->OnPlayResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Previous", true) == 0) {
+        m_Delegate->OnPreviousResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Seek", true) == 0) {
+        m_Delegate->OnSeekResult(res, device, userdata);
+    }
+    else if (actionName.Compare("SetAVTransportURI", true) == 0) {
+        m_Delegate->OnSetAVTransportURIResult(res, device, userdata);
+    }
+    else if (actionName.Compare("SetPlayMode", true) == 0) {
+        m_Delegate->OnSetPlayModeResult(res, device, userdata);
+    }
+    else if (actionName.Compare("Stop", true) == 0) {
+        m_Delegate->OnStopResult(res, device, userdata);
+    }
+    else if (actionName.Compare("GetCurrentConnectionIDs", true) == 0) {
+        return OnGetCurrentConnectionIDsResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetCurrentConnectionInfo", true) == 0) {
+        return OnGetCurrentConnectionInfoResponse(res, device, action, userdata);
+    }
+    else if (actionName.Compare("GetProtocolInfo", true) == 0) {
+        return OnGetProtocolInfoResponse(res, device, action, userdata);
+    }
+
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetCurrentTransportActionsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentTransportActionsResponse(NPT_Result res, 
+                                                          PLT_DeviceDataReference& device, 
+                                                          PLT_ActionReference& action, 
+                                                          void* userdata)
+{
+    NPT_String actions;
+    PLT_StringList values;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("Actions", actions))) {
+        goto bad_action;
+    }
+
+    // parse the list of actions and return a list to listener
+    ParseCSV(actions, values);
+
+    m_Delegate->OnGetCurrentTransportActionsResult(NPT_SUCCESS, device, &values, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetCurrentTransportActionsResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetDeviceCapabilitiesResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetDeviceCapabilitiesResponse(NPT_Result res, 
+                                                     PLT_DeviceDataReference& device, 
+                                                     PLT_ActionReference& action, 
+                                                     void* userdata)
+{
+    NPT_String value;
+    PLT_DeviceCapabilities capabilities;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("PlayMedia", value))) {
+        goto bad_action;
+    }
+    // parse the list of medias and return a list to listener
+    ParseCSV(value, capabilities.play_media);
+
+    if (NPT_FAILED(action->GetArgumentValue("RecMedia", value))) {
+        goto bad_action;
+    }
+    // parse the list of rec and return a list to listener
+    ParseCSV(value, capabilities.rec_media);
+
+    if (NPT_FAILED(action->GetArgumentValue("RecQualityModes", value))) {
+        goto bad_action;
+    }
+    // parse the list of modes and return a list to listener
+    ParseCSV(value, capabilities.rec_quality_modes);
+
+    m_Delegate->OnGetDeviceCapabilitiesResult(NPT_SUCCESS, device, &capabilities, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetDeviceCapabilitiesResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetMediaInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetMediaInfoResponse(NPT_Result res, 
+                                            PLT_DeviceDataReference& device, 
+                                            PLT_ActionReference& action, 
+                                            void* userdata)
+{
+    NPT_String      value;
+    PLT_MediaInfo   info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("NrTracks", info.num_tracks))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("MediaDuration", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.media_duration))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("CurrentURI", info.cur_uri))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("CurrentURIMetaData", info.cur_metadata))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("NextURI", info.next_uri))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("NextURIMetaData",  info.next_metadata))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("PlayMedium", info.play_medium))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("RecordMedium", info.rec_medium))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("WriteStatus", info.write_status))) {
+        goto bad_action;
+    }
+
+    m_Delegate->OnGetMediaInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetMediaInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetPositionInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetPositionInfoResponse(NPT_Result res, 
+                                               PLT_DeviceDataReference& device, 
+                                               PLT_ActionReference& action, 
+                                               void* userdata)
+{
+    NPT_String       value;
+    PLT_PositionInfo info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("Track", info.track))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("TrackDuration", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.track_duration))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("TrackMetaData", info.track_metadata))) {
+        goto bad_action;
+    }    
+    
+    if (NPT_FAILED(action->GetArgumentValue("TrackURI", info.track_uri))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("RelTime", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.rel_time))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("AbsTime", value))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.abs_time))) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("RelCount", info.rel_count))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("AbsCount", info.abs_count))) {
+        goto bad_action;
+    }
+
+    m_Delegate->OnGetPositionInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetPositionInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetTransportInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetTransportInfoResponse(NPT_Result res, 
+                                                PLT_DeviceDataReference& device, 
+                                                PLT_ActionReference& action, 
+                                                void* userdata)
+{
+    PLT_TransportInfo info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("CurrentTransportState", info.cur_transport_state))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("CurrentTransportStatus", info.cur_transport_status))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("CurrentSpeed", info.cur_speed))) {
+        goto bad_action;
+    }    
+
+    m_Delegate->OnGetTransportInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetTransportInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetTransportSettingsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetTransportSettingsResponse(NPT_Result res, 
+                                                    PLT_DeviceDataReference& device, 
+                                                    PLT_ActionReference& action, 
+                                                    void* userdata)
+{
+    PLT_TransportSettings settings;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("PlayMode", settings.play_mode))) {
+        goto bad_action;
+    }    
+    if (NPT_FAILED(action->GetArgumentValue("RecQualityMode", settings.rec_quality_mode))) {
+        goto bad_action;
+    }    
+
+    m_Delegate->OnGetTransportSettingsResult(NPT_SUCCESS, device, &settings, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetTransportSettingsResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetCurrentConnectionIDsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentConnectionIDsResponse(NPT_Result res, 
+                                                       PLT_DeviceDataReference& device, 
+                                                       PLT_ActionReference& action, 
+                                                       void* userdata)
+{
+    NPT_String value;
+    PLT_StringList IDs;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("ConnectionIDs", value))) {
+        goto bad_action;
+    }
+    // parse the list of medias and return a list to listener
+    ParseCSV(value, IDs);
+
+    m_Delegate->OnGetCurrentConnectionIDsResult(NPT_SUCCESS, device, &IDs, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetCurrentConnectionIDsResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetCurrentConnectionInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentConnectionInfoResponse(NPT_Result res, 
+                                                        PLT_DeviceDataReference& device, 
+                                                        PLT_ActionReference& action, 
+                                                        void* userdata)
+{
+    NPT_String value;
+    PLT_ConnectionInfo info;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("RcsID", info.rcs_id))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("AVTransportID", info.avtransport_id))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("ProtocolInfo", info.protocol_info))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("PeerConnectionManager", info.peer_connection_mgr))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("PeerConnectionID", info.peer_connection_id))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("Direction", info.direction))) {
+        goto bad_action;
+    }
+    if (NPT_FAILED(action->GetArgumentValue("Status", info.status))) {
+        goto bad_action;
+    }
+    m_Delegate->OnGetCurrentConnectionInfoResult(NPT_SUCCESS, device, &info, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetCurrentConnectionInfoResult(NPT_FAILURE, device, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnGetProtocolInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetProtocolInfoResponse(NPT_Result res, 
+                                               PLT_DeviceDataReference& device, 
+                                               PLT_ActionReference& action, 
+                                               void* userdata)
+{
+    NPT_String     source_info, sink_info;
+    PLT_StringList sources, sinks;
+
+    if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+        goto bad_action;
+    }
+
+    if (NPT_FAILED(action->GetArgumentValue("Source", source_info))) {
+        goto bad_action;
+    }
+    ParseCSV(source_info, sources);
+
+    if (NPT_FAILED(action->GetArgumentValue("Sink", sink_info))) {
+        goto bad_action;
+    }
+    ParseCSV(sink_info, sinks);
+
+    m_Delegate->OnGetProtocolInfoResult(NPT_SUCCESS, device, &sources, &sinks, userdata);
+    return NPT_SUCCESS;
+
+bad_action:
+    m_Delegate->OnGetProtocolInfoResult(NPT_FAILURE, device, NULL, NULL, userdata);
+    return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_MediaController::OnEventNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
+{
+    if (!m_Delegate) return NPT_SUCCESS;
+    
+    // parse LastChange var into smaller vars
+    PLT_StateVariable* lastChangeVar = NULL;
+    if (NPT_SUCCEEDED(NPT_ContainerFind(*vars, PLT_ListStateVariableNameFinder("LastChange"), lastChangeVar))) {
+        vars->Remove(lastChangeVar);
+        PLT_Service* var_service = lastChangeVar->GetService();
+        NPT_String text = lastChangeVar->GetValue();
+        
+        NPT_XmlNode* xml = NULL;
+        NPT_XmlParser parser;
+        if (NPT_FAILED(parser.Parse(text, xml)) || !xml || !xml->AsElementNode()) {
+            delete xml;
+            return NPT_FAILURE;
+        }
+
+        NPT_XmlElementNode* node = xml->AsElementNode();
+        if (!node->GetTag().Compare("Event", true)) {
+            // look for the instance with attribute id = 0
+            NPT_XmlElementNode* instance = NULL;
+            for (NPT_Cardinal i=0; i<node->GetChildren().GetItemCount(); i++) {
+                NPT_XmlElementNode* child;
+                if (NPT_FAILED(PLT_XmlHelper::GetChild(node, child, i)))
+                    continue;
+
+                if (!child->GetTag().Compare("InstanceID", true)) {
+                    // extract the "val" attribute value
+                    NPT_String value;
+                    if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(child, "val", value)) &&
+                        !value.Compare("0")) {
+                        instance = child;
+                        break;
+                    }
+                }
+            }
+
+            // did we find an instance with id = 0 ?
+            if (instance != NULL) {
+                // all the children of the Instance node are state variables
+                for (NPT_Cardinal j=0; j<instance->GetChildren().GetItemCount(); j++) {
+                    NPT_XmlElementNode* var_node;
+                    if (NPT_FAILED(PLT_XmlHelper::GetChild(instance, var_node, j)))
+                        continue;
+
+                    // look for the state variable in this service
+                    const NPT_String* value = var_node->GetAttribute("val");
+                    PLT_StateVariable* var = var_service->FindStateVariable(var_node->GetTag());
+                    if (value != NULL && var != NULL) {
+                        // get the value and set the state variable
+                        // if it succeeded, add it to the list of vars we'll event
+                        if (NPT_SUCCEEDED(var->SetValue(*value))) {
+                            vars->Add(var);
+                            NPT_LOG_FINE_2("PLT_MediaController received var change for (%s): %s", (const char*)var->GetName(), (const char*)var->GetValue());
+                        }
+                    }
+                }
+            }
+        }
+        delete xml;
+    }
+
+    if (vars->GetItemCount()) {
+        m_Delegate->OnMRStateVariablesChanged(service, vars);
+    }
+    
+    return NPT_SUCCESS;
+}