/*---------------------------------------------------------------------- | NPT_DynamicLibrary::Load +---------------------------------------------------------------------*/ NPT_Result NPT_DynamicLibrary::Load(const char* name, NPT_Flags flags, NPT_DynamicLibrary*& library) { NPT_WIN32_USE_CHAR_CONVERSION; NPT_COMPILER_UNUSED(flags); if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS; // default return value library = NULL; // load the lib NPT_LOG_FINE_2("loading library %s, flags=%x", name, flags); HMODULE handle = LoadLibraryW(NPT_WIN32_A2W(name)); if (handle == NULL) { NPT_LOG_FINE("library not found"); return NPT_FAILURE; } // instantiate the object NPT_LOG_FINE_1("library %s loaded", name); library = new NPT_DynamicLibrary(new NPT_Win32DynamicLibrary(handle, name)); return NPT_SUCCESS; }
void Run() { do { // wait for a connection NPT_Socket* client = NULL; NPT_LOG_FINE_1("waiting for connection on port %d...", m_Port); NPT_Result result = m_Socket.WaitForNewClient(client, NPT_TIMEOUT_INFINITE); if (NPT_FAILED(result) || client == NULL) return; NPT_SocketInfo client_info; client->GetInfo(client_info); NPT_LOG_FINE_2("client connected (%s -> %s)", client_info.local_address.ToString().GetChars(), client_info.remote_address.ToString().GetChars()); // get the output stream NPT_OutputStreamReference output; client->GetOutputStream(output); // generate policy based on our current IP NPT_String policy = "<cross-domain-policy>"; policy += "<allow-access-from domain=\""+client_info.local_address.GetIpAddress().ToString()+"\" to-ports=\""+m_AuthorizedPorts+"\"/>"; policy += "<allow-access-from domain=\""+client_info.remote_address.GetIpAddress().ToString()+"\" to-ports=\""+m_AuthorizedPorts+"\"/>"; policy += "</cross-domain-policy>"; NPT_MemoryStream* mem_input = new NPT_MemoryStream(); mem_input->Write(policy.GetChars(), policy.GetLength()); NPT_InputStreamReference input(mem_input); NPT_StreamToStreamCopy(*input, *output); delete client; } while (!m_Aborted); }
/*---------------------------------------------------------------------- | PLT_MediaBrowser::OnDeviceRemoved +---------------------------------------------------------------------*/ NPT_Result PLT_MediaBrowser::OnDeviceRemoved(PLT_DeviceDataReference& device) { if (!device->GetType().StartsWith("urn:schemas-upnp-org:device:MediaServer")) return NPT_FAILURE; { NPT_AutoLock lock(m_MediaServers); // only release if we have kept it around PLT_DeviceDataReference data; NPT_String uuid = device->GetUUID(); // Have we seen that device? if (NPT_FAILED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) { NPT_LOG_WARNING_1("Device (%s) not found in our list!", (const char*)uuid); return NPT_FAILURE; } NPT_LOG_FINE_1("Device Removed: %s", (const char*)*device); m_MediaServers.Remove(device); } if (m_Delegate) { m_Delegate->OnMSRemoved(device); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpHelper::GetDeviceSignature +---------------------------------------------------------------------*/ PLT_DeviceSignature PLT_HttpHelper::GetDeviceSignature(const NPT_HttpRequest& request) { const NPT_String* agent = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_USER_AGENT); const NPT_String* hdr = request.GetHeaders().GetHeaderValue("X-AV-Client-Info"); const NPT_String* server = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_SERVER); if ((agent && (agent->Find("XBox", 0, true) >= 0 || agent->Find("Xenon", 0, true) >= 0)) || (server && server->Find("Xbox", 0, true) >= 0)) { return PLT_DEVICE_XBOX; } else if (agent && (agent->Find("Windows Media Player", 0, true) >= 0 || agent->Find("Windows-Media-Player", 0, true) >= 0 || agent->Find("Mozilla/4.0", 0, true) >= 0 || agent->Find("WMFSDK", 0, true) >= 0)) { return PLT_DEVICE_WMP; } else if (agent && (agent->Find("Sonos", 0, true) >= 0)) { return PLT_DEVICE_SONOS; } else if ((agent && agent->Find("PLAYSTATION 3", 0, true) >= 0) || (hdr && hdr->Find("PLAYSTATION 3", 0, true) >= 0)) { return PLT_DEVICE_PS3; } else if (agent && agent->Find("Windows", 0, true) >= 0) { return PLT_DEVICE_WINDOWS; } else if (agent && (agent->Find("Mac", 0, true) >= 0 || agent->Find("OS X", 0, true) >= 0 || agent->Find("OSX", 0, true) >= 0)) { return PLT_DEVICE_MAC; } else { NPT_LOG_FINE_1("Unknown device signature (ua=%s)", agent?agent->GetChars():"none"); } return PLT_DEVICE_UNKNOWN; }
/*---------------------------------------------------------------------- | PLT_HttpServer::ServeFile +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServer::ServeFile(const NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse& response, NPT_String file_path) { NPT_InputStreamReference stream; NPT_File file(file_path); NPT_FileInfo file_info; // prevent hackers from accessing files outside of our root if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0) || NPT_FAILED(NPT_File::GetInfo(file_path, &file_info))) { return NPT_ERROR_NO_SUCH_ITEM; } // check for range requests const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE); // handle potential 304 only if range header not set NPT_DateTime date; NPT_TimeStamp timestamp; if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetIfModifiedSince((NPT_HttpMessage&)request, date)) && !range_spec) { date.ToTimeStamp(timestamp); NPT_LOG_INFO_5("File %s timestamps: request=%d (%s) vs file=%d (%s)", (const char*)request.GetUrl().GetPath(), (NPT_UInt32)timestamp.ToSeconds(), (const char*)date.ToString(), (NPT_UInt32)file_info.m_ModificationTime, (const char*)NPT_DateTime(file_info.m_ModificationTime).ToString()); if (timestamp >= file_info.m_ModificationTime) { // it's a match NPT_LOG_FINE_1("Returning 304 for %s", request.GetUrl().GetPath().GetChars()); response.SetStatus(304, "Not Modified", NPT_HTTP_PROTOCOL_1_1); return NPT_SUCCESS; } } // open file if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || NPT_FAILED(file.GetInputStream(stream)) || stream.IsNull()) { return NPT_ERROR_NO_SUCH_ITEM; } // set Last-Modified and Cache-Control headers if (file_info.m_ModificationTime) { NPT_DateTime last_modified = NPT_DateTime(file_info.m_ModificationTime); response.GetHeaders().SetHeader("Last-Modified", last_modified.ToString(NPT_DateTime::FORMAT_RFC_1123), true); response.GetHeaders().SetHeader("Cache-Control", "max-age=0,must-revalidate", true); //response.GetHeaders().SetHeader("Cache-Control", "max-age=1800", true); } PLT_HttpRequestContext tmp_context(request, context); return ServeStream(request, context, response, stream, PLT_MimeType::GetMimeType(file_path, &tmp_context)); }
/*---------------------------------------------------------------------- | PLT_EventSubscriber::~PLT_EventSubscriber +---------------------------------------------------------------------*/ PLT_EventSubscriber::~PLT_EventSubscriber() { NPT_LOG_FINE_1("Deleting subscriber (%s)", m_SID.GetChars()); if (m_SubscriberTask) { m_SubscriberTask->Kill(); m_SubscriberTask = NULL; } }
/*---------------------------------------------------------------------- | PLT_MediaBrowser::OnDeviceAdded +---------------------------------------------------------------------*/ NPT_Result PLT_MediaBrowser::OnDeviceAdded(PLT_DeviceDataReference& device) { // verify the device implements the function we need PLT_Service* serviceCDS; PLT_Service* serviceCMR; NPT_String type; if (!device->GetType().StartsWith("urn:schemas-upnp-org:device:MediaServer")) return NPT_FAILURE; type = "urn:schemas-upnp-org:service:ContentDirectory:*"; if (NPT_FAILED(device->FindServiceByType(type, serviceCDS))) { NPT_LOG_WARNING_2("Service %s not found in device \"%s\"", type.GetChars(), device->GetFriendlyName().GetChars()); return NPT_FAILURE; } else { // in case it's a newer upnp implementation, force to 1 serviceCDS->ForceVersion(1); } type = "urn:schemas-upnp-org:service:ConnectionManager:*"; if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) { NPT_LOG_WARNING_2("Service %s not found in device \"%s\"", type.GetChars(), device->GetFriendlyName().GetChars()); return NPT_FAILURE; } else { // in case it's a newer upnp implementation, force to 1 serviceCMR->ForceVersion(1); } { NPT_AutoLock lock(m_MediaServers); PLT_DeviceDataReference data; NPT_String uuid = device->GetUUID(); // is it a new device? if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) { NPT_LOG_WARNING_1("Device (%s) is already in our list!", (const char*)uuid); return NPT_FAILURE; } NPT_LOG_FINE_1("Device Found: %s", (const char*)*device); m_MediaServers.Add(device); } if (m_Delegate && m_Delegate->OnMSAdded(device)) { m_CtrlPoint->Subscribe(serviceCDS); m_CtrlPoint->Subscribe(serviceCMR); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_Win32DynamicLibrary::Unload +---------------------------------------------------------------------*/ NPT_Result NPT_Win32DynamicLibrary::Unload() { NPT_LOG_FINE_1("unloading library %s", (const char*)m_Name); BOOL result = FreeLibrary(m_Library); if (result) { return NPT_SUCCESS; } else { return NPT_FAILURE; } }
/*---------------------------------------------------------------------- | PLT_MediaBrowser::FindServer +---------------------------------------------------------------------*/ NPT_Result PLT_MediaBrowser::FindServer(const char* uuid, PLT_DeviceDataReference& device) { NPT_AutoLock lock(m_MediaServers); if (NPT_FAILED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), device))) { NPT_LOG_FINE_1("Device (%s) not found in our list of servers", (const char*)uuid); return NPT_FAILURE; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaController::FindActionDesc +---------------------------------------------------------------------*/ NPT_Result PLT_MediaController::FindActionDesc(PLT_DeviceDataReference& device, const char* service_type, const char* action_name, PLT_ActionDesc*& action_desc) { // look for the service PLT_Service* service; if (NPT_FAILED(device->FindServiceByType(service_type, service))) { NPT_LOG_FINE_1("Service %s not found", (const char*)service_type); return NPT_FAILURE; } action_desc = service->FindActionDesc(action_name); if (action_desc == NULL) { NPT_LOG_FINE_1("Action %s not found in service", action_name); return NPT_FAILURE; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaController::OnDeviceAdded +---------------------------------------------------------------------*/ NPT_Result PLT_MediaController::OnDeviceAdded(PLT_DeviceDataReference& device) { PLT_DeviceDataReference data; NPT_String uuid = device->GetUUID(); // is it a new device? if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), data))) { NPT_LOG_FINE_1("Device (%s) is already in our list!", (const char*)uuid); return NPT_FAILURE; } NPT_LOG_FINE("Device Found:"); device->ToLog(NPT_LOG_LEVEL_FINE); // verify the device implements the function we need PLT_Service* serviceAVT; PLT_Service* serviceCMR; NPT_String type; type = "urn:schemas-upnp-org:service:AVTransport:1"; if (NPT_FAILED(device->FindServiceByType(type, serviceAVT))) { NPT_LOG_FINE_1("Service %s not found", (const char*)type); return NPT_FAILURE; } type = "urn:schemas-upnp-org:service:ConnectionManager:1"; if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) { NPT_LOG_FINE_1("Service %s not found", (const char*)type); return NPT_FAILURE; } m_MediaRenderers.Add(device); if (m_Listener) { m_Listener->OnMRAddedRemoved(device, 1); } // subscribe to AVT eventing m_CtrlPoint->Subscribe(serviceAVT); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_EventSubscriber::PLT_EventSubscriber +---------------------------------------------------------------------*/ PLT_EventSubscriber::PLT_EventSubscriber(PLT_TaskManager* task_manager, PLT_Service* service, const char* sid, NPT_Timeout timeout_secs /* = -1 */) : m_TaskManager(task_manager), m_Service(service), m_EventKey(0), m_SubscriberTask(NULL), m_SID(sid) { NPT_LOG_FINE_1("Creating new subscriber (%s)", m_SID.GetChars()); SetTimeout(timeout_secs); }
/*---------------------------------------------------------------------- | NPT_Win32DynamicLibrary::FindSymbol +---------------------------------------------------------------------*/ NPT_Result NPT_Win32DynamicLibrary::FindSymbol(const char* name, void*& symbol) { if (name == NULL) return NPT_ERROR_INVALID_PARAMETERS; symbol = NULL; if (m_Library == NULL) return NPT_ERROR_NO_SUCH_ITEM; NPT_LOG_FINE_1("finding symbol %s", name); #if defined(_WIN32_WCE) NPT_WIN32_USE_CHAR_CONVERSION; symbol = GetProcAddress(m_Library, NPT_WIN32_A2W(name)); #else symbol = GetProcAddress(m_Library, name); #endif return symbol?NPT_SUCCESS:NPT_ERROR_NO_SUCH_ITEM; }
/*---------------------------------------------------------------------- | PLT_InputDatagramStream::Read +---------------------------------------------------------------------*/ NPT_Result PLT_InputDatagramStream::Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read /*= 0*/) { NPT_Result res = NPT_SUCCESS; if (bytes_read) *bytes_read = 0; // always try to read from socket if needed even if bytes_to_read is 0 if (m_Buffer.GetDataSize() == 0) { // read data into it now NPT_SocketAddress addr; res = m_Socket->Receive(m_Buffer, &addr); // update info m_Socket->GetInfo(m_Info); m_Info.remote_address = addr; NPT_LOG_FINE_1("PLT_InputDatagramStream received %d", m_Buffer.GetDataSize()); } if (bytes_to_read == 0) return res; if (NPT_SUCCEEDED(res)) { NPT_Size available = m_Buffer.GetDataSize()-(NPT_Size)m_BufferOffset; NPT_Size _bytes_to_read = bytes_to_read<available?bytes_to_read:available; NPT_CopyMemory(buffer, m_Buffer.UseData()+m_BufferOffset, _bytes_to_read); m_BufferOffset += _bytes_to_read; if (bytes_read) *bytes_read = _bytes_to_read; // read buffer entirety, reset for next time if (m_BufferOffset == m_Buffer.GetDataSize()) { m_BufferOffset = 0; m_Buffer.SetDataSize(0); } NPT_LOG_FINE_3("PLT_InputDatagramStream requested %d, consumed %d, left %d", bytes_to_read, _bytes_to_read, m_Buffer.GetDataSize()); } return res; }
/*---------------------------------------------------------------------- | PLT_MediaServer::OnBrowse +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::OnBrowse(PLT_ActionReference& action, const NPT_HttpRequestContext& context) { NPT_Result res; NPT_String object_id; if (NPT_FAILED(action->GetArgumentValue("ObjectId", object_id))) { NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - invalid arguments."); return NPT_FAILURE; } NPT_LOG_FINE_1("PLT_FileMediaServer::OnOnBrowse - id = %s\r\n", (const char*)object_id); // extract server uuid and server object id from our object id NPT_String server_uuid; NPT_String server_object_id; if (NPT_FAILED(SplitObjectId(object_id, server_uuid, server_object_id))) { /* error */ NPT_LOG_WARNING("CMediaCrawler::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } // root ? if (server_uuid.GetLength() == 0) { res = OnBrowseRoot(action); } else { // we have a device to browse // is it device root? if (server_object_id.GetLength() == 0) { server_object_id = "0"; } res = OnBrowseDevice(action, server_uuid, server_object_id, context); } if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) { action->SetError(800, "Internal error"); } return res; }
/*---------------------------------------------------------------------- | PLT_MediaController::OnDeviceRemoved +---------------------------------------------------------------------*/ NPT_Result PLT_MediaController::OnDeviceRemoved(PLT_DeviceDataReference& device) { // only release if we have kept it around PLT_DeviceDataReference data; NPT_String uuid = device->GetUUID(); // is it a new device? if (NPT_FAILED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), data))) { NPT_LOG_FINE_1("Device (%s) not found in our list!", (const char*)uuid); return NPT_FAILURE; } NPT_LOG_FINE("Device Removed:"); device->ToLog(NPT_LOG_LEVEL_FINE); m_MediaRenderers.Remove(device); if (m_Listener) { m_Listener->OnMRAddedRemoved(device, 0); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpServerSocketTask::SendResponseBody +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServerSocketTask::SendResponseBody(NPT_HttpResponse* response, NPT_OutputStream& output_stream) { NPT_HttpEntity* entity = response->GetEntity(); if (!entity) return NPT_SUCCESS; NPT_InputStreamReference body_stream; entity->GetInputStream(body_stream); if (body_stream.IsNull()) return NPT_SUCCESS; // check for chunked transfer encoding NPT_OutputStream* dest = &output_stream; if (entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) { dest = new NPT_HttpChunkedOutputStream(output_stream); } // send body NPT_LOG_FINE_1("sending body stream, %lld bytes", entity->GetContentLength()); NPT_LargeSize bytes_written = 0; NPT_Result result = NPT_StreamToStreamCopy(*body_stream, *dest, 0, entity->GetContentLength(), &bytes_written); /* passing 0 if content length is unknown will read until nothing is left */ if (NPT_FAILED(result)) { NPT_LOG_FINE_3("body stream only partially sent, %lld bytes (%d:%s)", bytes_written, result, NPT_ResultText(result)); } // flush to write out any buffered data left in chunked output if used dest->Flush(); // cleanup (this will send zero size chunk followed by CRLF) if (dest != &output_stream) delete dest; return result; }
/*---------------------------------------------------------------------- | PLT_MediaController::OnActionResponse +---------------------------------------------------------------------*/ NPT_Result PLT_MediaController::OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata) { if (m_Listener == NULL) { return NPT_SUCCESS; } /* make sure device is a renderer we've previously found */ PLT_DeviceDataReference device; NPT_String uuid = action->GetActionDesc()->GetService()->GetDevice()->GetUUID(); if (NPT_FAILED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), device))) { NPT_LOG_FINE_1("Device (%s) not found in our list of renderers", (const char*)uuid); res = NPT_FAILURE; } /* extract action name */ NPT_String actionName = action->GetActionDesc()->GetName(); /* AVTransport response ? */ if (actionName.Compare("GetCurrentTransportActions", true) == 0) { return OnGetCurrentTransportActionsResponse(res, device, action, userdata); } else if (actionName.Compare("GetDeviceCapabilities", true) == 0) { return OnGetDeviceCapabilitiesResponse(res, device, action, userdata); } else if (actionName.Compare("GetMediaInfo", true) == 0) { return OnGetMediaInfoResponse(res, device, action, userdata); } else if (actionName.Compare("GetPositionInfo", true) == 0) { return OnGetPositionInfoResponse(res, device, action, userdata); } else if (actionName.Compare("GetTransportInfo", true) == 0) { return OnGetTransportInfoResponse(res, device, action, userdata); } else if (actionName.Compare("GetTransportSettings", true) == 0) { return OnGetTransportSettingsResponse(res, device, action, userdata); } else if (actionName.Compare("Next", true) == 0) { m_Listener->OnNextResult(res, device, userdata); } else if (actionName.Compare("Pause", true) == 0) { m_Listener->OnPauseResult(res, device, userdata); } else if (actionName.Compare("Play", true) == 0) { m_Listener->OnPlayResult(res, device, userdata); } else if (actionName.Compare("Previous", true) == 0) { m_Listener->OnPreviousResult(res, device, userdata); } else if (actionName.Compare("Seek", true) == 0) { m_Listener->OnSeekResult(res, device, userdata); } else if (actionName.Compare("SetAVTransportURI", true) == 0) { m_Listener->OnSetAVTransportURIResult(res, device, userdata); } else if (actionName.Compare("SetPlayMode", true) == 0) { m_Listener->OnSetPlayModeResult(res, device, userdata); } else if (actionName.Compare("Stop", true) == 0) { m_Listener->OnStopResult(res, device, userdata); } else if (actionName.Compare("GetCurrentConnectionIDs", true) == 0) { return OnGetCurrentConnectionIDsResponse(res, device, action, userdata); } else if (actionName.Compare("GetCurrentConnectionInfo", true) == 0) { return OnGetCurrentConnectionInfoResponse(res, device, action, userdata); } else if (actionName.Compare("GetProtocolInfo", true) == 0) { return OnGetProtocolInfoResponse(res, device, action, userdata); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | BtPlayerServer::SendStatus +---------------------------------------------------------------------*/ NPT_Result BtPlayerServer::SendStatus(NPT_HttpResponse& response, NPT_UrlQuery& query) { NPT_String json; // json start const char* json_callback = query.GetField("callback"); if (json_callback) { json += NPT_UrlQuery::UrlDecode(json_callback)+'('; } json += '{'; // state json += "\"state\": "; switch (m_DecoderState) { case BLT_DecoderServer::STATE_STOPPED: json += "\"STOPPED\""; break; case BLT_DecoderServer::STATE_PLAYING: json += "\"PLAYING\""; break; case BLT_DecoderServer::STATE_PAUSED: json += "\"PAUSED\""; break; case BLT_DecoderServer::STATE_EOS: json += "\"END OF STREAM\""; break; default: json += "\"UNKNOWN\""; break; } json += ','; // timecode json += NPT_String::Format("\"timecode\": \"%02d:%02d:%02d\", ", m_DecoderTimecode.h, m_DecoderTimecode.m, m_DecoderTimecode.s); // position json += NPT_String::Format("\"position\": %f, ", m_DecoderPosition); // stream info json += "\"streamInfo\": {"; if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_NOMINAL_BITRATE) { json += NPT_String::Format("\"nominalBitrate\": %d, ", m_StreamInfo.nominal_bitrate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_AVERAGE_BITRATE) { json += NPT_String::Format("\"averageBitrate\": %d, ", m_StreamInfo.average_bitrate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_INSTANT_BITRATE) { json += NPT_String::Format("\"instantBitrate\": %d, ", m_StreamInfo.instant_bitrate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_SIZE) { json += NPT_String::Format("\"size\": %d, ", m_StreamInfo.size); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_DURATION) { unsigned int seconds = m_StreamInfo.duration/1000; json += NPT_String::Format("\"duration\": \"%02d:%02d:%02d\", ", (seconds)/36000, (seconds%3600)/60, (seconds%60)); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_SAMPLE_RATE) { json += NPT_String::Format("\"sampleRate\": %d, ", m_StreamInfo.sample_rate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_CHANNEL_COUNT) { json += NPT_String::Format("\"channelCount\": %d, ", m_StreamInfo.channel_count); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_DATA_TYPE) { json += NPT_String::Format("\"dataType\": \"%s\", ", m_StreamInfo.data_type); } json += "},"; // stream properties // json end json += '}'; if (json_callback) { json += ')'; } // send the html document NPT_HttpEntity* entity = response.GetEntity(); entity->SetContentType("application/json"); entity->SetInputStream(json); NPT_LOG_FINE_1("status: %s", json.GetChars()); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaController::OnDeviceAdded +---------------------------------------------------------------------*/ NPT_Result PLT_MediaController::OnDeviceAdded(PLT_DeviceDataReference& device) { // verify the device implements the function we need PLT_Service* serviceAVT = NULL; PLT_Service* serviceCMR; PLT_Service* serviceRC; NPT_String type; if (!device->GetType().StartsWith("urn:schemas-upnp-org:device:MediaRenderer")) return NPT_FAILURE; // optional service type = "urn:schemas-upnp-org:service:AVTransport:*"; if (NPT_SUCCEEDED(device->FindServiceByType(type, serviceAVT))) { // in case it's a newer upnp implementation, force to 1 NPT_LOG_FINE_1("Service %s found", (const char*)type); serviceAVT->ForceVersion(1); } // required services type = "urn:schemas-upnp-org:service:ConnectionManager:*"; if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) { NPT_LOG_FINE_1("Service %s not found", (const char*)type); return NPT_FAILURE; } else { // in case it's a newer upnp implementation, force to 1 serviceCMR->ForceVersion(1); } type = "urn:schemas-upnp-org:service:RenderingControl:*"; if (NPT_FAILED(device->FindServiceByType(type, serviceRC))) { NPT_LOG_FINE_1("Service %s not found", (const char*)type); return NPT_FAILURE; } else { // in case it's a newer upnp implementation, force to 1 serviceRC->ForceVersion(1); } { NPT_AutoLock lock(m_MediaRenderers); PLT_DeviceDataReference data; NPT_String uuid = device->GetUUID(); // is it a new device? if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaRenderers, PLT_DeviceDataFinder(uuid), data))) { NPT_LOG_WARNING_1("Device (%s) is already in our list!", (const char*)uuid); return NPT_FAILURE; } NPT_LOG_FINE_1("Device Found: %s", (const char*)*device); m_MediaRenderers.Add(device); } if (m_Delegate && m_Delegate->OnMRAdded(device)) { // subscribe to services eventing only if delegate wants it if (serviceAVT) m_CtrlPoint->Subscribe(serviceAVT); // subscribe to required services m_CtrlPoint->Subscribe(serviceCMR); m_CtrlPoint->Subscribe(serviceRC); } return NPT_SUCCESS; }