/*---------------------------------------------------------------------- | CUPnPRenderer::OnSetAVTransportURI +---------------------------------------------------------------------*/ NPT_Result CUPnPRenderer::OnSetAVTransportURI(PLT_ActionReference& action) { NPT_String uri, meta; PLT_Service* service; NPT_CHECK_SEVERE(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service)); NPT_CHECK_SEVERE(action->GetArgumentValue("CurrentURI", uri)); NPT_CHECK_SEVERE(action->GetArgumentValue("CurrentURIMetaData", meta)); // if not playing already, just keep around uri & metadata // and wait for play command if (!g_application.m_pPlayer->IsPlaying() && g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW) { service->SetStateVariable("TransportState", "STOPPED"); service->SetStateVariable("TransportStatus", "OK"); service->SetStateVariable("TransportPlaySpeed", "1"); service->SetStateVariable("AVTransportURI", uri); service->SetStateVariable("AVTransportURIMetaData", meta); service->SetStateVariable("NextAVTransportURI", ""); service->SetStateVariable("NextAVTransportURIMetaData", ""); NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable()); return NPT_SUCCESS; } return PlayMedia(uri, meta, action.AsPointer()); }
/*---------------------------------------------------------------------- | PLT_SsdpAnnounceInterfaceIterator class +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpAnnounceInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const { // don't use this interface address if it's not broadcast capable if (m_Broadcast && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_BROADCAST)) { return NPT_FAILURE; } NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = net_if->GetAddresses().GetFirstItem(); if (!niaddr) return NPT_FAILURE; // Remove disconnected interfaces NPT_IpAddress addr = (*niaddr).GetPrimaryAddress(); if (!addr.ToString().Compare("0.0.0.0")) return NPT_FAILURE; if (!m_Broadcast && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK)) { NPT_LOG_INFO_2("Not a valid interface: %s (flags: %d)", (const char*)addr.ToString(), net_if->GetFlags()); return NPT_FAILURE; } NPT_HttpUrl url; NPT_UdpMulticastSocket multicast_socket; NPT_UdpSocket broadcast_socket; NPT_UdpSocket* socket; if (m_Broadcast) { url = NPT_HttpUrl((*niaddr).GetBroadcastAddress().ToString(), 1900, "*"); socket = &broadcast_socket; } else { url = NPT_HttpUrl("239.255.255.250", 1900, "*"); NPT_CHECK_SEVERE(multicast_socket.SetInterface(addr)); socket = &multicast_socket; multicast_socket.SetTimeToLive(PLT_Constants::GetInstance().GetAnnounceMulticastTimeToLive()); } NPT_HttpRequest req(url, "NOTIFY", NPT_HTTP_PROTOCOL_1_1); PLT_HttpHelper::SetHost(req, "239.255.255.250:1900"); // Location header valid only for ssdp:alive or ssdp:update messages if (m_Type != PLT_ANNOUNCETYPE_BYEBYE) { PLT_UPnPMessageHelper::SetLocation(req, m_Device->GetDescriptionUrl(addr.ToString())); } NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_Type)); #if defined(PLATINUM_UPNP_SPECS_STRICT) // delay alive only as we don't want to delay when stopping if (m_Type != PLT_ANNOUNCETYPE_BYEBYE) { NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY_GROUP)); } NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_Type)); #endif return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_UPnP::Start() +---------------------------------------------------------------------*/ NPT_Result PLT_UPnP::Start() { NPT_LOG_INFO("Starting UPnP..."); NPT_AutoLock lock(m_Lock); if (m_Started == true) NPT_CHECK_SEVERE(NPT_ERROR_INVALID_STATE); NPT_List<NPT_IpAddress> ips; PLT_UPnPMessageHelper::GetIPAddresses(ips); /* Create multicast socket and bind on 1900. If other apps didn't play nicely by setting the REUSE_ADDR flag, this could fail */ NPT_UdpMulticastSocket* socket = new NPT_UdpMulticastSocket(); NPT_CHECK_SEVERE(socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900), true)); /* Join multicast group for every ip we found */ NPT_CHECK_SEVERE(ips.ApplyUntil(PLT_SsdpInitMulticastIterator(socket), NPT_UntilResultNotEquals(NPT_SUCCESS))); /* create the ssdp listener */ m_SsdpListenTask = new PLT_SsdpListenTask(socket); NPT_CHECK_SEVERE(m_TaskManager.StartTask(m_SsdpListenTask)); /* start devices & ctrlpoints */ // TODO: Starting devices and ctrlpoints could fail? m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStartIterator(m_SsdpListenTask)); m_Devices.Apply(PLT_UPnP_DeviceStartIterator(m_SsdpListenTask)); m_Started = true; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_SsdpDeviceSearchResponseInterfaceIterator class +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpDeviceSearchResponseInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const { const NPT_SocketAddress* remote_addr = &m_RemoteAddr; NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = net_if->GetAddresses().GetFirstItem(); if (!niaddr) return NPT_SUCCESS; // don't try to bind on port 1900 or connect will fail later NPT_UdpSocket socket; //socket.Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900), true); // by connecting, the kernel chooses which interface to use to route to the remote // this is the IP we should use in our Location URL header NPT_CHECK_WARNING(socket.Connect(m_RemoteAddr, 5000)); NPT_SocketInfo info; socket.GetInfo(info); // did we successfully connect and found out which interface is used? if (info.local_address.GetIpAddress().AsLong()) { // check that the interface the kernel chose matches the interface // we wanted to send on if ((*niaddr).GetPrimaryAddress().AsLong() != info.local_address.GetIpAddress().AsLong()) { return NPT_SUCCESS; } // socket already connected, so we don't need to specify where to go remote_addr = NULL; } NPT_HttpResponse response(200, "OK", NPT_HTTP_PROTOCOL_1_1); PLT_UPnPMessageHelper::SetLocation(response, m_Device->GetDescriptionUrl(info.local_address.GetIpAddress().ToString())); PLT_UPnPMessageHelper::SetLeaseTime(response, m_Device->GetLeaseTime()); PLT_UPnPMessageHelper::SetServer(response, PLT_HTTP_DEFAULT_SERVER, false); response.GetHeaders().SetHeader("EXT", ""); // process search response twice to be DLNA compliant #if defined(PLATINUM_UPNP_SPECS_STRICT) { //NPT_UdpSocket socket; NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); } NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY_GROUP)); #endif { //NPT_UdpSocket socket; NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpServer::Start +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServer::Start() { NPT_Result res = NPT_FAILURE; // we can't restart an aborted server if (m_Aborted) return NPT_ERROR_INVALID_STATE; // if we're given a port for our http server, try it if (m_Port) { res = SetListenPort(m_Port, m_ReuseAddress); // return right away if failed and not allowed to try again randomly if (NPT_FAILED(res) && !m_AllowRandomPortOnBindFailure) { NPT_CHECK_SEVERE(res); } } // try random port now if (!m_Port || NPT_FAILED(res)) { int retries = 100; do { int random = NPT_System::GetRandomInteger(); int port = (unsigned short)(1024 + (random % 1024)); if (NPT_SUCCEEDED(SetListenPort(port, m_ReuseAddress))) { break; } } while (--retries > 0); if (retries == 0) NPT_CHECK_SEVERE(NPT_FAILURE); } // keep track of port server has successfully bound m_Port = m_BoundPort; // Tell server to try to listen to more incoming sockets // (this could fail silently) if (m_TaskManager->GetMaxTasks() > 20) { m_Socket.Listen(m_TaskManager->GetMaxTasks()); } // start a task to listen for incoming connections // and keep it around so we can abort the server m_HttpListenTask = new PLT_HttpListenTask(this, &m_Socket, false); m_TaskManager->StartTask(m_HttpListenTask, NULL, false); NPT_SocketInfo info; m_Socket.GetInfo(info); NPT_LOG_INFO_2("HttpServer listening on %s:%d", (const char*)info.local_address.GetIpAddress().ToString(), m_Port); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpClient::Connect +---------------------------------------------------------------------*/ NPT_Result PLT_HttpClient::Connect(NPT_Socket* connection, NPT_HttpRequest& request, NPT_Timeout timeout) { // get the address of the server NPT_IpAddress server_address; NPT_CHECK_SEVERE(server_address.ResolveName(request.GetUrl().GetHost(), timeout)); NPT_SocketAddress address(server_address, request.GetUrl().GetPort()); // connect to the server NPT_LOG_FINER_2("Connecting to %s:%d\n", (const char*)request.GetUrl().GetHost(), request.GetUrl().GetPort()); NPT_CHECK_SEVERE(connection->Connect(address, timeout)); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_ArgumentDesc::GetSCPDXML +---------------------------------------------------------------------*/ NPT_Result PLT_ArgumentDesc::GetSCPDXML(NPT_XmlElementNode* node) { NPT_XmlElementNode* argument = new NPT_XmlElementNode("argument"); NPT_CHECK_SEVERE(node->AddChild(argument)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "name", m_Name)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "direction", m_Direction)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "relatedStateVariable", m_RelatedStateVariable->GetName())); if (m_HasReturnValue) { NPT_CHECK_SEVERE(argument->AddChild(new NPT_XmlElementNode("retval"))); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | CUPnPRenderer::OnSetAVTransportURI +---------------------------------------------------------------------*/ NPT_Result CUPnPRenderer::OnSetNextAVTransportURI(PLT_ActionReference& action) { NPT_String uri, meta; PLT_Service* service; NPT_CHECK_SEVERE(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service)); NPT_CHECK_SEVERE(action->GetArgumentValue("NextURI", uri)); NPT_CHECK_SEVERE(action->GetArgumentValue("NextURIMetaData", meta)); CFileItemPtr item = GetFileItem(uri, meta); if (!item) { return NPT_FAILURE; } #if 0 if (g_application.m_pPlayer->IsPlaying()) { int playlist = PLAYLIST_MUSIC; if(item->IsVideo()) playlist = PLAYLIST_VIDEO; { CSingleLock lock(g_graphicsContext); g_playlistPlayer.ClearPlaylist(playlist); g_playlistPlayer.Add(playlist, item); g_playlistPlayer.SetCurrentSong(-1); g_playlistPlayer.SetCurrentPlaylist(playlist); } CGUIMessage msg(GUI_MSG_PLAYLIST_CHANGED, 0, 0); g_windowManager.SendThreadMessage(msg); service->SetStateVariable("NextAVTransportURI", uri); service->SetStateVariable("NextAVTransportURIMetaData", meta); NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable()); return NPT_SUCCESS; } else if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { return NPT_FAILURE; } else { return NPT_FAILURE; } #endif return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaController::SetVolume +---------------------------------------------------------------------*/ NPT_Result PLT_MediaController::SetVolume(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* channel, int volume, void* userdata) { PLT_ActionReference action; NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction( device, "urn:schemas-upnp-org:service:RenderingControl:1", "SetVolume", action)); // set the channel if (NPT_FAILED(action->SetArgumentValue("Channel", channel))) { return NPT_ERROR_INVALID_PARAMETERS; } if (NPT_FAILED(action->SetArgumentValue("DesiredVolume", NPT_String::FromInteger(volume)))) { return NPT_ERROR_INVALID_PARAMETERS; } return InvokeActionWithInstance(action, instance_id, userdata); }
/*---------------------------------------------------------------------- | PLT_MediaContainer::ToDidl +---------------------------------------------------------------------*/ NPT_Result PLT_MediaContainer::ToDidl(NPT_UInt32 mask, NPT_String& didl) { // container id property didl += "<container id=\""; PLT_Didl::AppendXmlEscape(didl, m_ObjectID); // parent id property didl += "\" parentID=\""; PLT_Didl::AppendXmlEscape(didl, m_ParentID); // ref id if ((mask & PLT_FILTER_MASK_REFID) && !m_ReferenceID.IsEmpty()) { didl += "\" refID=\""; PLT_Didl::AppendXmlEscape(didl, m_ReferenceID); } // restricted property didl += "\" restricted=\""; didl += m_Restricted?"1\"":"0\""; // searchable property if (mask & PLT_FILTER_MASK_SEARCHABLE) { didl += " searchable=\""; didl += m_Searchable?"1\"":"0\""; } // childcount property if ((mask & PLT_FILTER_MASK_CHILDCOUNT) && m_ChildrenCount != -1) { didl += " childCount=\""; didl += NPT_String::FromInteger(m_ChildrenCount); didl += "\""; } didl += ">"; if ((mask & PLT_FILTER_MASK_SEARCHCLASS) && m_SearchClasses.GetItemCount()) { NPT_List<PLT_SearchClass>::Iterator search_class = m_SearchClasses.GetFirstItem(); while (search_class) { didl += "<upnp:searchClass includeDerived=\""; didl += (*search_class).include_derived?"1\"":"0\""; // frienly name is any if (!(*search_class).friendly_name.IsEmpty()) { didl += " name=\"" + (*search_class).friendly_name + "\""; } didl += ">"; didl += (*search_class).type; didl += "</upnp:searchClass>"; ++search_class; } } NPT_CHECK_SEVERE(PLT_MediaObject::ToDidl(mask, didl)); /* close tag */ didl += "</container>"; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaRenderer::OnSetAVTransportURI +---------------------------------------------------------------------*/ NPT_Result PLT_MediaRenderer::OnSetAVTransportURI(PLT_ActionReference& action) { if (m_Delegate) { return m_Delegate->OnSetAVTransportURI(action); } // default implementation is using state variable NPT_String uri; NPT_CHECK_WARNING(action->GetArgumentValue("CurrentURI", uri)); NPT_String metadata; NPT_CHECK_WARNING(action->GetArgumentValue("CurrentURIMetaData", metadata)); PLT_Service* serviceAVT; NPT_CHECK_WARNING(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", serviceAVT)); // update service state variables serviceAVT->SetStateVariable("AVTransportURI", uri); serviceAVT->SetStateVariable("AVTransportURIMetaData", metadata); serviceAVT->SetStateVariable("TransportState", "STOPPED"); serviceAVT->SetStateVariable("TransportStatus", "OK"); serviceAVT->SetStateVariable("TransportPlaySpeed", "1"); NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable()); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaBrowser::Browse +---------------------------------------------------------------------*/ NPT_Result PLT_MediaBrowser::Browse(PLT_DeviceDataReference& device, const char* obj_id, NPT_UInt32 start_index, NPT_UInt32 count, bool browse_metadata, const char* filter, const char* sort_criteria, void* userdata) { // verify device still in our list PLT_DeviceDataReference device_data; NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data)); // create action PLT_ActionReference action; NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction( device, "urn:schemas-upnp-org:service:ContentDirectory:1", "Browse", action)); // Set the object id PLT_Arguments args; if (NPT_FAILED(action->SetArgumentValue("ObjectID", obj_id))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the browse_flag if (NPT_FAILED(action->SetArgumentValue("BrowseFlag", browse_metadata?"BrowseMetadata":"BrowseDirectChildren"))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Filter if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Starting Index if (NPT_FAILED(action->SetArgumentValue("StartingIndex", NPT_String::FromInteger(start_index)))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Requested Count if (NPT_FAILED(action->SetArgumentValue("RequestedCount", NPT_String::FromInteger(count)))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Requested Count if (NPT_FAILED(action->SetArgumentValue("SortCriteria", sort_criteria))) { return NPT_ERROR_INVALID_PARAMETERS; } // invoke the action if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) { return NPT_ERROR_INVALID_PARAMETERS; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaBrowser::Search +---------------------------------------------------------------------*/ NPT_Result PLT_MediaBrowser::Search(PLT_DeviceDataReference& device, const char* container_id, const char* search_criteria, NPT_UInt32 start_index, NPT_UInt32 count, const char* filter, void* userdata) { // verify device still in our list PLT_DeviceDataReference device_data; NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data)); // create action PLT_ActionReference action; NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction( device, "urn:schemas-upnp-org:service:ContentDirectory:1", "Search", action)); // Set the container id PLT_Arguments args; if (NPT_FAILED(action->SetArgumentValue("ContainerID", container_id))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Search Criteria if (NPT_FAILED(action->SetArgumentValue("SearchCriteria", search_criteria))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Filter if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Starting Index if (NPT_FAILED(action->SetArgumentValue("StartingIndex", NPT_String::FromInteger(start_index)))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Requested Count if (NPT_FAILED(action->SetArgumentValue("RequestedCount", NPT_String::FromInteger(count)))) { return NPT_ERROR_INVALID_PARAMETERS; } // set the Requested Count if (NPT_FAILED(action->SetArgumentValue("SortCriteria", ""))) { return NPT_ERROR_INVALID_PARAMETERS; } // invoke the action if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) { return NPT_ERROR_INVALID_PARAMETERS; } return NPT_SUCCESS; }
bool InvokeUpdateObject(const char* id, const char* curr_value, const char* new_value) { CURL url(id); PLT_DeviceDataReference device; PLT_Service* cds; PLT_ActionReference action; CLog::Log(LOGDEBUG, "UPNP: attempting to invoke UpdateObject for %s", id); // check this server supports UpdateObject action NPT_CHECK_LABEL(FindServer(url.GetHostName().c_str(), device),failed); NPT_CHECK_LABEL(device->FindServiceById("urn:upnp-org:serviceId:ContentDirectory", cds),failed); NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction( device, "urn:schemas-upnp-org:service:ContentDirectory:1", "UpdateObject", action)); NPT_CHECK_LABEL(action->SetArgumentValue("ObjectID", url.GetFileName().c_str()), failed); NPT_CHECK_LABEL(action->SetArgumentValue("CurrentTagValue", curr_value), failed); NPT_CHECK_LABEL(action->SetArgumentValue("NewTagValue", new_value), failed); NPT_CHECK_LABEL(m_CtrlPoint->InvokeAction(action, NULL),failed); CLog::Log(LOGDEBUG, "UPNP: invoked UpdateObject successfully"); return true; failed: CLog::Log(LOGINFO, "UPNP: invoking UpdateObject failed"); return false; }
/*---------------------------------------------------------------------- | PLT_MediaItem::ToDidl +---------------------------------------------------------------------*/ NPT_Result PLT_MediaItem::ToDidl(NPT_UInt32 mask, NPT_String& didl) { NPT_String tmp; // Allocate enough space for a big string we're going to concatenate in tmp.Reserve(2048); tmp = "<item id=\""; PLT_Didl::AppendXmlEscape(tmp, m_ObjectID); tmp += "\" parentID=\""; PLT_Didl::AppendXmlEscape(tmp, m_ParentID); if (!m_ReferenceID.IsEmpty()) { tmp += "\" refID=\""; PLT_Didl::AppendXmlEscape(tmp, m_ReferenceID); } tmp += "\" restricted=\""; tmp += m_Restricted?"1\"":"0\""; tmp += ">"; NPT_CHECK_SEVERE(PLT_MediaObject::ToDidl(mask, tmp)); /* close tag */ tmp += "</item>"; didl += tmp; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_SsdpSender::SendSsdp +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpSender::SendSsdp(NPT_HttpRequest& request, const char* usn, const char* target, NPT_UdpSocket& socket, bool notify, const NPT_SocketAddress* addr /* = NULL */) { NPT_CHECK_SEVERE(FormatPacket(request, usn, target, socket, notify)); // logging NPT_String prefix = NPT_String::Format("Sending SSDP %s packet for %s", (const char*)request.GetMethod(), usn); PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINER, prefix, &request); // use a memory stream to write all the data NPT_MemoryStream stream; NPT_Result res = request.Emit(stream); NPT_CHECK(res); // copy stream into a data packet and send it NPT_LargeSize size; stream.GetSize(size); if (size != (NPT_Size)size) NPT_CHECK(NPT_ERROR_OUT_OF_RANGE); NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size); NPT_CHECK_WARNING(socket.Send(packet, addr)); 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(m_CtrlPoint->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::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(m_CtrlPoint->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 InvokeActionWithInstance(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(m_CtrlPoint->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 InvokeActionWithInstance(action, instance_id, userdata); }
/*---------------------------------------------------------------------- | PLT_MediaItem::ToDidl +---------------------------------------------------------------------*/ NPT_Result PLT_MediaItem::ToDidl(NPT_UInt32 mask, NPT_String& didl) { didl += "<item id=\""; PLT_Didl::AppendXmlEscape(didl, m_ObjectID); didl += "\" parentID=\""; PLT_Didl::AppendXmlEscape(didl, m_ParentID); if ((mask & PLT_FILTER_MASK_REFID) && !m_ReferenceID.IsEmpty()) { didl += "\" refID=\""; PLT_Didl::AppendXmlEscape(didl, m_ReferenceID); } didl += "\" restricted=\""; didl += m_Restricted?"1\"":"0\""; didl += ">"; NPT_CHECK_SEVERE(PLT_MediaObject::ToDidl(mask, didl)); /* close tag */ didl += "</item>"; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_SsdpSender::SendSsdp +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpSender::SendSsdp(NPT_HttpResponse& response, const char* usn, const char* target, NPT_UdpSocket& socket, bool notify, const NPT_SocketAddress* addr /* = NULL */) { NPT_CHECK_SEVERE(FormatPacket(response, usn, target, socket, notify)); // logging NPT_LOG_FINE("Sending SSDP:"); PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &response); // use a memory stream to write all the data NPT_MemoryStream stream; NPT_Result res = response.Emit(stream); if (NPT_FAILED(res)) return res; // copy stream into a data packet and send it NPT_LargeSize size; stream.GetSize(size); if (size != (NPT_Size)size) return NPT_ERROR_OUT_OF_RANGE; NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size); return socket.Send(packet, addr); }
/*---------------------------------------------------------------------- | PLT_SyncMediaBrowser::BrowseSync +---------------------------------------------------------------------*/ NPT_Result PLT_SyncMediaBrowser::BrowseSync(PLT_BrowseDataReference& browse_data, PLT_DeviceDataReference& device, const char* object_id, NPT_Int32 index, NPT_Int32 count, bool browse_metadata, const char* filter, const char* sort) { NPT_Result res; browse_data->shared_var.SetValue(0); // send off the browse packet. Note that this will // not block. There is a call to WaitForResponse in order // to block until the response comes back. res = PLT_MediaBrowser::Browse(device, (const char*)object_id, index, count, browse_metadata, filter, sort, new PLT_BrowseDataReference(browse_data)); NPT_CHECK_SEVERE(res); return WaitForResponse(browse_data->shared_var); }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int /* argc */, char** argv) { /* parse command line */ ParseCommandLine(argv+1); PLT_UPnP upnp(1900, !Options.broadcast); PLT_DeviceHostReference device( new PLT_FileMediaServer( Options.path, Options.friendly_name?Options.friendly_name:"Platinum UPnP Media Server", false, "SAMEDEVICEGUID", (NPT_UInt16)Options.port) ); NPT_List<NPT_String> list; NPT_CHECK_SEVERE(PLT_UPnPMessageHelper::GetIPAddresses(list)); NPT_String ip = *(list.GetFirstItem()); //device->m_PresentationURL = NPT_HttpUrl(ip, 80, "/").ToString(); device->m_ModelDescription = "Platinum File Media Server"; device->m_ModelURL = "http://www.plutinosoft.com/"; device->m_ModelNumber = "1.0"; device->m_ModelName = "Platinum File Media Server"; device->m_Manufacturer = "Plutinosoft"; device->m_ManufacturerURL = "http://www.plutinosoft.com/"; if (Options.broadcast) device->SetBroadcast(true); upnp.AddDevice(device); NPT_String uuid = device->GetUUID(); NPT_CHECK_SEVERE(upnp.Start()); NPT_LOG_INFO("Press 'q' to quit."); char buf[256]; while (gets(buf)) { if (*buf == 'q') break; } upnp.Stop(); return 0; }
/*---------------------------------------------------------------------- | PLT_Argument::SetValue +---------------------------------------------------------------------*/ NPT_Result PLT_Argument::SetValue(const char* value) { NPT_CHECK_SEVERE(ValidateValue(value)); m_Value = value; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | CUPnPRenderer::OnSetVolume +---------------------------------------------------------------------*/ NPT_Result CUPnPRenderer::OnSetVolume(PLT_ActionReference& action) { NPT_String volume; NPT_CHECK_SEVERE(action->GetArgumentValue("DesiredVolume", volume)); g_application.SetVolume((float)strtod((const char*)volume, NULL)); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_FrameServer::Start +---------------------------------------------------------------------*/ NPT_Result PLT_FrameServer::Start() { // start main server so we can get the listening port NPT_CHECK_SEVERE(PLT_HttpServer::Start()); // start the xml socket policy server for flash if (m_PolicyServerEnabled) { m_PolicyServer = new PLT_SocketPolicyServer( "", 8989, "5900,"+NPT_String::FromInteger(GetPort())); NPT_CHECK_SEVERE(m_PolicyServer->Start()); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | CUPnPRenderer::OnSeek +---------------------------------------------------------------------*/ NPT_Result CUPnPRenderer::OnSeek(PLT_ActionReference& action) { if (!g_application.m_pPlayer->IsPlaying()) return NPT_ERROR_INVALID_STATE; NPT_String unit, target; NPT_CHECK_SEVERE(action->GetArgumentValue("Unit", unit)); NPT_CHECK_SEVERE(action->GetArgumentValue("Target", target)); if (!unit.Compare("REL_TIME")) { // converts target to seconds NPT_UInt32 seconds; NPT_CHECK_SEVERE(PLT_Didl::ParseTimeStamp(target, seconds)); g_application.SeekTime(seconds); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | CUPnPRenderer::OnSetMute +---------------------------------------------------------------------*/ NPT_Result CUPnPRenderer::OnSetMute(PLT_ActionReference& action) { NPT_String mute; NPT_CHECK_SEVERE(action->GetArgumentValue("DesiredMute",mute)); if((mute == "1") ^ g_application.IsMuted()) g_application.ToggleMute(); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaContainer::FromDidl +---------------------------------------------------------------------*/ NPT_Result PLT_MediaContainer::FromDidl(NPT_XmlElementNode* entry) { NPT_String str; /* reset first */ Reset(); // check entry type if (entry->GetTag().Compare("Container", true) != 0) return NPT_ERROR_INTERNAL; // check if item is searchable (is default true?) if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "searchable", str, "", 5))) { m_Searchable = PLT_Service::IsTrue(str); } // look for childCount if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "childCount", str, "", 256))) { NPT_UInt32 count; NPT_CHECK_SEVERE(str.ToInteger(count)); m_ChildrenCount = count; } // upnp:searchClass child elements NPT_Array<NPT_XmlElementNode*> children; PLT_XmlHelper::GetChildren(entry, children, "upnp:searchClass"); for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) { PLT_SearchClass search_class; // extract url if (children[i]->GetText() == NULL) { NPT_LOG_WARNING_1("No searchClass text found in: %s", (const char*)PLT_XmlHelper::Serialize(*children[i])); continue; } // DLNA 7.3.17.4 search_class.type = children[i]->GetText()->SubString(0, 256); // extract optional attribute name PLT_XmlHelper::GetAttribute(children[i], "name", search_class.friendly_name); // includeDerived property if (NPT_FAILED(PLT_XmlHelper::GetAttribute(children[i], "includeDerived", str))) { NPT_LOG_WARNING_1("No required attribute searchClass@includeDerived found in: %s", (const char*)PLT_XmlHelper::Serialize(*children[i])); continue; } search_class.include_derived = PLT_Service::IsTrue(str); m_SearchClasses.Add(search_class); } return PLT_MediaObject::FromDidl(entry); }
/*---------------------------------------------------------------------- | PLT_SsdpAnnounceInterfaceIterator class +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpAnnounceInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const { // don't use this interface address if it's not broadcast capable if (m_Broadcast && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_BROADCAST)) { return NPT_FAILURE; } NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = net_if->GetAddresses().GetFirstItem(); if (!niaddr) return NPT_FAILURE; // Remove disconnected interfaces NPT_IpAddress addr = (*niaddr).GetPrimaryAddress(); if (!addr.ToString().Compare("0.0.0.0")) return NPT_FAILURE; NPT_HttpUrl url; NPT_UdpMulticastSocket multicast_socket; NPT_UdpSocket broadcast_socket; NPT_UdpSocket* socket; if (m_Broadcast) { //url = NPT_HttpUrl("255.255.255.255", 1900, "*"); url = NPT_HttpUrl((*niaddr).GetBroadcastAddress().ToString(), 1900, "*"); socket = &broadcast_socket; } else { url = NPT_HttpUrl("239.255.255.250", 1900, "*"); socket = &multicast_socket; NPT_CHECK_SEVERE(((NPT_UdpMulticastSocket*)socket)->SetInterface(addr)); } NPT_HttpRequest req(url, "NOTIFY", NPT_HTTP_PROTOCOL_1_1); PLT_HttpHelper::SetHost(req, "239.255.255.250:1900"); // put a location only if alive message if (m_IsByeBye == false) { PLT_UPnPMessageHelper::SetLocation(req, m_Device->GetDescriptionUrl(addr.ToString())); } NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_IsByeBye)); NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_IsByeBye)); return NPT_SUCCESS; }