diff --git a/Build/Boot.scons b/Build/Boot.scons index 9b15737d..e83d54ba 100644 --- a/Build/Boot.scons +++ b/Build/Boot.scons @@ -1,6 +1,7 @@ import sys import os import platform +import re EnsureSConsVersion(0,98,1) @@ -16,7 +17,8 @@ PLATFORM_TO_TARGET_MAP = { 'linux2' : 'x86-unknown-linux', 'win32' : 'x86-microsoft-win32', 'cygwin' : 'x86-unknown-cygwin', - 'darwin' : 'universal-apple-macosx' + 'darwin' : 'universal-apple-macosx', + 'raspberry-pi-arm' : 'arm-raspberry-pi-linux' } # list all target dirs @@ -25,20 +27,53 @@ targets_dir = scons_root+'/Build/Targets' targets_dirs = os.listdir(targets_dir) TARGET_PLATFORMS = [x for x in targets_dirs if os.path.exists(targets_dir +'/'+x+'/Config.scons')] +def pi_version(): + """Detect the version of the Raspberry Pi. Returns either 1, 2 or + None depending on if it's a Raspberry Pi 1 (model A, B, A+, B+), + Raspberry Pi 2 (model B+), or not a Raspberry Pi. + """ + # Check /proc/cpuinfo for the Hardware field value. + # 2708 is pi 1 + # 2709 is pi 2 + # 2835 is pi 3 on 4.9.x kernel + # Anything else is not a pi. + with open('/proc/cpuinfo', 'r') as infile: + cpuinfo = infile.read() + # Match a line like 'Hardware : BCM2709' + match = re.search('^Hardware\s+:\s+(\w+)$', cpuinfo, + flags=re.MULTILINE | re.IGNORECASE) + if not match: + # Couldn't find the hardware, assume it isn't a pi. + return None + if match.group(1) == 'BCM2708': + # Pi 1 + return 1 + elif match.group(1) == 'BCM2709': + # Pi 2 + return 2 + elif match.group(1) == 'BCM2835': + # Pi 3 / Pi on 4.9.x kernel + return 3 + else: + # Something else, not a pi. + return None + def DefaultTarget(): platform_id = sys.platform if platform.system() == 'Linux': - if (platform.machine() == 'i386' or + if pi_version() is not None: + platform_id = 'raspberry-pi-arm' + elif (platform.machine() == 'i386' or platform.machine() == 'i486' or platform.machine() == 'i586'or platform.machine() == 'i686'): platform_id = 'linux-i386' - if (platform.machine() == 'x86_64'): + elif (platform.machine() == 'x86_64'): platform_id = 'linux-x86_64' - if (platform.machine().startswith('arm')): + elif (platform.machine().startswith('arm')): platform_id = 'linux-arm' - if PLATFORM_TO_TARGET_MAP.has_key(platform_id): + if platform_id in PLATFORM_TO_TARGET_MAP: return PLATFORM_TO_TARGET_MAP[platform_id] else: return None @@ -67,5 +102,5 @@ base_env = env for build_config in env['build_config']: env = base_env.Clone() env['build_config'] = build_config - print '********** Configuring Build Target =', env['target'], '/', build_config, '********' + print ('********** Configuring Build Target =', env['target'], '/', build_config, '********') SConscript('Build.scons', variant_dir='Targets/'+env['target']+'/'+build_config, exports='env', duplicate=0) diff --git a/Build/Build.scons b/Build/Build.scons index ab9a95d3..92726be9 100644 --- a/Build/Build.scons +++ b/Build/Build.scons @@ -35,7 +35,7 @@ def DeclareBuildDir(dir): def GetIncludeDirs(modules, exclude=None): dirs = [] for module in Split(modules): - if Modules.has_key(module) and not module == exclude: + if module in Modules and not module == exclude: dirs += Modules[module].GetIncludeDirs() else: dirs += [GetDirPath(module)] @@ -44,7 +44,7 @@ def GetIncludeDirs(modules, exclude=None): def GetLibraries(modules): libs = [] for module in Split(modules): - if Modules.has_key(module): + if module in Modules: libs += Modules[module].GetLibraries() else: libs += [module] @@ -114,6 +114,7 @@ class LibraryModule(Module): # the product is a library self.env.AppendUnique(CPPPATH=cpp_path) + self.env.AppendUnique(CCFLAGS='-fPIC') if shared is False: self.product = self.env.Library(target=name, source=sources) else: @@ -145,6 +146,42 @@ def Application(name, dir, deps, install = False): if env['build_config'] == 'Release' and env.has_key('STRIP'): env.AddPostAction(inst, env['STRIP']+' $TARGETS'); +def Swig(name, dir, deps): + DeclareBuildDir(dir) + cpp_path = GetIncludeDirs(deps) + + inc = '-I' + ' -I'.join([env.GetBuildPath(x) for x in cpp_path]) + + def generator(source, target, env, for_signature): + return 'swig -python -py3 -threads -c++ {} -o {} {}'.format(inc, target[0], source[0]) + + bld = Builder(generator = generator) + env.Append(BUILDERS={'Swig' : bld}) + + return env.Swig([name + '_wrap.cxx', name + '_wrap.h', name + '.py'], GlobSources(dir, ['*.i'])) + +def PythonBinding(name, dir, deps): + swig_out = Swig(name, dir, deps) + + DeclareBuildDir(dir) + cpp_path = GetIncludeDirs(deps) + [GetDirPath(dir)] + libs = GetLibraries(deps) + + # the product is a library + env_ = env.Clone() + env_.AppendUnique(CPPPATH=cpp_path, LIBS=libs) + env_.ParseConfig('pkg-config python3 --cflags --libs') + product = env_.SharedLibrary(target=name, + source=GlobSources(dir, ['*.cxx']) + [swig_out[0]], + SHLIBSUFFIX='.so', SHLIBPREFIX='_') + env_.Alias(name, product) + + # copy to Targets folder + inst = env.Install(dir=env.GetBuildPath('#/Targets/'+env['target']+'/'+env['build_config']), source=product) + if env['build_config'] == 'Release' and env.has_key('STRIP'): + env.AddPostAction(inst, env['STRIP']+' $TARGETS'); + + env.Install(dir=env.GetBuildPath('#/Targets/'+env['target']+'/'+env['build_config']), source=swig_out[2]) ####################################################### # Main Build ####################################################### @@ -163,7 +200,8 @@ else: target_config_file = env.GetBuildPath('#/Build/Targets/'+env['target']+'/Config.scons') if os.path.exists(target_config_file): # Load the target-specific config file - execfile(target_config_file) + with open(target_config_file) as f: + exec(f.read()) ####################################################### # modules @@ -273,3 +311,7 @@ for tool in ['TextToHeader']: dir = 'Source/Tools/' + tool, deps = ['Platinum'], install = True) + +PythonBinding(name = 'media_renderer', + dir = 'binding/python', + deps = ['Platinum', 'PltMediaRenderer']) diff --git a/Build/Targets/arm-raspberry-pi-linux/Config.scons b/Build/Targets/arm-raspberry-pi-linux/Config.scons new file mode 100644 index 00000000..b6fdd140 --- /dev/null +++ b/Build/Targets/arm-raspberry-pi-linux/Config.scons @@ -0,0 +1,7 @@ +LoadTool('gcc-generic', env, gcc_cross_prefix='') + +### Neptune System Files +env['NPT_SYSTEM_SOURCES']={'System/StdC':'*.cpp', 'System/Bsd':'*.cpp', 'System/Posix':'*.cpp', 'System/Null':'NptNullAutoreleasePool.cpp'} +env['NPT_EXTRA_LIBS']=['pthread'] + +env['STRIP'] = '' diff --git a/Build/Targets/universal-apple-macosx/Config.scons b/Build/Targets/universal-apple-macosx/Config.scons new file mode 100644 index 00000000..a8824bc6 --- /dev/null +++ b/Build/Targets/universal-apple-macosx/Config.scons @@ -0,0 +1,5 @@ +LoadTool('gcc-generic', env) + +### Neptune System Files +env['NPT_SYSTEM_SOURCES']={'System/StdC':'*.cpp', 'System/Bsd':'*.cpp', 'System/Posix':'*.cpp', 'System/Null':'NptNullAutoreleasePool.cpp NptNullSerialPort.cpp'} +env['NPT_EXTRA_LIBS']=['pthread'] diff --git a/Build/Targets/x86_64-unknown-linux/Config.scons b/Build/Targets/x86_64-unknown-linux/Config.scons new file mode 100644 index 00000000..a8824bc6 --- /dev/null +++ b/Build/Targets/x86_64-unknown-linux/Config.scons @@ -0,0 +1,5 @@ +LoadTool('gcc-generic', env) + +### Neptune System Files +env['NPT_SYSTEM_SOURCES']={'System/StdC':'*.cpp', 'System/Bsd':'*.cpp', 'System/Posix':'*.cpp', 'System/Null':'NptNullAutoreleasePool.cpp NptNullSerialPort.cpp'} +env['NPT_EXTRA_LIBS']=['pthread'] diff --git a/Source/Apps/FrameStreamer/main.cpp b/Source/Apps/FrameStreamer/main.cpp index d0d77e16..ef6f327b 100644 --- a/Source/Apps/FrameStreamer/main.cpp +++ b/Source/Apps/FrameStreamer/main.cpp @@ -11,14 +11,14 @@ | as published by the Free Software Foundation; either version 2 | of the License, or (at your option) any later version. | -| OEMs, ISVs, VARs and other distributors that combine and +| OEMs, ISVs, VARs and other distributors that combine and | distribute commercially licensed software with Platinum software | and do not wish to distribute the source code for the commercially | licensed software under version 2, or (at your option) any later | version, of the GNU General Public License (the "GPL") must enter | into a commercial license agreement with Plutinosoft, LLC. | licensing@plutinosoft.com -| +| | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -26,7 +26,7 @@ | | You should have received a copy of the GNU General Public License | along with this program; see the file LICENSE.txt. If not, write to -| the Free Software Foundation, Inc., +| the Free Software Foundation, Inc., | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | http://www.gnu.org/licenses/gpl-2.0.html | @@ -59,11 +59,11 @@ class StreamValidator : public PLT_StreamValidator public: StreamValidator(NPT_Reference& buffer) : m_Buffer(buffer) {} virtual ~StreamValidator() {} - + // PLT_StreamValidator methods - bool OnNewRequestAccept(const NPT_HttpRequest& request, + bool OnNewRequestAccept(const NPT_HttpRequest& request, const NPT_HttpRequestContext& context, - NPT_HttpResponse& response, + NPT_HttpResponse& response, NPT_Reference& buffer) { NPT_COMPILER_UNUSED(request); NPT_COMPILER_UNUSED(response); @@ -72,7 +72,7 @@ class StreamValidator : public PLT_StreamValidator buffer = m_Buffer; return true; } - + NPT_Reference m_Buffer; }; @@ -83,7 +83,7 @@ class FrameWriter : public NPT_Thread { public: FrameWriter(NPT_Reference& frame_buffer, - const char* frame_folder) : + const char* frame_folder) : m_FrameBuffer(frame_buffer), m_Aborted(false), m_Folder(frame_folder) @@ -104,12 +104,12 @@ class FrameWriter : public NPT_Thread const char* frame_path = NULL; NPT_DataBuffer frame; NPT_List::Iterator entry; - + while (!m_Aborted) { // has number of images changed since last time? NPT_LargeSize count; NPT_File::GetSize(m_Folder, count); - + if (entries.GetItemCount() == 0 || entries.GetItemCount() != count) { NPT_File::ListDir(m_Folder, entries); entry = entries.GetFirstItem(); @@ -118,18 +118,18 @@ class FrameWriter : public NPT_Thread NPT_System::Sleep(NPT_TimeInterval(0.2f)); continue; } - + // set delay based on number of files if necessary m_Delay = NPT_TimeInterval((float)1.f/entries.GetItemCount()); } - + // look for path to next image if (!(frame_path = GetPath(entry))) { // loop back if necessary entry = entries.GetFirstItem(); continue; } - + if (NPT_FAILED(NPT_File::Load(NPT_FilePath::Create(m_Folder, frame_path), frame))) { NPT_LOG_SEVERE_1("Image \"%s\" not found!", frame_path?frame_path:"none"); // clear previously loaded names so we reload entire set @@ -137,7 +137,7 @@ class FrameWriter : public NPT_Thread continue; } - if (NPT_FAILED(m_FrameBuffer->SetNextFrame(frame.GetData(), + if (NPT_FAILED(m_FrameBuffer->SetNextFrame(frame.GetData(), frame.GetDataSize()))) { NPT_LOG_SEVERE_1("Failed to set next frame %s", frame_path); goto failure; @@ -183,7 +183,7 @@ ParseCommandLine(char** args) /* default values */ Options.path = NULL; - + while ((arg = *args++)) { if (Options.path == NULL) { Options.path = arg; @@ -207,13 +207,13 @@ int main(int argc, char** argv) { NPT_COMPILER_UNUSED(argc); - + /* parse command line */ ParseCommandLine(argv); - - // frame buffer + + // frame buffer NPT_Reference frame_buffer(new PLT_FrameBuffer("image/jpeg")); - + // A Framewriter reading images from a folder and writing them // into frame buffer in a loop FrameWriter writer(frame_buffer, Options.path); @@ -221,10 +221,10 @@ main(int argc, char** argv) // stream request validation StreamValidator validator(frame_buffer); - - // frame server receiving requests and serving frames + + // frame server receiving requests and serving frames // read from frame buffer - NPT_Reference device( + NPT_Reference device( new PLT_FrameServer( "frame", validator, @@ -235,7 +235,7 @@ main(int argc, char** argv) return 1; char buf[256]; - while (true) { + while (true) { fgets(buf, 256, stdin); if (*buf == 'q') break; diff --git a/Source/Apps/MediaConnect/main.cpp b/Source/Apps/MediaConnect/main.cpp index b9777e8b..d9b8bd15 100644 --- a/Source/Apps/MediaConnect/main.cpp +++ b/Source/Apps/MediaConnect/main.cpp @@ -11,14 +11,14 @@ | as published by the Free Software Foundation; either version 2 | of the License, or (at your option) any later version. | -| OEMs, ISVs, VARs and other distributors that combine and +| OEMs, ISVs, VARs and other distributors that combine and | distribute commercially licensed software with Platinum software | and do not wish to distribute the source code for the commercially | licensed software under version 2, or (at your option) any later | version, of the GNU General Public License (the "GPL") must enter | into a commercial license agreement with Plutinosoft, LLC. | licensing@plutinosoft.com -| +| | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -26,7 +26,7 @@ | | You should have received a copy of the GNU General Public License | along with this program; see the file LICENSE.txt. If not, write to -| the Free Software Foundation, Inc., +| the Free Software Foundation, Inc., | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | http://www.gnu.org/licenses/gpl-2.0.html | @@ -70,7 +70,7 @@ ParseCommandLine(char** args) /* default values */ Options.path = NULL; - + while ((arg = *args++)) { if (Options.path == NULL) { Options.path = arg; @@ -95,22 +95,22 @@ main(int argc, char** argv) { // setup Neptune logging NPT_LogManager::GetDefault().Configure("plist:.level=FINE;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=63"); - + NPT_COMPILER_UNUSED(argc); - + // parse command line ParseCommandLine(argv); - + // setup device PLT_MediaConnect* connect( new PLT_MediaConnect("Platinum")); connect->SetByeByeFirst(false); - + // setup delegate - NPT_Reference delegate( + NPT_Reference delegate( new PLT_FileMediaConnectDelegate("/", Options.path)); connect->SetDelegate((PLT_MediaServerDelegate*)delegate.AsPointer()); - + PLT_UPnP upnp; PLT_DeviceHostReference device(connect); upnp.AddDevice(device); diff --git a/Source/Apps/MediaCrawler/main.cpp b/Source/Apps/MediaCrawler/main.cpp index cb57f613..66c4af42 100644 --- a/Source/Apps/MediaCrawler/main.cpp +++ b/Source/Apps/MediaCrawler/main.cpp @@ -11,14 +11,14 @@ | as published by the Free Software Foundation; either version 2 | of the License, or (at your option) any later version. | -| OEMs, ISVs, VARs and other distributors that combine and +| OEMs, ISVs, VARs and other distributors that combine and | distribute commercially licensed software with Platinum software | and do not wish to distribute the source code for the commercially | licensed software under version 2, or (at your option) any later | version, of the GNU General Public License (the "GPL") must enter | into a commercial license agreement with Plutinosoft, LLC. | licensing@plutinosoft.com -| +| | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -26,7 +26,7 @@ | | You should have received a copy of the GNU General Public License | along with this program; see the file LICENSE.txt. If not, write to -| the Free Software Foundation, Inc., +| the Free Software Foundation, Inc., | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | http://www.gnu.org/licenses/gpl-2.0.html | @@ -53,21 +53,21 @@ int main(void) PLT_CtrlPointReference ctrlPoint(new PLT_CtrlPoint()); upnp.AddCtrlPoint(ctrlPoint); - CMediaCrawler* crawler = - new CMediaCrawler(ctrlPoint, + CMediaCrawler* crawler = + new CMediaCrawler(ctrlPoint, "Sylvain: Platinum: Crawler"); - CPassThroughStreamHandler* handler = + CPassThroughStreamHandler* handler = new CPassThroughStreamHandler(crawler); crawler->AddStreamHandler(handler); PLT_DeviceHostReference device(crawler); upnp.AddDevice(device); - + // make sure we ignore ourselves ctrlPoint->IgnoreUUID(device->GetUUID()); upnp.Start(); - // extra broadcast discover + // extra broadcast discover ctrlPoint->Discover(NPT_HttpUrl("255.255.255.255", 1900, "*"), "upnp:rootdevice", 1); char buf[256]; diff --git a/Source/Tests/FileMediaServer/FileMediaServerTest.cpp b/Source/Tests/FileMediaServer/FileMediaServerTest.cpp index 3aca9704..893da737 100644 --- a/Source/Tests/FileMediaServer/FileMediaServerTest.cpp +++ b/Source/Tests/FileMediaServer/FileMediaServerTest.cpp @@ -12,14 +12,14 @@ | as published by the Free Software Foundation; either version 2 | of the License, or (at your option) any later version. | -| OEMs, ISVs, VARs and other distributors that combine and +| OEMs, ISVs, VARs and other distributors that combine and | distribute commercially licensed software with Platinum software | and do not wish to distribute the source code for the commercially | licensed software under version 2, or (at your option) any later | version, of the GNU General Public License (the "GPL") must enter | into a commercial license agreement with Plutinosoft, LLC. | licensing@plutinosoft.com -| +| | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -27,7 +27,7 @@ | | You should have received a copy of the GNU General Public License | along with this program; see the file LICENSE.txt. If not, write to -| the Free Software Foundation, Inc., +| the Free Software Foundation, Inc., | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | http://www.gnu.org/licenses/gpl-2.0.html | @@ -119,11 +119,11 @@ main(int /* argc */, char** argv) /* for faster DLNA faster testing */ PLT_Constants::GetInstance().SetDefaultDeviceLease(NPT_TimeInterval(60.)); - + PLT_UPnP upnp; PLT_DeviceHostReference device( new PLT_FileMediaServer( - Options.path, + Options.path, Options.friendly_name?Options.friendly_name:"Platinum UPnP Media Server", false, Options.guid, // NULL for random ID diff --git a/Source/Tests/LightSample/LightSampleTest.cpp b/Source/Tests/LightSample/LightSampleTest.cpp index 1ca30109..d7b61916 100644 --- a/Source/Tests/LightSample/LightSampleTest.cpp +++ b/Source/Tests/LightSample/LightSampleTest.cpp @@ -11,14 +11,14 @@ | as published by the Free Software Foundation; either version 2 | of the License, or (at your option) any later version. | -| OEMs, ISVs, VARs and other distributors that combine and +| OEMs, ISVs, VARs and other distributors that combine and | distribute commercially licensed software with Platinum software | and do not wish to distribute the source code for the commercially | licensed software under version 2, or (at your option) any later | version, of the GNU General Public License (the "GPL") must enter | into a commercial license agreement with Plutinosoft, LLC. | licensing@plutinosoft.com -| +| | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -26,7 +26,7 @@ | | You should have received a copy of the GNU General Public License | along with this program; see the file LICENSE.txt. If not, write to -| the Free Software Foundation, Inc., +| the Free Software Foundation, Inc., | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | http://www.gnu.org/licenses/gpl-2.0.html | @@ -56,7 +56,7 @@ main(int /* argc */, char** /* argv */) #ifdef TEST_EMBEDDED_DEVICE PLT_DeviceDataReference device2(new PLT_LightSampleDevice("Platinum Light Bulb embed 1")); device->AddEmbeddedDevice((PLT_DeviceDataReference&)device2); - + PLT_DeviceDataReference device3(new PLT_LightSampleDevice("Platinum Light Bulb embed 2")); device->AddEmbeddedDevice(device3); #endif diff --git a/Source/Tests/MediaRenderer/MediaRendererTest.cpp b/Source/Tests/MediaRenderer/MediaRendererTest.cpp index 2e9d0f5e..29eecd7a 100644 --- a/Source/Tests/MediaRenderer/MediaRendererTest.cpp +++ b/Source/Tests/MediaRenderer/MediaRendererTest.cpp @@ -11,14 +11,14 @@ | as published by the Free Software Foundation; either version 2 | of the License, or (at your option) any later version. | -| OEMs, ISVs, VARs and other distributors that combine and +| OEMs, ISVs, VARs and other distributors that combine and | distribute commercially licensed software with Platinum software | and do not wish to distribute the source code for the commercially | licensed software under version 2, or (at your option) any later | version, of the GNU General Public License (the "GPL") must enter | into a commercial license agreement with Plutinosoft, LLC. | licensing@plutinosoft.com -| +| | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -26,7 +26,7 @@ | | You should have received a copy of the GNU General Public License | along with this program; see the file LICENSE.txt. If not, write to -| the Free Software Foundation, Inc., +| the Free Software Foundation, Inc., | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | http://www.gnu.org/licenses/gpl-2.0.html | @@ -86,7 +86,7 @@ ParseCommandLine(char** args) +---------------------------------------------------------------------*/ int main(int /* argc */, char** argv) -{ +{ PLT_UPnP upnp; /* parse command line */ @@ -104,6 +104,7 @@ main(int /* argc */, char** argv) char buf[256]; while (true) { fgets(buf, 256, stdin); + if (*buf == 'q') break; diff --git a/binding/python/media_renderer.cxx b/binding/python/media_renderer.cxx new file mode 100644 index 00000000..0f05c47e --- /dev/null +++ b/binding/python/media_renderer.cxx @@ -0,0 +1,306 @@ +#include +#include + +#include "PltUPnP.h" +#include "PltMediaRenderer.h" +#include "NptLogging.h" +#include "media_renderer.h" + +NPT_SET_LOCAL_LOGGER("media_render.upnp.renderer") + +namespace media_renderer { +class PLT_MediaRendererDelegateImpl : public PLT_MediaRendererDelegate +{ +public: + PLT_MediaRendererDelegateImpl(PLT_MediaRenderer * renderer, MediaRendererDelegate * delegate) + : m_Delegate(delegate) + , m_Renderer(renderer) { + } + + virtual ~PLT_MediaRendererDelegateImpl() {} + + // ConnectionManager + virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action) { + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentTransportState", curURI); + NPT_String metaData; + action->GetArgumentValue("CurrentURIMetaData", metaData); + + m_Delegate->OnGetCurrentConnectionInfo(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + } + + // AVTransport + virtual NPT_Result OnNext(PLT_ActionReference& action){ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("NextURI", curURI); + NPT_String metaData; + action->GetArgumentValue("NextURIMetaData", metaData); + + m_Delegate->OnNext(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + } + + virtual NPT_Result OnPause(PLT_ActionReference& action){ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentURI", curURI); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + + m_Delegate->OnPause(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + } + + virtual NPT_Result OnPlay(PLT_ActionReference& action){ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentURI", curURI); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + + m_Delegate->OnPlay(curURI.GetChars(), metaData.GetChars()); + + PLT_Service* service; + NPT_CHECK_SEVERE(m_Renderer->FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service)); + + NPT_CHECK_SEVERE(service->GetStateVariableValue("AVTransportURI", curURI)); + NPT_CHECK_SEVERE(service->GetStateVariableValue("AVTransportURIMetaData", metaData)); + + service->SetStateVariable("TransportState", "PLAYING"); + service->SetStateVariable("TransportStatus", "OK"); + service->SetStateVariable("AVTransportURI", curURI); + service->SetStateVariable("AVTransportURIMetaData", metaData); + + service->SetStateVariable("NextAVTransportURI", ""); + service->SetStateVariable("NextAVTransportURIMetaData", ""); + + NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable()); + return NPT_SUCCESS; + } + + virtual NPT_Result OnPrevious(PLT_ActionReference& action){ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentURI", curURI); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + + m_Delegate->OnPrevious(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + + } + + virtual NPT_Result OnSeek(PLT_ActionReference& action) { + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("Target", curURI); + NPT_String metaData; + action->GetArgumentValue("Unit", metaData); + + m_Delegate->OnSeek(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + } + + virtual NPT_Result OnStop(PLT_ActionReference& action) { + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentURI", curURI); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + m_Delegate->OnStop(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + } + + virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action) { + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentURI", curURI); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + + m_Delegate->OnSetAVTransportURI(curURI.GetChars(), metaData.GetChars()); + + PLT_Service* service; + NPT_CHECK_SEVERE(m_Renderer->FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service)); + + service->SetStateVariable("TransportState", "PLAYING"); + service->SetStateVariable("TransportStatus", "OK"); + service->SetStateVariable("AVTransportURI", curURI); + service->SetStateVariable("AVTransportURIMetaData", metaData); + + service->SetStateVariable("NextAVTransportURI", ""); + service->SetStateVariable("NextAVTransportURIMetaData", ""); + + NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable()); + + return NPT_SUCCESS; + } + + virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action) { + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String playMode; + action->GetArgumentValue("NewPlayMode", playMode); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + m_Delegate->OnSetPlayMode(playMode.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + + } + + // RenderingControl + virtual NPT_Result OnSetVolume(PLT_ActionReference& action) { + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("DesiredVolume", curURI); + NPT_String metaData ; + action->GetArgumentValue("Channel", metaData); + + m_Delegate->OnSetVolume(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + } + + virtual NPT_Result OnSetVolumeDB(PLT_ActionReference& action){ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentURI", curURI); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + m_Delegate->OnSetVolumeDB(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + + } + + virtual NPT_Result OnGetVolumeDBRange(PLT_ActionReference& action){ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + NPT_String curURI; + action->GetArgumentValue("CurrentURI", curURI); + NPT_String metaData; + action->GetArgumentValue("CurrentURIMetaData", metaData); + m_Delegate->OnGetVolumeDBRange(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + + } + + virtual NPT_Result OnSetMute(PLT_ActionReference& action){ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + + NPT_String curURI; + action->GetArgumentValue("DesiredMute", curURI); + NPT_String metaData ; + action->GetArgumentValue("CurrentURIMetaData", metaData); + m_Delegate->OnSetMute(curURI.GetChars(), metaData.GetChars()); + + return NPT_SUCCESS; + } + + +private: + std::shared_ptr m_Delegate; + PLT_MediaRenderer * m_Renderer; +}; + +class MediaRendererImpl : public MediaRenderer { +public: + MediaRendererImpl(MediaRendererDelegate * delegate, + const char* friendly_name, + bool show_ip, + const char* uuid, + unsigned int port, + bool port_rebind) + : m_Upnp() + , m_Delegate(delegate) + , m_FriendlyName(friendly_name) + , m_ShowIp(show_ip) + , m_Uuid(uuid) + , m_Port(port) + , m_PortRebind(port_rebind) { + + PLT_MediaRenderer * renderer = + new PLT_MediaRenderer(m_FriendlyName, + m_ShowIp, + m_Uuid, + m_Port, + m_PortRebind); + m_PLTDelegate = std::make_shared(renderer, delegate); + renderer->SetDelegate(m_PLTDelegate.get()); + + PLT_DeviceHostReference device(renderer); + + m_Upnp.AddDevice(device); + } + + virtual ~MediaRendererImpl() { + } + +public: + virtual void Start(); + virtual void Stop(); + +private: + PLT_UPnP m_Upnp; + + std::shared_ptr m_Delegate; + + const char* m_FriendlyName; + bool m_ShowIp; + const char* m_Uuid; + unsigned int m_Port; + bool m_PortRebind; + + std::shared_ptr m_PLTDelegate; +}; + +void MediaRendererImpl::Start() { + m_Upnp.Start(); +} + +void MediaRendererImpl::Stop() { + m_Upnp.Stop(); +} + +} + +MediaRenderer * create_media_renderer(MediaRendererDelegate * delegate, + const char* friendly_name, + bool show_ip, + const char* uuid, + unsigned int port, + bool port_rebind) { + return new media_renderer::MediaRendererImpl(delegate, + friendly_name, + show_ip, + uuid, + port, + port_rebind); +} + +void release_media_renderer(MediaRenderer * renderer) { + if (renderer) + delete renderer; +} diff --git a/binding/python/media_renderer.h b/binding/python/media_renderer.h new file mode 100644 index 00000000..9f80c3ce --- /dev/null +++ b/binding/python/media_renderer.h @@ -0,0 +1,46 @@ +#ifndef __MEDIA_RENDER_H__ +#define __MEDIA_RENDER_H__ + +class MediaRendererDelegate +{ +public: + virtual ~MediaRendererDelegate() {} + + // ConnectionManager + virtual int OnGetCurrentConnectionInfo(const char * uri, const char * data) = 0; + + // AVTransport + virtual int OnNext(const char * uri, const char * data) = 0; + virtual int OnPause(const char * uri, const char * data) = 0; + virtual int OnPlay(const char * uri, const char * data) = 0; + virtual int OnPrevious(const char * uri, const char * data) = 0; + virtual int OnSeek(const char * uri, const char * data) = 0; + virtual int OnStop(const char * uri, const char * data) = 0; + virtual int OnSetAVTransportURI(const char * uri, const char * data) = 0; + virtual int OnSetPlayMode(const char * uri, const char * data) = 0; + + // RenderingControl + virtual int OnSetVolume(const char * uri, const char * data) = 0; + virtual int OnSetVolumeDB(const char * uri, const char * data) = 0; + virtual int OnGetVolumeDBRange(const char * uri, const char * data) = 0; + virtual int OnSetMute(const char * uri, const char * data) = 0; +}; + + +class MediaRenderer { +public: + virtual ~MediaRenderer() {} + +public: + virtual void Start() = 0; + virtual void Stop() = 0; +}; + +MediaRenderer * create_media_renderer(MediaRendererDelegate * delegate, + const char* friendly_name, + bool show_ip = false, + const char* uuid = NULL, + unsigned int port = 0, + bool port_rebind = false); + +#endif //__MEDIA_RENDER_H__ diff --git a/binding/python/media_renderer.i b/binding/python/media_renderer.i new file mode 100644 index 00000000..a146f64c --- /dev/null +++ b/binding/python/media_renderer.i @@ -0,0 +1,8 @@ +%module(directors="1") media_renderer +%{ +#include "media_renderer.h" +%} + +%feature("director"); + +%include "media_renderer.h"