/*---------------------------------------------------------------------- | PLT_Constants::PLT_Constant +---------------------------------------------------------------------*/ PLT_Constants::PLT_Constants() { SetDefaultUserAgent(PLT_HTTP_DEFAULT_USER_AGENT); SetDefaultDeviceLease(NPT_TimeInterval(1800.)); SetDefaultSubscribeLease(NPT_TimeInterval(1800.)); SetAnnounceMulticastTimeToLive(1); SetSearchMulticastTimeToLive(1); }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | Test1 +---------------------------------------------------------------------*/ static void Test1() { NPT_Debug("--- Test1 Start ---\n"); T1 runnable; NPT_Debug("+++ creating non-detached thread +++\n"); NPT_Thread* thread1 = new NPT_Thread(runnable); // not detached NPT_Debug("+++ starting non-detached thread +++\n"); thread1->Start(); NPT_Debug("+++ waiting for non-detached thread +++\n"); NPT_Result result = thread1->Wait(); CHECK(NPT_SUCCEEDED(result)); NPT_Debug("+++ deleting non-detached thread +++\n"); delete thread1; NPT_Debug("+++ done with non-detached thread +++\n"); NPT_Debug("+++ creating detached thread +++\n"); thread1 = new NPT_Thread(runnable, true); // detached NPT_Debug("+++ starting detached thread +++\n"); thread1->Start(); NPT_Debug("+++ waiting for detached thread +++\n"); NPT_System::Sleep(NPT_TimeInterval(3.0f)); //delete thread1; NPT_Debug("+++ done with detached thread +++\n"); NPT_Debug("+++ creating non-detached thread +++\n"); thread1 = new NPT_Thread(runnable); // not detached NPT_Debug("+++ starting non-detached thread +++\n"); thread1->Start(); NPT_Debug("+++ deleting non-detached thread +++\n"); delete thread1; NPT_Debug("+++ done with non-detached thread +++\n"); }
/*---------------------------------------------------------------------- | Test1 +---------------------------------------------------------------------*/ static bool Test1(PLT_TaskManager* task_manager, const char* url, NPT_Size& size) { NPT_LOG_INFO("########### TEST 1 ######################"); NPT_MemoryStreamReference memory_stream(new NPT_MemoryStream()); NPT_OutputStreamReference output_stream(memory_stream); PLT_Downloader downloader(task_manager, url, output_stream); downloader.Start(); while (1) { switch(downloader.GetState()) { case PLT_DOWNLOADER_SUCCESS: { size = memory_stream->GetDataSize(); return true; } case PLT_DOWNLOADER_ERROR: return false; default: NPT_System::Sleep(NPT_TimeInterval(0, 10000)); break; } }; return false; }
static bool FindDeviceWait(CUPnP* upnp, const char* uuid, PLT_DeviceDataReference& device) { bool client_started = upnp->IsClientStarted(); upnp->StartClient(); // look for device in our list // (and wait for it to respond for 5 secs if we're just starting upnp client) NPT_TimeStamp watchdog; NPT_System::GetCurrentTimeStamp(watchdog); watchdog += 5.f; for (;;) { if (NPT_SUCCEEDED(upnp->m_MediaBrowser->FindServer(uuid, device)) && !device.IsNull()) break; // fail right away if device not found and upnp client was already running if (client_started) return false; // otherwise check if we've waited long enough without success NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); if (now > watchdog) return false; // sleep a bit and try again NPT_System::Sleep(NPT_TimeInterval((double)1)); } return !device.IsNull(); }
/*---------------------------------------------------------------------- | Test3 +---------------------------------------------------------------------*/ static bool Test3(PLT_TaskManager* task_manager, NPT_HttpUrl url, PLT_RingBufferStreamReference& ringbuffer_stream, NPT_Size& size) { NPT_LOG_INFO("########### TEST 3 ######################"); /* reset output param first */ size = 0; NPT_MemoryStreamReference memory_stream(new NPT_MemoryStream()); NPT_OutputStreamReference output_stream(memory_stream); PLT_Downloader downloader(task_manager, url, output_stream); downloader.Start(); /* asynchronously write onto ring buffer stream */ task_manager->StartTask(new RingBufferWriterTask(ringbuffer_stream)); /* start pulling data */ while (1) { switch(downloader.GetState()) { case PLT_DOWNLOADER_SUCCESS: size = memory_stream->GetDataSize(); return true; case PLT_DOWNLOADER_ERROR: return false; default: NPT_System::Sleep(NPT_TimeInterval(.1f)); break; } }; return false; }
/*---------------------------------------------------------------------- | 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_SsdpSearchTask::PLT_SsdpSearchTask +---------------------------------------------------------------------*/ PLT_SsdpSearchTask::PLT_SsdpSearchTask(NPT_UdpSocket* socket, PLT_SsdpSearchResponseListener* listener, NPT_HttpRequest* request, NPT_TimeInterval frequency) : m_Listener(listener), m_Request(request), m_Frequency(frequency?frequency:NPT_TimeInterval(30.)), m_Repeat(frequency.ToSeconds()!=0), m_Socket(socket) { m_Socket->SetReadTimeout((NPT_Timeout)m_Frequency.ToMillis()); m_Socket->SetWriteTimeout(10000); }
/*---------------------------------------------------------------------- | PLT_MediaServer::SetupServices +---------------------------------------------------------------------*/ NPT_Result PLT_MediaServer::SetupServices() { PLT_Service* service; { service = new PLT_Service( this, "urn:schemas-upnp-org:service:ContentDirectory:1", "urn:upnp-org:serviceId:ContentDirectory", "ContentDirectory"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ContentDirectorywSearchSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariable("ContainerUpdateIDs", ""); service->SetStateVariableRate("ContainerUpdateIDs", NPT_TimeInterval(2.)); service->SetStateVariable("SystemUpdateID", "0"); service->SetStateVariableRate("SystemUpdateID", NPT_TimeInterval(2.)); service->SetStateVariable("SearchCapability", "@id,@refID,dc:title,upnp:class,upnp:genre,upnp:artist,upnp:author,upnp:author@role,upnp:album,dc:creator,res@size,res@duration,res@protocolInfo,res@protection,dc:publisher,dc:language,upnp:originalTrackNumber,dc:date,upnp:producer,upnp:rating,upnp:actor,upnp:director,upnp:toc,dc:description,microsoft:userRatingInStars,microsoft:userEffectiveRatingInStars,microsoft:userRating,microsoft:userEffectiveRating,microsoft:serviceProvider,microsoft:artistAlbumArtist,microsoft:artistPerformer,microsoft:artistConductor,microsoft:authorComposer,microsoft:authorOriginalLyricist,microsoft:authorWriter,upnp:userAnnotation,upnp:channelName,upnp:longDescription,upnp:programTitle"); service->SetStateVariable("SortCapability", "dc:title,upnp:genre,upnp:album,dc:creator,res@size,res@duration,res@bitrate,dc:publisher,dc:language,upnp:originalTrackNumber,dc:date,upnp:producer,upnp:rating,upnp:actor,upnp:director,upnp:toc,dc:description,microsoft:year,microsoft:userRatingInStars,microsoft:userEffectiveRatingInStars,microsoft:userRating,microsoft:userEffectiveRating,microsoft:serviceProvider,microsoft:artistAlbumArtist,microsoft:artistPerformer,microsoft:artistConductor,microsoft:authorComposer,microsoft:authorOriginalLyricist,microsoft:authorWriter,microsoft:sourceUrl,upnp:userAnnotation,upnp:channelName,upnp:longDescription,upnp:programTitle"); } { service = new PLT_Service( this, "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:ConnectionManager", "ConnectionManager"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ConnectionManagerSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariable("CurrentConnectionIDs", "0"); service->SetStateVariable("SinkProtocolInfo", ""); service->SetStateVariable("SourceProtocolInfo", "http-get:*:*:*"); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaServer::SetupServices +---------------------------------------------------------------------*/ NPT_Result PLT_MediaServer::SetupServices() { PLT_Service* service; { service = new PLT_Service( this, "urn:schemas-upnp-org:service:ContentDirectory:1", "urn:upnp-org:serviceId:ContentDirectory", "ContentDirectory"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ContentDirectorywSearchSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariable("ContainerUpdateIDs", ""); service->SetStateVariableRate("ContainerUpdateIDs", NPT_TimeInterval(2.)); service->SetStateVariable("SystemUpdateID", "0"); service->SetStateVariableRate("SystemUpdateID", NPT_TimeInterval(2.)); service->SetStateVariable("SearchCapability", "upnp:class"); service->SetStateVariable("SortCapability", ""); } { service = new PLT_Service( this, "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:ConnectionManager", "ConnectionManager"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ConnectionManagerSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariable("CurrentConnectionIDs", "0"); service->SetStateVariable("SinkProtocolInfo", ""); service->SetStateVariable("SourceProtocolInfo", "http-get:*:*:*"); } return NPT_SUCCESS; }
void Run() { for (int i=0; i<10;) { NPT_Debug("CBR2: processing [%d]\n", i); NPT_Result result = m_Slot.ReceiveCallback(*this); if (result == NPT_ERROR_CALLBACK_NOTHING_PENDING) { } else { i++; } NPT_Debug("CBR2: sleeping\n"); NPT_System::Sleep(NPT_TimeInterval(0.2f)); } NPT_Debug("CBR2: shutting down\n"); m_Slot.Shutdown(); }
NPT_Result SendResponseBody(const NPT_HttpRequestContext& /*context*/, NPT_HttpResponse& /*response*/, NPT_OutputStream& output) { output.WriteString("<html><body>\r\n"); for (unsigned int i=0; i<30; i++) { output.WriteString("Line "); output.WriteString(NPT_String::FromInteger(i).GetChars()); output.WriteString("\r\n"); output.Flush(); NPT_System::Sleep(NPT_TimeInterval(0.2f)); } output.WriteString("</body></html>\r\n"); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_EventSubscriber::SetExpirationTime +---------------------------------------------------------------------*/ NPT_Result PLT_EventSubscriber::SetTimeout(NPT_Timeout seconds) { NPT_LOG_FINE_2("subscriber (%s) expiring in %d seconds", m_SID.GetChars(), seconds); // -1 means infinite but we default to 300 secs if (seconds == -1) seconds = 300; NPT_System::GetCurrentTimeStamp(m_ExpirationTime); m_ExpirationTime += NPT_TimeInterval((double)seconds); return NPT_SUCCESS; }
void Run() { volatile int res = -1; for (int i=0; i<m_Cycles; i++) { _CB_T args = {&res, m_Var+1}; if (m_Sleep != 0.0f) { NPT_Debug("@CBR [%d] - calling back\n", m_Var); } NPT_Result result = m_Slot.SendCallback(&args); if (result == NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN) { NPT_Debug("SHUTDOWN\n"); return; } CHECK(res == m_Var); res -= (m_Var+1); if (m_Sleep != 0.0f) { NPT_Debug("@CBR [%d] - sleeping\n", m_Var); } if (m_Sleep != 0.0f) NPT_System::Sleep(NPT_TimeInterval(m_Sleep)); } }
/*---------------------------------------------------------------------- | Test2 +---------------------------------------------------------------------*/ static bool Test2(PLT_TaskManager* task_manager, const char* url, NPT_Size& size) { NPT_LOG_INFO("########### TEST 2 ######################"); /* reset output param first */ size = 0; PLT_RingBufferStreamReference ringbuffer_stream(new PLT_RingBufferStream()); NPT_OutputStreamReference output_stream(ringbuffer_stream); NPT_InputStreamReference input_stream(ringbuffer_stream); PLT_Downloader downloader(task_manager, url, output_stream); downloader.Start(); while (1) { switch(downloader.GetState()) { case PLT_DOWNLOADER_SUCCESS: ringbuffer_stream->SetEos(); /* fallthrough */ case PLT_DOWNLOADER_DOWNLOADING: { NPT_Size bytes_read; NPT_Result res = ReadBody(downloader, input_stream, bytes_read); if (NPT_FAILED(res)) { return (res==NPT_ERROR_EOS)?true:false; } size += bytes_read; } break; case PLT_DOWNLOADER_ERROR: return false; default: NPT_System::Sleep(NPT_TimeInterval(0, 10000)); break; } }; return false; }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int, char**) { NPT_LogManager::GetDefault().Configure("plist:hop.level=INFO;"); NPT_HttpLoggerConfigurator* server = new NPT_HttpLoggerConfigurator(); server->Start(); NPT_Logger* loggers[16]; loggers[ 0] = NPT_LogManager::GetLogger("test.log.one"); loggers[ 1] = NPT_LogManager::GetLogger("test.log.two"); loggers[ 2] = NPT_LogManager::GetLogger("test.log.three"); loggers[ 3] = NPT_LogManager::GetLogger("test.foo.bla.bli"); loggers[ 4] = NPT_LogManager::GetLogger("test.bar"); loggers[ 5] = NPT_LogManager::GetLogger("test.bar.one"); loggers[ 6] = NPT_LogManager::GetLogger("test.bar.two"); loggers[ 7] = NPT_LogManager::GetLogger("test.bar.three"); loggers[ 8] = NPT_LogManager::GetLogger("hop"); loggers[ 9] = NPT_LogManager::GetLogger("hop.hop.hop.boom"); loggers[10] = NPT_LogManager::GetLogger("kiki"); loggers[11] = NPT_LogManager::GetLogger("koko"); loggers[12] = NPT_LogManager::GetLogger("kaka.coucou"); loggers[13] = NPT_LogManager::GetLogger("kaka.test.coucou"); loggers[14] = NPT_LogManager::GetLogger("kaka.kaka"); loggers[15] = NPT_LogManager::GetLogger("kuku"); for (;;) { NPT_System::Sleep(NPT_TimeInterval(1.0f)); for (unsigned int i=0; i<sizeof(loggers)/sizeof(loggers[0]); i++) { NPT_LoggerReference logger = { loggers[i], "test" }; int level = NPT_System::GetRandomInteger()%800; NPT_LOG_L2(logger, level, "hello from logger %d, level %d", i, level); } } server->Wait(); delete server; return 0; }
/*---------------------------------------------------------------------- | DumpBody +---------------------------------------------------------------------*/ static NPT_Result ReadBody(PLT_Downloader& downloader, NPT_InputStreamReference& stream, NPT_Size& size) { NPT_LargeSize avail; char buffer[2048]; NPT_Result ret = NPT_ERROR_WOULD_BLOCK; /* reset output param first */ size = 0; /* we test for availability first to avoid getting stuck in Read forever in case blocking is true and the download is done writing to the stream */ NPT_CHECK(stream->GetAvailable(avail)); if (avail) { ret = stream->Read(buffer, 2048, &size); NPT_LOG_FINER_2("Read %d bytes (result = %d)\n", size, ret); return ret; } else { Plt_DowloaderState state = downloader.GetState(); switch (state) { case PLT_DOWNLOADER_ERROR: return NPT_FAILURE; case PLT_DOWNLOADER_SUCCESS: /* no more data expected */ return NPT_ERROR_EOS; default: NPT_System::Sleep(NPT_TimeInterval(0, 10000)); break; } } return NPT_SUCCESS; }
void Run() { for (int i=0; i<m_Cycles;) { if (m_Sleep != 0.0f) { NPT_Debug(".CBR [%d] - processing\n", m_Var); } NPT_Result result = m_Slot.ReceiveCallback(*this); if (result == NPT_ERROR_CALLBACK_NOTHING_PENDING) { if (m_Sleep != 0.0f) { NPT_Debug(".CBR [%d] - nothing pending\n", m_Var); } } else { CHECK(result == NPT_SUCCESS); CHECK(m_FlipFlop == true); m_FlipFlop = false; i++; } if (m_Sleep != 0.0f) { NPT_Debug(".CBR [%d] - sleeping\n", m_Var); } if (m_Sleep != 0.0f) NPT_System::Sleep(NPT_TimeInterval(m_Sleep)); } }
/*---------------------------------------------------------------------- | Test3 +---------------------------------------------------------------------*/ static bool Test3(PLT_TaskManager* task_manager, const char* url, PLT_RingBufferStreamReference& ringbuffer_stream, NPT_Size& size) { NPT_LOG_INFO("########### TEST 3 ######################"); /* reset output param first */ size = 0; NPT_MemoryStreamReference memory_stream(new NPT_MemoryStream()); NPT_OutputStreamReference output_stream(memory_stream); PLT_Downloader downloader(task_manager, url, output_stream); downloader.Start(); /* asynchronously write onto ring buffer stream */ char buffer[32768]; ringbuffer_stream->WriteFully(buffer, 32768); /* mark as done */ ringbuffer_stream->SetEos(); while (1) { switch(downloader.GetState()) { case PLT_DOWNLOADER_SUCCESS: size = memory_stream->GetDataSize(); return true; case PLT_DOWNLOADER_ERROR: return false; default: NPT_System::Sleep(NPT_TimeInterval(0, 10000)); break; } }; return false; }
/*---------------------------------------------------------------------- | PLT_TaskManager::StopAllTasks +---------------------------------------------------------------------*/ NPT_Result PLT_TaskManager::StopAllTasks() { // unblock the queue if any if (m_Queue) { NPT_Queue<NPT_Integer>* queue = m_Queue; m_Queue = NULL; delete queue; } // stop all tasks first but don't block // otherwise when RemoveTask is called by PLT_ThreadTask::Run // it will deadlock with m_TasksLock { NPT_AutoLock lock(m_TasksLock); NPT_List<PLT_ThreadTask*>::Iterator task = m_Tasks.GetFirstItem(); while (task) { (*task)->Stop(false); ++task; } } // then wait for list to become empty // as tasks remove themselves from the list while (1) { { NPT_AutoLock lock(m_TasksLock); if (m_Tasks.GetItemCount() == 0) return NPT_SUCCESS; } NPT_System::Sleep(NPT_TimeInterval(0, 10000)); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { NPT_COMPILER_UNUSED(argc); NPT_HttpRequestHandler *handler, *custom_handler; NPT_Reference<NPT_DataBuffer> buffer; NPT_Size size; bool result; PLT_RingBufferStreamReference ringbuffer_stream(new PLT_RingBufferStream()); /* parse command line */ ParseCommandLine(argv); /* create http server */ PLT_HttpServer http_server(Options.port?Options.port:80); NPT_String url = "http://127.0.0.1:" + NPT_String::FromInteger(http_server.GetPort()); NPT_String custom_url = url; if (!Options.path.IsEmpty()) { /* extract folder path */ int index1 = Options.path.ReverseFind('\\'); int index2 = Options.path.ReverseFind('/'); if (index1 <= 0 && index2 <=0) { fprintf(stderr, "ERROR: invalid path\n"); exit(1); } NPT_DirectoryEntryInfo info; NPT_CHECK_SEVERE(NPT_DirectoryEntry::GetInfo(Options.path, &info)); /* add file request handler */ handler = new NPT_HttpFileRequestHandler( Options.path.Left(index1>index2?index1:index2), "/"); http_server.AddRequestHandler(handler, "/", true); /* build url*/ url += "/" + Options.path.SubString((index1>index2?index1:index2)+1); } else { /* create random data */ buffer = new NPT_DataBuffer(32768); buffer->SetDataSize(32768); /* add static handler */ handler = new NPT_HttpStaticRequestHandler(buffer->GetData(), buffer->GetDataSize(), "text/xml"); http_server.AddRequestHandler(handler, "/test"); /* build url*/ url += "/test"; } /* add custom handler */ NPT_InputStreamReference stream(ringbuffer_stream); custom_handler = new PLT_HttpCustomRequestHandler(stream, "text/xml"); http_server.AddRequestHandler(custom_handler, "/custom"); custom_url += "/custom"; /* start server */ NPT_CHECK_SEVERE(http_server.Start()); /* a task manager for the tests downloader */ PLT_TaskManager task_manager; /* small delay to let the server start */ NPT_System::Sleep(NPT_TimeInterval(1, 0)); /* execute tests */ result = Test1(&task_manager, url.GetChars(), size); if (!result) return -1; result = Test2(&task_manager, url.GetChars(), size); if (!result) return -1; result = Test3(&task_manager, custom_url.GetChars(), ringbuffer_stream, size); if (!result) return -1; NPT_System::Sleep(NPT_TimeInterval(1, 0)); http_server.Stop(); delete handler; delete custom_handler; return 0; }
/*---------------------------------------------------------------------- | PLT_SsdpSearchTask::DoRun +---------------------------------------------------------------------*/ void PLT_SsdpSearchTask::DoRun() { NPT_HttpResponse* response = NULL; NPT_Timeout timeout = 30000; NPT_HttpRequestContext context; do { // get the address of the server NPT_IpAddress server_address; NPT_CHECK_LABEL_SEVERE(server_address.ResolveName( m_Request->GetUrl().GetHost(), timeout), done); NPT_SocketAddress address(server_address, m_Request->GetUrl().GetPort()); // send 2 requests in a row NPT_OutputStreamReference output_stream( new PLT_OutputDatagramStream(m_Socket, 4096, &address)); NPT_CHECK_LABEL_SEVERE(NPT_HttpClient::WriteRequest( *output_stream.AsPointer(), *m_Request, false), done); NPT_CHECK_LABEL_SEVERE(NPT_HttpClient::WriteRequest( *output_stream.AsPointer(), *m_Request, false), done); output_stream = NULL; // keep track of when we sent the request NPT_TimeStamp last_send; NPT_System::GetCurrentTimeStamp(last_send); while (!IsAborting(0)) { // read response PLT_InputDatagramStreamReference input_stream( new PLT_InputDatagramStream(m_Socket)); NPT_InputStreamReference stream = input_stream; NPT_Result res = NPT_HttpClient::ReadResponse( stream, false, false, response); // callback to process response if (NPT_SUCCEEDED(res)) { // get source info NPT_SocketInfo info; input_stream->GetInfo(info); context.SetLocalAddress(info.local_address); context.SetRemoteAddress(info.remote_address); // process response ProcessResponse(NPT_SUCCESS, *m_Request, context, response); delete response; response = NULL; } else if (res != NPT_ERROR_TIMEOUT) { NPT_LOG_WARNING_1("PLT_SsdpSearchTask got an error (%d) waiting for response", res); NPT_System::Sleep(NPT_TimeInterval(.5f)); } input_stream = NULL; // check if it's time to resend request NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); if (now >= last_send + m_Frequency) break; } } while (!IsAborting(0) && m_Repeat); done: return; }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(void) { // setup Neptune logging NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=24"); // Create upnp engine PLT_UPnP upnp; #ifdef SIMULATE_XBOX_360 // override default headers NPT_HttpClient::m_UserAgentHeader = "Xbox/2.0.8955.0 UPnP/1.0 Xbox/2.0.8955.0"; NPT_HttpServer::m_ServerHeader = "Xbox/2.0.8955.0 UPnP/1.0 Xbox/2.0.8955.0"; #endif #ifdef SIMULATE_PS3 // TODO: We need a way to add an extra header to all HTTP requests //X-AV-Client-Info: av=5.0; cn="Sony Computer Entertainment Inc."; mn="PLAYSTATION 3"; mv="1.0"; #endif // Create control point PLT_CtrlPointReference ctrlPoint(new PLT_CtrlPoint()); // Create controller PLT_MicroMediaController controller(ctrlPoint); #ifdef HAS_SERVER // create device PLT_DeviceHostReference server( new PLT_FileMediaServer("C:\\Music", "Platinum UPnP Media Server")); server->m_ModelDescription = "Platinum File Media Server"; server->m_ModelURL = "http://www.plutinosoft.com/"; server->m_ModelNumber = "1.0"; server->m_ModelName = "Platinum File Media Server"; server->m_Manufacturer = "Plutinosoft"; server->m_ManufacturerURL = "http://www.plutinosoft.com/"; // add device upnp.AddDevice(server); // remove device uuid from ctrlpoint ctrlPoint->IgnoreUUID(server->GetUUID()); #endif // add control point to upnp engine and start it upnp.AddCtrlPoint(ctrlPoint); upnp.Start(); #ifdef BROADCAST_EXTRA // tell control point to perform extra broadcast discover every 6 secs // in case our device doesn't support multicast ctrlPoint->Discover(NPT_HttpUrl("255.255.255.255", 1900, "*"), "upnp:rootdevice", 1, 6000); ctrlPoint->Discover(NPT_HttpUrl("239.255.255.250", 1900, "*"), "upnp:rootdevice", 1, 6000); #endif #ifdef SIMULATE_XBOX_360 // create device PLT_DeviceHostReference xbox(new PLT_Xbox360("30848576-1775-2000-0000-00125a8fefad")); xbox->SetByeByeFirst(false); xbox->m_SerialNumber = "308485761776"; // add device upnp.AddDevice(xbox); ctrlPoint->IgnoreUUID(xbox->GetUUID()); // xbox issues a search for the content directory service // 10 secs after announcing itself to make sure // it got detected and inspected first ctrlPoint->Search( NPT_HttpUrl("239.255.255.250", 1900, "*"), "urn:schemas-microsoft-com:service:MSContentDirectory:1", 2, 10000, NPT_TimeInterval(10, 0)); ctrlPoint->Search( NPT_HttpUrl("239.255.255.250", 1900, "*"), "urn:schemas-upnp-org:service:ContentDirectory:1", 2, 10000, NPT_TimeInterval(10, 0)); #endif // start to process commands controller.ProcessCommandLoop(); // stop everything upnp.Stop(); return 0; }
NPT_Result GPAC_MediaRenderer::SetupServices(PLT_DeviceData& data) { PLT_Service* service; { /* AVTransport */ m_pAVService = new PLT_Service( &data, "urn:schemas-upnp-org:service:AVTransport:1", "urn:upnp-org:serviceId:AVT_1-0", "urn:schemas-upnp-org:metadata-1-0/AVT/"); NPT_CHECK_FATAL(m_pAVService->SetSCPDXML((const char*) RDR_AVTransportSCPD)); NPT_CHECK_FATAL(m_pAVService->InitURLs("AVTransport", data.GetUUID())); NPT_CHECK_FATAL(data.AddService(m_pAVService)); m_pAVService->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); m_pAVService->SetStateVariable("A_ARG_TYPE_InstanceID", "0"); // GetCurrentTransportActions m_pAVService->SetStateVariable("CurrentTransportActions", "Play,Pause,Stop,Seek,Next,Previous"); // GetDeviceCapabilities m_pAVService->SetStateVariable("PossiblePlaybackStorageMedia", "NONE,NETWORK"); m_pAVService->SetStateVariable("PossibleRecordStorageMedia", "NOT_IMPLEMENTED"); m_pAVService->SetStateVariable("PossibleRecordQualityModes", "NOT_IMPLEMENTED"); // GetMediaInfo m_pAVService->SetStateVariable("NumberOfTracks", "0"); m_pAVService->SetStateVariable("CurrentMediaDuration", "00:00:00");; m_pAVService->SetStateVariable("AVTransportURI", ""); m_pAVService->SetStateVariable("AVTransportURIMetadata", "");; m_pAVService->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED"); m_pAVService->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED"); m_pAVService->SetStateVariable("PlaybackStorageMedium", "NONE"); m_pAVService->SetStateVariable("RecordStorageMedium", "NOT_IMPLEMENTED"); m_pAVService->SetStateVariable("RecordMediumWriteStatus", "NOT_IMPLEMENTED"); // GetPositionInfo m_pAVService->SetStateVariable("CurrentTrack", "0"); m_pAVService->SetStateVariable("CurrentTrackDuration", "00:00:00"); m_pAVService->SetStateVariable("CurrentTrackMetadata", ""); m_pAVService->SetStateVariable("CurrentTrackURI", ""); m_pAVService->SetStateVariable("RelativeTimePosition", "00:00:00"); m_pAVService->SetStateVariable("AbsoluteTimePosition", "00:00:00"); m_pAVService->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTED m_pAVService->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED // disable indirect eventing for certain state variables //PLT_StateVariable* var; //var = m_pAVService->FindStateVariable("RelativeTimePosition"); //if (var) var->DisableIndirectEventing(); //var = m_pAVService->FindStateVariable("AbsoluteTimePosition"); //if (var) var->DisableIndirectEventing(); //var = m_pAVService->FindStateVariable("RelativeCounterPosition"); //if (var) var->DisableIndirectEventing(); //var = m_pAVService->FindStateVariable("AbsoluteCounterPosition"); //if (var) var->DisableIndirectEventing(); // GetTransportInfo m_pAVService->SetStateVariable("TransportState", "NO_MEDIA_PRESENT"); m_pAVService->SetStateVariable("TransportStatus", "OK"); m_pAVService->SetStateVariable("TransportPlaySpeed", "1"); // GetTransportSettings m_pAVService->SetStateVariable("CurrentPlayMode", "NORMAL"); m_pAVService->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED"); } { /* ConnectionManager */ service = new PLT_Service( &data, "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:CMGR_1-0"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD)); NPT_CHECK_FATAL(service->InitURLs("ConnectionManager", data.GetUUID())); NPT_CHECK_FATAL(data.AddService(service)); service->SetStateVariable("CurrentConnectionIDs", "0"); // put all supported mime types here instead service->SetStateVariable("SinkProtocolInfo", "http-get:*:*:*, rtsp-rtp-udp:*:*:*"); service->SetStateVariable("SourceProtocolInfo", ""); } { /* RenderingControl */ service = new PLT_Service( &data, "urn:schemas-upnp-org:service:RenderingControl:1", "urn:upnp-org:serviceId:RCS_1-0", "urn:schemas-upnp-org:metadata-1-0/RCS/"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD)); NPT_CHECK_FATAL(service->InitURLs("RenderingControl", data.GetUUID())); NPT_CHECK_FATAL(data.AddService(service)); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); service->SetStateVariable("Mute", "0"); service->SetStateVariable("Volume", "100"); } { static NPT_UInt8 MIGRATION_SCPDXML[] = "<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">\ <serviceStateTable>\ <stateVariable>\ <name>MigrationStatus</name>\ <sendEventsAttribute>no</sendEventsAttribute>\ <dataType>string</dataType>\ <allowedValueList>\ <allowedValue>OK</allowedValue>\ <allowedValue>ERROR_OCCURRED</allowedValue>\ </allowedValueList>\ </stateVariable>\ <stateVariable>\ <name>MigrationMetaData</name>\ <sendEventsAttribute>no</sendEventsAttribute>\ <dataType>string</dataType>\ </stateVariable>\ <stateVariable>\ <name>A_ARG_TYPE_InstanceID</name>\ <sendEventsAttribute>no</sendEventsAttribute>\ <dataType>ui4</dataType>\ </stateVariable>\ </serviceStateTable>\ <actionList>\ <action>\ <name>StopForMigration</name>\ <argumentList>\ <argument>\ <name>InstanceID</name>\ <direction>in</direction>\ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>\ </argument>\ <argument>\ <name>MigrationStatus</name>\ <direction>out</direction>\ <relatedStateVariable>MigrationStatus</relatedStateVariable>\ </argument>\ <argument>\ <name>MigrationMetaData</name>\ <direction>out</direction>\ <relatedStateVariable>MigrationMetaData</relatedStateVariable>\ </argument>\ </argumentList>\ </action>\ </actionList>\ </scpd>"; /* MigrationService */ m_pMigrationService = new PLT_Service(&data, "urn:intermedia:service:migration:1", "urn:intermedia:service:migration.001"); NPT_CHECK_FATAL(m_pMigrationService->SetSCPDXML((const char*) MIGRATION_SCPDXML)); NPT_CHECK_FATAL(m_pMigrationService->InitURLs("SessionMigration", data.GetUUID())); NPT_CHECK_FATAL(data.AddService(m_pMigrationService)); m_pMigrationService->SetStateVariable("MigrationStatus", "OK"); m_pMigrationService->SetStateVariable("MigrationMetaData", ""); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaRenderer::SetupServices +---------------------------------------------------------------------*/ NPT_Result PLT_MediaRenderer::SetupServices() { PLT_Service* service; { /* AVTransport */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:AVTransport:1", "urn:upnp-org:serviceId:AVTransport", "AVTransport", "urn:schemas-upnp-org:metadata-1-0/AVT/"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_AVTransportSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); service->SetStateVariable("A_ARG_TYPE_InstanceID", "0"); // GetCurrentTransportActions service->SetStateVariable("CurrentTransportActions", "Play,Pause,Stop,Seek,Next,Previous"); // GetDeviceCapabilities service->SetStateVariable("PossiblePlaybackStorageMedia", "NONE,NETWORK,HDD,CD-DA,UNKNOWN"); service->SetStateVariable("PossibleRecordStorageMedia", "NOT_IMPLEMENTED"); service->SetStateVariable("PossibleRecordQualityModes", "NOT_IMPLEMENTED"); // GetMediaInfo service->SetStateVariable("NumberOfTracks", "0"); service->SetStateVariable("CurrentMediaDuration", "00:00:00"); service->SetStateVariable("AVTransportURI", ""); service->SetStateVariable("AVTransportURIMetadata", "");; service->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED"); service->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED"); service->SetStateVariable("PlaybackStorageMedium", "NONE"); service->SetStateVariable("RecordStorageMedium", "NOT_IMPLEMENTED"); service->SetStateVariable("RecordMediumWriteStatus", "NOT_IMPLEMENTED"); // GetPositionInfo service->SetStateVariable("CurrentTrack", "0"); service->SetStateVariable("CurrentTrackDuration", "00:00:00"); service->SetStateVariable("CurrentTrackMetadata", ""); service->SetStateVariable("CurrentTrackURI", ""); service->SetStateVariable("RelativeTimePosition", "00:00:00"); service->SetStateVariable("AbsoluteTimePosition", "00:00:00"); service->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTED service->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED // disable indirect eventing for certain state variables PLT_StateVariable* var; var = service->FindStateVariable("RelativeTimePosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("AbsoluteTimePosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("RelativeCounterPosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("AbsoluteCounterPosition"); if (var) var->DisableIndirectEventing(); // GetTransportInfo service->SetStateVariable("TransportState", "NO_MEDIA_PRESENT"); service->SetStateVariable("TransportStatus", "OK"); service->SetStateVariable("TransportPlaySpeed", "1"); // GetTransportSettings service->SetStateVariable("CurrentPlayMode", "NORMAL"); service->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED"); } { /* ConnectionManager */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:ConnectionManager", "ConnectionManager"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariable("CurrentConnectionIDs", "0"); // put all supported mime types here instead service->SetStateVariable("SinkProtocolInfo", "http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_SP_G726,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMDRM_WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPLL_BASE,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC_XAC3,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMDRM_WMVSPLL_BASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_BASE,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L5_SO_G726,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL_XAC3,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAPRO,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L4_SO_G726,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3X,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_MP3,http-get:*:video/x-ms-wmv:*"); service->SetStateVariable("SourceProtocolInfo", ""); } { /* RenderingControl */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:RenderingControl:1", "urn:upnp-org:serviceId:RenderingControl", "RenderingControl", "urn:schemas-upnp-org:metadata-1-0/RCS/"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); service->SetStateVariable("Mute", "0"); service->SetStateVariableExtraAttribute("Mute", "Channel", "Master"); service->SetStateVariable("Volume", "100"); service->SetStateVariableExtraAttribute("Volume", "Channel", "Master"); service->SetStateVariable("VolumeDB", "0"); service->SetStateVariableExtraAttribute("VolumeDB", "Channel", "Master"); service->SetStateVariable("PresetNameList", "FactoryDefaults"); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaRenderer::SetupServices +---------------------------------------------------------------------*/ NPT_Result PLT_MediaRenderer::SetupServices(PLT_DeviceData& data) { PLT_Service* service; { /* AVTransport */ service = new PLT_Service( &data, "urn:schemas-upnp-org:service:AVTransport:1", "urn:upnp-org:serviceId:AVT_1-0", "urn:schemas-upnp-org:metadata-1-0/AVT/"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_AVTransportSCPD)); NPT_CHECK_FATAL(service->InitURLs("AVTransport", data.GetUUID())); NPT_CHECK_FATAL(data.AddService(service)); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); service->SetStateVariable("A_ARG_TYPE_InstanceID", "0"); // GetCurrentTransportActions service->SetStateVariable("CurrentTransportActions", "Play,Pause,Stop,Seek,Next,Previous"); // GetDeviceCapabilities service->SetStateVariable("PossiblePlaybackStorageMedia", "NONE,NETWORK"); service->SetStateVariable("PossibleRecordStorageMedia", "NOT_IMPLEMENTED"); service->SetStateVariable("PossibleRecordQualityModes", "NOT_IMPLEMENTED"); // GetMediaInfo service->SetStateVariable("NumberOfTracks", "0"); service->SetStateVariable("CurrentMediaDuration", "00:00:00");; service->SetStateVariable("AVTransportURI", ""); service->SetStateVariable("AVTransportURIMetadata", "");; service->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED"); service->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED"); service->SetStateVariable("PlaybackStorageMedium", "NONE"); service->SetStateVariable("RecordStorageMedium", "NOT_IMPLEMENTED"); service->SetStateVariable("RecordMediumWriteStatus", "NOT_IMPLEMENTED"); // GetPositionInfo service->SetStateVariable("CurrentTrack", "0"); service->SetStateVariable("CurrentTrackDuration", "00:00:00"); service->SetStateVariable("CurrentTrackMetadata", ""); service->SetStateVariable("CurrentTrackURI", ""); service->SetStateVariable("RelativeTimePosition", "00:00:00"); service->SetStateVariable("AbsoluteTimePosition", "00:00:00"); service->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTED service->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED // disable indirect eventing for certain state variables PLT_StateVariable* var; var = service->FindStateVariable("RelativeTimePosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("AbsoluteTimePosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("RelativeCounterPosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("AbsoluteCounterPosition"); if (var) var->DisableIndirectEventing(); // GetTransportInfo service->SetStateVariable("TransportState", "NO_MEDIA_PRESENT"); service->SetStateVariable("TransportStatus", "OK"); service->SetStateVariable("TransportPlaySpeed", "1"); // GetTransportSettings service->SetStateVariable("CurrentPlayMode", "NORMAL"); service->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED"); } { /* ConnectionManager */ service = new PLT_Service( &data, "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:CMGR_1-0"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD)); NPT_CHECK_FATAL(service->InitURLs("ConnectionManager", data.GetUUID())); NPT_CHECK_FATAL(data.AddService(service)); service->SetStateVariable("CurrentConnectionIDs", "0"); // put all supported mime types here instead service->SetStateVariable("SinkProtocolInfo", "http-get:*:*:*"); service->SetStateVariable("SourceProtocolInfo", ""); } { /* RenderingControl */ service = new PLT_Service( &data, "urn:schemas-upnp-org:service:RenderingControl:1", "urn:upnp-org:serviceId:RCS_1-0", "urn:schemas-upnp-org:metadata-1-0/RCS/"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD)); NPT_CHECK_FATAL(service->InitURLs("RenderingControl", data.GetUUID())); NPT_CHECK_FATAL(data.AddService(service)); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); service->SetStateVariable("Mute", "0"); service->SetStateVariable("Volume", "100"); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaRenderer::SetupServices +---------------------------------------------------------------------*/ NPT_Result PLT_MediaRenderer::SetupServices() { PLT_Service* service; { /* AVTransport */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:AVTransport:1", "urn:upnp-org:serviceId:AVTransport", "AVTransport", "urn:schemas-upnp-org:metadata-1-0/AVT/"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_AVTransportSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); service->SetStateVariable("A_ARG_TYPE_InstanceID", "0"); // GetCurrentTransportActions service->SetStateVariable("CurrentTransportActions", "Play,Pause,Stop,Seek,Next,Previous"); // GetDeviceCapabilities service->SetStateVariable("PossiblePlaybackStorageMedia", "NONE,NETWORK,HDD,CD-DA,UNKNOWN"); service->SetStateVariable("PossibleRecordStorageMedia", "NOT_IMPLEMENTED"); service->SetStateVariable("PossibleRecordQualityModes", "NOT_IMPLEMENTED"); // GetMediaInfo service->SetStateVariable("NumberOfTracks", "0"); service->SetStateVariable("CurrentMediaDuration", "00:00:00"); service->SetStateVariable("AVTransportURI", ""); service->SetStateVariable("AVTransportURIMetadata", "");; service->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED"); service->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED"); service->SetStateVariable("PlaybackStorageMedium", "NONE"); service->SetStateVariable("RecordStorageMedium", "NOT_IMPLEMENTED"); service->SetStateVariable("RecordMediumWriteStatus", "NOT_IMPLEMENTED"); // GetPositionInfo service->SetStateVariable("CurrentTrack", "0"); service->SetStateVariable("CurrentTrackDuration", "00:00:00"); service->SetStateVariable("CurrentTrackMetadata", ""); service->SetStateVariable("CurrentTrackURI", ""); service->SetStateVariable("RelativeTimePosition", "00:00:00"); service->SetStateVariable("AbsoluteTimePosition", "00:00:00"); service->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTED service->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED // disable indirect eventing for certain state variables PLT_StateVariable* var; var = service->FindStateVariable("RelativeTimePosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("AbsoluteTimePosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("RelativeCounterPosition"); if (var) var->DisableIndirectEventing(); var = service->FindStateVariable("AbsoluteCounterPosition"); if (var) var->DisableIndirectEventing(); // GetTransportInfo service->SetStateVariable("TransportState", "NO_MEDIA_PRESENT"); service->SetStateVariable("TransportStatus", "OK"); service->SetStateVariable("TransportPlaySpeed", "1"); // GetTransportSettings service->SetStateVariable("CurrentPlayMode", "NORMAL"); service->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED"); } { /* ConnectionManager */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:ConnectionManager", "ConnectionManager"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariable("CurrentConnectionIDs", "0"); // put all supported mime types here instead //service->SetStateVariable("SinkProtocolInfo", "http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_SP_G726,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMDRM_WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPLL_BASE,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC_XAC3,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMDRM_WMVSPLL_BASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_BASE,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L5_SO_G726,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL_XAC3,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAPRO,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L4_SO_G726,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3X,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_MP3,http-get:*:video/x-ms-wmv:*"); service->SetStateVariable("SinkProtocolInfo" ,"http-get:*:*:*" ",xbmc-get:*:*:*" ",http-get:*:audio/mpegurl:*" ",http-get:*:audio/mpeg:*" ",http-get:*:audio/mpeg3:*" ",http-get:*:audio/mp3:*" ",http-get:*:audio/mp4:*" ",http-get:*:audio/basic:*" ",http-get:*:audio/midi:*" ",http-get:*:audio/ulaw:*" ",http-get:*:audio/ogg:*" ",http-get:*:audio/DVI4:*" ",http-get:*:audio/G722:*" ",http-get:*:audio/G723:*" ",http-get:*:audio/G726-16:*" ",http-get:*:audio/G726-24:*" ",http-get:*:audio/G726-32:*" ",http-get:*:audio/G726-40:*" ",http-get:*:audio/G728:*" ",http-get:*:audio/G729:*" ",http-get:*:audio/G729D:*" ",http-get:*:audio/G729E:*" ",http-get:*:audio/GSM:*" ",http-get:*:audio/GSM-EFR:*" ",http-get:*:audio/L8:*" ",http-get:*:audio/L16:*" ",http-get:*:audio/LPC:*" ",http-get:*:audio/MPA:*" ",http-get:*:audio/PCMA:*" ",http-get:*:audio/PCMU:*" ",http-get:*:audio/QCELP:*" ",http-get:*:audio/RED:*" ",http-get:*:audio/VDVI:*" ",http-get:*:audio/ac3:*" ",http-get:*:audio/vorbis:*" ",http-get:*:audio/speex:*" ",http-get:*:audio/x-aiff:*" ",http-get:*:audio/x-pn-realaudio:*" ",http-get:*:audio/x-realaudio:*" ",http-get:*:audio/x-wav:*" ",http-get:*:audio/x-ms-wma:*" ",http-get:*:audio/x-mpegurl:*" ",http-get:*:application/x-shockwave-flash:*" ",http-get:*:application/ogg:*" ",http-get:*:application/sdp:*" ",http-get:*:image/gif:*" ",http-get:*:image/jpeg:*" ",http-get:*:image/ief:*" ",http-get:*:image/png:*" ",http-get:*:image/tiff:*" ",http-get:*:video/avi:*" ",http-get:*:video/mpeg:*" ",http-get:*:video/fli:*" ",http-get:*:video/flv:*" ",http-get:*:video/quicktime:*" ",http-get:*:video/vnd.vivo:*" ",http-get:*:video/vc1:*" ",http-get:*:video/ogg:*" ",http-get:*:video/mp4:*" ",http-get:*:video/BT656:*" ",http-get:*:video/CelB:*" ",http-get:*:video/JPEG:*" ",http-get:*:video/H261:*" ",http-get:*:video/H263:*" ",http-get:*:video/H263-1998:*" ",http-get:*:video/H263-2000:*" ",http-get:*:video/MPV:*" ",http-get:*:video/MP2T:*" ",http-get:*:video/MP1S:*" ",http-get:*:video/MP2P:*" ",http-get:*:video/BMPEG:*" ",http-get:*:video/x-ms-wmv:*" ",http-get:*:video/x-ms-avi:*" ",http-get:*:video/x-flv:*" ",http-get:*:video/x-fli:*" ",http-get:*:video/x-ms-asf:*" ",http-get:*:video/x-ms-asx:*" ",http-get:*:video/x-ms-wmx:*" ",http-get:*:video/x-ms-wvx:*" ",http-get:*:video/x-msvideo:*" ); service->SetStateVariable("SourceProtocolInfo", ""); } { /* RenderingControl */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:RenderingControl:1", "urn:upnp-org:serviceId:RenderingControl", "RenderingControl", "urn:schemas-upnp-org:metadata-1-0/RCS/"); NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD)); NPT_CHECK_FATAL(AddService(service)); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); service->SetStateVariable("Mute", "0"); service->SetStateVariableExtraAttribute("Mute", "Channel", "Master"); service->SetStateVariable("Volume", "100"); service->SetStateVariableExtraAttribute("Volume", "Channel", "Master"); service->SetStateVariable("VolumeDB", "0"); service->SetStateVariableExtraAttribute("VolumeDB", "Channel", "Master"); service->SetStateVariable("PresetNameList", "FactoryDefaults"); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | CUPnPDirectory::GetDirectory +---------------------------------------------------------------------*/ bool CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { CGUIDialogProgress* dlgProgress = NULL; CUPnP* upnp = CUPnP::GetInstance(); /* upnp should never be cached, it has internal cache */ items.SetCacheToDisc(CFileItemList::CACHE_NEVER); // start client if it hasn't been done yet bool client_started = upnp->IsClientStarted(); upnp->StartClient(); // We accept upnp://devuuid/[item_id/] NPT_String path = strPath.c_str(); if (!path.StartsWith("upnp://", true)) { return false; } if (path.Compare("upnp://", true) == 0) { // root -> get list of devices const NPT_Lock<PLT_DeviceMap>& devices = upnp->m_MediaBrowser->GetMediaServers(); const NPT_List<PLT_DeviceMapEntry*>& entries = devices.GetEntries(); NPT_List<PLT_DeviceMapEntry*>::Iterator entry = entries.GetFirstItem(); while (entry) { PLT_DeviceDataReference device = (*entry)->GetValue(); NPT_String name = device->GetFriendlyName(); NPT_String uuid = (*entry)->GetKey(); CFileItemPtr pItem(new CFileItem((const char*)name)); pItem->m_strPath = (const char*) "upnp://" + uuid + "/"; pItem->m_bIsFolder = true; pItem->SetThumbnailImage((const char*)device->GetIconUrl("image/jpeg")); items.Add(pItem); ++entry; } } else { if (!path.EndsWith("/")) path += "/"; // look for nextslash int next_slash = path.Find('/', 7); NPT_String uuid = (next_slash==-1)?path.SubString(7):path.SubString(7, next_slash-7); NPT_String object_id = (next_slash==-1)?"":path.SubString(next_slash+1); object_id.TrimRight("/"); if (object_id.GetLength()) { CStdString tmp = (char*) object_id; CUtil::UrlDecode(tmp); object_id = tmp; } // look for device in our list // (and wait for it to respond for 5 secs if we're just starting upnp client) NPT_TimeStamp watchdog; NPT_System::GetCurrentTimeStamp(watchdog); watchdog += 5.f; PLT_DeviceDataReference* device; for (;;) { const NPT_Lock<PLT_DeviceMap>& devices = upnp->m_MediaBrowser->GetMediaServers(); if (NPT_SUCCEEDED(devices.Get(uuid, device)) && device) break; // fail right away if device not found and upnp client was already running if (client_started) goto failure; // otherwise check if we've waited long enough without success NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); if (now > watchdog) goto failure; // sleep a bit and try again NPT_System::Sleep(NPT_TimeInterval(1, 0)); } // issue a browse request with object_id // if object_id is empty use "0" for root object_id = object_id.IsEmpty()?"0":object_id; // just a guess as to what types of files we want bool video = true; bool audio = true; bool image = true; m_strFileMask.TrimLeft("/"); if (!m_strFileMask.IsEmpty()) { video = m_strFileMask.Find(".wmv") >= 0; audio = m_strFileMask.Find(".wma") >= 0; image = m_strFileMask.Find(".jpg") >= 0; } // special case for Windows Media Connect and WMP11 when looking for root // We can target which root subfolder we want based on directory mask if (object_id == "0" && (((*device)->GetFriendlyName().Find("Windows Media Connect", 0, true) >= 0) || ((*device)->m_ModelName == "Windows Media Player Sharing"))) { // look for a specific type to differentiate which folder we want if (audio && !video && !image) { // music object_id = "1"; } else if (!audio && video && !image) { // video object_id = "2"; } else if (!audio && !video && image) { // pictures object_id = "3"; } } #ifdef DISABLE_SPECIALCASE // same thing but special case for XBMC if (object_id == "0" && (((*device)->m_ModelName.Find("XBMC", 0, true) >= 0) || ((*device)->m_ModelName.Find("Xbox Media Center", 0, true) >= 0))) { // look for a specific type to differentiate which folder we want if (audio && !video && !image) { // music object_id = "virtualpath://upnpmusic"; } else if (!audio && video && !image) { // video object_id = "virtualpath://upnpvideo"; } else if (!audio && !video && image) { // pictures object_id = "virtualpath://upnppictures"; } } #endif // bring up dialog if object is not cached if (!upnp->m_MediaBrowser->IsCached(uuid, object_id)) { dlgProgress = (CGUIDialogProgress*)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRESS); if (dlgProgress) { dlgProgress->ShowProgressBar(false); dlgProgress->SetCanCancel(false); dlgProgress->SetHeading(20334); dlgProgress->SetLine(0, 194); dlgProgress->SetLine(1, ""); dlgProgress->SetLine(2, ""); dlgProgress->StartModal(); } } // if error, return now, the device could have gone away // this will make us go back to the sources list PLT_MediaObjectListReference list; NPT_Result res = upnp->m_MediaBrowser->Browse(*device, object_id, list); if (NPT_FAILED(res)) goto failure; // empty list is ok if (list.IsNull()) goto cleanup; PLT_MediaObjectList::Iterator entry = list->GetFirstItem(); while (entry) { // disregard items with wrong class/type if( (!video && (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0) || (!audio && (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0) || (!image && (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0) ) { ++entry; continue; } // never show empty containers in media views if((*entry)->IsContainer()) { if( (audio || video || image) && ((PLT_MediaContainer*)(*entry))->m_ChildrenCount == 0) { ++entry; continue; } } CFileItemPtr pItem(new CFileItem((const char*)(*entry)->m_Title)); pItem->SetLabelPreformated(true); pItem->m_bIsFolder = (*entry)->IsContainer(); // if it's a container, format a string as upnp://uuid/object_id if (pItem->m_bIsFolder) { CStdString id = (char*) (*entry)->m_ObjectID; CUtil::URLEncode(id); pItem->m_strPath = (const char*) "upnp://" + uuid + "/" + id.c_str() + "/"; } else { if ((*entry)->m_Resources.GetItemCount()) { PLT_MediaItemResource& resource = (*entry)->m_Resources[0]; // look for a resource with "xbmc-get" protocol // if we can't find one, keep the first resource NPT_ContainerFind((*entry)->m_Resources, CProtocolFinder("xbmc-get"), resource); CLog::Log(LOGDEBUG, "CUPnPDirectory::GetDirectory - resource protocol info '%s'", (const char*)(resource.m_ProtocolInfo)); // if it's an item, path is the first url to the item // we hope the server made the first one reachable for us // (it could be a format we dont know how to play however) pItem->m_strPath = (const char*) resource.m_Uri; // set metadata if (resource.m_Size > 0) { pItem->m_dwSize = resource.m_Size; } // set a general content type CStdString type = (const char*)(*entry)->m_ObjectClass.type.Left(21); if (type.Equals("object.item.videoitem")) pItem->SetContentType("video/octet-stream"); else if(type.Equals("object.item.audioitem")) pItem->SetContentType("audio/octet-stream"); else if(type.Equals("object.item.imageitem")) pItem->SetContentType("image/octet-stream"); // look for content type in protocol info if (resource.m_ProtocolInfo.GetLength()) { char proto[1024]; char dummy1[1024]; char ct[1204]; char dummy2[1024]; int fields = sscanf(resource.m_ProtocolInfo, "%[^:]:%[^:]:%[^:]:%[^:]", proto, dummy1, ct, dummy2); if (fields == 4) { if (strcmp(ct, "application/octet-stream") != 0) { pItem->SetContentType(ct); } } else { CLog::Log(LOGERROR, "CUPnPDirectory::GetDirectory - invalid protocol info '%s'", (const char*)(resource.m_ProtocolInfo)); } } // look for date? if((*entry)->m_Description.date.GetLength()) { SYSTEMTIME time = {}; sscanf((*entry)->m_Description.date, "%hu-%hu-%huT%hu:%hu:%hu", &time.wYear, &time.wMonth, &time.wDay, &time.wHour, &time.wMinute, &time.wSecond); pItem->m_dateTime = time; } // look for metadata if( (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0 ) { pItem->SetLabelPreformated(false); CUPnP::PopulateTagFromObject(*pItem->GetVideoInfoTag(), *(*entry), &resource); } else if( (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0 ) { pItem->SetLabelPreformated(false); CUPnP::PopulateTagFromObject(*pItem->GetMusicInfoTag(), *(*entry), &resource); } else if( (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0 ) { //CPictureInfoTag* tag = pItem->GetPictureInfoTag(); } } } // if there is a thumbnail available set it here if((*entry)->m_ExtraInfo.album_art_uri.GetLength()) pItem->SetThumbnailImage((const char*) (*entry)->m_ExtraInfo.album_art_uri); else if((*entry)->m_Description.icon_uri.GetLength()) pItem->SetThumbnailImage((const char*) (*entry)->m_Description.icon_uri); items.Add(pItem); ++entry; } } cleanup: if (dlgProgress) dlgProgress->Close(); return true; failure: if (dlgProgress) dlgProgress->Close(); return false; }
/*---------------------------------------------------------------------- | PLT_MediaRenderer::PLT_MediaRenderer +---------------------------------------------------------------------*/ PLT_MediaRenderer::PLT_MediaRenderer(PlaybackCmdListener* listener, const char* friendly_name, bool show_ip, const char* uuid, unsigned int port) : PLT_DeviceHost("/", uuid, "urn:schemas-upnp-org:device:MediaRenderer:1", friendly_name, show_ip, port) { NPT_COMPILER_UNUSED(listener); PLT_Service* service; /* AVTransport */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:AVTransport:1", "urn:upnp-org:serviceId:AVT_1-0"); if (NPT_SUCCEEDED(service->SetSCPDXML((const char*) RDR_AVTransportSCPD))) { service->InitURLs("AVTransport", m_UUID); AddService(service); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); // GetCurrentTransportActions service->SetStateVariable("CurrentTransportActions", "", false); // GetDeviceCapabilities service->SetStateVariable("PossiblePlaybackStorageMedia", "vendor-defined ,NOT_IMPLEMENTED,NONE,NETWORK,MICRO-MV,HDD,LD,DAT,DVD-AUDIO,DVD-RAM,DVD-RW,DVD+RW,DVD-R,DVD-VIDEO,DVD-ROM,MD-PICTURE,MD-AUDIO,SACD,VIDEO-CD,CD-RW,CD-R,CD-DA,CD-ROM,HI8,VIDEO8,VHSC,D-VHS,S-VHS,W-VHS,VHS,MINI-DV,DV,UNKNOWN", false); service->SetStateVariable("PossibleRecordStorageMedia", "vendor-defined ,NOT_IMPLEMENTED,NONE,NETWORK,MICRO-MV,HDD,LD,DAT,DVD-AUDIO,DVD-RAM,DVD-RW,DVD+RW,DVD-R,DVD-VIDEO,DVD-ROM,MD-PICTURE,MD-AUDIO,SACD,VIDEO-CD,CD-RW,CD-R,CD-DA,CD-ROM,HI8,VIDEO8,VHSC,D-VHS,S-VHS,W-VHS,VHS,MINI-DV,DV,UNKNOWN", false); service->SetStateVariable("PossibleRecordQualityModes", "vendor-defined ,NOT_IMPLEMENTED,2:HIGH,1:MEDIUM,0:BASIC,2:SP,1:LP,0:EP", false); // GetMediaInfo service->SetStateVariable("PlaybackStorageMedium", "UNKNOWN", false); service->SetStateVariable("RecordStorageMedium", "UNKNOWN", false); service->SetStateVariable("RecordMediumWriteStatus", "UNKNOWN", false); service->SetStateVariable("NumberOfTracks", "0", false); service->SetStateVariable("CurrentTrackDuration", "00:00:00", false); service->SetStateVariable("CurrentMediaDuration", "00:00:00", false); service->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED", false); service->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED", false); // GetPositionInfo service->SetStateVariable("AbsTime", "NOT_IMPLEMENTED", false); service->SetStateVariable("CurrentTrack", "0", false); service->SetStateVariable("RelativeTimePosition", "00:00:00", false); //?? service->SetStateVariable("AbsoluteTimePosition", "NOT_IMPLEMENTED", false); //?? service->SetStateVariable("RelativeCounterPosition", "0", false); //?? service->SetStateVariable("AbsoluteCounterPosition", "0", false); //?? // GetTransportInfo service->SetStateVariable("TransportState", "NO_MEDIA_PRESENT", false); service->SetStateVariable("TransportStatus", "OK", false); service->SetStateVariable("TransportPlaySpeed", "1", false); // GetTransportSettings service->SetStateVariable("CurrentPlayMode", "NORMAL", false); service->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED", false); } /* ConnectionManager */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:CMGR_1-0"); if (NPT_SUCCEEDED(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD))) { service->InitURLs("ConnectionManager", m_UUID); AddService(service); service->SetStateVariable("CurrentConnectionIDs", "0", false); // put all supported mime types here instead service->SetStateVariable("SinkProtocolInfo", "http-get:*:*:*", false); service->SetStateVariable("SourceProtocolInfo", "", false); } /* RenderingControl */ service = new PLT_Service( this, "urn:schemas-upnp-org:service:RenderingControl:1", "urn:upnp-org:serviceId:RCS_1-0"); if (NPT_SUCCEEDED(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD))) { service->InitURLs("RenderingControl", m_UUID); AddService(service); service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f)); } }
/*---------------------------------------------------------------------- | PLT_MediaRenderer::OnPlay +---------------------------------------------------------------------*/ NPT_Result PLT_MediaRenderer::OnPlay(PLT_ActionReference& action) { if (m_Delegate) { return m_Delegate->OnPlay(action); } NPT_String uri, meta; PLT_Service* service; //NPT_Cardinal max_items = 4; //PLT_ThreadTask *task; // look for value set previously by SetAVTransportURI NPT_CHECK_SEVERE(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service)); NPT_CHECK_SEVERE(service->GetStateVariableValue("AVTransportURI", uri)); NPT_CHECK_SEVERE(service->GetStateVariableValue("AVTransportURIMetaData", meta)); { NPT_AutoLock lock(m_state); service->SetStateVariable("TransportState", "TRANSITIONING"); service->SetStateVariable("TransportStatus", "OK"); } // transcoder process takes over here. it shall put the output to the media server's // media folder which can then be served by the media server when the media renderer // requests it via a media controller that is instantiated here to connect(control) // the transport of av between the renderer and the transcoder. //PLT_TaskManager manager(max_items); //manager.StartTask(task,0,true) ; int child_pid; char cmd[200]; char vcodec[] = "copy"; char acodec[] = "copy"; char fext[] = "flv"; //asf char fname[] = "/home/ted/Music/transcoded.flv"; //ffmpeg -i bbb.m4v -vf "movie=aa-logo.png [wm];[in][wm] overlay=10:H-h-10 [out]" -f m4v output.m4v //char* arg_list[] = {"ffmpeg",//"-v",//"0","-i",uri,"-vcodec",vcodec,"-acodec",acodec,//"-b",//"600k",//"-s",//"hd720","-f",fext,"-y",fname,NULL}; char* arg_list[] = { "ffmpeg", //"-v", //"0", "-i", uri, "-vcodec", "libx264", //"-coder", //"0", //"-bf", //"0", //"-flags2", //"fast", //"-wpredp", //"0", "-vpre", "lossless_ultrafast", "-vpre", "baseline", "-crf", "25", "-acodec", "libmp3lame", "-ar", "44100", "-deblockalpha", "0", "-deblockbeta", "0", "-r", "25", "-vb", "2000000", "-vf", "movie=/home/ted/Logo/aa-logo.png[wm];[in][wm]overlay=10:H-h-10[out]", "-f", fext, "-y", fname, NULL }; printf("\n\n****%s****\n\n",arg_list); //int n=sprintf (cmd, "ffmpeg.exe -i %s -vcodec %s -acodec %s -f %s -y %s", uri,vcodec,acodec,fext,fname); //int n=sprintf (cmd, "ffmpeg.exe -i %s -i aa.png -i pv.png -filter_complex 'overlay=10:H-h-10,overlay=W-w-10:H-h-10' -vcodec %s -b:v 200k -acodec %s -f %s -y %s", uri,vcodec,acodec,fext,fname); /* Spawn a child process running the “ls” command. Ignore the returned child process ID. */ /* Duplicate this process. */ child_pid = fork (); if (child_pid != 0){ /* This is the parent process. */ // setup Neptune logging //NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=63"); // Create upnp engine PLT_UPnP upnp; #ifdef SIMULATE_XBOX_360 // override default headers NPT_HttpClient::m_UserAgentHeader = "Xbox/2.0.8955.0 UPnP/1.0 Xbox/2.0.8955.0"; NPT_HttpServer::m_ServerHeader = "Xbox/2.0.8955.0 UPnP/1.0 Xbox/2.0.8955.0"; #endif #ifdef SIMULATE_PS3 // TODO: We need a way to add an extra header to all HTTP requests //X-AV-Client-Info: av=5.0; cn="Sony Computer Entertainment Inc."; mn="PLAYSTATION 3"; mv="1.0"; #endif // Create control point PLT_CtrlPointReference ctrlPoint(new PLT_CtrlPoint()); // Create controller PLT_MicroMediaController controller(ctrlPoint); #ifdef HAS_SERVER // create device PLT_DeviceHostReference server( new PLT_FileMediaServer("/home/ted/Music/", "Embedded Media Server")); server->m_ModelDescription = "Embedded File Media Server"; server->m_ModelURL = "http://www.plutinosoft.com/"; server->m_ModelNumber = "1.0"; server->m_ModelName = "Platinum File Media Server"; server->m_Manufacturer = "Plutinosoft"; server->m_ManufacturerURL = "http://www.plutinosoft.com/"; // add device upnp.AddDevice(server); NPT_String uuid = server->GetUUID(); //printf("****** surver name is: %s\n", uuid); // remove device uuid from ctrlpoint //ctrlPoint->IgnoreUUID(server->GetUUID()); #endif #ifdef HAS_RENDERER //create a device PLT_DeviceHostReference renderer( new PLT_MediaRenderer("Platinum Media Based \C5bo Test Transcoder", false, "e6572b54-f3c7-2d91-2fb5-b757f2537e21")); upnp.AddDevice(renderer); #endif // add control point to upnp engine and start it upnp.AddCtrlPoint(ctrlPoint); upnp.Start(); #ifdef BROADCAST_EXTRA // tell control point to perform extra broadcast discover every 6 secs // in case our device doesn't support multicast ctrlPoint->Discover(NPT_HttpUrl("255.255.255.255", 1900, "*"), "upnp:rootdevice", 1, NPT_TimeInterval(6.0)); ctrlPoint->Discover(NPT_HttpUrl("239.255.255.250", 1900, "*"), "upnp:rootdevice", 1, NPT_TimeInterval(6.0)); #endif #ifdef SIMULATE_XBOX_360 // create device PLT_DeviceHostReference xbox(new PLT_Xbox360("30848576-1775-2000-0000-00125a8fefad")); xbox->SetByeByeFirst(false); xbox->m_SerialNumber = "308485761776"; // add device upnp.AddDevice(xbox); ctrlPoint->IgnoreUUID(xbox->GetUUID()); // xbox issues a search for the content directory service // 10 secs after announcing itself to make sure // it got detected and inspected first ctrlPoint->Search( NPT_HttpUrl("239.255.255.250", 1900, "*"), "urn:schemas-microsoft-com:service:MSContentDirectory:1", 2, 10000, NPT_TimeInterval(10, 0)); ctrlPoint->Search( NPT_HttpUrl("239.255.255.250", 1900, "*"), "urn:schemas-upnp-org:service:ContentDirectory:1", 2, 10000, NPT_TimeInterval(10, 0)); #endif // start to process commands //controller.ProcessCommandLoop(); //upnp.m_Devices // stop everything //upnp.Stop(); //controller.DoEmbeddedServerCheck(); const char embeddedServerName[]="Embedded Media Server"; //PC as a renderer //const char mediaRendererName[]="XBMC: Media Renderer (192.168.11.3)"; //mina laptop //const char mediaRendererName[]="XBMC (ted-HP-2230s)"; //Raspbmc const char mediaRendererName[]="XBMC (raspbmc)"; controller.SetEmbeddedServer(embeddedServerName); controller.SetMediaRenderer(mediaRendererName); sleep(25); controller.HandleCmd_open(); sleep(1); controller.HandleCmd_play(); NPT_AutoLock lock(m_state); service->SetStateVariable("TransportState", "PLAYING"); service->SetStateVariable("TransportStatus", "OK"); service->SetStateVariable("AVTransportURI", uri); service->SetStateVariable("AVTransportURIMetaData", meta); //wait till play finished char buf[256]; while (gets(buf)) { if (*buf == 'q'){ kill( child_pid, SIGKILL ); break; } } // Wait until child process exits. //int child_status; wait(); upnp.Stop(); return NPT_SUCCESS; }else { /* Now execute PROGRAM, searching for it in the path. */ execvp ("ffmpeg", arg_list); /* The execvp function returns only if an error occurs. */ fprintf (stderr, "an error occurred in execvp\n"); abort (); } }