From 5d2626f3186848f5d22e8702b231daf6208384da Mon Sep 17 00:00:00 2001 From: Alasdair Campbell Date: Mon, 17 Sep 2012 14:46:18 +0100 Subject: [UPnP] fix: use Announcement manager to update metadata and volume statevariables rather than every second in Application::ProcessSlow. Also handle play/pause toggling. --- xbmc/network/upnp/UPnPRenderer.cpp | 115 +++++++++++++++++++++++++------------ xbmc/network/upnp/UPnPRenderer.h | 7 ++- 2 files changed, 84 insertions(+), 38 deletions(-) diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp index f409357b52..f2605077c8 100644 --- a/xbmc/network/upnp/UPnPRenderer.cpp +++ b/xbmc/network/upnp/UPnPRenderer.cpp @@ -9,12 +9,34 @@ #include "guilib/GUIWindowManager.h" #include "pictures/GUIWindowSlideShow.h" #include "pictures/PictureInfoTag.h" +#include "interfaces/AnnouncementManager.h" #include "settings/Settings.h" #include "utils/URIUtils.h" +#include "utils/Variant.h" + +using namespace ANNOUNCEMENT; namespace UPNP { +/*---------------------------------------------------------------------- +| CUPnPRenderer::CUPnPRenderer ++---------------------------------------------------------------------*/ +CUPnPRenderer::CUPnPRenderer(const char* friendly_name, bool show_ip /*= false*/, + const char* uuid /*= NULL*/, unsigned int port /*= 0*/) + : PLT_MediaRenderer(friendly_name, show_ip, uuid, port) +{ + CAnnouncementManager::AddAnnouncer(this); +} + +/*---------------------------------------------------------------------- +| CUPnPRenderer::~CUPnPRenderer ++---------------------------------------------------------------------*/ +CUPnPRenderer::~CUPnPRenderer() +{ + CAnnouncementManager::RemoveAnnouncer(this); +} + /*---------------------------------------------------------------------- | CUPnPRenderer::SetupServices +---------------------------------------------------------------------*/ @@ -174,6 +196,58 @@ CUPnPRenderer::ProcessHttpRequest(NPT_HttpRequest& request, return PLT_MediaRenderer::ProcessHttpGetRequest(request, context, response); } +/*---------------------------------------------------------------------- +| CUPnPRenderer::Announce ++---------------------------------------------------------------------*/ +void +CUPnPRenderer::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) +{ + if (strcmp(sender, "xbmc") != 0) + return; + + NPT_AutoLock lock(m_state); + PLT_Service *avt, *rct; + + if (flag == Player) { + if (NPT_FAILED(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", avt))) + return; + if (strcmp(message, "OnPlay") == 0) { + avt->SetStateVariable("AVTransportURI", g_application.CurrentFile().c_str()); + avt->SetStateVariable("CurrentTrackURI", g_application.CurrentFile().c_str()); + + NPT_String meta; + if (NPT_SUCCEEDED(GetMetadata(meta))) { + avt->SetStateVariable("CurrentTrackMetadata", meta); + avt->SetStateVariable("AVTransportURIMetaData", meta); + } + + avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["speed"].asInteger())); + avt->SetStateVariable("TransportState", "PLAYING"); + } + else if (strcmp(message, "OnPause") == 0) { + avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["speed"].asInteger())); + avt->SetStateVariable("TransportState", "PAUSED_PLAYBACK"); + } + else if (strcmp(message, "OnSpeedChanged") == 0) { + avt->SetStateVariable("TransportPlaySpeed", NPT_String::FromInteger(data["speed"].asInteger())); + } + } + else if (flag == Application && strcmp(message, "OnVolumeChanged") == 0) { + if (NPT_FAILED(FindServiceByType("urn:schemas-upnp-org:service:RenderingControl:1", rct))) + return; + + CStdString buffer; + + buffer.Format("%ld", data["volume"].asInteger()); + rct->SetStateVariable("Volume", buffer.c_str()); + + buffer.Format("%ld", 256 * (data["volume"].asInteger() * 60 - 60) / 100); + rct->SetStateVariable("VolumeDb", buffer.c_str()); + + rct->SetStateVariable("Mute", data["muted"].asBoolean() ? "1" : "0"); + } +} + /*---------------------------------------------------------------------- | CUPnPRenderer::UpdateState +---------------------------------------------------------------------*/ @@ -182,11 +256,10 @@ CUPnPRenderer::UpdateState() { NPT_AutoLock lock(m_state); - PLT_Service *avt, *rct; + PLT_Service *avt; + if (NPT_FAILED(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", avt))) return; - if (NPT_FAILED(FindServiceByType("urn:schemas-upnp-org:service:RenderingControl:1", rct))) - return; /* don't update state while transitioning */ NPT_String state; @@ -194,34 +267,13 @@ CUPnPRenderer::UpdateState() if(state == "TRANSITIONING") return; - CStdString buffer; - int volume; - if (g_settings.m_bMute) { - rct->SetStateVariable("Mute", "1"); - } else { - rct->SetStateVariable("Mute", "0"); - } - volume = g_application.GetVolume(); - - buffer.Format("%d", volume); - rct->SetStateVariable("Volume", buffer.c_str()); - - buffer.Format("%d", 256 * (volume * 60 - 60) / 100); - rct->SetStateVariable("VolumeDb", buffer.c_str()); + avt->SetStateVariable("TransportStatus", "OK"); if (g_application.IsPlaying() || g_application.IsPaused()) { - if (g_application.IsPaused()) { - avt->SetStateVariable("TransportState", "PAUSED_PLAYBACK"); - } else { - avt->SetStateVariable("TransportState", "PLAYING"); - } - - avt->SetStateVariable("TransportStatus", "OK"); - avt->SetStateVariable("TransportPlaySpeed", (const char*)NPT_String::FromInteger(g_application.GetPlaySpeed())); avt->SetStateVariable("NumberOfTracks", "1"); avt->SetStateVariable("CurrentTrack", "1"); - buffer = g_infoManager.GetCurrentPlayTime(TIME_FORMAT_HH_MM_SS); + CStdString buffer = g_infoManager.GetCurrentPlayTime(TIME_FORMAT_HH_MM_SS); avt->SetStateVariable("RelativeTimePosition", buffer.c_str()); avt->SetStateVariable("AbsoluteTimePosition", buffer.c_str()); @@ -234,17 +286,6 @@ CUPnPRenderer::UpdateState() avt->SetStateVariable("CurrentMediaDuration", "00:00:00"); } - avt->SetStateVariable("AVTransportURI", g_application.CurrentFile().c_str()); - avt->SetStateVariable("CurrentTrackURI", g_application.CurrentFile().c_str()); - - NPT_String metadata; - avt->GetStateVariableValue("AVTransportURIMetaData", metadata); - // try to recreate the didl dynamically if not set - if (metadata.IsEmpty()) { - GetMetadata(metadata); - } - avt->SetStateVariable("CurrentTrackMetadata", metadata); - avt->SetStateVariable("AVTransportURIMetaData", metadata); } else if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { avt->SetStateVariable("TransportState", "PLAYING"); diff --git a/xbmc/network/upnp/UPnPRenderer.h b/xbmc/network/upnp/UPnPRenderer.h index 0a00ccbc17..b539399773 100644 --- a/xbmc/network/upnp/UPnPRenderer.h +++ b/xbmc/network/upnp/UPnPRenderer.h @@ -19,6 +19,7 @@ * */ #include "PltMediaRenderer.h" +#include "interfaces/IAnnouncer.h" namespace UPNP { @@ -30,13 +31,17 @@ public: }; class CUPnPRenderer : public PLT_MediaRenderer + , public ANNOUNCEMENT::IAnnouncer { public: CUPnPRenderer(const char* friendly_name, bool show_ip = false, const char* uuid = NULL, - unsigned int port = 0) : PLT_MediaRenderer(friendly_name, show_ip, uuid, port) {} + unsigned int port = 0); + virtual ~CUPnPRenderer(); + + virtual void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); void UpdateState(); // Http server handler -- cgit v1.2.3