summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Platinum
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/Platinum')
-rw-r--r--lib/libUPnP/Platinum/Build/Boot.scons71
-rw-r--r--lib/libUPnP/Platinum/Build/Build.scons275
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/arm-android-linux/Config.scons107
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/arm-gp2x-linux/Config.scons9
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/arm-unknown-linux/Config.scons7
-rwxr-xr-xlib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist30
-rwxr-xr-xlib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser.xcodeproj/project.pbxproj316
-rwxr-xr-xlib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser_Prefix.pch9
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/README5
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/MobileMediaServer-Info.plist37
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/project.pbxproj3653
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-Mac.xcscheme77
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-iOS.xcscheme77
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Info.plist26
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Neptune.h2
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Platinum.h66
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/x86-unknown-cygwin/Config.scons4
-rw-r--r--lib/libUPnP/Platinum/Build/Targets/x86-unknown-linux/Config.scons5
-rw-r--r--lib/libUPnP/Platinum/Build/Tools/SCons/gcc-generic.py36
-rwxr-xr-xlib/libUPnP/Platinum/Build/Tools/Scripts/GenDocumentation.py77
-rw-r--r--lib/libUPnP/Platinum/Build/Tools/Scripts/GenSvnVersionHeader.py41
-rw-r--r--lib/libUPnP/Platinum/Build/Tools/Scripts/MakeAllVs.py37
-rw-r--r--lib/libUPnP/Platinum/Build/Tools/Scripts/VsMake.py97
-rwxr-xr-xlib/libUPnP/Platinum/Build/Tools/Scripts/XCodeMake.py83
-rw-r--r--lib/libUPnP/Platinum/CHANGELOG.txt730
-rw-r--r--lib/libUPnP/Platinum/Extras/neptune-logging.properties13
-rw-r--r--lib/libUPnP/Platinum/Extras/platinum-120x120.jpgbin0 -> 16096 bytes
-rw-r--r--lib/libUPnP/Platinum/Extras/platinum-120x120.pngbin0 -> 26577 bytes
-rw-r--r--lib/libUPnP/Platinum/Extras/platinum-48x48.jpgbin0 -> 3041 bytes
-rw-r--r--lib/libUPnP/Platinum/Extras/platinum-48x48.pngbin0 -> 4681 bytes
-rw-r--r--lib/libUPnP/Platinum/LICENSE.txt375
-rw-r--r--lib/libUPnP/Platinum/README.md131
-rw-r--r--lib/libUPnP/Platinum/SConstruct1
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist22
-rwxr-xr-xlib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.h44
-rwxr-xr-xlib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.m73
-rwxr-xr-xlib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MainWindow.xib267
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.h101
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.mm130
-rwxr-xr-xlib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.h38
-rwxr-xr-xlib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.m179
-rwxr-xr-xlib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.xib192
-rwxr-xr-xlib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/main.m43
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/FrameStreamer/main.cpp249
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MediaConnect/main.cpp131
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.cpp566
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.h118
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MediaCrawler/StreamHandler.h113
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MediaCrawler/main.cpp83
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.cpp869
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.h176
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MicroMediaController/main.cpp136
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.h17
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.m45
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/LaunchScreen.xib41
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/Main.storyboard25
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.h14
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.mm70
-rw-r--r--lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/main.m16
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltAction.cpp505
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltAction.h321
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltArgument.cpp156
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltArgument.h168
-rwxr-xr-xlib/libUPnP/Platinum/Source/Core/PltConstants.cpp62
-rwxr-xr-xlib/libUPnP/Platinum/Source/Core/PltConstants.h87
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp1875
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.h254
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.cpp213
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.h225
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltDatagramStream.cpp169
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltDatagramStream.h117
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltDeviceData.cpp830
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltDeviceData.h260
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp953
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltDeviceHost.h341
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltEvent.cpp328
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltEvent.h191
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttp.cpp352
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttp.h214
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.cpp190
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.h121
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttpServer.cpp310
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttpServer.h100
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.cpp443
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.h163
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltIconsData.cpp2580
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltMimeType.cpp162
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltMimeType.h75
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp598
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.h158
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltService.cpp920
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltService.h522
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltSsdp.cpp513
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltSsdp.h389
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltStateVariable.cpp269
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltStateVariable.h231
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltTaskManager.cpp236
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltTaskManager.h116
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltThreadTask.cpp190
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltThreadTask.h140
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp298
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltUPnP.h143
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltUtilities.h766
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.cpp348
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.h110
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.cpp214
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.h73
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.cpp176
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.xml88
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaConnect/process_scpds.sh9
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.cpp996
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.xml515
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPDFull.xml561
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp1392
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.h349
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.cpp516
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.h119
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.cpp257
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.xml132
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.cpp434
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.xml216
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD_Full.xml749
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaRenderer/process_scpds.sh15
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.cpp262
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.xml132
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.cpp267
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.xml148
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.cpp453
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.xml231
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp406
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h197
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.cpp519
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.h151
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.cpp571
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.h184
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.cpp37
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.h203
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp1128
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h348
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp711
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.h196
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp578
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h218
-rw-r--r--lib/libUPnP/Platinum/Source/Devices/MediaServer/process_scpds.sh15
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Action.cpp92
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Action.h159
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.cpp45
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.h153
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.cpp69
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.h123
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Clix.h202
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.cpp115
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.h227
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.cpp88
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.h68
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.cpp168
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.h264
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.cpp38
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.h124
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Didl.cpp39
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Didl.h70
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptArray.h226
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptList.h234
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.cpp39
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.h378
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Http.cpp38
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Http.h286
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.cpp59
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.h80
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.cpp118
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.h735
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.cpp121
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.h131
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.cpp103
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.h97
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Neptun_marshal_as.h104
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.cpp39
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.h64
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.cpp38
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.h207
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Service.cpp97
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/Service.h147
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.cpp44
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.h165
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.cpp81
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.h131
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/Managed/clix.hpp209
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.h84
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.mm198
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.h61
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.mm118
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltDownloader.cpp132
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltDownloader.h89
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.cpp129
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.h76
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltFrameServer.cpp236
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltFrameServer.h103
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltFrameStream.cpp128
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltFrameStream.h79
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltLeaks.cpp99
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltLeaks.h51
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.cpp90
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.h91
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.cpp255
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.h119
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltStreamPump.cpp227
-rw-r--r--lib/libUPnP/Platinum/Source/Extras/PltStreamPump.h131
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/AndroidManifest.xml14
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Android.mk52
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Application.mk1
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.cpp81
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.h37
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/update-header.sh1
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/proguard-project.txt20
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/project.properties15
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-ldpi/ic_launcher.pngbin0 -> 2729 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/layout/main.xml12
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/values/strings.xml7
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/src/com/plutinosoft/platinum/UPnP.java25
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/AndroidManifest.xml24
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/proguard-project.txt20
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/project.properties15
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-ldpi/ic_launcher.pngbin0 -> 2729 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/layout/main.xml22
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/values/strings.xml7
-rw-r--r--lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/src/com/plutinosoft/platinum/sample/PlatinumUPnPActivity.java44
-rw-r--r--lib/libUPnP/Platinum/Source/Platinum/Platinum.h111
-rw-r--r--lib/libUPnP/Platinum/Source/Platinum/PltVersion.h44
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/FileMediaServer/FileMediaServerTest.cpp159
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp526
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/LightSample/LightSampleTest.cpp76
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.cpp171
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.h59
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaRenderer/MediaRendererTest.cpp121
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/InfoPlist.strings1
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/MainMenu.xib3224
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest-Info.plist32
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.h20
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.mm64
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.h28
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.m212
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.mm195
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/elementsbin0 -> 1199 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/layoutbin0 -> 475 bytes
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_Prefix.pch7
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/main.mm14
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.cpp111
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.h56
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/Simple/SimpleTest.cpp63
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/Ssdp/SsdpTest1.cpp66
-rw-r--r--lib/libUPnP/Platinum/Source/Tests/Time/TimeTest1.cpp189
-rw-r--r--lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.cpp405
-rw-r--r--lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.h109
-rw-r--r--lib/libUPnP/Platinum/Source/Tools/TextToHeader/TextToHeader.cpp267
260 files changed, 56871 insertions, 0 deletions
diff --git a/lib/libUPnP/Platinum/Build/Boot.scons b/lib/libUPnP/Platinum/Build/Boot.scons
new file mode 100644
index 0000000..9b15737
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Boot.scons
@@ -0,0 +1,71 @@
+import sys
+import os
+import platform
+
+EnsureSConsVersion(0,98,1)
+
+#######################################################
+# reusable functions and data structures
+#######################################################
+
+# Platform to Target Map (specifies which default target to build on a platform)
+PLATFORM_TO_TARGET_MAP = {
+ 'linux-i386' : 'x86-unknown-linux',
+ 'linux-x86_64': 'x86_64-unknown-linux',
+ 'linux-arm' : 'arm-unknown-linux',
+ 'linux2' : 'x86-unknown-linux',
+ 'win32' : 'x86-microsoft-win32',
+ 'cygwin' : 'x86-unknown-cygwin',
+ 'darwin' : 'universal-apple-macosx'
+}
+
+# list all target dirs
+scons_root = Environment().GetBuildPath('#')
+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 DefaultTarget():
+ platform_id = sys.platform
+ if platform.system() == 'Linux':
+ if (platform.machine() == 'i386' or
+ platform.machine() == 'i486' or
+ platform.machine() == 'i586'or
+ platform.machine() == 'i686'):
+ platform_id = 'linux-i386'
+ if (platform.machine() == 'x86_64'):
+ platform_id = 'linux-x86_64'
+ if (platform.machine().startswith('arm')):
+ platform_id = 'linux-arm'
+
+ if PLATFORM_TO_TARGET_MAP.has_key(platform_id):
+ return PLATFORM_TO_TARGET_MAP[platform_id]
+ else:
+ return None
+
+#######################################################
+# Main Build
+#######################################################
+options = Variables()
+options.AddVariables(
+ EnumVariable('target', 'Build Target', DefaultTarget(), allowed_values=TARGET_PLATFORMS),
+ BoolVariable('stop_on_warning', 'Stop the build on warnings', False),
+ ListVariable('build_config', 'build configurations', 'Debug', names=['Debug', 'Release'])
+)
+
+env = Environment(variables=options)
+Help(options.GenerateHelpText(env))
+
+if 'NPT_CONFIG_NO_SSL' in os.environ:
+ env['NPT_CONFIG_NO_SSL'] = os.environ['NPT_CONFIG_NO_SSL']
+if 'NPT_CONFIG_NO_ZIP' in os.environ:
+ env['NPT_CONFIG_NO_ZIP'] = os.environ['NPT_CONFIG_NO_ZIP']
+if 'NPT_CONFIG_NO_CRYPTO' in os.environ:
+ env['NPT_CONFIG_NO_CRYPTO'] = os.environ['NPT_CONFIG_NO_CRYPTO']
+
+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, '********'
+ SConscript('Build.scons', variant_dir='Targets/'+env['target']+'/'+build_config, exports='env', duplicate=0)
diff --git a/lib/libUPnP/Platinum/Build/Build.scons b/lib/libUPnP/Platinum/Build/Build.scons
new file mode 100644
index 0000000..ab9a95d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Build.scons
@@ -0,0 +1,275 @@
+import sys
+import os
+import imp
+from glob import glob
+
+#######################################################
+# reusable functions and data structures
+#######################################################
+def LoadTool(name, env, **kw):
+ config_path = GetBuildPath('#/Build/Tools/SCons')
+ file, path, desc = imp.find_module(name, [config_path])
+ module = imp.load_module(name, file, path, desc)
+ module.generate(env, **kw)
+
+def MergeListUnique(item_list, items):
+ for item in items:
+ if not item in item_list: item_list.append(item)
+
+def MergeItemUnique(item_list, item):
+ if not item in item_list: item_list.append(item)
+
+def GlobSources(drct, patterns, excluded_files=[]):
+ root = GetBuildPath('#'+drct)
+ files = []
+ for pattern in Split(patterns):
+ files += glob(root+'/'+pattern)
+ return [drct+'/'+os.path.basename(x) for x in files if os.path.basename(x) not in excluded_files]
+
+def GetDirPath(dir):
+ return '#/'+dir
+
+def DeclareBuildDir(dir):
+ env.VariantDir(dir, GetDirPath(dir), duplicate=0)
+
+def GetIncludeDirs(modules, exclude=None):
+ dirs = []
+ for module in Split(modules):
+ if Modules.has_key(module) and not module == exclude:
+ dirs += Modules[module].GetIncludeDirs()
+ else:
+ dirs += [GetDirPath(module)]
+ return dirs
+
+def GetLibraries(modules):
+ libs = []
+ for module in Split(modules):
+ if Modules.has_key(module):
+ libs += Modules[module].GetLibraries()
+ else:
+ libs += [module]
+ return libs
+
+Modules = {}
+class Module:
+ def __init__(self, name, included_modules = [], linked_modules = []):
+ self.name = name
+ self.included_modules = included_modules
+ self.linked_modules = linked_modules
+ self.product = []
+
+ def GetLibraries(self):
+ return self.product+GetLibraries(self.linked_modules)
+
+ def GetIncludeDirs(self):
+ return GetIncludeDirs(self.included_modules+self.build_include_dirs, self.name)
+
+class LibraryModule(Module):
+ def __init__(self, name,
+ build_source_dirs = ['.'],
+ build_source_files = {},
+ source_root = 'Source',
+ build_source_pattern = ['*.c', '*.cpp'],
+ build_include_dirs = [],
+ included_modules = [],
+ included_only_modules = [],
+ linked_modules = [],
+ environment = None,
+ excluded_files = [],
+ extra_cpp_defines = [],
+ shared = False,
+ install = False) :
+ build_source_dirs = [source_root+'/'+drct for drct in build_source_dirs]
+ Module.__init__(self,
+ name,
+ Split(included_modules)+Split(included_only_modules)+Split(build_source_dirs),
+ Split(linked_modules)+Split(included_modules))
+ self.build_include_dirs = build_include_dirs
+ if environment is None:
+ self.env = env.Clone()
+ else:
+ self.env = environment.Clone()
+ self.env.AppendUnique(CPPDEFINES = extra_cpp_defines)
+
+ # store this new object in the module dictionary
+ Modules[name] = self
+
+ # for each source drct to build, create a VariantDir
+ # to say where we want the object files to be built,
+ # and compute the list of source files to build
+ sources = []
+ for drct in Split(build_source_dirs):
+ DeclareBuildDir(drct)
+ sources += GlobSources(drct, build_source_pattern, excluded_files)
+
+ # add cherry-picked files
+ for drct in build_source_files.keys():
+ pattern = build_source_files[drct]
+ drct_path = source_root+'/'+drct
+ DeclareBuildDir(drct_path)
+ sources += GlobSources(drct_path, pattern)
+
+ # calculate our build include path
+ cpp_path = GetIncludeDirs(Split(self.build_include_dirs) + Split(build_source_dirs) + self.included_modules + self.linked_modules)
+
+ # the product is a library
+ self.env.AppendUnique(CPPPATH=cpp_path)
+ if shared is False:
+ self.product = self.env.Library(target=name, source=sources)
+ else:
+ libs = GetLibraries(Split(linked_modules))
+ self.product = self.env.SharedLibrary(target=name, LIBS=libs, source=sources)
+ self.env.Alias(name, self.product)
+
+ # copy to Targets folder
+ if install is True:
+ inst = env.Install(dir=env.GetBuildPath('#/Targets/'+env['target']+'/'+env['build_config']), source=self.product)
+ if env['build_config'] == 'Release' and env.has_key('STRIP'):
+ env.AddPostAction(inst, env['STRIP']+' $TARGETS');
+
+def Application(name, dir, deps, install = False):
+ DeclareBuildDir(dir)
+ libs = GetLibraries(deps)
+ cpp_path = GetIncludeDirs(deps)
+
+ prog = env.Program(name,
+ GlobSources(dir, ['*.c', '*.cpp']) + env['NPT_EXTRA_EXECUTABLE_OBJECTS'],
+ LIBS=libs, CPPPATH=cpp_path)
+ #env.Alias(name, prog)
+ if env.has_key('NPT_EXECUTABLE_POST_PROCESSOR'):
+ env.AddPostAction(prog, env['NPT_EXECUTABLE_POST_PROCESSOR'])
+
+ # copy to Targets folder
+ if install is True:
+ inst = env.Install(dir=env.GetBuildPath('#/Targets/'+env['target']+'/'+env['build_config']), source=prog)
+ if env['build_config'] == 'Release' and env.has_key('STRIP'):
+ env.AddPostAction(inst, env['STRIP']+' $TARGETS');
+
+#######################################################
+# Main Build
+#######################################################
+Import("env")
+
+### defaults
+env['NPT_EXTRA_LIBS'] = []
+env['NPT_EXTRA_EXECUTABLE_OBJECTS'] = []
+
+if (env['build_config'] == 'Debug'):
+ env.AppendUnique(CPPDEFINES=['NPT_DEBUG', 'NPT_CONFIG_ENABLE_LOGGING', 'PLATINUM_UPNP_SPECS_STRICT'])
+else:
+ env.AppendUnique(CPPDEFINES=['NDEBUG', 'NPT_CONFIG_ENABLE_LOGGING', 'PLATINUM_UPNP_SPECS_STRICT'])
+
+### try to read in any target specific configuration
+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)
+
+#######################################################
+# modules
+#
+# Usage:
+#
+# The LibraryModule() function declares a code module
+# The included_modules parameter is a list of all the modules and/or directories
+# that will be added to the include path when building this module AND to
+# the include path of any other module that depends on this one.
+# The linked_modules parameter is a list of all the modules and/or directories
+# that are necessary to build this module. These modules will be added to
+# the include path of this module, but not to that of the modules that depend
+# on this module. The modules that depend on this module, however, will
+# automatically link with the linked_modules.
+# Note that the included_modules list is automatically added to the
+# linked_modules list, so that you do not need to list in linked_modules
+# the modules that are already listed in included_modules.
+# If a module needs to export an include path to its dependents that
+# is not a module that the dependent can link with (ex: an include dir),
+# list it in the included_only_modules.
+# To summarize: included_modules should list all the modules that users
+# of the public interface should depend on; linked_modules should list
+# all the modules not listed in included_modules that are used by the
+# module's implementation only.
+#######################################################
+# Neptune
+NPT_SOURCE_ROOT = 'ThirdParty/Neptune'
+
+extra_cpp_flags = []
+neptune_extra_linked_modules = []
+if not env.has_key('NPT_CONFIG_NO_ZIP'):
+ extra_cpp_flags = ['NPT_CONFIG_ENABLE_ZIP']
+ neptune_extra_linked_modules += ['Zlib']
+
+ LibraryModule(name = 'Zlib',
+ source_root = NPT_SOURCE_ROOT,
+ build_source_dirs = ['ThirdParty/zlib-1.2.3'])
+
+if not env.has_key('NPT_CONFIG_NO_SSL'):
+ extra_cpp_flags += ['NPT_CONFIG_ENABLE_TLS']
+ tls_data_dirs = ['Data/TLS']
+ tls_tests = ['Tls1']
+ neptune_extra_linked_modules += ['axTLS']
+
+ LibraryModule(name = 'axTLS',
+ source_root = NPT_SOURCE_ROOT,
+ build_source_dirs = ['ThirdParty/axTLS/crypto', 'ThirdParty/axTLS/ssl', 'ThirdParty/axTLS/config/Generic'])
+else:
+ tls_data_dirs = []
+ tls_tests = []
+
+if not env.has_key('NPT_CONFIG_NO_CRYPTO'):
+ extra_cpp_flags += ['NPT_CONFIG_ENABLE_CRYPTO']
+ neptune_excluded_files = []
+else:
+ neptune_excluded_files = ['NptCrypto.cpp', 'NptDigest.cpp']
+
+LibraryModule(name = 'Neptune',
+ build_source_dirs = ['Core']+tls_data_dirs,
+ build_source_files = env['NPT_SYSTEM_SOURCES'],
+ excluded_files = neptune_excluded_files,
+ extra_cpp_defines = extra_cpp_flags,
+ linked_modules = env['NPT_EXTRA_LIBS']+neptune_extra_linked_modules,
+ source_root = NPT_SOURCE_ROOT + '/Source')
+
+# Platinum
+LibraryModule(name = 'Platinum',
+ build_source_dirs = ['Core', 'Extras'],
+ build_include_dirs = ['Source/Platinum'],
+ extra_cpp_defines = extra_cpp_flags,
+ included_modules = ['Neptune'])
+
+# Platinum MediaServer
+LibraryModule(name = 'PltMediaServer',
+ build_source_dirs = ['MediaServer'],
+ included_modules = ['Platinum'],
+ source_root = 'Source/Devices')
+
+# Platinum MediaRenderer
+LibraryModule(name = 'PltMediaRenderer',
+ build_source_dirs = ['MediaRenderer'],
+ included_modules = ['Platinum', 'PltMediaServer'],
+ source_root = 'Source/Devices')
+
+# Platinum MediaConnect
+LibraryModule(name = 'PltMediaConnect',
+ build_source_dirs = ['MediaConnect'],
+ included_modules = ['Platinum', 'PltMediaServer', 'PltMediaRenderer'],
+ excluded_files = ['MACFromIP.cpp'],
+ source_root = 'Source/Devices')
+
+for app in ['MicroMediaController', 'MediaCrawler', 'MediaConnect', 'FrameStreamer']:
+ Application(name = app,
+ dir = 'Source/Apps/' + app,
+ deps = ['Platinum', 'PltMediaServer', 'PltMediaRenderer', 'PltMediaConnect'],
+ install = True)
+
+for test in ['FileMediaServer', 'MediaRenderer', 'LightSample', 'Http', 'Time']:
+ Application(name = test+'Test',
+ dir = 'Source/Tests/' + test,
+ deps = ['Platinum', 'PltMediaServer', 'PltMediaRenderer', 'PltMediaConnect'],
+ install = True)
+
+for tool in ['TextToHeader']:
+ Application(name = tool,
+ dir = 'Source/Tools/' + tool,
+ deps = ['Platinum'],
+ install = True)
diff --git a/lib/libUPnP/Platinum/Build/Targets/arm-android-linux/Config.scons b/lib/libUPnP/Platinum/Build/Targets/arm-android-linux/Config.scons
new file mode 100644
index 0000000..bdbf08d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/arm-android-linux/Config.scons
@@ -0,0 +1,107 @@
+#################################################################
+# Important: this build file has been tested with Android NDK r6, r7 and r8
+# It may or may not work with other releases of the NDK. Please notify
+# us if you find a newer NDK for which this does not work.
+#################################################################
+
+import os
+import re
+import sys
+import platform
+
+# we need to know when the NDK is
+ANDROID_NDK_ROOT=os.getenv('ANDROID_NDK_ROOT')
+if not ANDROID_NDK_ROOT:
+ raise Exception('ANDROID_NDK_ROOT environment variable not set')
+
+# detect the host system on which we're running
+if env.has_key('android_host_system') and env['android_host_system']:
+ ANDROID_HOST_SYSTEM = env['android_host_system']
+else:
+ PLATFORM_TO_TARGET_MAP = {
+ 'linux-i386' : 'linux-x86',
+ 'linux2' : 'linux-x86',
+ 'win32' : 'windows',
+ 'cygwin' : 'windows',
+ 'darwin' : 'darwin-x86'
+ }
+ if sys.platform in PLATFORM_TO_TARGET_MAP:
+ ANDROID_HOST_SYSTEM = PLATFORM_TO_TARGET_MAP[sys.platform]
+ else:
+ raise Exception('Android Host Platform cannot be determined')
+
+# set defaults
+ANDROID_ARCH = 'arm'
+ANDROID_PLATFORM = 'android-9'
+ANDROID_TOOLCHAIN = 'arm-linux-androideabi-4.4.3'
+ANDROID_CROSS_PREFIX = 'arm-linux-androideabi'
+
+if not os.path.exists(os.path.join(ANDROID_NDK_ROOT, 'toolchains', ANDROID_TOOLCHAIN)):
+ toolchain_dirs = os.listdir(ANDROID_NDK_ROOT+'/toolchains')
+ for toolchain_dir in toolchain_dirs:
+ if os.path.exists(os.path.join(ANDROID_NDK_ROOT, 'toolchains', toolchain_dir, 'prebuilt', ANDROID_HOST_SYSTEM)):
+ ANDROID_TOOLCHAIN=toolchain_dir
+ suffix_pos = toolchain_dir.rfind('-')
+ if (suffix_pos >= 0):
+ ANDROID_CROSS_PREFIX = ANDROID_TOOLCHAIN[:suffix_pos]
+ print "Auto-selecting toolchain:", ANDROID_TOOLCHAIN
+ break
+
+# override defaults from command line args
+if ARGUMENTS.get('android_toolchain'):
+ ANDROID_TOOLCHAIN=ARGUMENTS.get('android_toolchain')
+
+if ARGUMENTS.get('android_cross_prefix'):
+ ANDROID_CROSS_PREFIX=ARGUMENTS.get('android_cross_prefix')
+
+if ARGUMENTS.get('android_platform'):
+ ANDROID_PLATFORM=ARGUMENTS.get('android_platform')
+
+if ARGUMENTS.get('android_arch'):
+ ANDROID_ARCH=ARGUMENTS.get('android_arch')
+
+print 'Building for Android: '
+print 'ANDROID_HOST_SYSTEM =', ANDROID_HOST_SYSTEM
+print 'ANDROID_TOOLCHAIN =', ANDROID_TOOLCHAIN
+print 'ANDROID_PLATFORM =', ANDROID_PLATFORM
+print 'ANDROID_ARCH =', ANDROID_ARCH
+
+ANDROID_TOOLCHAIN_BIN = ANDROID_NDK_ROOT+'/toolchains/'+ANDROID_TOOLCHAIN+'/prebuilt/'+ANDROID_HOST_SYSTEM+'/bin'
+ANDROID_SYSROOT = ANDROID_NDK_ROOT+'/platforms/'+ANDROID_PLATFORM+'/arch-'+ANDROID_ARCH
+
+### add the tools to the path
+env.PrependENVPath('PATH', ANDROID_TOOLCHAIN_BIN)
+
+### special C Runtime startup for executables
+env['NPT_EXTRA_EXECUTABLE_OBJECTS'] = []
+env['NPT_EXTRA_LIBS'] = ['gcc']
+
+### Load the tools
+LoadTool('gcc-generic', env, gcc_cross_prefix=ANDROID_CROSS_PREFIX, gcc_strict=False)
+env.AppendUnique(CCFLAGS = ['-I'+ANDROID_NDK_ROOT+'/sources/cxx-stl/system/include' ,
+ '--sysroot', ANDROID_SYSROOT,
+ '-msoft-float',
+ '-fpic',
+ '-mthumb-interwork',
+ '-ffunction-sections',
+ '-funwind-tables',
+ '-fstack-protector',
+ '-fno-short-enums'])
+env.AppendUnique(CXXFLAGS = ['-fno-exceptions', '-fno-rtti'])
+env.AppendUnique(CPPDEFINES = ['ANDROID', 'NPT_CONFIG_HAVE_SYSTEM_LOG_CONFIG'])
+env.AppendUnique(LINKFLAGS = ['--sysroot', ANDROID_SYSROOT,
+ '-Wl,--no-undefined',
+ '-Wl,-z,noexecstack',
+ '-L'+ANDROID_SYSROOT+'/usr/lib',
+ '-lc',
+ '-lstdc++',
+ '-lm',
+ '-llog',
+ '-ldl'])
+
+### Specific System choices
+env['NPT_SYSTEM_SOURCES']={'System/StdC':'NptStdc[!D]*.cpp',
+ 'System/Bsd':'*.cpp',
+ 'System/Posix':'*.cpp',
+ 'System/Null':['NptNullSerialPort.cpp', 'NptNullAutoreleasePool.cpp'],
+ 'System/Android':'*.cpp'}
diff --git a/lib/libUPnP/Platinum/Build/Targets/arm-gp2x-linux/Config.scons b/lib/libUPnP/Platinum/Build/Targets/arm-gp2x-linux/Config.scons
new file mode 100644
index 0000000..0d6a316
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/arm-gp2x-linux/Config.scons
@@ -0,0 +1,9 @@
+LoadTool('gcc-generic', env, gcc_cross_prefix='arm-linux')
+
+## change exec suffix
+env['PROGSUFFIX'] = '.gpe'
+
+### 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']
+
diff --git a/lib/libUPnP/Platinum/Build/Targets/arm-unknown-linux/Config.scons b/lib/libUPnP/Platinum/Build/Targets/arm-unknown-linux/Config.scons
new file mode 100644
index 0000000..8e9c4f1
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/arm-unknown-linux/Config.scons
@@ -0,0 +1,7 @@
+LoadTool('gcc-generic', env, gcc_cross_prefix='arm-linux')
+
+### 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/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist
new file mode 100755
index 0000000..491ea7a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.plutinosoft.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>NSMainNibFile</key>
+ <string>MainWindow</string>
+</dict>
+</plist>
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser.xcodeproj/project.pbxproj b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser.xcodeproj/project.pbxproj
new file mode 100755
index 0000000..91299b9
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser.xcodeproj/project.pbxproj
@@ -0,0 +1,316 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+ 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; };
+ E445E63C144997E800F221B3 /* README in Resources */ = {isa = PBXBuildFile; fileRef = E445E63B144997E800F221B3 /* README */; };
+ E4A7DC061085A49400E6ADE2 /* CocoaTouchBrowserAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DC021085A49400E6ADE2 /* CocoaTouchBrowserAppDelegate.m */; };
+ E4A7DC071085A49400E6ADE2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DC031085A49400E6ADE2 /* main.m */; };
+ E4A7DC081085A49400E6ADE2 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DC051085A49400E6ADE2 /* RootViewController.m */; };
+ E4A7DC0B1085A4B300E6ADE2 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = E4A7DC091085A4B300E6ADE2 /* MainWindow.xib */; };
+ E4A7DC0C1085A4B300E6ADE2 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E4A7DC0A1085A4B300E6ADE2 /* RootViewController.xib */; };
+ E4A7DCF31085AC7000E6ADE2 /* MediaBrowserWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DCF21085AC7000E6ADE2 /* MediaBrowserWrapper.mm */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 1D6058910D05DD3D006BFB54 /* CocoaTouchBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CocoaTouchBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 28A0AAE50D9B0CCF005BE974 /* CocoaTouchBrowser_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocoaTouchBrowser_Prefix.pch; sourceTree = "<group>"; };
+ 8D1107310486CEB800E47090 /* CocoaTouchBrowser-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "CocoaTouchBrowser-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
+ E445E63B144997E800F221B3 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ E4A7DC011085A49400E6ADE2 /* CocoaTouchBrowserAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CocoaTouchBrowserAppDelegate.h; path = ../../../../Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.h; sourceTree = SOURCE_ROOT; };
+ E4A7DC021085A49400E6ADE2 /* CocoaTouchBrowserAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CocoaTouchBrowserAppDelegate.m; path = ../../../../Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.m; sourceTree = SOURCE_ROOT; };
+ E4A7DC031085A49400E6ADE2 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../../../../Source/Apps/CocoaTouchBrowser/main.m; sourceTree = SOURCE_ROOT; };
+ E4A7DC041085A49400E6ADE2 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RootViewController.h; path = ../../../../Source/Apps/CocoaTouchBrowser/RootViewController.h; sourceTree = SOURCE_ROOT; };
+ E4A7DC051085A49400E6ADE2 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RootViewController.m; path = ../../../../Source/Apps/CocoaTouchBrowser/RootViewController.m; sourceTree = SOURCE_ROOT; };
+ E4A7DC091085A4B300E6ADE2 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainWindow.xib; path = ../../../../Source/Apps/CocoaTouchBrowser/MainWindow.xib; sourceTree = SOURCE_ROOT; };
+ E4A7DC0A1085A4B300E6ADE2 /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = RootViewController.xib; path = ../../../../Source/Apps/CocoaTouchBrowser/RootViewController.xib; sourceTree = SOURCE_ROOT; };
+ E4A7DCF11085AC7000E6ADE2 /* MediaBrowserWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MediaBrowserWrapper.h; path = ../../../../Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.h; sourceTree = SOURCE_ROOT; };
+ E4A7DCF21085AC7000E6ADE2 /* MediaBrowserWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MediaBrowserWrapper.mm; path = ../../../../Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.mm; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
+ 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 1D6058910D05DD3D006BFB54 /* CocoaTouchBrowser.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+ isa = PBXGroup;
+ children = (
+ E4A7DC131085A4DB00E6ADE2 /* Classes */,
+ 29B97315FDCFA39411CA2CEA /* Other Sources */,
+ 29B97317FDCFA39411CA2CEA /* Resources */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = CustomTemplate;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ E4A7DC031085A49400E6ADE2 /* main.m */,
+ 28A0AAE50D9B0CCF005BE974 /* CocoaTouchBrowser_Prefix.pch */,
+ E445E63B144997E800F221B3 /* README */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ E4A7DC091085A4B300E6ADE2 /* MainWindow.xib */,
+ E4A7DC0A1085A4B300E6ADE2 /* RootViewController.xib */,
+ 8D1107310486CEB800E47090 /* CocoaTouchBrowser-Info.plist */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ E4A7DC131085A4DB00E6ADE2 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ E4A7DCF11085AC7000E6ADE2 /* MediaBrowserWrapper.h */,
+ E4A7DCF21085AC7000E6ADE2 /* MediaBrowserWrapper.mm */,
+ E4A7DC011085A49400E6ADE2 /* CocoaTouchBrowserAppDelegate.h */,
+ E4A7DC021085A49400E6ADE2 /* CocoaTouchBrowserAppDelegate.m */,
+ E4A7DC041085A49400E6ADE2 /* RootViewController.h */,
+ E4A7DC051085A49400E6ADE2 /* RootViewController.m */,
+ );
+ name = Classes;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 1D6058900D05DD3D006BFB54 /* CocoaTouchBrowser */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "CocoaTouchBrowser" */;
+ buildPhases = (
+ 1D60588D0D05DD3D006BFB54 /* Resources */,
+ 1D60588E0D05DD3D006BFB54 /* Sources */,
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = CocoaTouchBrowser;
+ productName = CocoaTouchBrowser;
+ productReference = 1D6058910D05DD3D006BFB54 /* CocoaTouchBrowser.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "CocoaTouchBrowser" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ en,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 1D6058900D05DD3D006BFB54 /* CocoaTouchBrowser */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 1D60588D0D05DD3D006BFB54 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E4A7DC0B1085A4B300E6ADE2 /* MainWindow.xib in Resources */,
+ E4A7DC0C1085A4B300E6ADE2 /* RootViewController.xib in Resources */,
+ E445E63C144997E800F221B3 /* README in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 1D60588E0D05DD3D006BFB54 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E4A7DC061085A49400E6ADE2 /* CocoaTouchBrowserAppDelegate.m in Sources */,
+ E4A7DC071085A49400E6ADE2 /* main.m in Sources */,
+ E4A7DC081085A49400E6ADE2 /* RootViewController.m in Sources */,
+ E4A7DCF31085AC7000E6ADE2 /* MediaBrowserWrapper.mm in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1D6058940D05DD3E006BFB54 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = (
+ armv6,
+ armv7,
+ );
+ "ARCHS[sdk=iphonesimulator*]" = i386;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../../Targets/universal-apple-ios/Debug\"",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = CocoaTouchBrowser_Prefix.pch;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = "CocoaTouchBrowser-Info.plist";
+ OTHER_LDFLAGS = (
+ "-all_load",
+ "-ObjC",
+ "-framework",
+ Platinum,
+ );
+ PREBINDING = "";
+ PRODUCT_NAME = CocoaTouchBrowser;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = "i386 armv6 armv7";
+ };
+ name = Debug;
+ };
+ 1D6058950D05DD3E006BFB54 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = (
+ armv6,
+ armv7,
+ );
+ "ARCHS[sdk=iphonesimulator*]" = i386;
+ COPY_PHASE_STRIP = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../../Targets/universal-apple-ios/Release\"",
+ );
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = CocoaTouchBrowser_Prefix.pch;
+ GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = "CocoaTouchBrowser-Info.plist";
+ OTHER_LDFLAGS = (
+ "-all_load",
+ "-ObjC",
+ "-framework",
+ Platinum,
+ );
+ PREBINDING = "";
+ PRODUCT_NAME = CocoaTouchBrowser;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ VALID_ARCHS = "i386 armv6 armv7";
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CODE_SIGN_IDENTITY = "Don't Code Sign";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Sylvain Rebaud (932JA7U7P9)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_VERSION = 4.2;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ PROVISIONING_PROFILE = "";
+ "PROVISIONING_PROFILE[sdk=iphoneos*]" = "5C4C1752-A4F3-4DEF-9250-B6A4DBB099B5";
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CODE_SIGN_IDENTITY = "Don't Code Sign";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Sylvain Rebaud (932JA7U7P9)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_VERSION = 4.2;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ PROVISIONING_PROFILE = "";
+ "PROVISIONING_PROFILE[sdk=iphoneos*]" = "5C4C1752-A4F3-4DEF-9250-B6A4DBB099B5";
+ SDKROOT = iphoneos;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "CocoaTouchBrowser" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1D6058940D05DD3E006BFB54 /* Debug */,
+ 1D6058950D05DD3E006BFB54 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "CocoaTouchBrowser" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser_Prefix.pch b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser_Prefix.pch
new file mode 100755
index 0000000..d59fade
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/CocoaTouchBrowser_Prefix.pch
@@ -0,0 +1,9 @@
+//
+// Prefix header for all source files of the 'CocoaTouchBrowser' target in the 'CocoaTouchBrowser' project
+//
+#import <Availability.h>
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+ #import <UIKit/UIKit.h>
+#endif
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/README b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/README
new file mode 100644
index 0000000..1da55e2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/CocoaTouchBrowser/README
@@ -0,0 +1,5 @@
+Run the target Platinum-iPhone-Framework-Universal of Platinum.xcodeproj project to build the Platinum framework which this sample needs.
+The framework will end up in Targets/universal-apple-iphoneos/Debug (or Release)
+
+Alternatively you can use scons :
+> scons build_config=Debug target=universal-apple-macosx-xcode \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/MobileMediaServer-Info.plist b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/MobileMediaServer-Info.plist
new file mode 100644
index 0000000..b0de486
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/MobileMediaServer-Info.plist
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.plutinosoft.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UIMainStoryboardFile</key>
+ <string>Main</string>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/project.pbxproj b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..bebf72e
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/project.pbxproj
@@ -0,0 +1,3653 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ E42D3B040FDC890A0045379C /* Apps */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = E42D3B170FDC894C0045379C /* Build configuration list for PBXAggregateTarget "Apps" */;
+ buildPhases = (
+ );
+ dependencies = (
+ E42D3B080FDC890F0045379C /* PBXTargetDependency */,
+ E42D3B0A0FDC890F0045379C /* PBXTargetDependency */,
+ E42D3B0C0FDC890F0045379C /* PBXTargetDependency */,
+ E42D3B0E0FDC890F0045379C /* PBXTargetDependency */,
+ );
+ name = Apps;
+ productName = Apps;
+ };
+ E42D3B640FDC8A120045379C /* Tests */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = E42D3B910FDC8AC10045379C /* Build configuration list for PBXAggregateTarget "Tests" */;
+ buildPhases = (
+ );
+ dependencies = (
+ E42D3B680FDC8A180045379C /* PBXTargetDependency */,
+ E44470C112C31C1100E01480 /* PBXTargetDependency */,
+ E42D3B6A0FDC8A180045379C /* PBXTargetDependency */,
+ E42D3B6C0FDC8A180045379C /* PBXTargetDependency */,
+ E42D3B6E0FDC8A180045379C /* PBXTargetDependency */,
+ E42D3B700FDC8A180045379C /* PBXTargetDependency */,
+ );
+ name = Tests;
+ productName = Tests;
+ };
+ E42D3B730FDC8A210045379C /* All */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = E42D3B920FDC8AC10045379C /* Build configuration list for PBXAggregateTarget "All" */;
+ buildPhases = (
+ );
+ dependencies = (
+ E44E2BD91AE775600092347B /* PBXTargetDependency */,
+ E42D3B770FDC8A290045379C /* PBXTargetDependency */,
+ E42D3B790FDC8A290045379C /* PBXTargetDependency */,
+ E459CC2811F82C7F00621896 /* PBXTargetDependency */,
+ );
+ name = All;
+ productName = All;
+ };
+ E44E2BD01AE775510092347B /* Frameworks */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = E44E2BD11AE775510092347B /* Build configuration list for PBXAggregateTarget "Frameworks" */;
+ buildPhases = (
+ );
+ dependencies = (
+ E44E2BD51AE7755C0092347B /* PBXTargetDependency */,
+ E44E2BD71AE7755C0092347B /* PBXTargetDependency */,
+ );
+ name = Frameworks;
+ productName = Frameworks;
+ };
+ E459CC2111F82C3F00621896 /* Help */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = E459CC2411F82C5E00621896 /* Build configuration list for PBXAggregateTarget "Help" */;
+ buildPhases = (
+ E459CC2011F82C3F00621896 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = Help;
+ productName = Help;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ E410161A1ACFA761000E994F /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E41016181ACFA761000E994F /* LaunchScreen.xib */; };
+ E410161B1ACFA761000E994F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E41016191ACFA761000E994F /* Main.storyboard */; };
+ E41016261ACFA826000E994F /* Platinum.h in Headers */ = {isa = PBXBuildFile; fileRef = E41016251ACFA826000E994F /* Platinum.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016381ACFA826000E994F /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E41016211ACFA826000E994F /* Platinum.framework */; };
+ E41016391ACFA826000E994F /* Platinum.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E41016211ACFA826000E994F /* Platinum.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ E41016411ACFA858000E994F /* PltAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43154FE0D6FFDEB00899579 /* PltAction.cpp */; };
+ E41016421ACFA858000E994F /* PltAction.h in Headers */ = {isa = PBXBuildFile; fileRef = E43154FF0D6FFDEB00899579 /* PltAction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016431ACFA858000E994F /* PltArgument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155000D6FFDEB00899579 /* PltArgument.cpp */; };
+ E41016441ACFA858000E994F /* PltArgument.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155010D6FFDEB00899579 /* PltArgument.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016451ACFA858000E994F /* PltConstants.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4BA7CBC0FE2200700A4D16B /* PltConstants.cpp */; };
+ E41016461ACFA858000E994F /* PltConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E4BA7CBB0FE2200700A4D16B /* PltConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016471ACFA858000E994F /* PltCtrlPoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155020D6FFDEB00899579 /* PltCtrlPoint.cpp */; };
+ E41016481ACFA858000E994F /* PltCtrlPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155030D6FFDEB00899579 /* PltCtrlPoint.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016491ACFA858000E994F /* PltCtrlPointTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155040D6FFDEB00899579 /* PltCtrlPointTask.cpp */; };
+ E410164A1ACFA858000E994F /* PltCtrlPointTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155050D6FFDEB00899579 /* PltCtrlPointTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410164B1ACFA858000E994F /* PltDatagramStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155060D6FFDEB00899579 /* PltDatagramStream.cpp */; };
+ E410164C1ACFA858000E994F /* PltDatagramStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155070D6FFDEB00899579 /* PltDatagramStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410164D1ACFA858000E994F /* PltDeviceData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155080D6FFDEB00899579 /* PltDeviceData.cpp */; };
+ E410164E1ACFA858000E994F /* PltDeviceData.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155090D6FFDEB00899579 /* PltDeviceData.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410164F1ACFA858000E994F /* PltDeviceHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431550A0D6FFDEB00899579 /* PltDeviceHost.cpp */; };
+ E41016501ACFA858000E994F /* PltDeviceHost.h in Headers */ = {isa = PBXBuildFile; fileRef = E431550B0D6FFDEB00899579 /* PltDeviceHost.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016511ACFA858000E994F /* PltEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431550E0D6FFDEB00899579 /* PltEvent.cpp */; };
+ E41016521ACFA858000E994F /* PltEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = E431550F0D6FFDEB00899579 /* PltEvent.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016531ACFA858000E994F /* PltHttp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155100D6FFDEB00899579 /* PltHttp.cpp */; };
+ E41016541ACFA858000E994F /* PltHttp.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155110D6FFDEB00899579 /* PltHttp.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016551ACFA858000E994F /* PltHttpClientTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155120D6FFDEB00899579 /* PltHttpClientTask.cpp */; };
+ E41016561ACFA858000E994F /* PltHttpClientTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155130D6FFDEB00899579 /* PltHttpClientTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016571ACFA858000E994F /* PltHttpServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155140D6FFDEB00899579 /* PltHttpServer.cpp */; };
+ E41016581ACFA858000E994F /* PltHttpServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155150D6FFDEB00899579 /* PltHttpServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016591ACFA858000E994F /* PltHttpServerTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155170D6FFDEB00899579 /* PltHttpServerTask.cpp */; };
+ E410165A1ACFA858000E994F /* PltHttpServerTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155180D6FFDEB00899579 /* PltHttpServerTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410165B1ACFA858000E994F /* PltIconsData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E9060FE4B12A00BEDFA6 /* PltIconsData.cpp */; };
+ E410165C1ACFA858000E994F /* PltMimeType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E48D4DA613B51CB600359E06 /* PltMimeType.cpp */; };
+ E410165D1ACFA858000E994F /* PltMimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = E48D4DA713B51CB600359E06 /* PltMimeType.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410165E1ACFA858000E994F /* PltProtocolInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E48D4D8F13B51BAC00359E06 /* PltProtocolInfo.cpp */; };
+ E410165F1ACFA858000E994F /* PltProtocolInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E48D4D9013B51BAC00359E06 /* PltProtocolInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016601ACFA858000E994F /* PltService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155210D6FFDEB00899579 /* PltService.cpp */; };
+ E41016611ACFA858000E994F /* PltService.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155220D6FFDEB00899579 /* PltService.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016621ACFA858000E994F /* PltSsdp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155230D6FFDEB00899579 /* PltSsdp.cpp */; };
+ E41016631ACFA858000E994F /* PltSsdp.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155240D6FFDEB00899579 /* PltSsdp.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016641ACFA858000E994F /* PltStateVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155260D6FFDEB00899579 /* PltStateVariable.cpp */; };
+ E41016651ACFA858000E994F /* PltStateVariable.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155270D6FFDEB00899579 /* PltStateVariable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016661ACFA858000E994F /* PltTaskManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431552A0D6FFDEB00899579 /* PltTaskManager.cpp */; };
+ E41016671ACFA858000E994F /* PltTaskManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E431552B0D6FFDEB00899579 /* PltTaskManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016681ACFA858000E994F /* PltThreadTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431552C0D6FFDEB00899579 /* PltThreadTask.cpp */; };
+ E41016691ACFA858000E994F /* PltThreadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E431552D0D6FFDEB00899579 /* PltThreadTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410166A1ACFA858000E994F /* PltUPnP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431552E0D6FFDEB00899579 /* PltUPnP.cpp */; };
+ E410166B1ACFA858000E994F /* PltUPnP.h in Headers */ = {isa = PBXBuildFile; fileRef = E431552F0D6FFDEB00899579 /* PltUPnP.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410166C1ACFA858000E994F /* PltUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155320D6FFDEB00899579 /* PltUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410166D1ACFA887000E994F /* PltXbox360.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E426B3271130DF9500C58542 /* PltXbox360.cpp */; };
+ E410166E1ACFA887000E994F /* PltXbox360.h in Headers */ = {isa = PBXBuildFile; fileRef = E426B3281130DF9500C58542 /* PltXbox360.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410166F1ACFA887000E994F /* X_MS_MediaReceiverRegistrarSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB7F108596C800E6ADE2 /* X_MS_MediaReceiverRegistrarSCPD.cpp */; };
+ E41016701ACFA887000E994F /* PltMediaConnect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155960D6FFE4C00899579 /* PltMediaConnect.cpp */; };
+ E41016711ACFA887000E994F /* PltMediaConnect.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155970D6FFE4C00899579 /* PltMediaConnect.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016721ACFA893000E994F /* AVTransportSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB76108596B900E6ADE2 /* AVTransportSCPD.cpp */; };
+ E41016731ACFA893000E994F /* RdrConnectionManagerSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB77108596B900E6ADE2 /* RdrConnectionManagerSCPD.cpp */; };
+ E41016741ACFA893000E994F /* RenderingControlSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB78108596B900E6ADE2 /* RenderingControlSCPD.cpp */; };
+ E41016751ACFA893000E994F /* PltMediaController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431559D0D6FFE4C00899579 /* PltMediaController.cpp */; };
+ E41016761ACFA893000E994F /* PltMediaController.h in Headers */ = {isa = PBXBuildFile; fileRef = E431559E0D6FFE4C00899579 /* PltMediaController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016771ACFA893000E994F /* PltMediaRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155A00D6FFE4C00899579 /* PltMediaRenderer.cpp */; };
+ E41016781ACFA893000E994F /* PltMediaRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155A10D6FFE4C00899579 /* PltMediaRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016791ACFA8A1000E994F /* ContentDirectorySCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E402C7541297CECB00565B76 /* ContentDirectorySCPD.cpp */; };
+ E410167A1ACFA8A1000E994F /* ConnectionManagerSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB82108596E400E6ADE2 /* ConnectionManagerSCPD.cpp */; };
+ E410167B1ACFA8A1000E994F /* ContentDirectorywSearchSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB83108596E400E6ADE2 /* ContentDirectorywSearchSCPD.cpp */; };
+ E410167C1ACFA8A1000E994F /* PltDidl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155A80D6FFE4C00899579 /* PltDidl.cpp */; };
+ E410167D1ACFA8A1000E994F /* PltDidl.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155A90D6FFE4C00899579 /* PltDidl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410167E1ACFA8A1000E994F /* PltFileMediaServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155AA0D6FFE4C00899579 /* PltFileMediaServer.cpp */; };
+ E410167F1ACFA8A1000E994F /* PltFileMediaServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155AB0D6FFE4C00899579 /* PltFileMediaServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016801ACFA8A1000E994F /* PltMediaBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155AC0D6FFE4C00899579 /* PltMediaBrowser.cpp */; };
+ E41016811ACFA8A1000E994F /* PltMediaBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155AD0D6FFE4C00899579 /* PltMediaBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016821ACFA8A1000E994F /* PltMediaCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155AF0D6FFE4C00899579 /* PltMediaCache.cpp */; };
+ E41016831ACFA8A1000E994F /* PltMediaCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B00D6FFE4C00899579 /* PltMediaCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016841ACFA8A1000E994F /* PltMediaItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155B10D6FFE4C00899579 /* PltMediaItem.cpp */; };
+ E41016851ACFA8A1000E994F /* PltMediaItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B20D6FFE4C00899579 /* PltMediaItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016861ACFA8A1000E994F /* PltMediaServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155B50D6FFE4C00899579 /* PltMediaServer.cpp */; };
+ E41016871ACFA8A1000E994F /* PltMediaServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B60D6FFE4C00899579 /* PltMediaServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016881ACFA8A1000E994F /* PltSyncMediaBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155B80D6FFE4C00899579 /* PltSyncMediaBrowser.cpp */; };
+ E41016891ACFA8A1000E994F /* PltSyncMediaBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B90D6FFE4C00899579 /* PltSyncMediaBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410168A1ACFA8B9000E994F /* PltMediaServerObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E4374C1512417AA800000109 /* PltMediaServerObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410168B1ACFA8B9000E994F /* PltMediaServerObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4374C1612417AA800000109 /* PltMediaServerObject.mm */; };
+ E410168C1ACFA8B9000E994F /* PltUPnPObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E4374C1712417AA800000109 /* PltUPnPObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410168D1ACFA8B9000E994F /* PltUPnPObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4374C1812417AA800000109 /* PltUPnPObject.mm */; };
+ E410168E1ACFA8B9000E994F /* PltDownloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69E211E6F0D90024CAD4 /* PltDownloader.cpp */; };
+ E410168F1ACFA8B9000E994F /* PltDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69E311E6F0D90024CAD4 /* PltDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016901ACFA8B9000E994F /* PltStreamPump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69E411E6F0D90024CAD4 /* PltStreamPump.cpp */; };
+ E41016911ACFA8B9000E994F /* PltStreamPump.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69E511E6F0D90024CAD4 /* PltStreamPump.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016921ACFA8B9000E994F /* PltFrameBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C699E11E6ED710024CAD4 /* PltFrameBuffer.cpp */; };
+ E41016931ACFA8B9000E994F /* PltFrameBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C699F11E6ED710024CAD4 /* PltFrameBuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016941ACFA8B9000E994F /* PltFrameServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A011E6ED710024CAD4 /* PltFrameServer.cpp */; };
+ E41016951ACFA8B9000E994F /* PltFrameServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A111E6ED710024CAD4 /* PltFrameServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016961ACFA8B9000E994F /* PltFrameStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A211E6ED710024CAD4 /* PltFrameStream.cpp */; };
+ E41016971ACFA8B9000E994F /* PltFrameStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A311E6ED710024CAD4 /* PltFrameStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E41016981ACFA8B9000E994F /* PltLeaks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A411E6ED710024CAD4 /* PltLeaks.cpp */; };
+ E41016991ACFA8B9000E994F /* PltLeaks.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A511E6ED710024CAD4 /* PltLeaks.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410169A1ACFA8B9000E994F /* PltMetadataHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A611E6ED710024CAD4 /* PltMetadataHandler.cpp */; };
+ E410169B1ACFA8B9000E994F /* PltMetadataHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A711E6ED710024CAD4 /* PltMetadataHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410169C1ACFA8B9000E994F /* PltRingBufferStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A811E6ED710024CAD4 /* PltRingBufferStream.cpp */; };
+ E410169D1ACFA8B9000E994F /* PltRingBufferStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A911E6ED710024CAD4 /* PltRingBufferStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E410169F1ACFA8CC000E994F /* PltVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = E43EEEFF101E1AEF007A9CE7 /* PltVersion.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E423F36918415DF900E24E39 /* SsdpTest1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E423F35A18415DA800E24E39 /* SsdpTest1.cpp */; };
+ E42D3AC40FDC87300045379C /* MediaCrawler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3A980FDC85E70045379C /* MediaCrawler.cpp */; };
+ E42D3AC50FDC87310045379C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3A970FDC85E70045379C /* main.cpp */; };
+ E42D3B110FDC89200045379C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3A950FDC85E70045379C /* main.cpp */; };
+ E42D3B120FDC89260045379C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3A9C0FDC85E70045379C /* main.cpp */; };
+ E42D3B130FDC89270045379C /* PltMicroMediaController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3A9D0FDC85E70045379C /* PltMicroMediaController.cpp */; };
+ E42D3B150FDC892B0045379C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3A930FDC85E70045379C /* main.cpp */; };
+ E42D3B220FDC89690045379C /* FileMediaServerTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3AAB0FDC86A60045379C /* FileMediaServerTest.cpp */; };
+ E42D3B330FDC89990045379C /* HttpTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3AAD0FDC86A60045379C /* HttpTest.cpp */; };
+ E42D3B400FDC89C40045379C /* LightSampleTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3AB00FDC86A60045379C /* LightSampleTest.cpp */; };
+ E42D3B410FDC89C40045379C /* PltLightSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3AB10FDC86A60045379C /* PltLightSample.cpp */; };
+ E42D3B4C0FDC89D90045379C /* MediaRendererTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3AB30FDC86A60045379C /* MediaRendererTest.cpp */; };
+ E42D3B570FDC89ED0045379C /* SimpleTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3AB70FDC86A60045379C /* SimpleTest.cpp */; };
+ E42D3B580FDC89ED0045379C /* PltSimple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42D3AB60FDC86A60045379C /* PltSimple.cpp */; };
+ E437424C123FFE9100000109 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E4374242123FFE9100000109 /* InfoPlist.strings */; };
+ E437424D123FFE9100000109 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E4374244123FFE9100000109 /* MainMenu.xib */; };
+ E437424E123FFE9100000109 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4374246123FFE9100000109 /* main.mm */; };
+ E4374250123FFE9100000109 /* MediaServerCocoaTest_AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4374249123FFE9100000109 /* MediaServerCocoaTest_AppDelegate.mm */; };
+ E4374251123FFE9100000109 /* MediaServerCocoaTest_DataModel.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = E437424A123FFE9100000109 /* MediaServerCocoaTest_DataModel.xcdatamodel */; };
+ E43F6BC910F1B78400C97612 /* TimeTest1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F6BC810F1B78400C97612 /* TimeTest1.cpp */; };
+ E4446FAB12C3168900E01480 /* MediaServerCocoaTestController.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4446FAA12C3168900E01480 /* MediaServerCocoaTestController.mm */; };
+ E44E2B251AE761220092347B /* PltMediaServerObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4374C1612417AA800000109 /* PltMediaServerObject.mm */; };
+ E44E2B261AE761220092347B /* PltFrameServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A011E6ED710024CAD4 /* PltFrameServer.cpp */; };
+ E44E2B271AE761220092347B /* PltRingBufferStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A811E6ED710024CAD4 /* PltRingBufferStream.cpp */; };
+ E44E2B281AE761220092347B /* PltHttp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155100D6FFDEB00899579 /* PltHttp.cpp */; };
+ E44E2B291AE761220092347B /* PltDeviceHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431550A0D6FFDEB00899579 /* PltDeviceHost.cpp */; };
+ E44E2B2A1AE761220092347B /* PltMediaController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431559D0D6FFE4C00899579 /* PltMediaController.cpp */; };
+ E44E2B2B1AE761220092347B /* PltProtocolInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E48D4D8F13B51BAC00359E06 /* PltProtocolInfo.cpp */; };
+ E44E2B2C1AE761220092347B /* PltCtrlPoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155020D6FFDEB00899579 /* PltCtrlPoint.cpp */; };
+ E44E2B2D1AE761220092347B /* X_MS_MediaReceiverRegistrarSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB7F108596C800E6ADE2 /* X_MS_MediaReceiverRegistrarSCPD.cpp */; };
+ E44E2B2E1AE761220092347B /* RdrConnectionManagerSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB77108596B900E6ADE2 /* RdrConnectionManagerSCPD.cpp */; };
+ E44E2B2F1AE761220092347B /* PltStreamPump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69E411E6F0D90024CAD4 /* PltStreamPump.cpp */; };
+ E44E2B301AE761220092347B /* RenderingControlSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB78108596B900E6ADE2 /* RenderingControlSCPD.cpp */; };
+ E44E2B311AE761220092347B /* PltMediaItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155B10D6FFE4C00899579 /* PltMediaItem.cpp */; };
+ E44E2B321AE761220092347B /* PltMediaRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155A00D6FFE4C00899579 /* PltMediaRenderer.cpp */; };
+ E44E2B331AE761220092347B /* PltFileMediaServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155AA0D6FFE4C00899579 /* PltFileMediaServer.cpp */; };
+ E44E2B341AE761220092347B /* PltDidl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155A80D6FFE4C00899579 /* PltDidl.cpp */; };
+ E44E2B351AE761220092347B /* PltDatagramStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155060D6FFDEB00899579 /* PltDatagramStream.cpp */; };
+ E44E2B361AE761220092347B /* PltThreadTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431552C0D6FFDEB00899579 /* PltThreadTask.cpp */; };
+ E44E2B371AE761220092347B /* PltCtrlPointTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155040D6FFDEB00899579 /* PltCtrlPointTask.cpp */; };
+ E44E2B381AE761220092347B /* PltFrameStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A211E6ED710024CAD4 /* PltFrameStream.cpp */; };
+ E44E2B391AE761220092347B /* ContentDirectorywSearchSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB83108596E400E6ADE2 /* ContentDirectorywSearchSCPD.cpp */; };
+ E44E2B3A1AE761220092347B /* PltMetadataHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A611E6ED710024CAD4 /* PltMetadataHandler.cpp */; };
+ E44E2B3B1AE761220092347B /* PltUPnP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431552E0D6FFDEB00899579 /* PltUPnP.cpp */; };
+ E44E2B3C1AE761220092347B /* PltEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431550E0D6FFDEB00899579 /* PltEvent.cpp */; };
+ E44E2B3D1AE761220092347B /* PltHttpServerTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155170D6FFDEB00899579 /* PltHttpServerTask.cpp */; };
+ E44E2B3E1AE761220092347B /* PltDownloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69E211E6F0D90024CAD4 /* PltDownloader.cpp */; };
+ E44E2B3F1AE761220092347B /* PltHttpClientTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155120D6FFDEB00899579 /* PltHttpClientTask.cpp */; };
+ E44E2B401AE761220092347B /* PltMediaConnect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155960D6FFE4C00899579 /* PltMediaConnect.cpp */; };
+ E44E2B411AE761220092347B /* PltMediaBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155AC0D6FFE4C00899579 /* PltMediaBrowser.cpp */; };
+ E44E2B421AE761220092347B /* PltXbox360.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E426B3271130DF9500C58542 /* PltXbox360.cpp */; };
+ E44E2B431AE761220092347B /* AVTransportSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB76108596B900E6ADE2 /* AVTransportSCPD.cpp */; };
+ E44E2B441AE761220092347B /* PltLeaks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C69A411E6ED710024CAD4 /* PltLeaks.cpp */; };
+ E44E2B451AE761220092347B /* PltTaskManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E431552A0D6FFDEB00899579 /* PltTaskManager.cpp */; };
+ E44E2B461AE761220092347B /* PltMediaCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155AF0D6FFE4C00899579 /* PltMediaCache.cpp */; };
+ E44E2B471AE761220092347B /* PltAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43154FE0D6FFDEB00899579 /* PltAction.cpp */; };
+ E44E2B481AE761220092347B /* PltSsdp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155230D6FFDEB00899579 /* PltSsdp.cpp */; };
+ E44E2B491AE761220092347B /* PltIconsData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E9060FE4B12A00BEDFA6 /* PltIconsData.cpp */; };
+ E44E2B4A1AE761220092347B /* PltArgument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155000D6FFDEB00899579 /* PltArgument.cpp */; };
+ E44E2B4B1AE761220092347B /* PltFrameBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40C699E11E6ED710024CAD4 /* PltFrameBuffer.cpp */; };
+ E44E2B4C1AE761220092347B /* PltHttpServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155140D6FFDEB00899579 /* PltHttpServer.cpp */; };
+ E44E2B4D1AE761220092347B /* PltStateVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155260D6FFDEB00899579 /* PltStateVariable.cpp */; };
+ E44E2B4E1AE761220092347B /* PltMediaServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155B50D6FFE4C00899579 /* PltMediaServer.cpp */; };
+ E44E2B4F1AE761220092347B /* PltSyncMediaBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155B80D6FFE4C00899579 /* PltSyncMediaBrowser.cpp */; };
+ E44E2B501AE761220092347B /* PltDeviceData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155080D6FFDEB00899579 /* PltDeviceData.cpp */; };
+ E44E2B511AE761220092347B /* PltConstants.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4BA7CBC0FE2200700A4D16B /* PltConstants.cpp */; };
+ E44E2B521AE761220092347B /* ContentDirectorySCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E402C7541297CECB00565B76 /* ContentDirectorySCPD.cpp */; };
+ E44E2B531AE761220092347B /* PltUPnPObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4374C1812417AA800000109 /* PltUPnPObject.mm */; };
+ E44E2B541AE761220092347B /* PltService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43155210D6FFDEB00899579 /* PltService.cpp */; };
+ E44E2B551AE761220092347B /* PltMimeType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E48D4DA613B51CB600359E06 /* PltMimeType.cpp */; };
+ E44E2B561AE761220092347B /* ConnectionManagerSCPD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A7DB82108596E400E6ADE2 /* ConnectionManagerSCPD.cpp */; };
+ E44E2B5A1AE761220092347B /* PltTaskManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E431552B0D6FFDEB00899579 /* PltTaskManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B5B1AE761220092347B /* PltDeviceHost.h in Headers */ = {isa = PBXBuildFile; fileRef = E431550B0D6FFDEB00899579 /* PltDeviceHost.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B5C1AE761220092347B /* PltLeaks.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A511E6ED710024CAD4 /* PltLeaks.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B5D1AE761220092347B /* PltHttpServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155150D6FFDEB00899579 /* PltHttpServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B5E1AE761220092347B /* PltMediaItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B20D6FFE4C00899579 /* PltMediaItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B5F1AE761220092347B /* PltFrameBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C699F11E6ED710024CAD4 /* PltFrameBuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B601AE761220092347B /* PltMediaBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155AD0D6FFE4C00899579 /* PltMediaBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B611AE761220092347B /* PltDatagramStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155070D6FFDEB00899579 /* PltDatagramStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B621AE761220092347B /* PltUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155320D6FFDEB00899579 /* PltUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B631AE761220092347B /* PltRingBufferStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A911E6ED710024CAD4 /* PltRingBufferStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B641AE761220092347B /* PltSsdp.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155240D6FFDEB00899579 /* PltSsdp.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B651AE761220092347B /* Platinum.h in Headers */ = {isa = PBXBuildFile; fileRef = E41016251ACFA826000E994F /* Platinum.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B661AE761220092347B /* PltConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E4BA7CBB0FE2200700A4D16B /* PltConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B671AE761220092347B /* PltThreadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E431552D0D6FFDEB00899579 /* PltThreadTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B681AE761220092347B /* PltUPnPObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E4374C1712417AA800000109 /* PltUPnPObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B691AE761220092347B /* PltProtocolInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E48D4D9013B51BAC00359E06 /* PltProtocolInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B6A1AE761220092347B /* PltCtrlPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155030D6FFDEB00899579 /* PltCtrlPoint.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B6B1AE761220092347B /* PltService.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155220D6FFDEB00899579 /* PltService.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B6C1AE761220092347B /* PltXbox360.h in Headers */ = {isa = PBXBuildFile; fileRef = E426B3281130DF9500C58542 /* PltXbox360.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B6D1AE761220092347B /* PltHttp.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155110D6FFDEB00899579 /* PltHttp.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B6E1AE761220092347B /* PltVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = E43EEEFF101E1AEF007A9CE7 /* PltVersion.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B6F1AE761220092347B /* PltMediaConnect.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155970D6FFE4C00899579 /* PltMediaConnect.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B701AE761220092347B /* PltHttpServerTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155180D6FFDEB00899579 /* PltHttpServerTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B711AE761220092347B /* PltMediaServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B60D6FFE4C00899579 /* PltMediaServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B721AE761220092347B /* PltFileMediaServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155AB0D6FFE4C00899579 /* PltFileMediaServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B731AE761220092347B /* PltStreamPump.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69E511E6F0D90024CAD4 /* PltStreamPump.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B741AE761220092347B /* PltMediaCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B00D6FFE4C00899579 /* PltMediaCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B751AE761220092347B /* PltFrameServer.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A111E6ED710024CAD4 /* PltFrameServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B761AE761220092347B /* PltMediaRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155A10D6FFE4C00899579 /* PltMediaRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B771AE761220092347B /* PltArgument.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155010D6FFDEB00899579 /* PltArgument.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B781AE761220092347B /* PltHttpClientTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155130D6FFDEB00899579 /* PltHttpClientTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B791AE761220092347B /* PltSyncMediaBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155B90D6FFE4C00899579 /* PltSyncMediaBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B7A1AE761220092347B /* PltStateVariable.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155270D6FFDEB00899579 /* PltStateVariable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B7B1AE761220092347B /* PltDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69E311E6F0D90024CAD4 /* PltDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B7C1AE761220092347B /* PltDidl.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155A90D6FFE4C00899579 /* PltDidl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B7D1AE761220092347B /* PltUPnP.h in Headers */ = {isa = PBXBuildFile; fileRef = E431552F0D6FFDEB00899579 /* PltUPnP.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B7E1AE761220092347B /* PltCtrlPointTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155050D6FFDEB00899579 /* PltCtrlPointTask.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B7F1AE761220092347B /* PltMetadataHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A711E6ED710024CAD4 /* PltMetadataHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B801AE761220092347B /* PltAction.h in Headers */ = {isa = PBXBuildFile; fileRef = E43154FF0D6FFDEB00899579 /* PltAction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B811AE761220092347B /* PltEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = E431550F0D6FFDEB00899579 /* PltEvent.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B821AE761220092347B /* PltMimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = E48D4DA713B51CB600359E06 /* PltMimeType.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B831AE761220092347B /* PltMediaServerObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E4374C1512417AA800000109 /* PltMediaServerObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B841AE761220092347B /* PltFrameStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E40C69A311E6ED710024CAD4 /* PltFrameStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B851AE761220092347B /* PltMediaController.h in Headers */ = {isa = PBXBuildFile; fileRef = E431559E0D6FFE4C00899579 /* PltMediaController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2B861AE761220092347B /* PltDeviceData.h in Headers */ = {isa = PBXBuildFile; fileRef = E43155090D6FFDEB00899579 /* PltDeviceData.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E44E2BC41AE76E0F0092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2BC51AE76E330092347B /* Platinum.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ E44E2BCB1AE76FF90092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BCC1AE770150092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E40616C01ADE5C9A008BDAEB /* Neptune.framework */; };
+ E44E2BCD1AE7701D0092347B /* Neptune.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E40616C01ADE5C9A008BDAEB /* Neptune.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ E44E2BCE1AE7702D0092347B /* Neptune.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ E44E2BCF1AE770500092347B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4374268123FFF5B00000109 /* Cocoa.framework */; };
+ E44E2BDE1AE776DD0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BDF1AE776E80092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2BF41AE779880092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BF51AE779890092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BF61AE7798A0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BF71AE7798A0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BF81AE7798B0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BF91AE7798B0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BFA1AE7798C0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BFB1AE7798C0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BFC1AE7798D0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BFD1AE7798D0092347B /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+ E44E2BFE1AE779950092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2BFF1AE779960092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C001AE779960092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C011AE779970092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C021AE779970092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C031AE779970092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C041AE779980092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C051AE779980092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C061AE779990092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E44E2C071AE779990092347B /* Platinum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8B1AE761220092347B /* Platinum.framework */; };
+ E45332B21AAED318004A52FD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E45332B11AAED318004A52FD /* main.m */; };
+ E45332B51AAED318004A52FD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E45332B41AAED318004A52FD /* AppDelegate.m */; };
+ E45332B81AAED318004A52FD /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = E45332B71AAED318004A52FD /* ViewController.mm */; };
+ E45BD1F71FC95BFC00F1D812 /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E40616C01ADE5C9A008BDAEB /* Neptune.framework */; };
+ E48EAA811AF1EDD800D9EDC0 /* Neptune.h in Headers */ = {isa = PBXBuildFile; fileRef = E48EAA801AF1EDD800D9EDC0 /* Neptune.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E48EAA821AF1EDD800D9EDC0 /* Neptune.h in Headers */ = {isa = PBXBuildFile; fileRef = E48EAA801AF1EDD800D9EDC0 /* Neptune.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E4B2A5A71FC90AE500C891D7 /* Neptune.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E44E2B8D1AE7622F0092347B /* Neptune.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ E41016361ACFA826000E994F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E41016201ACFA826000E994F;
+ remoteInfo = Platinum;
+ };
+ E42D3B070FDC890F0045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3ABC0FDC87130045379C;
+ remoteInfo = MediaCrawler;
+ };
+ E42D3B090FDC890F0045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3AD20FDC87DB0045379C;
+ remoteInfo = MediaConnect;
+ };
+ E42D3B0B0FDC890F0045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3ADC0FDC87F50045379C;
+ remoteInfo = MicroMediaController;
+ };
+ E42D3B0D0FDC890F0045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3AE60FDC880D0045379C;
+ remoteInfo = FrameStreamer;
+ };
+ E42D3B670FDC8A180045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3B1A0FDC895A0045379C;
+ remoteInfo = FileMediaServerTest;
+ };
+ E42D3B690FDC8A180045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3B250FDC89720045379C;
+ remoteInfo = HttpTest;
+ };
+ E42D3B6B0FDC8A180045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3B380FDC89B70045379C;
+ remoteInfo = LightSampleTest;
+ };
+ E42D3B6D0FDC8A180045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3B440FDC89CD0045379C;
+ remoteInfo = MediaRendererTest;
+ };
+ E42D3B6F0FDC8A180045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3B4F0FDC89E10045379C;
+ remoteInfo = SimpleTest;
+ };
+ E42D3B760FDC8A290045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3B040FDC890A0045379C;
+ remoteInfo = Apps;
+ };
+ E42D3B780FDC8A290045379C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E42D3B640FDC8A120045379C;
+ remoteInfo = Tests;
+ };
+ E44470C012C31C1100E01480 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E43741FB123FFB9800000109;
+ remoteInfo = MediaServerCocoaTest;
+ };
+ E44E2BC21AE76D7B0092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BD41AE7755C0092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E41016201ACFA826000E994F;
+ remoteInfo = "Platinum-iOS";
+ };
+ E44E2BD61AE7755C0092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BD81AE775600092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2BD01AE775510092347B;
+ remoteInfo = Frameworks;
+ };
+ E44E2BDA1AE776060092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BE01AE779130092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BE21AE7794D0092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BE41AE779520092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BE61AE779580092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BE81AE7795C0092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BEA1AE779600092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BEC1AE779640092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BEE1AE779680092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BF01AE7796C0092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E44E2BF21AE779700092347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E44E2B231AE761220092347B;
+ remoteInfo = "Platinum-Mac";
+ };
+ E459CC2711F82C7F00621896 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E459CC2111F82C3F00621896;
+ remoteInfo = Help;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ E410163D1ACFA826000E994F /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ E44E2BCD1AE7701D0092347B /* Neptune.framework in Embed Frameworks */,
+ E41016391ACFA826000E994F /* Platinum.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E4516B8E1446C3F600EC613B /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ E44E2BCE1AE7702D0092347B /* Neptune.framework in CopyFiles */,
+ E44E2BC51AE76E330092347B /* Platinum.framework in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ E402C7541297CECB00565B76 /* ContentDirectorySCPD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentDirectorySCPD.cpp; sourceTree = "<group>"; };
+ E40616C01ADE5C9A008BDAEB /* Neptune.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Neptune.framework; path = ../../../Carthage/Build/iOS/Neptune.framework; sourceTree = "<group>"; };
+ E40C699E11E6ED710024CAD4 /* PltFrameBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltFrameBuffer.cpp; sourceTree = "<group>"; };
+ E40C699F11E6ED710024CAD4 /* PltFrameBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltFrameBuffer.h; sourceTree = "<group>"; };
+ E40C69A011E6ED710024CAD4 /* PltFrameServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltFrameServer.cpp; sourceTree = "<group>"; };
+ E40C69A111E6ED710024CAD4 /* PltFrameServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltFrameServer.h; sourceTree = "<group>"; };
+ E40C69A211E6ED710024CAD4 /* PltFrameStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltFrameStream.cpp; sourceTree = "<group>"; };
+ E40C69A311E6ED710024CAD4 /* PltFrameStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltFrameStream.h; sourceTree = "<group>"; };
+ E40C69A411E6ED710024CAD4 /* PltLeaks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltLeaks.cpp; sourceTree = "<group>"; };
+ E40C69A511E6ED710024CAD4 /* PltLeaks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltLeaks.h; sourceTree = "<group>"; };
+ E40C69A611E6ED710024CAD4 /* PltMetadataHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltMetadataHandler.cpp; sourceTree = "<group>"; };
+ E40C69A711E6ED710024CAD4 /* PltMetadataHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltMetadataHandler.h; sourceTree = "<group>"; };
+ E40C69A811E6ED710024CAD4 /* PltRingBufferStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltRingBufferStream.cpp; sourceTree = "<group>"; };
+ E40C69A911E6ED710024CAD4 /* PltRingBufferStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltRingBufferStream.h; sourceTree = "<group>"; };
+ E40C69E211E6F0D90024CAD4 /* PltDownloader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltDownloader.cpp; sourceTree = "<group>"; };
+ E40C69E311E6F0D90024CAD4 /* PltDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltDownloader.h; sourceTree = "<group>"; };
+ E40C69E411E6F0D90024CAD4 /* PltStreamPump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltStreamPump.cpp; sourceTree = "<group>"; };
+ E40C69E511E6F0D90024CAD4 /* PltStreamPump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltStreamPump.h; sourceTree = "<group>"; };
+ E41016161ACFA70C000E994F /* MobileMediaServer-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MobileMediaServer-Info.plist"; sourceTree = "<group>"; };
+ E41016181ACFA761000E994F /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = LaunchScreen.xib; path = ../../../Source/Apps/MobileMediaServer/LaunchScreen.xib; sourceTree = "<group>"; };
+ E41016191ACFA761000E994F /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = ../../../Source/Apps/MobileMediaServer/Main.storyboard; sourceTree = "<group>"; };
+ E41016211ACFA826000E994F /* Platinum.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Platinum.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ E41016241ACFA826000E994F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ E41016251ACFA826000E994F /* Platinum.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Platinum.h; sourceTree = "<group>"; };
+ E423F35A18415DA800E24E39 /* SsdpTest1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SsdpTest1.cpp; path = ../../../Source/Tests/Ssdp/SsdpTest1.cpp; sourceTree = "<group>"; };
+ E423F36818415DC500E24E39 /* SsdpTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SsdpTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E426B3271130DF9500C58542 /* PltXbox360.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltXbox360.cpp; sourceTree = "<group>"; };
+ E426B3281130DF9500C58542 /* PltXbox360.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltXbox360.h; sourceTree = "<group>"; };
+ E4294C6014319C9400B6FDED /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
+ E42D3A930FDC85E70045379C /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../../Source/Apps/FrameStreamer/main.cpp; sourceTree = SOURCE_ROOT; };
+ E42D3A950FDC85E70045379C /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+ E42D3A970FDC85E70045379C /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+ E42D3A980FDC85E70045379C /* MediaCrawler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaCrawler.cpp; sourceTree = "<group>"; };
+ E42D3A990FDC85E70045379C /* MediaCrawler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaCrawler.h; sourceTree = "<group>"; };
+ E42D3A9A0FDC85E70045379C /* StreamHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamHandler.h; sourceTree = "<group>"; };
+ E42D3A9C0FDC85E70045379C /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+ E42D3A9D0FDC85E70045379C /* PltMicroMediaController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltMicroMediaController.cpp; sourceTree = "<group>"; };
+ E42D3A9E0FDC85E70045379C /* PltMicroMediaController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltMicroMediaController.h; sourceTree = "<group>"; };
+ E42D3AAB0FDC86A60045379C /* FileMediaServerTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileMediaServerTest.cpp; sourceTree = "<group>"; usesTabs = 0; };
+ E42D3AAD0FDC86A60045379C /* HttpTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpTest.cpp; sourceTree = "<group>"; };
+ E42D3AAF0FDC86A60045379C /* PltLightSample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltLightSample.h; sourceTree = "<group>"; };
+ E42D3AB00FDC86A60045379C /* LightSampleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LightSampleTest.cpp; sourceTree = "<group>"; };
+ E42D3AB10FDC86A60045379C /* PltLightSample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltLightSample.cpp; sourceTree = "<group>"; };
+ E42D3AB30FDC86A60045379C /* MediaRendererTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRendererTest.cpp; sourceTree = "<group>"; };
+ E42D3AB50FDC86A60045379C /* PltSimple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltSimple.h; sourceTree = "<group>"; };
+ E42D3AB60FDC86A60045379C /* PltSimple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltSimple.cpp; sourceTree = "<group>"; };
+ E42D3AB70FDC86A60045379C /* SimpleTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleTest.cpp; sourceTree = "<group>"; };
+ E42D3ABD0FDC87130045379C /* MediaCrawler */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MediaCrawler; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3AD30FDC87DB0045379C /* MediaConnect */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MediaConnect; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3ADD0FDC87F50045379C /* MicroMediaController */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MicroMediaController; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3AE70FDC880D0045379C /* FrameStreamer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FrameStreamer; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3B1B0FDC895A0045379C /* FileMediaServerTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FileMediaServerTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3B260FDC89720045379C /* HttpTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = HttpTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3B390FDC89B70045379C /* LightSampleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = LightSampleTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3B450FDC89CD0045379C /* MediaRendererTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MediaRendererTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E42D3B500FDC89E10045379C /* SimpleTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SimpleTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E43154FE0D6FFDEB00899579 /* PltAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltAction.cpp; path = ../../../Source/Core/PltAction.cpp; sourceTree = SOURCE_ROOT; };
+ E43154FF0D6FFDEB00899579 /* PltAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltAction.h; path = ../../../Source/Core/PltAction.h; sourceTree = SOURCE_ROOT; };
+ E43155000D6FFDEB00899579 /* PltArgument.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltArgument.cpp; path = ../../../Source/Core/PltArgument.cpp; sourceTree = SOURCE_ROOT; };
+ E43155010D6FFDEB00899579 /* PltArgument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltArgument.h; path = ../../../Source/Core/PltArgument.h; sourceTree = SOURCE_ROOT; };
+ E43155020D6FFDEB00899579 /* PltCtrlPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltCtrlPoint.cpp; path = ../../../Source/Core/PltCtrlPoint.cpp; sourceTree = SOURCE_ROOT; };
+ E43155030D6FFDEB00899579 /* PltCtrlPoint.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltCtrlPoint.h; path = ../../../Source/Core/PltCtrlPoint.h; sourceTree = SOURCE_ROOT; };
+ E43155040D6FFDEB00899579 /* PltCtrlPointTask.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltCtrlPointTask.cpp; path = ../../../Source/Core/PltCtrlPointTask.cpp; sourceTree = SOURCE_ROOT; };
+ E43155050D6FFDEB00899579 /* PltCtrlPointTask.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltCtrlPointTask.h; path = ../../../Source/Core/PltCtrlPointTask.h; sourceTree = SOURCE_ROOT; };
+ E43155060D6FFDEB00899579 /* PltDatagramStream.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltDatagramStream.cpp; path = ../../../Source/Core/PltDatagramStream.cpp; sourceTree = SOURCE_ROOT; };
+ E43155070D6FFDEB00899579 /* PltDatagramStream.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltDatagramStream.h; path = ../../../Source/Core/PltDatagramStream.h; sourceTree = SOURCE_ROOT; };
+ E43155080D6FFDEB00899579 /* PltDeviceData.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltDeviceData.cpp; path = ../../../Source/Core/PltDeviceData.cpp; sourceTree = SOURCE_ROOT; };
+ E43155090D6FFDEB00899579 /* PltDeviceData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltDeviceData.h; path = ../../../Source/Core/PltDeviceData.h; sourceTree = SOURCE_ROOT; };
+ E431550A0D6FFDEB00899579 /* PltDeviceHost.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltDeviceHost.cpp; path = ../../../Source/Core/PltDeviceHost.cpp; sourceTree = SOURCE_ROOT; };
+ E431550B0D6FFDEB00899579 /* PltDeviceHost.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltDeviceHost.h; path = ../../../Source/Core/PltDeviceHost.h; sourceTree = SOURCE_ROOT; };
+ E431550E0D6FFDEB00899579 /* PltEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltEvent.cpp; path = ../../../Source/Core/PltEvent.cpp; sourceTree = SOURCE_ROOT; };
+ E431550F0D6FFDEB00899579 /* PltEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltEvent.h; path = ../../../Source/Core/PltEvent.h; sourceTree = SOURCE_ROOT; };
+ E43155100D6FFDEB00899579 /* PltHttp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltHttp.cpp; path = ../../../Source/Core/PltHttp.cpp; sourceTree = SOURCE_ROOT; };
+ E43155110D6FFDEB00899579 /* PltHttp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltHttp.h; path = ../../../Source/Core/PltHttp.h; sourceTree = SOURCE_ROOT; };
+ E43155120D6FFDEB00899579 /* PltHttpClientTask.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltHttpClientTask.cpp; path = ../../../Source/Core/PltHttpClientTask.cpp; sourceTree = SOURCE_ROOT; };
+ E43155130D6FFDEB00899579 /* PltHttpClientTask.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltHttpClientTask.h; path = ../../../Source/Core/PltHttpClientTask.h; sourceTree = SOURCE_ROOT; };
+ E43155140D6FFDEB00899579 /* PltHttpServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltHttpServer.cpp; path = ../../../Source/Core/PltHttpServer.cpp; sourceTree = SOURCE_ROOT; };
+ E43155150D6FFDEB00899579 /* PltHttpServer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltHttpServer.h; path = ../../../Source/Core/PltHttpServer.h; sourceTree = SOURCE_ROOT; };
+ E43155170D6FFDEB00899579 /* PltHttpServerTask.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltHttpServerTask.cpp; path = ../../../Source/Core/PltHttpServerTask.cpp; sourceTree = SOURCE_ROOT; };
+ E43155180D6FFDEB00899579 /* PltHttpServerTask.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltHttpServerTask.h; path = ../../../Source/Core/PltHttpServerTask.h; sourceTree = SOURCE_ROOT; };
+ E43155210D6FFDEB00899579 /* PltService.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltService.cpp; path = ../../../Source/Core/PltService.cpp; sourceTree = SOURCE_ROOT; };
+ E43155220D6FFDEB00899579 /* PltService.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltService.h; path = ../../../Source/Core/PltService.h; sourceTree = SOURCE_ROOT; };
+ E43155230D6FFDEB00899579 /* PltSsdp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltSsdp.cpp; path = ../../../Source/Core/PltSsdp.cpp; sourceTree = SOURCE_ROOT; };
+ E43155240D6FFDEB00899579 /* PltSsdp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltSsdp.h; path = ../../../Source/Core/PltSsdp.h; sourceTree = SOURCE_ROOT; };
+ E43155260D6FFDEB00899579 /* PltStateVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltStateVariable.cpp; path = ../../../Source/Core/PltStateVariable.cpp; sourceTree = SOURCE_ROOT; };
+ E43155270D6FFDEB00899579 /* PltStateVariable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltStateVariable.h; path = ../../../Source/Core/PltStateVariable.h; sourceTree = SOURCE_ROOT; };
+ E431552A0D6FFDEB00899579 /* PltTaskManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltTaskManager.cpp; path = ../../../Source/Core/PltTaskManager.cpp; sourceTree = SOURCE_ROOT; };
+ E431552B0D6FFDEB00899579 /* PltTaskManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltTaskManager.h; path = ../../../Source/Core/PltTaskManager.h; sourceTree = SOURCE_ROOT; };
+ E431552C0D6FFDEB00899579 /* PltThreadTask.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltThreadTask.cpp; path = ../../../Source/Core/PltThreadTask.cpp; sourceTree = SOURCE_ROOT; };
+ E431552D0D6FFDEB00899579 /* PltThreadTask.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltThreadTask.h; path = ../../../Source/Core/PltThreadTask.h; sourceTree = SOURCE_ROOT; };
+ E431552E0D6FFDEB00899579 /* PltUPnP.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PltUPnP.cpp; path = ../../../Source/Core/PltUPnP.cpp; sourceTree = SOURCE_ROOT; };
+ E431552F0D6FFDEB00899579 /* PltUPnP.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltUPnP.h; path = ../../../Source/Core/PltUPnP.h; sourceTree = SOURCE_ROOT; };
+ E43155320D6FFDEB00899579 /* PltUtilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PltUtilities.h; path = ../../../Source/Core/PltUtilities.h; sourceTree = SOURCE_ROOT; };
+ E43155960D6FFE4C00899579 /* PltMediaConnect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltMediaConnect.cpp; sourceTree = "<group>"; };
+ E43155970D6FFE4C00899579 /* PltMediaConnect.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltMediaConnect.h; sourceTree = "<group>"; };
+ E431559D0D6FFE4C00899579 /* PltMediaController.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltMediaController.cpp; sourceTree = "<group>"; };
+ E431559E0D6FFE4C00899579 /* PltMediaController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltMediaController.h; sourceTree = "<group>"; };
+ E43155A00D6FFE4C00899579 /* PltMediaRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltMediaRenderer.cpp; sourceTree = "<group>"; };
+ E43155A10D6FFE4C00899579 /* PltMediaRenderer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltMediaRenderer.h; sourceTree = "<group>"; };
+ E43155A80D6FFE4C00899579 /* PltDidl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltDidl.cpp; sourceTree = "<group>"; };
+ E43155A90D6FFE4C00899579 /* PltDidl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltDidl.h; sourceTree = "<group>"; };
+ E43155AA0D6FFE4C00899579 /* PltFileMediaServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltFileMediaServer.cpp; sourceTree = "<group>"; };
+ E43155AB0D6FFE4C00899579 /* PltFileMediaServer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltFileMediaServer.h; sourceTree = "<group>"; };
+ E43155AC0D6FFE4C00899579 /* PltMediaBrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltMediaBrowser.cpp; sourceTree = "<group>"; };
+ E43155AD0D6FFE4C00899579 /* PltMediaBrowser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltMediaBrowser.h; sourceTree = "<group>"; };
+ E43155AF0D6FFE4C00899579 /* PltMediaCache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltMediaCache.cpp; sourceTree = "<group>"; };
+ E43155B00D6FFE4C00899579 /* PltMediaCache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltMediaCache.h; sourceTree = "<group>"; };
+ E43155B10D6FFE4C00899579 /* PltMediaItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltMediaItem.cpp; sourceTree = "<group>"; };
+ E43155B20D6FFE4C00899579 /* PltMediaItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltMediaItem.h; sourceTree = "<group>"; };
+ E43155B50D6FFE4C00899579 /* PltMediaServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltMediaServer.cpp; sourceTree = "<group>"; };
+ E43155B60D6FFE4C00899579 /* PltMediaServer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltMediaServer.h; sourceTree = "<group>"; };
+ E43155B80D6FFE4C00899579 /* PltSyncMediaBrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PltSyncMediaBrowser.cpp; sourceTree = "<group>"; };
+ E43155B90D6FFE4C00899579 /* PltSyncMediaBrowser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PltSyncMediaBrowser.h; sourceTree = "<group>"; };
+ E43741FC123FFB9800000109 /* MediaServerCocoaTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MediaServerCocoaTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ E4374243123FFE9100000109 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ E4374245123FFE9100000109 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ E4374246123FFE9100000109 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
+ E4374247123FFE9100000109 /* MediaServerCocoaTest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MediaServerCocoaTest-Info.plist"; sourceTree = "<group>"; };
+ E4374248123FFE9100000109 /* MediaServerCocoaTest_AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaServerCocoaTest_AppDelegate.h; sourceTree = "<group>"; };
+ E4374249123FFE9100000109 /* MediaServerCocoaTest_AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaServerCocoaTest_AppDelegate.mm; sourceTree = "<group>"; };
+ E437424A123FFE9100000109 /* MediaServerCocoaTest_DataModel.xcdatamodel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = wrapper.xcdatamodel; path = MediaServerCocoaTest_DataModel.xcdatamodel; sourceTree = "<group>"; };
+ E437424B123FFE9100000109 /* MediaServerCocoaTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaServerCocoaTest_Prefix.pch; sourceTree = "<group>"; };
+ E4374268123FFF5B00000109 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ E43744C8124014D500000109 /* MediaServerCocoaTestController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaServerCocoaTestController.h; sourceTree = "<group>"; };
+ E4374C1512417AA800000109 /* PltMediaServerObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltMediaServerObject.h; sourceTree = "<group>"; };
+ E4374C1612417AA800000109 /* PltMediaServerObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PltMediaServerObject.mm; sourceTree = "<group>"; };
+ E4374C1712417AA800000109 /* PltUPnPObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltUPnPObject.h; sourceTree = "<group>"; };
+ E4374C1812417AA800000109 /* PltUPnPObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PltUPnPObject.mm; sourceTree = "<group>"; };
+ E43EEEFD101E1AEF007A9CE7 /* Platinum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Platinum.h; sourceTree = "<group>"; };
+ E43EEEFF101E1AEF007A9CE7 /* PltVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltVersion.h; sourceTree = "<group>"; };
+ E43F6BC510F1B74E00C97612 /* TimeTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TimeTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E43F6BC810F1B78400C97612 /* TimeTest1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeTest1.cpp; sourceTree = "<group>"; };
+ E4446FAA12C3168900E01480 /* MediaServerCocoaTestController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaServerCocoaTestController.mm; sourceTree = "<group>"; };
+ E44E2B8B1AE761220092347B /* Platinum.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Platinum.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ E44E2B8D1AE7622F0092347B /* Neptune.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Neptune.framework; path = ../../../Carthage/Build/Mac/Neptune.framework; sourceTree = "<group>"; };
+ E4516A331446A54400EC613B /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
+ E45332AD1AAED318004A52FD /* MobileMediaServer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MobileMediaServer.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ E45332B11AAED318004A52FD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ E45332B31AAED318004A52FD /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+ E45332B41AAED318004A52FD /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+ E45332B61AAED318004A52FD /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
+ E45332B71AAED318004A52FD /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = "<group>"; };
+ E467AC771447747D00CEAACA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+ E467AC791447747D00CEAACA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+ E477694512A9C00E0011EEE4 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+ E48D4D8F13B51BAC00359E06 /* PltProtocolInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PltProtocolInfo.cpp; path = ../../../Source/Core/PltProtocolInfo.cpp; sourceTree = SOURCE_ROOT; };
+ E48D4D9013B51BAC00359E06 /* PltProtocolInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PltProtocolInfo.h; path = ../../../Source/Core/PltProtocolInfo.h; sourceTree = SOURCE_ROOT; };
+ E48D4DA613B51CB600359E06 /* PltMimeType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PltMimeType.cpp; path = ../../../Source/Core/PltMimeType.cpp; sourceTree = SOURCE_ROOT; };
+ E48D4DA713B51CB600359E06 /* PltMimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PltMimeType.h; path = ../../../Source/Core/PltMimeType.h; sourceTree = SOURCE_ROOT; };
+ E48EAA801AF1EDD800D9EDC0 /* Neptune.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Neptune.h; sourceTree = "<group>"; };
+ E48F8A9E1632026F009E46A5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ E4A7DB76108596B900E6ADE2 /* AVTransportSCPD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AVTransportSCPD.cpp; sourceTree = "<group>"; };
+ E4A7DB77108596B900E6ADE2 /* RdrConnectionManagerSCPD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RdrConnectionManagerSCPD.cpp; sourceTree = "<group>"; };
+ E4A7DB78108596B900E6ADE2 /* RenderingControlSCPD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderingControlSCPD.cpp; sourceTree = "<group>"; };
+ E4A7DB7F108596C800E6ADE2 /* X_MS_MediaReceiverRegistrarSCPD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = X_MS_MediaReceiverRegistrarSCPD.cpp; sourceTree = "<group>"; };
+ E4A7DB82108596E400E6ADE2 /* ConnectionManagerSCPD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConnectionManagerSCPD.cpp; sourceTree = "<group>"; };
+ E4A7DB83108596E400E6ADE2 /* ContentDirectorywSearchSCPD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentDirectorywSearchSCPD.cpp; sourceTree = "<group>"; };
+ E4B95ECF1446575700DBBF49 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+ E4B95ED01446575700DBBF49 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
+ E4BA7CBB0FE2200700A4D16B /* PltConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PltConstants.h; path = ../../../Source/Core/PltConstants.h; sourceTree = SOURCE_ROOT; };
+ E4BA7CBC0FE2200700A4D16B /* PltConstants.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PltConstants.cpp; path = ../../../Source/Core/PltConstants.cpp; sourceTree = SOURCE_ROOT; };
+ E4CB6A441640354E002478B0 /* CHANGELOG.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = CHANGELOG.txt; path = ../../../CHANGELOG.txt; sourceTree = "<group>"; };
+ E4CB6A451640354E002478B0 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = LICENSE.txt; path = ../../../LICENSE.txt; sourceTree = "<group>"; };
+ E4CB6A461640354E002478B0 /* README.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = README.txt; path = ../../../README.txt; sourceTree = "<group>"; };
+ E4F7E9060FE4B12A00BEDFA6 /* PltIconsData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PltIconsData.cpp; path = ../../../Source/Core/PltIconsData.cpp; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ E410161D1ACFA826000E994F /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E45BD1F71FC95BFC00F1D812 /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E423F36018415DC500E24E39 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C071AE779990092347B /* Platinum.framework in Frameworks */,
+ E44E2BFD1AE7798D0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3ABB0FDC87130045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2BDF1AE776E80092347B /* Platinum.framework in Frameworks */,
+ E44E2BDE1AE776DD0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3AD10FDC87DB0045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2BFE1AE779950092347B /* Platinum.framework in Frameworks */,
+ E44E2BF41AE779880092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3ADB0FDC87F50045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2BFF1AE779960092347B /* Platinum.framework in Frameworks */,
+ E44E2BF51AE779890092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3AE50FDC880D0045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C001AE779960092347B /* Platinum.framework in Frameworks */,
+ E44E2BF61AE7798A0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B190FDC895A0045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C011AE779970092347B /* Platinum.framework in Frameworks */,
+ E44E2BF71AE7798A0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B240FDC89720045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C021AE779970092347B /* Platinum.framework in Frameworks */,
+ E44E2BF81AE7798B0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B370FDC89B70045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C031AE779970092347B /* Platinum.framework in Frameworks */,
+ E44E2BF91AE7798B0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B430FDC89CD0045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C041AE779980092347B /* Platinum.framework in Frameworks */,
+ E44E2BFA1AE7798C0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B4E0FDC89E10045379C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C051AE779980092347B /* Platinum.framework in Frameworks */,
+ E44E2BFB1AE7798C0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E43741FA123FFB9800000109 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2BCF1AE770500092347B /* Cocoa.framework in Frameworks */,
+ E44E2BCB1AE76FF90092347B /* Neptune.framework in Frameworks */,
+ E44E2BC41AE76E0F0092347B /* Platinum.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E43F6BC010F1B74E00C97612 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2C061AE779990092347B /* Platinum.framework in Frameworks */,
+ E44E2BFC1AE7798D0092347B /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E44E2B571AE761220092347B /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E4B2A5A71FC90AE500C891D7 /* Neptune.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E45332AA1AAED318004A52FD /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2BCC1AE770150092347B /* Neptune.framework in Frameworks */,
+ E41016381ACFA826000E994F /* Platinum.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* Platinum */ = {
+ isa = PBXGroup;
+ children = (
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ E44470B312C31B5900E01480 /* Resources */,
+ C6A0FF2B0290797F04C91782 /* Documentation */,
+ E41016221ACFA826000E994F /* Platinum */,
+ E4294C5F14319C9400B6FDED /* Frameworks */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = Platinum;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3A910FDC85E70045379C /* Apps */,
+ E4096BAD0AF34CE2000AB1CD /* Core */,
+ E4096C180AF34D3A000AB1CD /* Devices */,
+ E40C699D11E6ED710024CAD4 /* Extras */,
+ E43EEEFC101E1AEF007A9CE7 /* Platinum */,
+ E42D3AA90FDC86730045379C /* Tests */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3ABD0FDC87130045379C /* MediaCrawler */,
+ E42D3AD30FDC87DB0045379C /* MediaConnect */,
+ E42D3ADD0FDC87F50045379C /* MicroMediaController */,
+ E42D3AE70FDC880D0045379C /* FrameStreamer */,
+ E42D3B1B0FDC895A0045379C /* FileMediaServerTest */,
+ E42D3B260FDC89720045379C /* HttpTest */,
+ E42D3B390FDC89B70045379C /* LightSampleTest */,
+ E42D3B450FDC89CD0045379C /* MediaRendererTest */,
+ E42D3B500FDC89E10045379C /* SimpleTest */,
+ E43F6BC510F1B74E00C97612 /* TimeTest */,
+ E43741FC123FFB9800000109 /* MediaServerCocoaTest.app */,
+ E423F36818415DC500E24E39 /* SsdpTest */,
+ E45332AD1AAED318004A52FD /* MobileMediaServer.app */,
+ E41016211ACFA826000E994F /* Platinum.framework */,
+ E44E2B8B1AE761220092347B /* Platinum.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6A0FF2B0290797F04C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ E4CB6A441640354E002478B0 /* CHANGELOG.txt */,
+ E4CB6A451640354E002478B0 /* LICENSE.txt */,
+ E4CB6A461640354E002478B0 /* README.txt */,
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+ E4096BAD0AF34CE2000AB1CD /* Core */ = {
+ isa = PBXGroup;
+ children = (
+ E43154FE0D6FFDEB00899579 /* PltAction.cpp */,
+ E43154FF0D6FFDEB00899579 /* PltAction.h */,
+ E43155000D6FFDEB00899579 /* PltArgument.cpp */,
+ E43155010D6FFDEB00899579 /* PltArgument.h */,
+ E4BA7CBC0FE2200700A4D16B /* PltConstants.cpp */,
+ E4BA7CBB0FE2200700A4D16B /* PltConstants.h */,
+ E43155020D6FFDEB00899579 /* PltCtrlPoint.cpp */,
+ E43155030D6FFDEB00899579 /* PltCtrlPoint.h */,
+ E43155040D6FFDEB00899579 /* PltCtrlPointTask.cpp */,
+ E43155050D6FFDEB00899579 /* PltCtrlPointTask.h */,
+ E43155060D6FFDEB00899579 /* PltDatagramStream.cpp */,
+ E43155070D6FFDEB00899579 /* PltDatagramStream.h */,
+ E43155080D6FFDEB00899579 /* PltDeviceData.cpp */,
+ E43155090D6FFDEB00899579 /* PltDeviceData.h */,
+ E431550A0D6FFDEB00899579 /* PltDeviceHost.cpp */,
+ E431550B0D6FFDEB00899579 /* PltDeviceHost.h */,
+ E431550E0D6FFDEB00899579 /* PltEvent.cpp */,
+ E431550F0D6FFDEB00899579 /* PltEvent.h */,
+ E43155100D6FFDEB00899579 /* PltHttp.cpp */,
+ E43155110D6FFDEB00899579 /* PltHttp.h */,
+ E43155120D6FFDEB00899579 /* PltHttpClientTask.cpp */,
+ E43155130D6FFDEB00899579 /* PltHttpClientTask.h */,
+ E43155140D6FFDEB00899579 /* PltHttpServer.cpp */,
+ E43155150D6FFDEB00899579 /* PltHttpServer.h */,
+ E43155170D6FFDEB00899579 /* PltHttpServerTask.cpp */,
+ E43155180D6FFDEB00899579 /* PltHttpServerTask.h */,
+ E4F7E9060FE4B12A00BEDFA6 /* PltIconsData.cpp */,
+ E48D4DA613B51CB600359E06 /* PltMimeType.cpp */,
+ E48D4DA713B51CB600359E06 /* PltMimeType.h */,
+ E48D4D8F13B51BAC00359E06 /* PltProtocolInfo.cpp */,
+ E48D4D9013B51BAC00359E06 /* PltProtocolInfo.h */,
+ E43155210D6FFDEB00899579 /* PltService.cpp */,
+ E43155220D6FFDEB00899579 /* PltService.h */,
+ E43155230D6FFDEB00899579 /* PltSsdp.cpp */,
+ E43155240D6FFDEB00899579 /* PltSsdp.h */,
+ E43155260D6FFDEB00899579 /* PltStateVariable.cpp */,
+ E43155270D6FFDEB00899579 /* PltStateVariable.h */,
+ E431552A0D6FFDEB00899579 /* PltTaskManager.cpp */,
+ E431552B0D6FFDEB00899579 /* PltTaskManager.h */,
+ E431552C0D6FFDEB00899579 /* PltThreadTask.cpp */,
+ E431552D0D6FFDEB00899579 /* PltThreadTask.h */,
+ E431552E0D6FFDEB00899579 /* PltUPnP.cpp */,
+ E431552F0D6FFDEB00899579 /* PltUPnP.h */,
+ E43155320D6FFDEB00899579 /* PltUtilities.h */,
+ );
+ name = Core;
+ sourceTree = "<group>";
+ };
+ E4096C180AF34D3A000AB1CD /* Devices */ = {
+ isa = PBXGroup;
+ children = (
+ E43155930D6FFE4C00899579 /* MediaConnect */,
+ E431559A0D6FFE4C00899579 /* MediaRenderer */,
+ E43155A40D6FFE4C00899579 /* MediaServer */,
+ );
+ name = Devices;
+ sourceTree = "<group>";
+ };
+ E40C699D11E6ED710024CAD4 /* Extras */ = {
+ isa = PBXGroup;
+ children = (
+ E4374C1412417AA800000109 /* ObjectiveC */,
+ E40C69E211E6F0D90024CAD4 /* PltDownloader.cpp */,
+ E40C69E311E6F0D90024CAD4 /* PltDownloader.h */,
+ E40C69E411E6F0D90024CAD4 /* PltStreamPump.cpp */,
+ E40C69E511E6F0D90024CAD4 /* PltStreamPump.h */,
+ E40C699E11E6ED710024CAD4 /* PltFrameBuffer.cpp */,
+ E40C699F11E6ED710024CAD4 /* PltFrameBuffer.h */,
+ E40C69A011E6ED710024CAD4 /* PltFrameServer.cpp */,
+ E40C69A111E6ED710024CAD4 /* PltFrameServer.h */,
+ E40C69A211E6ED710024CAD4 /* PltFrameStream.cpp */,
+ E40C69A311E6ED710024CAD4 /* PltFrameStream.h */,
+ E40C69A411E6ED710024CAD4 /* PltLeaks.cpp */,
+ E40C69A511E6ED710024CAD4 /* PltLeaks.h */,
+ E40C69A611E6ED710024CAD4 /* PltMetadataHandler.cpp */,
+ E40C69A711E6ED710024CAD4 /* PltMetadataHandler.h */,
+ E40C69A811E6ED710024CAD4 /* PltRingBufferStream.cpp */,
+ E40C69A911E6ED710024CAD4 /* PltRingBufferStream.h */,
+ );
+ name = Extras;
+ path = ../../../Source/Extras;
+ sourceTree = SOURCE_ROOT;
+ };
+ E41016151ACFA4E0000E994F /* MobileMediaServer */ = {
+ isa = PBXGroup;
+ children = (
+ E41016181ACFA761000E994F /* LaunchScreen.xib */,
+ E41016191ACFA761000E994F /* Main.storyboard */,
+ E41016161ACFA70C000E994F /* MobileMediaServer-Info.plist */,
+ );
+ name = MobileMediaServer;
+ sourceTree = "<group>";
+ };
+ E41016221ACFA826000E994F /* Platinum */ = {
+ isa = PBXGroup;
+ children = (
+ E48EAA801AF1EDD800D9EDC0 /* Neptune.h */,
+ E41016251ACFA826000E994F /* Platinum.h */,
+ E41016231ACFA826000E994F /* Supporting Files */,
+ );
+ path = Platinum;
+ sourceTree = "<group>";
+ };
+ E41016231ACFA826000E994F /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ E41016241ACFA826000E994F /* Info.plist */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ E423F35918415D8E00E24E39 /* SsdpTest */ = {
+ isa = PBXGroup;
+ children = (
+ E423F35A18415DA800E24E39 /* SsdpTest1.cpp */,
+ );
+ name = SsdpTest;
+ sourceTree = "<group>";
+ };
+ E4294C5F14319C9400B6FDED /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ E44E2B8D1AE7622F0092347B /* Neptune.framework */,
+ E40616C01ADE5C9A008BDAEB /* Neptune.framework */,
+ E48F8A9E1632026F009E46A5 /* Foundation.framework */,
+ E467AC771447747D00CEAACA /* Foundation.framework */,
+ E467AC791447747D00CEAACA /* UIKit.framework */,
+ E4516A331446A54400EC613B /* CoreServices.framework */,
+ E4374268123FFF5B00000109 /* Cocoa.framework */,
+ E477694512A9C00E0011EEE4 /* SystemConfiguration.framework */,
+ E4294C6014319C9400B6FDED /* CoreFoundation.framework */,
+ E4B95ECE1446575700DBBF49 /* Other Frameworks */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ E42D3A910FDC85E70045379C /* Apps */ = {
+ isa = PBXGroup;
+ children = (
+ E45332AE1AAED318004A52FD /* MobileMediaServer */,
+ E45332A81AAED263004A52FD /* MediaServer */,
+ E42D3A940FDC85E70045379C /* MediaConnect */,
+ E42D3A960FDC85E70045379C /* MediaCrawler */,
+ E42D3A9B0FDC85E70045379C /* MicroMediaController */,
+ E42D3A920FDC85E70045379C /* FrameStreamer */,
+ );
+ name = Apps;
+ sourceTree = "<group>";
+ };
+ E42D3A920FDC85E70045379C /* FrameStreamer */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3A930FDC85E70045379C /* main.cpp */,
+ );
+ name = FrameStreamer;
+ sourceTree = "<group>";
+ };
+ E42D3A940FDC85E70045379C /* MediaConnect */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3A950FDC85E70045379C /* main.cpp */,
+ );
+ name = MediaConnect;
+ path = ../../../Source/Apps/MediaConnect;
+ sourceTree = SOURCE_ROOT;
+ };
+ E42D3A960FDC85E70045379C /* MediaCrawler */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3A970FDC85E70045379C /* main.cpp */,
+ E42D3A980FDC85E70045379C /* MediaCrawler.cpp */,
+ E42D3A990FDC85E70045379C /* MediaCrawler.h */,
+ E42D3A9A0FDC85E70045379C /* StreamHandler.h */,
+ );
+ name = MediaCrawler;
+ path = ../../../Source/Apps/MediaCrawler;
+ sourceTree = SOURCE_ROOT;
+ };
+ E42D3A9B0FDC85E70045379C /* MicroMediaController */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3A9C0FDC85E70045379C /* main.cpp */,
+ E42D3A9D0FDC85E70045379C /* PltMicroMediaController.cpp */,
+ E42D3A9E0FDC85E70045379C /* PltMicroMediaController.h */,
+ );
+ name = MicroMediaController;
+ path = ../../../Source/Apps/MicroMediaController;
+ sourceTree = SOURCE_ROOT;
+ };
+ E42D3AA90FDC86730045379C /* Tests */ = {
+ isa = PBXGroup;
+ children = (
+ E423F35918415D8E00E24E39 /* SsdpTest */,
+ E4374241123FFE9100000109 /* MediaServerCocoaTest */,
+ E43F6BC710F1B78400C97612 /* Time */,
+ E42D3AAA0FDC86A60045379C /* FileMediaServer */,
+ E42D3AAC0FDC86A60045379C /* Http */,
+ E42D3AAE0FDC86A60045379C /* LightSample */,
+ E42D3AB20FDC86A60045379C /* MediaRenderer */,
+ E42D3AB40FDC86A60045379C /* Simple */,
+ );
+ name = Tests;
+ sourceTree = "<group>";
+ };
+ E42D3AAA0FDC86A60045379C /* FileMediaServer */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3AAB0FDC86A60045379C /* FileMediaServerTest.cpp */,
+ );
+ name = FileMediaServer;
+ path = ../../../Source/Tests/FileMediaServer;
+ sourceTree = SOURCE_ROOT;
+ };
+ E42D3AAC0FDC86A60045379C /* Http */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3AAD0FDC86A60045379C /* HttpTest.cpp */,
+ );
+ name = Http;
+ path = ../../../Source/Tests/Http;
+ sourceTree = SOURCE_ROOT;
+ };
+ E42D3AAE0FDC86A60045379C /* LightSample */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3AAF0FDC86A60045379C /* PltLightSample.h */,
+ E42D3AB00FDC86A60045379C /* LightSampleTest.cpp */,
+ E42D3AB10FDC86A60045379C /* PltLightSample.cpp */,
+ );
+ name = LightSample;
+ path = ../../../Source/Tests/LightSample;
+ sourceTree = SOURCE_ROOT;
+ };
+ E42D3AB20FDC86A60045379C /* MediaRenderer */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3AB30FDC86A60045379C /* MediaRendererTest.cpp */,
+ );
+ name = MediaRenderer;
+ path = ../../../Source/Tests/MediaRenderer;
+ sourceTree = SOURCE_ROOT;
+ };
+ E42D3AB40FDC86A60045379C /* Simple */ = {
+ isa = PBXGroup;
+ children = (
+ E42D3AB50FDC86A60045379C /* PltSimple.h */,
+ E42D3AB60FDC86A60045379C /* PltSimple.cpp */,
+ E42D3AB70FDC86A60045379C /* SimpleTest.cpp */,
+ );
+ name = Simple;
+ path = ../../../Source/Tests/Simple;
+ sourceTree = SOURCE_ROOT;
+ };
+ E43155930D6FFE4C00899579 /* MediaConnect */ = {
+ isa = PBXGroup;
+ children = (
+ E426B3271130DF9500C58542 /* PltXbox360.cpp */,
+ E426B3281130DF9500C58542 /* PltXbox360.h */,
+ E4A7DB7F108596C800E6ADE2 /* X_MS_MediaReceiverRegistrarSCPD.cpp */,
+ E43155960D6FFE4C00899579 /* PltMediaConnect.cpp */,
+ E43155970D6FFE4C00899579 /* PltMediaConnect.h */,
+ );
+ name = MediaConnect;
+ path = ../../../Source/Devices/MediaConnect;
+ sourceTree = SOURCE_ROOT;
+ };
+ E431559A0D6FFE4C00899579 /* MediaRenderer */ = {
+ isa = PBXGroup;
+ children = (
+ E4A7DB76108596B900E6ADE2 /* AVTransportSCPD.cpp */,
+ E4A7DB77108596B900E6ADE2 /* RdrConnectionManagerSCPD.cpp */,
+ E4A7DB78108596B900E6ADE2 /* RenderingControlSCPD.cpp */,
+ E431559D0D6FFE4C00899579 /* PltMediaController.cpp */,
+ E431559E0D6FFE4C00899579 /* PltMediaController.h */,
+ E43155A00D6FFE4C00899579 /* PltMediaRenderer.cpp */,
+ E43155A10D6FFE4C00899579 /* PltMediaRenderer.h */,
+ );
+ name = MediaRenderer;
+ path = ../../../Source/Devices/MediaRenderer;
+ sourceTree = SOURCE_ROOT;
+ };
+ E43155A40D6FFE4C00899579 /* MediaServer */ = {
+ isa = PBXGroup;
+ children = (
+ E402C7541297CECB00565B76 /* ContentDirectorySCPD.cpp */,
+ E4A7DB82108596E400E6ADE2 /* ConnectionManagerSCPD.cpp */,
+ E4A7DB83108596E400E6ADE2 /* ContentDirectorywSearchSCPD.cpp */,
+ E43155A80D6FFE4C00899579 /* PltDidl.cpp */,
+ E43155A90D6FFE4C00899579 /* PltDidl.h */,
+ E43155AA0D6FFE4C00899579 /* PltFileMediaServer.cpp */,
+ E43155AB0D6FFE4C00899579 /* PltFileMediaServer.h */,
+ E43155AC0D6FFE4C00899579 /* PltMediaBrowser.cpp */,
+ E43155AD0D6FFE4C00899579 /* PltMediaBrowser.h */,
+ E43155AF0D6FFE4C00899579 /* PltMediaCache.cpp */,
+ E43155B00D6FFE4C00899579 /* PltMediaCache.h */,
+ E43155B10D6FFE4C00899579 /* PltMediaItem.cpp */,
+ E43155B20D6FFE4C00899579 /* PltMediaItem.h */,
+ E43155B50D6FFE4C00899579 /* PltMediaServer.cpp */,
+ E43155B60D6FFE4C00899579 /* PltMediaServer.h */,
+ E43155B80D6FFE4C00899579 /* PltSyncMediaBrowser.cpp */,
+ E43155B90D6FFE4C00899579 /* PltSyncMediaBrowser.h */,
+ );
+ name = MediaServer;
+ path = ../../../Source/Devices/MediaServer;
+ sourceTree = SOURCE_ROOT;
+ };
+ E4374241123FFE9100000109 /* MediaServerCocoaTest */ = {
+ isa = PBXGroup;
+ children = (
+ E4446FAA12C3168900E01480 /* MediaServerCocoaTestController.mm */,
+ E4374265123FFECE00000109 /* Models */,
+ E4374264123FFEC200000109 /* Other Sources */,
+ E4374252123FFEAE00000109 /* Resources */,
+ E4374248123FFE9100000109 /* MediaServerCocoaTest_AppDelegate.h */,
+ E4374249123FFE9100000109 /* MediaServerCocoaTest_AppDelegate.mm */,
+ E43744C8124014D500000109 /* MediaServerCocoaTestController.h */,
+ );
+ name = MediaServerCocoaTest;
+ path = ../../../Source/Tests/MediaServerCocoaTest;
+ sourceTree = SOURCE_ROOT;
+ };
+ E4374252123FFEAE00000109 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ E4374242123FFE9100000109 /* InfoPlist.strings */,
+ E4374244123FFE9100000109 /* MainMenu.xib */,
+ E4374247123FFE9100000109 /* MediaServerCocoaTest-Info.plist */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ E4374264123FFEC200000109 /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ E4374246123FFE9100000109 /* main.mm */,
+ E437424B123FFE9100000109 /* MediaServerCocoaTest_Prefix.pch */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ E4374265123FFECE00000109 /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ E437424A123FFE9100000109 /* MediaServerCocoaTest_DataModel.xcdatamodel */,
+ );
+ name = Models;
+ sourceTree = "<group>";
+ };
+ E4374C1412417AA800000109 /* ObjectiveC */ = {
+ isa = PBXGroup;
+ children = (
+ E4374C1512417AA800000109 /* PltMediaServerObject.h */,
+ E4374C1612417AA800000109 /* PltMediaServerObject.mm */,
+ E4374C1712417AA800000109 /* PltUPnPObject.h */,
+ E4374C1812417AA800000109 /* PltUPnPObject.mm */,
+ );
+ path = ObjectiveC;
+ sourceTree = "<group>";
+ };
+ E43EEEFC101E1AEF007A9CE7 /* Platinum */ = {
+ isa = PBXGroup;
+ children = (
+ E43EEEFD101E1AEF007A9CE7 /* Platinum.h */,
+ E43EEEFF101E1AEF007A9CE7 /* PltVersion.h */,
+ );
+ name = Platinum;
+ path = ../../../Source/Platinum;
+ sourceTree = SOURCE_ROOT;
+ };
+ E43F6BC710F1B78400C97612 /* Time */ = {
+ isa = PBXGroup;
+ children = (
+ E43F6BC810F1B78400C97612 /* TimeTest1.cpp */,
+ );
+ name = Time;
+ path = ../../../Source/Tests/Time;
+ sourceTree = SOURCE_ROOT;
+ };
+ E44470B312C31B5900E01480 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ E41016151ACFA4E0000E994F /* MobileMediaServer */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ E45332A81AAED263004A52FD /* MediaServer */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = MediaServer;
+ sourceTree = "<group>";
+ };
+ E45332AE1AAED318004A52FD /* MobileMediaServer */ = {
+ isa = PBXGroup;
+ children = (
+ E45332B11AAED318004A52FD /* main.m */,
+ E45332B31AAED318004A52FD /* AppDelegate.h */,
+ E45332B41AAED318004A52FD /* AppDelegate.m */,
+ E45332B61AAED318004A52FD /* ViewController.h */,
+ E45332B71AAED318004A52FD /* ViewController.mm */,
+ );
+ name = MobileMediaServer;
+ path = ../../../Source/Apps/MobileMediaServer;
+ sourceTree = "<group>";
+ };
+ E4B95ECE1446575700DBBF49 /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ E4B95ECF1446575700DBBF49 /* AppKit.framework */,
+ E4B95ED01446575700DBBF49 /* CoreData.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ E410161E1ACFA826000E994F /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E41016671ACFA858000E994F /* PltTaskManager.h in Headers */,
+ E41016501ACFA858000E994F /* PltDeviceHost.h in Headers */,
+ E41016991ACFA8B9000E994F /* PltLeaks.h in Headers */,
+ E41016581ACFA858000E994F /* PltHttpServer.h in Headers */,
+ E41016851ACFA8A1000E994F /* PltMediaItem.h in Headers */,
+ E41016931ACFA8B9000E994F /* PltFrameBuffer.h in Headers */,
+ E41016811ACFA8A1000E994F /* PltMediaBrowser.h in Headers */,
+ E410164C1ACFA858000E994F /* PltDatagramStream.h in Headers */,
+ E410166C1ACFA858000E994F /* PltUtilities.h in Headers */,
+ E410169D1ACFA8B9000E994F /* PltRingBufferStream.h in Headers */,
+ E41016631ACFA858000E994F /* PltSsdp.h in Headers */,
+ E41016261ACFA826000E994F /* Platinum.h in Headers */,
+ E41016461ACFA858000E994F /* PltConstants.h in Headers */,
+ E41016691ACFA858000E994F /* PltThreadTask.h in Headers */,
+ E410168C1ACFA8B9000E994F /* PltUPnPObject.h in Headers */,
+ E410165F1ACFA858000E994F /* PltProtocolInfo.h in Headers */,
+ E41016481ACFA858000E994F /* PltCtrlPoint.h in Headers */,
+ E41016611ACFA858000E994F /* PltService.h in Headers */,
+ E410166E1ACFA887000E994F /* PltXbox360.h in Headers */,
+ E41016541ACFA858000E994F /* PltHttp.h in Headers */,
+ E410169F1ACFA8CC000E994F /* PltVersion.h in Headers */,
+ E41016711ACFA887000E994F /* PltMediaConnect.h in Headers */,
+ E410165A1ACFA858000E994F /* PltHttpServerTask.h in Headers */,
+ E41016871ACFA8A1000E994F /* PltMediaServer.h in Headers */,
+ E410167F1ACFA8A1000E994F /* PltFileMediaServer.h in Headers */,
+ E41016911ACFA8B9000E994F /* PltStreamPump.h in Headers */,
+ E41016831ACFA8A1000E994F /* PltMediaCache.h in Headers */,
+ E41016951ACFA8B9000E994F /* PltFrameServer.h in Headers */,
+ E41016781ACFA893000E994F /* PltMediaRenderer.h in Headers */,
+ E41016441ACFA858000E994F /* PltArgument.h in Headers */,
+ E41016561ACFA858000E994F /* PltHttpClientTask.h in Headers */,
+ E41016891ACFA8A1000E994F /* PltSyncMediaBrowser.h in Headers */,
+ E41016651ACFA858000E994F /* PltStateVariable.h in Headers */,
+ E410168F1ACFA8B9000E994F /* PltDownloader.h in Headers */,
+ E410167D1ACFA8A1000E994F /* PltDidl.h in Headers */,
+ E410166B1ACFA858000E994F /* PltUPnP.h in Headers */,
+ E410164A1ACFA858000E994F /* PltCtrlPointTask.h in Headers */,
+ E410169B1ACFA8B9000E994F /* PltMetadataHandler.h in Headers */,
+ E41016421ACFA858000E994F /* PltAction.h in Headers */,
+ E41016521ACFA858000E994F /* PltEvent.h in Headers */,
+ E410165D1ACFA858000E994F /* PltMimeType.h in Headers */,
+ E410168A1ACFA8B9000E994F /* PltMediaServerObject.h in Headers */,
+ E41016971ACFA8B9000E994F /* PltFrameStream.h in Headers */,
+ E41016761ACFA893000E994F /* PltMediaController.h in Headers */,
+ E48EAA811AF1EDD800D9EDC0 /* Neptune.h in Headers */,
+ E410164E1ACFA858000E994F /* PltDeviceData.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E44E2B591AE761220092347B /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2B5A1AE761220092347B /* PltTaskManager.h in Headers */,
+ E44E2B5B1AE761220092347B /* PltDeviceHost.h in Headers */,
+ E44E2B5C1AE761220092347B /* PltLeaks.h in Headers */,
+ E44E2B5D1AE761220092347B /* PltHttpServer.h in Headers */,
+ E44E2B5E1AE761220092347B /* PltMediaItem.h in Headers */,
+ E44E2B5F1AE761220092347B /* PltFrameBuffer.h in Headers */,
+ E44E2B601AE761220092347B /* PltMediaBrowser.h in Headers */,
+ E44E2B611AE761220092347B /* PltDatagramStream.h in Headers */,
+ E44E2B621AE761220092347B /* PltUtilities.h in Headers */,
+ E44E2B631AE761220092347B /* PltRingBufferStream.h in Headers */,
+ E44E2B641AE761220092347B /* PltSsdp.h in Headers */,
+ E44E2B651AE761220092347B /* Platinum.h in Headers */,
+ E44E2B661AE761220092347B /* PltConstants.h in Headers */,
+ E44E2B671AE761220092347B /* PltThreadTask.h in Headers */,
+ E44E2B681AE761220092347B /* PltUPnPObject.h in Headers */,
+ E44E2B691AE761220092347B /* PltProtocolInfo.h in Headers */,
+ E44E2B6A1AE761220092347B /* PltCtrlPoint.h in Headers */,
+ E44E2B6B1AE761220092347B /* PltService.h in Headers */,
+ E44E2B6C1AE761220092347B /* PltXbox360.h in Headers */,
+ E44E2B6D1AE761220092347B /* PltHttp.h in Headers */,
+ E44E2B6E1AE761220092347B /* PltVersion.h in Headers */,
+ E44E2B6F1AE761220092347B /* PltMediaConnect.h in Headers */,
+ E44E2B701AE761220092347B /* PltHttpServerTask.h in Headers */,
+ E44E2B711AE761220092347B /* PltMediaServer.h in Headers */,
+ E44E2B721AE761220092347B /* PltFileMediaServer.h in Headers */,
+ E44E2B731AE761220092347B /* PltStreamPump.h in Headers */,
+ E44E2B741AE761220092347B /* PltMediaCache.h in Headers */,
+ E44E2B751AE761220092347B /* PltFrameServer.h in Headers */,
+ E44E2B761AE761220092347B /* PltMediaRenderer.h in Headers */,
+ E44E2B771AE761220092347B /* PltArgument.h in Headers */,
+ E44E2B781AE761220092347B /* PltHttpClientTask.h in Headers */,
+ E44E2B791AE761220092347B /* PltSyncMediaBrowser.h in Headers */,
+ E44E2B7A1AE761220092347B /* PltStateVariable.h in Headers */,
+ E44E2B7B1AE761220092347B /* PltDownloader.h in Headers */,
+ E44E2B7C1AE761220092347B /* PltDidl.h in Headers */,
+ E44E2B7D1AE761220092347B /* PltUPnP.h in Headers */,
+ E44E2B7E1AE761220092347B /* PltCtrlPointTask.h in Headers */,
+ E44E2B7F1AE761220092347B /* PltMetadataHandler.h in Headers */,
+ E44E2B801AE761220092347B /* PltAction.h in Headers */,
+ E44E2B811AE761220092347B /* PltEvent.h in Headers */,
+ E44E2B821AE761220092347B /* PltMimeType.h in Headers */,
+ E44E2B831AE761220092347B /* PltMediaServerObject.h in Headers */,
+ E44E2B841AE761220092347B /* PltFrameStream.h in Headers */,
+ E48EAA821AF1EDD800D9EDC0 /* Neptune.h in Headers */,
+ E44E2B851AE761220092347B /* PltMediaController.h in Headers */,
+ E44E2B861AE761220092347B /* PltDeviceData.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ E41016201ACFA826000E994F /* Platinum-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E410163A1ACFA826000E994F /* Build configuration list for PBXNativeTarget "Platinum-iOS" */;
+ buildPhases = (
+ E410161C1ACFA826000E994F /* Sources */,
+ E410161D1ACFA826000E994F /* Frameworks */,
+ E410161E1ACFA826000E994F /* Headers */,
+ E410161F1ACFA826000E994F /* Resources */,
+ E4B2A5A41FC8F8EB00C891D7 /* Copy Products to Carthage/Build/iOS */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Platinum-iOS";
+ productName = Platinum;
+ productReference = E41016211ACFA826000E994F /* Platinum.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ E423F35B18415DC500E24E39 /* SsdpTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E423F36518415DC500E24E39 /* Build configuration list for PBXNativeTarget "SsdpTest" */;
+ buildPhases = (
+ E423F35E18415DC500E24E39 /* Sources */,
+ E423F36018415DC500E24E39 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BF31AE779700092347B /* PBXTargetDependency */,
+ );
+ name = SsdpTest;
+ productName = HttpTest;
+ productReference = E423F36818415DC500E24E39 /* SsdpTest */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3ABC0FDC87130045379C /* MediaCrawler */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3AC30FDC87290045379C /* Build configuration list for PBXNativeTarget "MediaCrawler" */;
+ buildPhases = (
+ E42D3ABA0FDC87130045379C /* Sources */,
+ E42D3ABB0FDC87130045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BDB1AE776060092347B /* PBXTargetDependency */,
+ );
+ name = MediaCrawler;
+ productName = MediaCrawler;
+ productReference = E42D3ABD0FDC87130045379C /* MediaCrawler */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3AD20FDC87DB0045379C /* MediaConnect */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3AF30FDC88180045379C /* Build configuration list for PBXNativeTarget "MediaConnect" */;
+ buildPhases = (
+ E42D3AD00FDC87DB0045379C /* Sources */,
+ E42D3AD10FDC87DB0045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BE11AE779130092347B /* PBXTargetDependency */,
+ );
+ name = MediaConnect;
+ productName = MediaConnect;
+ productReference = E42D3AD30FDC87DB0045379C /* MediaConnect */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3ADC0FDC87F50045379C /* MicroMediaController */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3AF40FDC88180045379C /* Build configuration list for PBXNativeTarget "MicroMediaController" */;
+ buildPhases = (
+ E42D3ADA0FDC87F50045379C /* Sources */,
+ E42D3ADB0FDC87F50045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BE31AE7794D0092347B /* PBXTargetDependency */,
+ );
+ name = MicroMediaController;
+ productName = MicroMediaController;
+ productReference = E42D3ADD0FDC87F50045379C /* MicroMediaController */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3AE60FDC880D0045379C /* FrameStreamer */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3AF50FDC88180045379C /* Build configuration list for PBXNativeTarget "FrameStreamer" */;
+ buildPhases = (
+ E42D3AE40FDC880D0045379C /* Sources */,
+ E42D3AE50FDC880D0045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BE51AE779520092347B /* PBXTargetDependency */,
+ );
+ name = FrameStreamer;
+ productName = FrameStreamer;
+ productReference = E42D3AE70FDC880D0045379C /* FrameStreamer */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3B1A0FDC895A0045379C /* FileMediaServerTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3B340FDC89B70045379C /* Build configuration list for PBXNativeTarget "FileMediaServerTest" */;
+ buildPhases = (
+ E42D3B180FDC895A0045379C /* Sources */,
+ E42D3B190FDC895A0045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BE71AE779580092347B /* PBXTargetDependency */,
+ );
+ name = FileMediaServerTest;
+ productName = FileMediaServerTest;
+ productReference = E42D3B1B0FDC895A0045379C /* FileMediaServerTest */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3B250FDC89720045379C /* HttpTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3B350FDC89B70045379C /* Build configuration list for PBXNativeTarget "HttpTest" */;
+ buildPhases = (
+ E42D3B230FDC89720045379C /* Sources */,
+ E42D3B240FDC89720045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BE91AE7795C0092347B /* PBXTargetDependency */,
+ );
+ name = HttpTest;
+ productName = HttpTest;
+ productReference = E42D3B260FDC89720045379C /* HttpTest */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3B380FDC89B70045379C /* LightSampleTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3B8D0FDC8AC10045379C /* Build configuration list for PBXNativeTarget "LightSampleTest" */;
+ buildPhases = (
+ E42D3B360FDC89B70045379C /* Sources */,
+ E42D3B370FDC89B70045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BEB1AE779600092347B /* PBXTargetDependency */,
+ );
+ name = LightSampleTest;
+ productName = LightSampleTest;
+ productReference = E42D3B390FDC89B70045379C /* LightSampleTest */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3B440FDC89CD0045379C /* MediaRendererTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3B8E0FDC8AC10045379C /* Build configuration list for PBXNativeTarget "MediaRendererTest" */;
+ buildPhases = (
+ E42D3B420FDC89CD0045379C /* Sources */,
+ E42D3B430FDC89CD0045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BED1AE779640092347B /* PBXTargetDependency */,
+ );
+ name = MediaRendererTest;
+ productName = MediaRendererTest;
+ productReference = E42D3B450FDC89CD0045379C /* MediaRendererTest */;
+ productType = "com.apple.product-type.tool";
+ };
+ E42D3B4F0FDC89E10045379C /* SimpleTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E42D3B8F0FDC8AC10045379C /* Build configuration list for PBXNativeTarget "SimpleTest" */;
+ buildPhases = (
+ E42D3B4D0FDC89E10045379C /* Sources */,
+ E42D3B4E0FDC89E10045379C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BEF1AE779680092347B /* PBXTargetDependency */,
+ );
+ name = SimpleTest;
+ productName = SimpleTest;
+ productReference = E42D3B500FDC89E10045379C /* SimpleTest */;
+ productType = "com.apple.product-type.tool";
+ };
+ E43741FB123FFB9800000109 /* MediaServerCocoaTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E4374201123FFB9800000109 /* Build configuration list for PBXNativeTarget "MediaServerCocoaTest" */;
+ buildPhases = (
+ E43741F8123FFB9800000109 /* Resources */,
+ E43741F9123FFB9800000109 /* Sources */,
+ E43741FA123FFB9800000109 /* Frameworks */,
+ E4516B8E1446C3F600EC613B /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BC31AE76D7B0092347B /* PBXTargetDependency */,
+ );
+ name = MediaServerCocoaTest;
+ productName = MediaServerCocoaTest;
+ productReference = E43741FC123FFB9800000109 /* MediaServerCocoaTest.app */;
+ productType = "com.apple.product-type.application";
+ };
+ E43F6BBB10F1B74E00C97612 /* TimeTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E43F6BC210F1B74E00C97612 /* Build configuration list for PBXNativeTarget "TimeTest" */;
+ buildPhases = (
+ E43F6BBE10F1B74E00C97612 /* Sources */,
+ E43F6BC010F1B74E00C97612 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E44E2BF11AE7796C0092347B /* PBXTargetDependency */,
+ );
+ name = TimeTest;
+ productName = SsdpTest;
+ productReference = E43F6BC510F1B74E00C97612 /* TimeTest */;
+ productType = "com.apple.product-type.tool";
+ };
+ E44E2B231AE761220092347B /* Platinum-Mac */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E44E2B881AE761220092347B /* Build configuration list for PBXNativeTarget "Platinum-Mac" */;
+ buildPhases = (
+ E44E2B241AE761220092347B /* Sources */,
+ E44E2B571AE761220092347B /* Frameworks */,
+ E44E2B591AE761220092347B /* Headers */,
+ E44E2B871AE761220092347B /* Resources */,
+ E4B2A5A51FC8F8F100C891D7 /* Copy Products to Carthage/Build/iOS */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Platinum-Mac";
+ productName = Platinum;
+ productReference = E44E2B8B1AE761220092347B /* Platinum.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ E45332AC1AAED318004A52FD /* MobileMediaServer */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E45332CD1AAED318004A52FD /* Build configuration list for PBXNativeTarget "MobileMediaServer" */;
+ buildPhases = (
+ E45332A91AAED318004A52FD /* Sources */,
+ E45332AA1AAED318004A52FD /* Frameworks */,
+ E45332AB1AAED318004A52FD /* Resources */,
+ E410163D1ACFA826000E994F /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E41016371ACFA826000E994F /* PBXTargetDependency */,
+ );
+ name = MobileMediaServer;
+ productName = MobileMediaServer;
+ productReference = E45332AD1AAED318004A52FD /* MobileMediaServer.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0620;
+ TargetAttributes = {
+ E41016201ACFA826000E994F = {
+ CreatedOnToolsVersion = 6.2;
+ };
+ E44E2BD01AE775510092347B = {
+ CreatedOnToolsVersion = 6.3;
+ };
+ E45332AC1AAED318004A52FD = {
+ CreatedOnToolsVersion = 6.2;
+ };
+ };
+ };
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "Platinum" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ en,
+ Base,
+ );
+ mainGroup = 08FB7794FE84155DC02AAC07 /* Platinum */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ E42D3B040FDC890A0045379C /* Apps */,
+ E42D3B640FDC8A120045379C /* Tests */,
+ E42D3B730FDC8A210045379C /* All */,
+ E459CC2111F82C3F00621896 /* Help */,
+ E44E2BD01AE775510092347B /* Frameworks */,
+ E42D3ABC0FDC87130045379C /* MediaCrawler */,
+ E42D3AD20FDC87DB0045379C /* MediaConnect */,
+ E42D3ADC0FDC87F50045379C /* MicroMediaController */,
+ E42D3AE60FDC880D0045379C /* FrameStreamer */,
+ E42D3B1A0FDC895A0045379C /* FileMediaServerTest */,
+ E42D3B250FDC89720045379C /* HttpTest */,
+ E42D3B380FDC89B70045379C /* LightSampleTest */,
+ E42D3B440FDC89CD0045379C /* MediaRendererTest */,
+ E42D3B4F0FDC89E10045379C /* SimpleTest */,
+ E43F6BBB10F1B74E00C97612 /* TimeTest */,
+ E423F35B18415DC500E24E39 /* SsdpTest */,
+ E43741FB123FFB9800000109 /* MediaServerCocoaTest */,
+ E45332AC1AAED318004A52FD /* MobileMediaServer */,
+ E41016201ACFA826000E994F /* Platinum-iOS */,
+ E44E2B231AE761220092347B /* Platinum-Mac */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ E410161F1ACFA826000E994F /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E43741F8123FFB9800000109 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E437424C123FFE9100000109 /* InfoPlist.strings in Resources */,
+ E437424D123FFE9100000109 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E44E2B871AE761220092347B /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E45332AB1AAED318004A52FD /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E410161B1ACFA761000E994F /* Main.storyboard in Resources */,
+ E410161A1ACFA761000E994F /* LaunchScreen.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ E459CC2011F82C3F00621896 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# shell script goes here\n# Build the doxygen documentation for the project and load the docset into Xcode.\n\n# Use the following to adjust the value of the $DOXYGEN_PATH User-Defined Setting:\n# Binary install location: /Applications/Doxygen.app/Contents/Resources/doxygen\n# Source build install location: /usr/local/bin/doxygen\n\n\ncd \"$SOURCE_ROOT/../../../Docs/Doxygen\"\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\necho $(pwd)\n\nif ! [ -f Doxyfile ] \nthen \n echo doxygen config file does not exist\nfi\n\nVERSION=$(python ../../Scripts/version.py)\n\n# Run doxygen on the updated config file.\n# Note: doxygen creates a Makefile that does most of the heavy lifting.\n\n( cat Doxyfile ; echo \"PROJECT_NUMBER=$VERSION\" ) | /usr/local/bin/doxygen -\n\n# make will invoke docsetutil. Take a look at the Makefile to see how this is done.\n\nmake -C Platinum-HTML install\n\n# Construct a temporary applescript file to tell Xcode to load a docset.\n\nrm -f \"$TEMP_DIR/loadDocSet.scpt\"\n\necho \"tell application \\\"Xcode\\\"\" >> \"$TEMP_DIR/loadDocSet.scpt\"\necho \"load documentation set with path \\\"/Users/$USER/Library/Developer/Shared/Documentation/DocSets/\\\"\" \n >> $TEMP_DIR/loadDocSet.scpt\necho \"end tell\" >> \"$TEMP_DIR/loadDocSet.scpt\"\n\n# Run the load-docset applescript command.\n\nosascript \"$TEMP_DIR/loadDocSet.scpt\"\n\nexit 0";
+ };
+ E4B2A5A41FC8F8EB00C891D7 /* Copy Products to Carthage/Build/iOS */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Copy Products to Carthage/Build/iOS";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "build_dir=\"$SRCROOT/../../../Carthage/Build\"\n\n# Only copy when the Carthage/Build directory is a symlink\nif ! [ -L \"$build_dir\" ]; then exit 0; fi\n\nrsync --delete -av \"$BUILT_PRODUCTS_DIR/$PRODUCT_NAME\"* \"$build_dir/iOS\"";
+ };
+ E4B2A5A51FC8F8F100C891D7 /* Copy Products to Carthage/Build/iOS */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Copy Products to Carthage/Build/iOS";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "build_dir=\"$SRCROOT/../../../Carthage/Build\"\n\n# Only copy when the Carthage/Build directory is a symlink\nif ! [ -L \"$build_dir\" ]; then exit 0; fi\n\nrsync --delete -av \"$BUILT_PRODUCTS_DIR/$PRODUCT_NAME\"* \"$build_dir/Mac\"";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ E410161C1ACFA826000E994F /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E410168B1ACFA8B9000E994F /* PltMediaServerObject.mm in Sources */,
+ E41016941ACFA8B9000E994F /* PltFrameServer.cpp in Sources */,
+ E410169C1ACFA8B9000E994F /* PltRingBufferStream.cpp in Sources */,
+ E41016531ACFA858000E994F /* PltHttp.cpp in Sources */,
+ E410164F1ACFA858000E994F /* PltDeviceHost.cpp in Sources */,
+ E41016751ACFA893000E994F /* PltMediaController.cpp in Sources */,
+ E410165E1ACFA858000E994F /* PltProtocolInfo.cpp in Sources */,
+ E41016471ACFA858000E994F /* PltCtrlPoint.cpp in Sources */,
+ E410166F1ACFA887000E994F /* X_MS_MediaReceiverRegistrarSCPD.cpp in Sources */,
+ E41016731ACFA893000E994F /* RdrConnectionManagerSCPD.cpp in Sources */,
+ E41016901ACFA8B9000E994F /* PltStreamPump.cpp in Sources */,
+ E41016741ACFA893000E994F /* RenderingControlSCPD.cpp in Sources */,
+ E41016841ACFA8A1000E994F /* PltMediaItem.cpp in Sources */,
+ E41016771ACFA893000E994F /* PltMediaRenderer.cpp in Sources */,
+ E410167E1ACFA8A1000E994F /* PltFileMediaServer.cpp in Sources */,
+ E410167C1ACFA8A1000E994F /* PltDidl.cpp in Sources */,
+ E410164B1ACFA858000E994F /* PltDatagramStream.cpp in Sources */,
+ E41016681ACFA858000E994F /* PltThreadTask.cpp in Sources */,
+ E41016491ACFA858000E994F /* PltCtrlPointTask.cpp in Sources */,
+ E41016961ACFA8B9000E994F /* PltFrameStream.cpp in Sources */,
+ E410167B1ACFA8A1000E994F /* ContentDirectorywSearchSCPD.cpp in Sources */,
+ E410169A1ACFA8B9000E994F /* PltMetadataHandler.cpp in Sources */,
+ E410166A1ACFA858000E994F /* PltUPnP.cpp in Sources */,
+ E41016511ACFA858000E994F /* PltEvent.cpp in Sources */,
+ E41016591ACFA858000E994F /* PltHttpServerTask.cpp in Sources */,
+ E410168E1ACFA8B9000E994F /* PltDownloader.cpp in Sources */,
+ E41016551ACFA858000E994F /* PltHttpClientTask.cpp in Sources */,
+ E41016701ACFA887000E994F /* PltMediaConnect.cpp in Sources */,
+ E41016801ACFA8A1000E994F /* PltMediaBrowser.cpp in Sources */,
+ E410166D1ACFA887000E994F /* PltXbox360.cpp in Sources */,
+ E41016721ACFA893000E994F /* AVTransportSCPD.cpp in Sources */,
+ E41016981ACFA8B9000E994F /* PltLeaks.cpp in Sources */,
+ E41016661ACFA858000E994F /* PltTaskManager.cpp in Sources */,
+ E41016821ACFA8A1000E994F /* PltMediaCache.cpp in Sources */,
+ E41016411ACFA858000E994F /* PltAction.cpp in Sources */,
+ E41016621ACFA858000E994F /* PltSsdp.cpp in Sources */,
+ E410165B1ACFA858000E994F /* PltIconsData.cpp in Sources */,
+ E41016431ACFA858000E994F /* PltArgument.cpp in Sources */,
+ E41016921ACFA8B9000E994F /* PltFrameBuffer.cpp in Sources */,
+ E41016571ACFA858000E994F /* PltHttpServer.cpp in Sources */,
+ E41016641ACFA858000E994F /* PltStateVariable.cpp in Sources */,
+ E41016861ACFA8A1000E994F /* PltMediaServer.cpp in Sources */,
+ E41016881ACFA8A1000E994F /* PltSyncMediaBrowser.cpp in Sources */,
+ E410164D1ACFA858000E994F /* PltDeviceData.cpp in Sources */,
+ E41016451ACFA858000E994F /* PltConstants.cpp in Sources */,
+ E41016791ACFA8A1000E994F /* ContentDirectorySCPD.cpp in Sources */,
+ E410168D1ACFA8B9000E994F /* PltUPnPObject.mm in Sources */,
+ E41016601ACFA858000E994F /* PltService.cpp in Sources */,
+ E410165C1ACFA858000E994F /* PltMimeType.cpp in Sources */,
+ E410167A1ACFA8A1000E994F /* ConnectionManagerSCPD.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E423F35E18415DC500E24E39 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E423F36918415DF900E24E39 /* SsdpTest1.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3ABA0FDC87130045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3AC40FDC87300045379C /* MediaCrawler.cpp in Sources */,
+ E42D3AC50FDC87310045379C /* main.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3AD00FDC87DB0045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B110FDC89200045379C /* main.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3ADA0FDC87F50045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B120FDC89260045379C /* main.cpp in Sources */,
+ E42D3B130FDC89270045379C /* PltMicroMediaController.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3AE40FDC880D0045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B150FDC892B0045379C /* main.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B180FDC895A0045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B220FDC89690045379C /* FileMediaServerTest.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B230FDC89720045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B330FDC89990045379C /* HttpTest.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B360FDC89B70045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B400FDC89C40045379C /* LightSampleTest.cpp in Sources */,
+ E42D3B410FDC89C40045379C /* PltLightSample.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B420FDC89CD0045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B4C0FDC89D90045379C /* MediaRendererTest.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E42D3B4D0FDC89E10045379C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E42D3B570FDC89ED0045379C /* SimpleTest.cpp in Sources */,
+ E42D3B580FDC89ED0045379C /* PltSimple.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E43741F9123FFB9800000109 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E437424E123FFE9100000109 /* main.mm in Sources */,
+ E4374250123FFE9100000109 /* MediaServerCocoaTest_AppDelegate.mm in Sources */,
+ E4374251123FFE9100000109 /* MediaServerCocoaTest_DataModel.xcdatamodel in Sources */,
+ E4446FAB12C3168900E01480 /* MediaServerCocoaTestController.mm in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E43F6BBE10F1B74E00C97612 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E43F6BC910F1B78400C97612 /* TimeTest1.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E44E2B241AE761220092347B /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E44E2B251AE761220092347B /* PltMediaServerObject.mm in Sources */,
+ E44E2B261AE761220092347B /* PltFrameServer.cpp in Sources */,
+ E44E2B271AE761220092347B /* PltRingBufferStream.cpp in Sources */,
+ E44E2B281AE761220092347B /* PltHttp.cpp in Sources */,
+ E44E2B291AE761220092347B /* PltDeviceHost.cpp in Sources */,
+ E44E2B2A1AE761220092347B /* PltMediaController.cpp in Sources */,
+ E44E2B2B1AE761220092347B /* PltProtocolInfo.cpp in Sources */,
+ E44E2B2C1AE761220092347B /* PltCtrlPoint.cpp in Sources */,
+ E44E2B2D1AE761220092347B /* X_MS_MediaReceiverRegistrarSCPD.cpp in Sources */,
+ E44E2B2E1AE761220092347B /* RdrConnectionManagerSCPD.cpp in Sources */,
+ E44E2B2F1AE761220092347B /* PltStreamPump.cpp in Sources */,
+ E44E2B301AE761220092347B /* RenderingControlSCPD.cpp in Sources */,
+ E44E2B311AE761220092347B /* PltMediaItem.cpp in Sources */,
+ E44E2B321AE761220092347B /* PltMediaRenderer.cpp in Sources */,
+ E44E2B331AE761220092347B /* PltFileMediaServer.cpp in Sources */,
+ E44E2B341AE761220092347B /* PltDidl.cpp in Sources */,
+ E44E2B351AE761220092347B /* PltDatagramStream.cpp in Sources */,
+ E44E2B361AE761220092347B /* PltThreadTask.cpp in Sources */,
+ E44E2B371AE761220092347B /* PltCtrlPointTask.cpp in Sources */,
+ E44E2B381AE761220092347B /* PltFrameStream.cpp in Sources */,
+ E44E2B391AE761220092347B /* ContentDirectorywSearchSCPD.cpp in Sources */,
+ E44E2B3A1AE761220092347B /* PltMetadataHandler.cpp in Sources */,
+ E44E2B3B1AE761220092347B /* PltUPnP.cpp in Sources */,
+ E44E2B3C1AE761220092347B /* PltEvent.cpp in Sources */,
+ E44E2B3D1AE761220092347B /* PltHttpServerTask.cpp in Sources */,
+ E44E2B3E1AE761220092347B /* PltDownloader.cpp in Sources */,
+ E44E2B3F1AE761220092347B /* PltHttpClientTask.cpp in Sources */,
+ E44E2B401AE761220092347B /* PltMediaConnect.cpp in Sources */,
+ E44E2B411AE761220092347B /* PltMediaBrowser.cpp in Sources */,
+ E44E2B421AE761220092347B /* PltXbox360.cpp in Sources */,
+ E44E2B431AE761220092347B /* AVTransportSCPD.cpp in Sources */,
+ E44E2B441AE761220092347B /* PltLeaks.cpp in Sources */,
+ E44E2B451AE761220092347B /* PltTaskManager.cpp in Sources */,
+ E44E2B461AE761220092347B /* PltMediaCache.cpp in Sources */,
+ E44E2B471AE761220092347B /* PltAction.cpp in Sources */,
+ E44E2B481AE761220092347B /* PltSsdp.cpp in Sources */,
+ E44E2B491AE761220092347B /* PltIconsData.cpp in Sources */,
+ E44E2B4A1AE761220092347B /* PltArgument.cpp in Sources */,
+ E44E2B4B1AE761220092347B /* PltFrameBuffer.cpp in Sources */,
+ E44E2B4C1AE761220092347B /* PltHttpServer.cpp in Sources */,
+ E44E2B4D1AE761220092347B /* PltStateVariable.cpp in Sources */,
+ E44E2B4E1AE761220092347B /* PltMediaServer.cpp in Sources */,
+ E44E2B4F1AE761220092347B /* PltSyncMediaBrowser.cpp in Sources */,
+ E44E2B501AE761220092347B /* PltDeviceData.cpp in Sources */,
+ E44E2B511AE761220092347B /* PltConstants.cpp in Sources */,
+ E44E2B521AE761220092347B /* ContentDirectorySCPD.cpp in Sources */,
+ E44E2B531AE761220092347B /* PltUPnPObject.mm in Sources */,
+ E44E2B541AE761220092347B /* PltService.cpp in Sources */,
+ E44E2B551AE761220092347B /* PltMimeType.cpp in Sources */,
+ E44E2B561AE761220092347B /* ConnectionManagerSCPD.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E45332A91AAED318004A52FD /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E45332B81AAED318004A52FD /* ViewController.mm in Sources */,
+ E45332B51AAED318004A52FD /* AppDelegate.m in Sources */,
+ E45332B21AAED318004A52FD /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ E41016371ACFA826000E994F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E41016201ACFA826000E994F /* Platinum-iOS */;
+ targetProxy = E41016361ACFA826000E994F /* PBXContainerItemProxy */;
+ };
+ E42D3B080FDC890F0045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3ABC0FDC87130045379C /* MediaCrawler */;
+ targetProxy = E42D3B070FDC890F0045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B0A0FDC890F0045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3AD20FDC87DB0045379C /* MediaConnect */;
+ targetProxy = E42D3B090FDC890F0045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B0C0FDC890F0045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3ADC0FDC87F50045379C /* MicroMediaController */;
+ targetProxy = E42D3B0B0FDC890F0045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B0E0FDC890F0045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3AE60FDC880D0045379C /* FrameStreamer */;
+ targetProxy = E42D3B0D0FDC890F0045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B680FDC8A180045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3B1A0FDC895A0045379C /* FileMediaServerTest */;
+ targetProxy = E42D3B670FDC8A180045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B6A0FDC8A180045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3B250FDC89720045379C /* HttpTest */;
+ targetProxy = E42D3B690FDC8A180045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B6C0FDC8A180045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3B380FDC89B70045379C /* LightSampleTest */;
+ targetProxy = E42D3B6B0FDC8A180045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B6E0FDC8A180045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3B440FDC89CD0045379C /* MediaRendererTest */;
+ targetProxy = E42D3B6D0FDC8A180045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B700FDC8A180045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3B4F0FDC89E10045379C /* SimpleTest */;
+ targetProxy = E42D3B6F0FDC8A180045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B770FDC8A290045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3B040FDC890A0045379C /* Apps */;
+ targetProxy = E42D3B760FDC8A290045379C /* PBXContainerItemProxy */;
+ };
+ E42D3B790FDC8A290045379C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E42D3B640FDC8A120045379C /* Tests */;
+ targetProxy = E42D3B780FDC8A290045379C /* PBXContainerItemProxy */;
+ };
+ E44470C112C31C1100E01480 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E43741FB123FFB9800000109 /* MediaServerCocoaTest */;
+ targetProxy = E44470C012C31C1100E01480 /* PBXContainerItemProxy */;
+ };
+ E44E2BC31AE76D7B0092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BC21AE76D7B0092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BD51AE7755C0092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E41016201ACFA826000E994F /* Platinum-iOS */;
+ targetProxy = E44E2BD41AE7755C0092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BD71AE7755C0092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BD61AE7755C0092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BD91AE775600092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2BD01AE775510092347B /* Frameworks */;
+ targetProxy = E44E2BD81AE775600092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BDB1AE776060092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BDA1AE776060092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BE11AE779130092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BE01AE779130092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BE31AE7794D0092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BE21AE7794D0092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BE51AE779520092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BE41AE779520092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BE71AE779580092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BE61AE779580092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BE91AE7795C0092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BE81AE7795C0092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BEB1AE779600092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BEA1AE779600092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BED1AE779640092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BEC1AE779640092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BEF1AE779680092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BEE1AE779680092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BF11AE7796C0092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BF01AE7796C0092347B /* PBXContainerItemProxy */;
+ };
+ E44E2BF31AE779700092347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E44E2B231AE761220092347B /* Platinum-Mac */;
+ targetProxy = E44E2BF21AE779700092347B /* PBXContainerItemProxy */;
+ };
+ E459CC2811F82C7F00621896 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E459CC2111F82C3F00621896 /* Help */;
+ targetProxy = E459CC2711F82C7F00621896 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ E4374242123FFE9100000109 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ E4374243123FFE9100000109 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+ E4374244123FFE9100000109 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ E4374245123FFE9100000109 /* English */,
+ );
+ name = MainMenu.xib;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1.0;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DYLIB_CURRENT_VERSION = 1.0.1.0;
+ GCC_GENERATE_TEST_COVERAGE_FILES = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ NPT_CONFIG_ENABLE_LOGGING,
+ PLATINUM_UPNP_SPECS_STRICT,
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = NO;
+ GCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_VERSION = "";
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_PEDANTIC = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VALUE = YES;
+ GCC_WARN_UNUSED_VARIABLE = NO;
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ ONLY_ACTIVE_ARCH = NO;
+ WARNING_CFLAGS = (
+ "-Wextra",
+ "-Wno-long-long",
+ );
+ };
+ name = Release;
+ };
+ E410163B1ACFA826000E994F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/iOS",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/iOS/Neptune.framework/Headers",
+ );
+ INFOPLIST_FILE = Platinum/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = "";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_NAME = Platinum;
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ E410163C1ACFA826000E994F /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/iOS",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/iOS/Neptune.framework/Headers",
+ );
+ INFOPLIST_FILE = Platinum/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = "";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = Platinum;
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
+ E423F36618415DC500E24E39 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = SsdpTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E423F36718415DC500E24E39 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = SsdpTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3ABF0FDC87140045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MediaCrawler;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3AC00FDC87140045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MediaCrawler;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3AD50FDC87DC0045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MediaConnect;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3AD60FDC87DC0045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MediaConnect;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3ADF0FDC87F60045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MicroMediaController;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3AE00FDC87F60045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MicroMediaController;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3AE90FDC880D0045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = FrameStreamer;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3AEA0FDC880D0045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = FrameStreamer;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B050FDC890A0045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = Apps;
+ };
+ name = Debug;
+ };
+ E42D3B060FDC890A0045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = Apps;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B1D0FDC895B0045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = FileMediaServerTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3B1E0FDC895B0045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = FileMediaServerTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B280FDC89720045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = HttpTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3B290FDC89720045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = HttpTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B3B0FDC89B80045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = LightSampleTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3B3C0FDC89B80045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = LightSampleTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B470FDC89CE0045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MediaRendererTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3B480FDC89CE0045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = MediaRendererTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B520FDC89E20045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = SimpleTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E42D3B530FDC89E20045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = SimpleTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B650FDC8A120045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = Tests;
+ };
+ name = Debug;
+ };
+ E42D3B660FDC8A120045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = Tests;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E42D3B740FDC8A210045379C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = All;
+ };
+ name = Debug;
+ };
+ E42D3B750FDC8A210045379C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = All;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E43741FF123FFB9800000109 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = YES;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ../../../Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_Prefix.pch;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = NO;
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ GCC_VERSION = "";
+ GCC_WARN_ABOUT_MISSING_NEWLINE = NO;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = NO;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = NO;
+ GCC_WARN_MISSING_PARENTHESES = NO;
+ GCC_WARN_PEDANTIC = NO;
+ GCC_WARN_SHADOW = NO;
+ GCC_WARN_SIGN_COMPARE = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = NO;
+ GCC_WARN_UNUSED_PARAMETER = NO;
+ GCC_WARN_UNUSED_VALUE = NO;
+ INFOPLIST_FILE = "../../../Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest-Info.plist";
+ INSTALL_PATH = "$(HOME)/Applications";
+ LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = MediaServerCocoaTest;
+ SDKROOT = macosx;
+ STRIP_INSTALLED_PRODUCT = NO;
+ SUPPORTED_PLATFORMS = macosx;
+ WARNING_CFLAGS = "";
+ };
+ name = Debug;
+ };
+ E4374200123FFB9800000109 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ../../../Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_Prefix.pch;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ GCC_VERSION = "";
+ GCC_WARN_UNUSED_PARAMETER = NO;
+ GCC_WARN_UNUSED_VALUE = NO;
+ INFOPLIST_FILE = "../../../Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest-Info.plist";
+ INSTALL_PATH = "$(HOME)/Applications";
+ LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
+ PRODUCT_NAME = MediaServerCocoaTest;
+ SDKROOT = macosx;
+ STRIP_INSTALLED_PRODUCT = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ WARNING_CFLAGS = "";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E43F6BC310F1B74E00C97612 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = TimeTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ E43F6BC410F1B74E00C97612 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ LD_RUNPATH_SEARCH_PATHS = "$(SRCROOT)/../../../Carthage/Build/Mac";
+ PRODUCT_NAME = TimeTest;
+ SUPPORTED_PLATFORMS = macosx;
+ VALID_ARCHS = "i386 x86_64";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E44E2B891AE761220092347B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ /Users/sylvain/dev/Plutinosoft/Platinum/Carthage/Build/Mac,
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INFOPLIST_FILE = Platinum/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_NAME = Platinum;
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ E44E2B8A1AE761220092347B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/Mac",
+ /Users/sylvain/dev/Plutinosoft/Platinum/Carthage/Build/Mac,
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "$(SRCROOT)/../../../Carthage/Build/Mac/Neptune.framework/Headers",
+ );
+ INFOPLIST_FILE = Platinum/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = Platinum;
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
+ E44E2BD21AE775510092347B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ E44E2BD31AE775510092347B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ E45332CE1AAED318004A52FD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/iOS",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_PARAMETER = NO;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "MobileMediaServer-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ E45332CF1AAED318004A52FD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/../../../Carthage/Build/iOS",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_PARAMETER = NO;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "MobileMediaServer-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ E459CC2211F82C4000621896 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = Help;
+ };
+ name = Debug;
+ };
+ E459CC2311F82C4000621896 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ PRODUCT_NAME = Help;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ E46270E90F81F4F8007FE869 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1.0;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DYLIB_CURRENT_VERSION = 1.0.1.0;
+ GCC_GENERATE_TEST_COVERAGE_FILES = NO;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ NPT_DEBUG,
+ _PLATINUM_UPNP_SPECS_STRICT,
+ NPT_CONFIG_ENABLE_LOGGING,
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = NO;
+ GCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_VERSION = "";
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_PEDANTIC = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VALUE = YES;
+ GCC_WARN_UNUSED_VARIABLE = NO;
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ ONLY_ACTIVE_ARCH = YES;
+ WARNING_CFLAGS = (
+ "-Wextra",
+ "-Wno-long-long",
+ );
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "Platinum" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E46270E90F81F4F8007FE869 /* Debug */,
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E410163A1ACFA826000E994F /* Build configuration list for PBXNativeTarget "Platinum-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E410163B1ACFA826000E994F /* Debug */,
+ E410163C1ACFA826000E994F /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E423F36518415DC500E24E39 /* Build configuration list for PBXNativeTarget "SsdpTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E423F36618415DC500E24E39 /* Debug */,
+ E423F36718415DC500E24E39 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3AC30FDC87290045379C /* Build configuration list for PBXNativeTarget "MediaCrawler" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3ABF0FDC87140045379C /* Debug */,
+ E42D3AC00FDC87140045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3AF30FDC88180045379C /* Build configuration list for PBXNativeTarget "MediaConnect" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3AD50FDC87DC0045379C /* Debug */,
+ E42D3AD60FDC87DC0045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3AF40FDC88180045379C /* Build configuration list for PBXNativeTarget "MicroMediaController" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3ADF0FDC87F60045379C /* Debug */,
+ E42D3AE00FDC87F60045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3AF50FDC88180045379C /* Build configuration list for PBXNativeTarget "FrameStreamer" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3AE90FDC880D0045379C /* Debug */,
+ E42D3AEA0FDC880D0045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B170FDC894C0045379C /* Build configuration list for PBXAggregateTarget "Apps" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B050FDC890A0045379C /* Debug */,
+ E42D3B060FDC890A0045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B340FDC89B70045379C /* Build configuration list for PBXNativeTarget "FileMediaServerTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B1D0FDC895B0045379C /* Debug */,
+ E42D3B1E0FDC895B0045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B350FDC89B70045379C /* Build configuration list for PBXNativeTarget "HttpTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B280FDC89720045379C /* Debug */,
+ E42D3B290FDC89720045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B8D0FDC8AC10045379C /* Build configuration list for PBXNativeTarget "LightSampleTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B3B0FDC89B80045379C /* Debug */,
+ E42D3B3C0FDC89B80045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B8E0FDC8AC10045379C /* Build configuration list for PBXNativeTarget "MediaRendererTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B470FDC89CE0045379C /* Debug */,
+ E42D3B480FDC89CE0045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B8F0FDC8AC10045379C /* Build configuration list for PBXNativeTarget "SimpleTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B520FDC89E20045379C /* Debug */,
+ E42D3B530FDC89E20045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B910FDC8AC10045379C /* Build configuration list for PBXAggregateTarget "Tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B650FDC8A120045379C /* Debug */,
+ E42D3B660FDC8A120045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E42D3B920FDC8AC10045379C /* Build configuration list for PBXAggregateTarget "All" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E42D3B740FDC8A210045379C /* Debug */,
+ E42D3B750FDC8A210045379C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E4374201123FFB9800000109 /* Build configuration list for PBXNativeTarget "MediaServerCocoaTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E43741FF123FFB9800000109 /* Debug */,
+ E4374200123FFB9800000109 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E43F6BC210F1B74E00C97612 /* Build configuration list for PBXNativeTarget "TimeTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E43F6BC310F1B74E00C97612 /* Debug */,
+ E43F6BC410F1B74E00C97612 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E44E2B881AE761220092347B /* Build configuration list for PBXNativeTarget "Platinum-Mac" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E44E2B891AE761220092347B /* Debug */,
+ E44E2B8A1AE761220092347B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E44E2BD11AE775510092347B /* Build configuration list for PBXAggregateTarget "Frameworks" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E44E2BD21AE775510092347B /* Debug */,
+ E44E2BD31AE775510092347B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E45332CD1AAED318004A52FD /* Build configuration list for PBXNativeTarget "MobileMediaServer" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E45332CE1AAED318004A52FD /* Debug */,
+ E45332CF1AAED318004A52FD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E459CC2411F82C5E00621896 /* Build configuration list for PBXAggregateTarget "Help" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E459CC2211F82C4000621896 /* Debug */,
+ E459CC2311F82C4000621896 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-Mac.xcscheme b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-Mac.xcscheme
new file mode 100644
index 0000000..0aacf19
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-Mac.xcscheme
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0630"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "E44E2B231AE761220092347B"
+ BuildableName = "Platinum.framework"
+ BlueprintName = "Platinum-Mac"
+ ReferencedContainer = "container:Platinum.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Debug">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Debug"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "E44E2B231AE761220092347B"
+ BuildableName = "Platinum.framework"
+ BlueprintName = "Platinum-Mac"
+ ReferencedContainer = "container:Platinum.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "E44E2B231AE761220092347B"
+ BuildableName = "Platinum.framework"
+ BlueprintName = "Platinum-Mac"
+ ReferencedContainer = "container:Platinum.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-iOS.xcscheme b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-iOS.xcscheme
new file mode 100644
index 0000000..33a6099
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum.xcodeproj/xcshareddata/xcschemes/Platinum-iOS.xcscheme
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0620"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "E41016201ACFA826000E994F"
+ BuildableName = "Platinum.framework"
+ BlueprintName = "Platinum-iOS"
+ ReferencedContainer = "container:Platinum.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Debug">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Debug"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "E41016201ACFA826000E994F"
+ BuildableName = "Platinum.framework"
+ BlueprintName = "Platinum-iOS"
+ ReferencedContainer = "container:Platinum.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "E41016201ACFA826000E994F"
+ BuildableName = "Platinum.framework"
+ BlueprintName = "Platinum-iOS"
+ ReferencedContainer = "container:Platinum.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Info.plist b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Info.plist
new file mode 100644
index 0000000..d7da8c8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.plutinosoft.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>$(CURRENT_PROJECT_VERSION)</string>
+ <key>NSPrincipalClass</key>
+ <string></string>
+</dict>
+</plist>
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Neptune.h b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Neptune.h
new file mode 100644
index 0000000..4baae68
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Neptune.h
@@ -0,0 +1,2 @@
+// Neptune Framework path
+#include <Neptune/Neptune.h>
diff --git a/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Platinum.h b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Platinum.h
new file mode 100644
index 0000000..d8a4ac2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/universal-apple-macosx/Platinum/Platinum.h
@@ -0,0 +1,66 @@
+//
+// Platinum.h
+// Platinum
+//
+// Created by Sylvain Rebaud on 4/3/15.
+//
+//
+
+//#include <UIKit/UIKit.h>
+//
+////! Project version number for Platinum.
+//FOUNDATION_EXPORT double PlatinumVersionNumber;
+//
+////! Project version string for Platinum.
+//FOUNDATION_EXPORT const unsigned char PlatinumVersionString[];
+
+#ifndef _PLATINUM_H_
+#define _PLATINUM_H_
+
+#include <Platinum/PltUPnP.h>
+#include <Platinum/PltCtrlPoint.h>
+#include <Platinum/PltDeviceData.h>
+#include <Platinum/PltHttpServer.h>
+#include <Platinum/PltVersion.h>
+
+#include <Platinum/PltMimeType.h>
+#include <Platinum/PltProtocolInfo.h>
+#include <Platinum/PltAction.h>
+#include <Platinum/PltArgument.h>
+#include <Platinum/PltConstants.h>
+#include <Platinum/PltCtrlPointTask.h>
+#include <Platinum/PltDatagramStream.h>
+#include <Platinum/PltDeviceHost.h>
+#include <Platinum/PltEvent.h>
+#include <Platinum/PltHttp.h>
+#include <Platinum/PltHttpClientTask.h>
+#include <Platinum/PltHttpServer.h>
+#include <Platinum/PltHttpServerTask.h>
+#include <Platinum/PltService.h>
+#include <Platinum/PltSsdp.h>
+#include <Platinum/PltStateVariable.h>
+#include <Platinum/PltTaskManager.h>
+#include <Platinum/PltThreadTask.h>
+#include <Platinum/PltUtilities.h>
+
+#include <Platinum/PltMediaServer.h>
+#include <Platinum/PltMediaBrowser.h>
+#include <Platinum/PltMediaRenderer.h>
+#include <Platinum/PltMediaController.h>
+#include <Platinum/PltDidl.h>
+#include <Platinum/PltFileMediaServer.h>
+#include <Platinum/PltMediaCache.h>
+#include <Platinum/PltMediaItem.h>
+#include <Platinum/PltSyncMediaBrowser.h>
+
+#include <Platinum/PltXbox360.h>
+#include <Platinum/PltMediaConnect.h>
+
+#include <Platinum/PltDownloader.h>
+#include <Platinum/PltStreamPump.h>
+#include <Platinum/PltFrameBuffer.h>
+#include <Platinum/PltFrameServer.h>
+#include <Platinum/PltFrameStream.h>
+#include <Platinum/PltRingBufferStream.h>
+
+#endif // _PLATINUM_H_
diff --git a/lib/libUPnP/Platinum/Build/Targets/x86-unknown-cygwin/Config.scons b/lib/libUPnP/Platinum/Build/Targets/x86-unknown-cygwin/Config.scons
new file mode 100644
index 0000000..9f2c801
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/x86-unknown-cygwin/Config.scons
@@ -0,0 +1,4 @@
+LoadTool('gcc-generic', env)
+
+### Neptune System Files
+env['NPT_SYSTEM_SOURCES']={'System/StdC':'*.cpp', 'System/Bsd':'*.cpp', 'System/Posix':'*.cpp', 'System/Null':'NptNullAutoreleasePool.cpp'} \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Build/Targets/x86-unknown-linux/Config.scons b/lib/libUPnP/Platinum/Build/Targets/x86-unknown-linux/Config.scons
new file mode 100644
index 0000000..a8824bc
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Targets/x86-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/lib/libUPnP/Platinum/Build/Tools/SCons/gcc-generic.py b/lib/libUPnP/Platinum/Build/Tools/SCons/gcc-generic.py
new file mode 100644
index 0000000..a3e3a1b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Tools/SCons/gcc-generic.py
@@ -0,0 +1,36 @@
+import os
+
+def generate(env, gcc_cross_prefix=None, gcc_strict=True, gcc_stop_on_warning=None, gcc_extra_options=''):
+ if gcc_stop_on_warning == None: gcc_stop_on_warning = env['stop_on_warning']
+
+ ### compiler flags
+ if gcc_strict:
+ env.AppendUnique(CCFLAGS = ['-pedantic', '-Wall', '-W', '-Wundef', '-Wno-long-long'])
+ env.AppendUnique(CFLAGS = ['-Wmissing-prototypes', '-Wmissing-declarations'])
+ else:
+ env.AppendUnique(CCFLAGS = ['-Wall'])
+
+ compiler_defines = ['-D_REENTRANT']
+ env.AppendUnique(CCFLAGS = compiler_defines)
+ env.AppendUnique(CPPFLAGS = compiler_defines)
+
+ if env['build_config'] == 'Debug':
+ env.AppendUnique(CCFLAGS = '-g')
+ else:
+ env.AppendUnique(CCFLAGS = '-O3')
+
+ if gcc_stop_on_warning:
+ env.AppendUnique(CCFLAGS = ['-Werror'])
+
+ env['STRIP'] = 'strip'
+
+ if gcc_cross_prefix:
+ env['ENV']['PATH'] += os.environ['PATH']
+ env['AR'] = gcc_cross_prefix+'-ar'
+ env['RANLIB'] = gcc_cross_prefix+'-ranlib'
+ env['CC'] = gcc_cross_prefix+'-gcc ' + gcc_extra_options
+ env['CXX'] = gcc_cross_prefix+'-g++ ' + gcc_extra_options
+ env['LINK'] = gcc_cross_prefix+'-g++ ' + gcc_extra_options
+ env['STRIP'] = gcc_cross_prefix+'-strip'
+
+ \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Build/Tools/Scripts/GenDocumentation.py b/lib/libUPnP/Platinum/Build/Tools/Scripts/GenDocumentation.py
new file mode 100755
index 0000000..72320a0
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Tools/Scripts/GenDocumentation.py
@@ -0,0 +1,77 @@
+#! /usr/bin/python
+
+#############################################################
+# This tool is used to generate the Platinum documentation #
+#############################################################
+
+import os
+import sys
+import subprocess
+import shutil
+import zipfile
+import tarfile
+
+#############################################################
+# ZIP support
+#############################################################
+def ZipDir(top, archive, dir) :
+ entries = os.listdir(top)
+ for entry in entries:
+ path = os.path.join(top, entry)
+ if os.path.isdir(path):
+ ZipDir(path, archive, os.path.join(dir, entry))
+ else:
+ zip_name = os.path.join(dir, entry)
+ archive.write(path, zip_name)
+
+def ZipIt(root, dir) :
+ zip_filename = root+'/'+dir+'.zip'
+
+ if os.path.exists(zip_filename):
+ os.remove(zip_filename)
+
+ archive = zipfile.ZipFile(zip_filename, "w", zipfile.ZIP_DEFLATED)
+ ZipDir(root+'/'+dir, archive, dir)
+ archive.close()
+
+def TarIt(root, dir) :
+ tar_filename = root+'/'+dir+'.tgz'
+
+ if os.path.exists(tar_filename):
+ os.remove(tar_filename)
+
+ archive = tarfile.TarFileCompat(tar_filename, "w", tarfile.TAR_GZIPPED)
+ ZipDir(root+'/'+dir, archive, dir)
+ archive.close()
+
+#############################################################
+# Main
+#############################################################
+# ensure that PLATINUM_KIT_HOME has been set and exists
+if not os.environ.has_key('PLATINUM_KIT_HOME'):
+ print 'ERROR: PLATINUM_KIT_HOME not set'
+ sys.exit(1)
+PLATINUM_KIT_HOME = os.environ['PLATINUM_KIT_HOME']
+
+if not os.path.exists(PLATINUM_KIT_HOME) :
+ print 'ERROR: PLATINUM_KIT_HOME ('+PLATINUM_KIT_HOME+') does not exist'
+ sys.exit(1)
+else :
+ print 'PLATINUM_KIT_HOME = ' + PLATINUM_KIT_HOME
+
+# compute paths
+SDK_DOC_NAME='Platinum-HTML'
+SDK_DOC_ROOT=PLATINUM_KIT_HOME+'/Platinum/Docs/Doxygen'
+
+# start doxygen
+retcode = subprocess.call(['doxygen'], cwd=SDK_DOC_ROOT)
+
+if retcode != 0:
+ print 'ERROR: doxygen failed'
+ sys.exit(1)
+
+# zip documentation
+ZipIt(SDK_DOC_ROOT, SDK_DOC_NAME)
+
+# cleanup
+shutil.rmtree(SDK_DOC_ROOT+'/'+SDK_DOC_NAME)
diff --git a/lib/libUPnP/Platinum/Build/Tools/Scripts/GenSvnVersionHeader.py b/lib/libUPnP/Platinum/Build/Tools/Scripts/GenSvnVersionHeader.py
new file mode 100644
index 0000000..9820b6d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Tools/Scripts/GenSvnVersionHeader.py
@@ -0,0 +1,41 @@
+#! /usr/bin/python
+
+#############################################################
+# This tool is used to generate the version info file #
+#############################################################
+import sys
+import os
+
+# ensure that PLATINUM_HOME has been set and exists
+if not os.environ.has_key('PLATINUM_KIT_HOME'):
+ print 'ERROR: PLATINUM_KIT_HOME not set'
+ sys.exit(1)
+PLATINUM_KIT_HOME = os.environ['PLATINUM_KIT_HOME']
+
+# ensure that PLATINUM_KIT_HOME has been set and exists
+if not os.path.exists(PLATINUM_KIT_HOME) :
+ print 'ERROR: PLATINUM_KIT_HOME ('+PLATINUM_KIT_HOME+') does not exist'
+ sys.exit(1)
+else :
+ print 'PLATINUM_KIT_HOME = ' + PLATINUM_KIT_HOME
+
+# get the SVN repo version
+version = os.popen('svnversion -n').readlines()[0]
+print 'current VERSION =',version
+if version.endswith('P'):
+ version = version[0:-1]
+if version.endswith('MP'):
+ version = version[0:-2]
+try:
+ version_int = int(version)+1 ## add one, because when we check it in, the rev will be incremented by one
+except:
+ print 'ERROR: you cannot run this on a modified working copy'
+ sys.exit(1)
+
+
+output = open(PLATINUM_KIT_HOME+'/Platinum/Source/Platinum/PltSvnVersion.h', 'w+')
+output.write('/* DO NOT EDIT. This file was automatically generated by GenSvnVersionHeader.py */\n')
+output.write('#define PLT_SVN_VERSION '+str(version_int)+'\n')
+output.write('#define PLT_SVN_VERSION_STRING "'+str(version_int)+'"\n')
+output.close()
+print 'upon check-in, version will be', str(version_int)
diff --git a/lib/libUPnP/Platinum/Build/Tools/Scripts/MakeAllVs.py b/lib/libUPnP/Platinum/Build/Tools/Scripts/MakeAllVs.py
new file mode 100644
index 0000000..32f1bd0
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Tools/Scripts/MakeAllVs.py
@@ -0,0 +1,37 @@
+#! /usr/bin/env python
+
+import os
+import sys
+import getopt
+import subprocess
+
+
+configs = ['Debug', 'Release']
+solutions = ['../../../Build/Targets/x86-microsoft-win32-vs2008/Platinum.sln']
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "b:rc")
+except getopt.GetoptError, (msg, opt):
+ print 'No build_config, defaulting to build all'
+
+for opt, arg in opts:
+ if opt == '-b':
+ config = arg
+
+
+def CallVsMake(sln, cfg):
+ cmd = 'python VsMake.py -s %s -b %s' % (sln, cfg)
+ print cmd
+ retVal = subprocess.call(cmd.split())
+ if retVal != 0:
+ sys.exit(retVal)
+
+for sln in solutions:
+ if 'config' not in locals() and 'config' not in globals():
+ print '************ Building all configurations **************'
+ for cfg in configs:
+ CallVsMake(sln, cfg)
+ else:
+ print '************ Building configuration=' + config + ' ****************'
+ CallVsMake(sln, config)
+ \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Build/Tools/Scripts/VsMake.py b/lib/libUPnP/Platinum/Build/Tools/Scripts/VsMake.py
new file mode 100644
index 0000000..07e0c33
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Tools/Scripts/VsMake.py
@@ -0,0 +1,97 @@
+#! /usr/bin/env python
+"""
+
+Visual Studio 2005 Build Script
+
+$Id: VsMake.py 655 2010-09-29 22:40:22Z soothe $
+
+"""
+
+import os
+import sys
+import getopt
+import subprocess
+
+# Setup some path stuff
+try:
+ if environ['VISUALSTUDIO_BIN']:
+ VSBINDIR = environ['VISUALSTUDIO_BIN']
+except NameError:
+ # Use default value for visual studio.
+ VSBINDIR = 'C:/Program Files/Microsoft Visual Studio 8/Common7/IDE'
+ print 'VISUALSTUDIO_BIN not set. Trying default value:'
+ print ' ' + VSBINDIR
+ print ''
+
+
+# ------------------------------------------------------------
+# usage
+# ------------------------------------------------------------
+def usage(errMsg):
+ try:
+ print 'Error: %s' % (errMsg)
+ except NameError:
+ pass
+
+ print 'Usage: '
+ print ' %s -s <path to solution> -b [Release|Debug|etc.]' % (sys.argv[0])
+ print ''
+ print ' REQUIRED OPTIONS'
+ print '\t-s <solution>'
+ print '\t-b <configuration>'
+ print ''
+ print ' BUILD OPTIONS'
+ print '\t-c\tMake clean'
+ print '\t-r\tRe-build all'
+
+
+# ------------------------------------------------------------
+# main
+# ------------------------------------------------------------
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "s:b:rc")
+except getopt.GetoptError, (msg, opt):
+# print 'Error: invalid argument, %s: %s' % (opt, msg)
+ usage('invalid argument, %s: %s' % (opt, msg))
+ sys.exit(2)
+
+# Build options
+doingBuild = False
+rebuildAll = False
+makeClean = False
+
+for opt, arg in opts:
+ if opt == '-s':
+ solutionFile = arg
+ doingBuild = True
+ elif opt == '-b':
+ buildName = arg
+ doingBuild = True
+ elif opt == '-r':
+ rebuildAll = True
+ doingBuild = True
+ elif opt == '-c':
+ makeClean = True
+
+if rebuildAll and makeClean:
+ usage('Error cannot specify -c and -r together')
+ sys.exit(2)
+
+try:
+ buildSwitch = 'build'
+ if rebuildAll: buildSwitch = 'rebuild'
+ elif makeClean: buildSwitch = 'clean'
+
+ cmd_list = ['%s/devenv.com' % VSBINDIR, '/%s' % buildSwitch, buildName, solutionFile]
+ cmd = " ".join(cmd_list)
+ print 'Executing:'
+ print cmd
+ retVal = subprocess.call(cmd_list)
+ # only the least sig 8 bits are the real return value
+ if retVal != 0:
+ print cmd
+ print '** BUILD FAILURE **'
+ sys.exit(retVal)
+except NameError, (name):
+ usage('missing argument %s' % (name))
+ sys.exit(2)
diff --git a/lib/libUPnP/Platinum/Build/Tools/Scripts/XCodeMake.py b/lib/libUPnP/Platinum/Build/Tools/Scripts/XCodeMake.py
new file mode 100755
index 0000000..15bce59
--- /dev/null
+++ b/lib/libUPnP/Platinum/Build/Tools/Scripts/XCodeMake.py
@@ -0,0 +1,83 @@
+#! /usr/bin/env python
+"""
+
+XCode Build Script
+
+$Id: XCodeMake.py 655 2010-09-29 22:40:22Z soothe $
+
+"""
+
+import os
+import sys
+import getopt
+import subprocess
+
+
+# ------------------------------------------------------------
+# usage
+# ------------------------------------------------------------
+def usage(errMsg):
+ try:
+ print 'Error: %s' % (errMsg)
+ except NameError:
+ pass
+
+ print 'Usage: '
+ print ' %s -p <path to project> -b [Release|Debug|etc.] -t [All|Platinum|PlatinumFramework|etc.] -s [macosx|iphoneos]' % (sys.argv[0])
+ print ''
+ print ' REQUIRED OPTIONS'
+ print '\t-p <project>'
+ print '\t-b <configuration>'
+ print '\t-t <target>'
+ print '\t-s <sdk>'
+ print ''
+ print ' BUILD OPTIONS'
+ print '\t-c\tMake clean'
+
+
+# ------------------------------------------------------------
+# main
+# ------------------------------------------------------------
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "p:b:t:s:c")
+except getopt.GetoptError, (msg, opt):
+# print 'Error: invalid argument, %s: %s' % (opt, msg)
+ usage('invalid argument, %s: %s' % (opt, msg))
+ sys.exit(2)
+
+# Build options
+doingBuild = False
+rebuildAll = False
+makeClean = False
+
+for opt, arg in opts:
+ if opt == '-p':
+ projectFile = arg
+ doingBuild = True
+ elif opt == '-b':
+ buildName = arg
+ doingBuild = True
+ elif opt == '-t':
+ targetName = arg
+ elif opt == '-s':
+ sdk = arg
+ elif opt == '-c':
+ makeClean = True
+
+try:
+ buildSwitch = 'build'
+ if makeClean: buildSwitch = 'clean'
+
+ cmd_list = ['xcodebuild', '-project', '%s' % projectFile, '-target', '%s' % targetName, '-sdk', '%s' % sdk, '-configuration', '%s' % buildName, '%s' % buildSwitch]
+ cmd = " ".join(cmd_list)
+ print 'Executing:'
+ print cmd
+ retVal = subprocess.call(cmd_list)
+ # only the least sig 8 bits are the real return value
+ if retVal != 0:
+ print cmd
+ print '** BUILD FAILURE **'
+ sys.exit(retVal)
+except NameError, (name):
+ usage('missing argument %s' % (name))
+ sys.exit(2)
diff --git a/lib/libUPnP/Platinum/CHANGELOG.txt b/lib/libUPnP/Platinum/CHANGELOG.txt
new file mode 100644
index 0000000..130566b
--- /dev/null
+++ b/lib/libUPnP/Platinum/CHANGELOG.txt
@@ -0,0 +1,730 @@
+Platinum 1.0.5.13
+-----------------
+- fixed: didl used "actors" instead of "actor"
+- changed: moved modelURL after serialNumber to please UCTT
+- added: relax exception to identify DIAL devices which are not UPnP compliant since they don't expose valid services.
+- changed: no more sscanf dependency
+- added: Android NDK r9b support
+- added: UDA 1.1 initial support
+- fixed: Crash fix when stopping device while a subscription request is received. The HttpServer uses its own task manager which could end up queuing a new task into the DeviceHost task manager after it had been stopped and this task would never be stopped. The ServiceEvent task would then try to access a service that had then be destroyed when DeviceHost:Stop returned. A TaskManager cannot be restarted now once Abort has been called.
+- fixed: memory leaks
+
+Platinum 1.0.4.11
+-----------------
+- fixed: crash when stopping UPnP while scheduling for scpd retrieval
+- fixed: rare crash when stopping UPnP while connections are opened.
+
+Platinum 1.0.4.10
+-----------------
+- fixed: simplified connection management fixing a potential crash on shutdown
+- fixed: Platinum.framework now contains fat library instead of Mach-o objects.
+- added: HTML help is now part of SDK (instead of zip)
+- fixed: android build was looking for axTls instead axTLS library.
+
+Platinum 1.0.4.9
+----------------
+- fixed: crash due to uninitialized variables
+
+Platinum 1.0.4.8
+----------------
+- fixed: leaks during exit by reworking the sequence of singletons automatic destruction.
+- added: now extracts presentationURL from device description.
+- added: can now opt in to use media cache in FileMediaServerTest.
+- fixed: 2008 VS project
+- added: 'down' command to MicroMediaController to download a media locally
+- fixed: interruption during download could happen if non blocking socket was full and returned NPT_ERROR_WOULD_BLOCK. Now retries.
+
+Platinum 1.0.4.3
+----------------
+- fixed: leaks during event processing.
+
+Platinum 1.0.4.2
+----------------
+- fixed: Potential leaks and crash when tasks failed to start due to UPnP entire stack shutting down.
+
+Platinum 1.0.4.1
+----------------
+- fixed: Slow shutting down.
+
+Platinum 1.0.4.0
+----------------
+- changed: Windows sockets are now fully cancellable.
+- fixed: crash when closing due to static cleanup orders when using TLS, possible leak instead. Proper fix in the works
+- fixed: potential cause for crash during socket cancellation due to references not carrying over thread safety
+
+Platinum 1.0.3.1
+----------------
+- changed: increased timeout for write io http server tasks to prevent PS3 from disconnecting too early (60 secs is not enough apparently)
+- changed: put back announcing bye-bye first.
+- fixed: http logger defines when not using logging
+- fixed: scons build for macosx
+- fixed: locking for 30 secs when stopping UPnP if sockets are in the middle of a connection than hangs.
+
+Platinum 1.0.3.0
+----------------
+- fixed: potential deadlock when subscribing to a service from the delegate upon being notified a device is ready
+- fixed: crash when device disappears while processing an event notification
+- changed: made posix mutexes recursive to simplify PLT_CtrlPoint implementation
+- changed: don't update device base url when receiving a SSDP Notify with a different IP as it could be unreachable.
+
+Platinum 1.0.2.1
+----------------
+- fixed: fault XML for DLNA compliance
+
+Platinum 1.0.2.0
+----------------
+- fixed: deadlock in PLT_CtrlPoint
+
+Platinum 1.0.1.0
+----------------
+- added: GetPort method to PLT_CtrlPoint in case one wants to attach to the event http server for serving static content
+- fixed: deadlocks with new PLT_CtrlPoint pending notifications
+- changed: increased subscriber notification renewal to 90 secs before end of subscription
+- fixed: PLT_CtrlPoint log formatting error
+- fixed: memory leaks in PLT_CtrlPoint
+- fixed: PLT_HttpServer now properly supports chunked-encoding responses.
+
+Platinum 1.0.9.3
+----------------
+changed: reworked event notifications to be reprocessed if subscriber is not known yet immediately after a subscription.
+fixed: some deadlocks due limiting number of tasks in task manager by default now.
+added: now keep track of pending inspections so that a bunch of SSDP notifications don't all trigger a bunch description requests.
+added: support for armv7s, Xcode 4.5
+added: added support for changing default TTL values
+changed: made DecomposeVar protected virtual
+
+Platinum 0.6.9.3
+----------------
+fixed: passing 0 for frequency to Search/Discover now disables repeat
+added: support for Scons 2.1
+changed: improved UPnP stopping process
+changed: limit max number of tasks per task manager to 50 by default
+changed: limit max number of HTTP clients handled by HTTP server to 50 by default
+changed: made PltCtrlPoint AddDevice & RemoveDevice protected so they can be called by custom implementations to manually remove expired devices
+
+Platinum 0.6.9.2
+----------------
+changed: less strict about invalid protocol info extra params parsing
+fixed: fixed embedded test
+added: android jni module and sample
+fixed: subscription notification events wouldn't be received after upnp got restarted
+fixed: task manager stop could be hanging while waiting for tasks to finish if a task was started during cancellation
+
+Platinum 0.6.9.1
+----------------
+added: support to bridge Neptune Logging to other loggers such as Cocoa Lumberjack
+fixed: better support for embedded devices detection
+added: GetVolumeState to PltMediaController
+fixed: crash in NPT_Socket::Cancel when stopping HTTP clients
+
+Platinum 0.6.9
+--------------
+changed: reverted trying to bind to source port 1900, it would fail eventually
+added: added back support for sending SSDP messages over broadcast in case multicast is blocked by routers or firewalls
+fixed: MediaRenderer channel attribute for volume was wrong
+changed: MediaBrowser caches only metadata now
+fixed: Scons XCode 4.3.1 support
+added: workaround for servers that start to return bogus total matches on the last page
+updated: Neptune 1.1.3
+added: some CTT 2.0 compliance re SSDP
+added: Date HTTP header to requests
+fixed: crash on exit due to static finalizers being called in random order
+fixed: Host HTTP header wasn't being reset properly on redirects
+removed: OSX Platinum frameworks depending on SystemConfiguration and Foundation frameworks
+
+Platinum 0.6.8
+--------------
+changed: try to bind source port to 1900 for ssdp notify and search responses
+added: capability to change user agent on the fly
+added: didl parsing and formatting of dc:description & upnp:icon
+added: user agent header to SSDP packets
+fixed: Windows build
+added: UPnP AV Renderer functions
+changed: verify we can seek the body of the response before returning Accept-Range: bytes
+fixed: don't use localhost address for SSDP announcements
+changed: short connection time out for subscribers since they may not exist and this would block when exiting
+fixed: bug when parsing W3C date time
+fixed: compiling issues when removing TLS support
+fixed: recursion that prevented some logs to be written
+fixed: potential issue with thread safe references
+added: support for removing HTTP header in a request or response before sending it
+changed: support bytes:0- range request for non seekable streams and avoid returning 416.
+changed: return 416 instead of 500 in case we can't stream the body and a range request was made (this makes XBox and PS3 happier)
+changed: make all references thread safe by default
+
+Platinum 0.6.7
+--------------
+fixed: request would fail when retrying on a new connection after the previous one failed because server closed it without using a Connection:close header. Only happens with requests containing a body.
+fixed: always adding Connection:close in HTTP 1.1 responses due to checking content-length prior to setting it.
+changed: allow DLNA interactive request.
+changed: Don't override accept-range header if already set.
+changed: more DLNA compliance for DMC
+changed: better handling of path extraction. Now url encodes url root as well
+changed: better support for persistent connections with http 1.0
+changed: eturn HTTP 416 if Accept-Range header is not bytes in the request and the server makes a range request
+
+Platinum 0.6.6
+--------------
+fixed: mime type detection was not properly handled
+fixed: bad parsing of file path from url when MediaServer url root was just '/'
+fixed: now builds universal framework for iOS and OSX properly
+added: missing files
+
+Platinum 0.6.5
+--------------
+added: Platinum.xcodeproj now builds Platinum.Framework for both iOS and OSX to make it easier to integrate as a 3rd party.
+changed: Better chunked-encoding support (don't write Content-Length)
+changed: Add Accept-Range header when returning HTTP 416 as per spec
+updated: based on Neptune 1.1.2 now
+fixed: potential crash due to using non thread safe references
+fixed: FindDevice could return invalid root device, now keep a reference of root device when fetching all SCPDs of root device and embedded devices just in case root device goes away
+fixed: crashes in MediaCrawler sample code
+changed: simplified getting default mime type
+changed: only allow keep-alive in response if it contains a ContentLength header or a Chunked transfer encoding
+changed: handlers can now be owned by NPT_HttpServer
+changed: simplified HttpClientTask by using new NPT_HttpClient pipelining feature
+fixed: now detects devices with SCPD urls containing query param or hash tags
+fixed: C++/CLR Managed Binding enumeration of embedded devices not using reference
+changed: removed VS2005 support
+changed: removing broadcast support (only needed for obsolete XBox v1)
+fixed: potential case where a task can be added as we're stopping
+changed: don't add Accept-Range bytes header if chunked encoding is used
+changed: when enumerating interfaces for SSDP, only returned MULTICAST enabled Interfaces and removed Point-To-Point ones
+changed: Forces port 1900 for SSDP now and don't depend on default Multicast interface and instead join on all valid interfaces
+changed: don't advertise resources on all interfaces unless ALLIP is found in filter (DLNA)
+fixed: localinterface not being set for embedded devices resulting in event subscription failing because the subscription IP was 0.0.0.0 rather than the IP of the control point.
+added: Sonos support back using Rhapsody (only visible in Desktop Controller though)
+fixed: @refID mask detection and use cases insensitive compare for tags now
+added: support to serve byte range requests for a stream, not just a file
+added: More DLNA compliance with certain DLNA HTTP headers
+changed: simplified XBox & WMP support to fix "Not Authorized" seen for Denon DLNA devices.
+fixed: mask overlapping with another, added more masks support for DLNA compliance
+fixed: more dlna compliance, let serveFile add Accept-Range header
+fixed: DLNA test failing due to sending refId when not requested
+fixed: DLNA protocol info parsing error due to trailing semi-colon
+fixed: ring buffer stream to only return prematurely on abort and not on eos
+added: .wavm for mono wave extension
+changed: stopped sending byebye first to stop confusing slow devices
+fixed: Windows Media Player 12 not being happy with wav protocol info
+fixed: deadlock when receiving a description response for an invalid device while doing house keeping on subscribers. Now uses only one lock.
+fixed: better handling of stopping UPnP immediately after starting it
+changed: don't bind hard for SSDP multicast listen
+changed: updated Server and UA HTTP header (does not include OS anymore)
+added: basic support for WMP11
+changed: lowered SSDP response time to 5 secs
+changed: no more accept-ranges on any file requests, only on serveFile
+fixed: DLNA profile didl attribute was not being written for albumArtURI
+added: lpcm working for both XBox 360 and PS3
+changed: asks for searchable and childCount didl attributes by default
+removed: extra logging when not finding didl attribute
+fixed: mimetype parsing
+added: support for audio/L16;44100...
+fixed: fails if can't get file length only if a range request is passed
+changed: returns 404 instead of 500 when file is missing
+added: didl support for multiple album arts
+improved: string serialization, reduces too many string copies during didl creation
+added: audio/L16 support to XBox
+fixed: dlna serialization, added audio/L16
+
+Platinum 0.6.4
+--------------
+fixed: android compilation
+fixed: crash when running FileMediaServerTest on a directory with Chinese characters
+fixed: now use real Computer Name or User Name next to Server name
+
+Platinum 0.6.3
+--------------
+fixed: 2005 and 2010 solutions
+added: 2010 Platinum.Managed strong-name signed assembly
+
+Platinum 0.6.2
+--------------
+improved: DLNA flags masks
+fixed: Managed wrapper now keeping the pointer to the native member when passed so we can modify members in place. But we have to be careful to not pass local stack objects that will be deallocated which will cause crashes
+added: Managed now can pass uuid to MediaServer
+fixed: Managed not running on x64 machines
+fixed: new XBox Dashboard support
+fixed: UTF-8 was not properly handled through Managed Interface
+changed: put back default byebye first otherwise xbox doesn't detect when same device arrives after a crash
+added: device signature detection (PS3, XBOX, WMP)
+changed: addIcon is now public
+changed: forced to bind on every interface on port 1900 otherwise we don't receive SSDP search requests sometimes
+changed: MediaConnect only advertise ContentDirectory with Search action to WMP and XBox now
+fixed: returning all resource metadata when receiving only "res" filter
+added: support for @duration metadata filter
+changed: don't prevent serializing resource in didl if it's invalid
+changed: allow ProtocolInfo without PN
+added: DeviceIcon .Net mapping
+added: now can pass byte[] through .Net interface when responding to HTTP request (thumbnails)
+changed: Managed don't throw exception when stopping UPnP if it hasn't been started
+added: signature to Platinum.Managed
+fixed: crash when stopping an already disposed Managed instance (?)
+changed: now exports to Targets root subfolder
+fixed: missing log4net bundle
+
+Platinum 0.6.1
+--------------
+fixed: potential vulnerability when receiving SSDP messages or SOAP requests
+added: now compiles for Android NDK
+added: PLT_UPnP::IsRunning method
+changed: moved LastChange variable parsing into controlpoint
+changed: pass sort criteria entire string to delegate instead of parsed split list
+added: Cocoa layer for Mac
+added: Managed C++ layer for .Net
+added: new Managed MediaServer Test
+changed: improved MimeType and ProtocolInfo support
+changed: being more strict on MX to pass UPnP certification
+fixed: dc:title is required
+added: serialization and parsing of upnp:searchClass and upnp:objectClass name attribute
+changed: searchable attribute is false by default
+changed: Can now pass uuid to Managed MediaServer
+changed: Can change lease time from Managed MediaServer
+changed: Don't adverstise bye-bye SSDP messages by default on startup anymore to pass DLNA compliance
+
+Platinum 0.6.0
+--------------
+added: Documentation Platinum-HTML.zip in Platinum/Docs/Doxygen subfolder
+added: fix for detecting requests with url decoded paths (for example from Windows Media Player)
+changed: PLT_SsdpListenTask timeout to 1 sec only for iPhone
+changed: Removed some PLT_HttpHelper functions that were problematic
+changed: No need to force contentlength to 0, task should set it automatically if no entity
+fixed: Socket leak in PLT_UPnP
+changed: completely reworked HTTP response handling
+changed: osx default target is leopard now
+fixed: osx i386 build issue
+changed: revamped & simplified media server delegate
+changed: updated latest Neptune and now use new time/date support
+changed: PLT_HttpRequestHandler not a template anymore
+updated: normalized use of timeout
+added: basic HTTP caching headers support to HTTP file server
+added: made PLT_MediaCache generic, MediaServer now sorts by date and caches directory listing
+added: axTls to build system for ssl connections (HTTPS)
+added: MicroMediaController can be specified a folder directly using the "cd" command
+fixed: Renderer Channel environment variable attribute name (must be "channel")
+fixed: crashes when enumerating net interfaces on iPhone
+added: more log to MicroMediaController
+added: XmlHelper Serialize function
+
+
+Platinum 0.5.4
+--------------
+updated: msdev 2008 output
+fixed: incorrect local filepath extraction from url
+fixed: xcode project
+fixed: gcc warnings
+added: CocoaTouchBrowser sample iphone app started (not finished)
+added: Platinum xcode proj for iphone into arm-apple-darwin
+changed: handling of http requests when device host server is being used for serving content from derived device (like FileMediaServer Device)
+added: more log to MicroMediaController
+added: XmlHelper Serialize function
+fixed: WMP wouldn't return resource url if the browse filter didn't contain 'res'
+changed: be more relaxed about invalid or missing resource uri and invalid protocolinfo, maybe the filter didn't request it afterall
+
+Platinum 0.5.3
+--------------
+fixed: MediaCrawler app updated
+fixed: crash on exit while Browse action is requested
+fixed: bug in ChunkDecoder
+changed: better support for HTTP 100 continue
+changed: DLNA compliance (handle 1xx responses, shutdown sockets better)
+added: code to check if ip or interface is within same network
+changed: increased stream copy buffer to 16k for better streaming performance
+fixed: crash on exit due to logging in PosixThread wait function
+changed: FileMediaServer now serves files at the root url and not "/content" anymore so that it can serve "/crossdomain.xml" url for Flash if needed.
+changed: putting back GetVolumeDBRange & GetVolumeDB since it seems to be required by DLNA
+fixed: GetTransportAction not returning current protocol info
+changed: remove argument from argument list if value was not allowed
+changed: now returns NPT_ERROR_INVALID_PARAMETERS when validating state variable value if failed
+changed: dont' fail if action contains unknown argument names, simply return NPT_ERROR_NO_SUCH_NAME
+changed: now uses individual scpd cpp files for each scpd
+updated: now uses a batch file and header tool to convert scpd xml file to cpp for inclusion
+added: PlayTo functionality by supporting advertising and responding on localhost
+changed: more DLNA compliance
+added: time class
+
+Platinum 0.5.2
+--------------
+fixed: recursive posix deadlock when notifying new devices are ready and delegates try to subscribe to services
+added: seek command to MicroMediaController
+changed: lowered log levels
+changed: removed SsdpProxy from Build.scons
+updated: scpd for MediaRenderer now has GetVolumeDB, SetVolumeDB, GetVolumeDBRange
+changed: now attach root device to action instead of device (in case of embedded) since embedded devices are not referenced, they're children of main root device
+changed: better embedded devices support in ctrl point, now keeps only root devices in list
+fixed: crashes when device goes away while an action is performed on service or waiting for responses
+fixed: scpd retrieval for embedded devices with same service (Sonos with onnectionManager service for example in both DMS and DMR)
+fixed: action arguments are serialized in same order as defined as scpd (to make WMP12 happy)
+changed: Search sockets are bound on port > 1024 and different than 1900 according to DLNA
+added: When looking for device, can return root if device is known to be embedded
+fixed: root device reference is attached to task that need to access service or action in response to prevent release if device goes away while waiting
+fixed: don't check if subscriber sid start with 'uuid:' even though it's the spec
+added: more WMP12 support parsing xml responses (uses UPnPError instead of upnp_error and any namespace)
+fixed: random crashes
+fixed: PS3 DLNA errors
+changed: Advertise on localhost now and respond properly if search was receiving on localhost
+changed: Now can ignore all local UUIDs when multiple devices are attached
+fixed: MediaController made AVTransport optional and RenderingControl required service
+added: MediaController added SetVolume, GetVolume
+fixed: MediaController better handling of invalid timestamp or duration
+added: MediaRenderer GetVolumeDBRange and SetVolumeDB
+added: Didl support for bitspersample, nraudiochannels and samplefrequency
+changed: Didl adding .000 for frame in timestamp otherwise 360 won't play tracks
+improved: Didl parsing if invalid xml node found
+fixed: Filter criteria was missing in Search function prototype
+added: Can now decide if protocol info should contain DLNA info or not
+added: MediaBrowser added search
+fixed: When receiving didl for item, don't try to validate resource url protocol and ip as it could be rtsp:// or FQDN addresses
+fixed: SetVariableValue can pass csvs and each value will be indepedently validated
+added: Can now set extra attributes to a state variables (for Volume that has a Channel)
+changed: The state variable now serializes itself into an xml node instead of the service doing it. That way we can add extra parameters if needed
+added: helper GetIPAddresses can be passed a flag to add localhost to list if needed
+fixed: vs2005 projects with new Neptune path
+changed: simplified AVTransport scpd for renderer
+added: Renderer now supports Windows 7 WMP PlayTo feature!
+added: now can choose to add xml header or not (some implementations like WMP needs it)
+fixed: bug where it would never keep a connection alive on the server side
+added: more DLNA improvements
+removed: Neptune from ThirdParty, now same level as Platinum in PlatinumKit
+fixed: 360 can play mov files now
+added: mimetype by extension
+fixed: WMP can see Platinum again (needs <?xml ?>
+changed: change mediatype after calling ServeFile instead of before, or it may get changed
+
+Platinum 0.5.1
+--------------
+removed: DMS 1.5 for 360, no need for it
+changed: more DLNA support, fixed deadlock when removing devices
+changed: moved back apps to Platinum proj on OSX
+fixed: ctrl point now renews subscribers in time
+added: mute/unmute function to micromediacontroller to pass DLNA tests
+fixed: fixed subscriber renewal, now wait 10 secs before doing first house keeping of old devices not renewed
+fixed: scons 1.2 support
+fixed: osx config for scons 1.2
+added: MediaServer Device Discovery & Control DLNA compliance
+changed: uses built-in Platinum icons instead of file based
+fixed: iPhone build
+fixed: xbox 360 was not playing divx anymore
+
+Platinum 0.5.0
+--------------
+added: better dlna support for embedded devices
+changed: now wait a bit before fetching device description after receiving first ssdp message just in case we have more ssdp byebye messages we have not received yet which could cause the device to be removed after we've just added it
+added: full support for HTTP/1.1 and persistent connections in compliance with dlna 1.5
+fixed: fixed rare deadlock
+changed: now uses http 1.1 for DLNA compliance
+changed: queues scpd requests instead of using one thread per scpd
+added: near DLNA compliance for device host and control point
+fixed: http server returning more than requested during HTTP byte range requests (fixed iphone playback)
+change: now DMS 1.5 for 360
+fixed: browse issue with syncbrowser
+added: SetDelegate functions to PLT_MediaBrowser and PLT_MediaController in case it is subclassed and this cannot be passed to ctor
+
+Platinum 0.4.9
+--------------
+added: PlatinumiPhone target to Platinum.xcodeproj
+changed: PlatinumApps.xcodeproj now depends on Platinum.xcodeproj
+changed: PLT_MediaBrowser and PLT_MediaController now asks delegate before subscribing to events to let a chance to decide if device is worth listening to events
+changed: renamed PLT_MediaBrowserListener to PLT_MediaBrowserDelegate and PLT_MediaControllerListener to PLT_MediaControllerDelegate
+changed: check for new event to notify every 100ms instead of 10ms, also reduce link list modifications to reduce allocatio/free
+added: can now specify custom user-agent and server http header
+fixed: missing didl resource if no protection attribute was set
+fixed: can now stop/restart devices without restarting entire upnp stack
+changed: honor Connection header from response if keep-alive is true
+fixed: more PS3 support
+added: now can specify initial port can be ignored if failed and try again with a random port
+added: support for resolution in didl, can now prevent certain files from being advertised in didl, better mimetype support in FileServer
+fixed: now aborts properly client socket tasks
+removed: null/null in array, uses NPT_ARRAY_SIZE instead
+removed: NPT_ERROR_INTERNAL result when closing a socket while still reading on it, now returns NPT_ERROR_EOS
+added: support for icons (MediaConnect sample for PS3)
+added: PLT_HttpRequestContext can hold a request and a context now
+changed: better dlna support, can now use request information to decide what to return (important to support xbox 360, ps3, etc..)
+fixed: XBox 360 not finding us anymore, don't hardcode same guid! and fix mp4 playback on 360
+
+Platinum 0.4.8
+--------------
+fixed: XBox 360 and PS3 video playback
+added: removed some FATAL logs, can pass path to MediaConnect cmd line
+changed: changes to http server to support path without a query
+added: frame streamer example (mjpeg live stream advertised via upnp)
+changed: verified that content-length was indeed set on the entity before writing it, to avoid writing 0 when the length wasn't known (multipart)
+
+Platinum 0.4.7
+--------------
+fixed: listener being called multiple times with same device when appearing or disapearing
+added: dc:date support in didl
+added: better dlna support for videos
+changed: don't cache empty results in media cache
+fixed: WMP 11 crash when unsubscribing
+fixed: crash after 15 min due to not cleaning up properly interface list before reusing it
+changed: allow for services with no actions (although not upnp compliant)
+fixed: lock media cache before access
+changed: switching to native eol
+changed: fixed xcode proj, add delay to get description/scpd for Rhapsody to be happy
+changed: uses HTTP 1.1 in server with keep-alive. Greatly improves performance
+updated: license is now GPLv2 or later
+changed: do not search, announce or respond on localhost anymore
+
+Platinum 0.4.6
+--------------
+changed: upnp server now uses same port for upnp and serving files (helps with firewall)
+added: upnp support for embedded devices
+changed: upnp device description can now be modified according to request (user agent header)
+fixed: better upnp eventing mechanism, can now pause eventing to set multiple state variables, and send update in a batch
+changed: detect xbox and change description to pretend to be WMP
+fixed: artist role attribute is not supposed to be in upnp namespace
+updated: Neptune to support Unicode filenames
+added: Sonos support! XBMC server can now be browsed by Sonos Desktop Controller and music can be played on multiple Sonos ZonePlayers all synchronously and streamed from XBMC. Sweeeeeeeeeeet!
+fixed: deadlock on subscribe
+fixed: crach on subscription cancellation
+fixed: first event notification was sent to early and could be missed
+fixed: UPnP Renderer Intel Validity Tool tests
+
+Platinum 0.4.5
+--------------
+fixed: better embedded devices support
+fixed: Unicode support on Win32 platforms
+changed: now can pause eventing to set multiple state variables and resume eventing then
+
+Platinum 0.4.3
+--------------
+fixed: vs2008 solution
+fixed: mp3 invalid protocol
+
+Platinum 0.4.2
+--------------
+changed: don't set an entity on request if no body is expected
+added: support for PS3 (basic dlna support)
+changed: MediaCrawler now derives from MediaConnect so that it's seen by XBox 360
+fixed: now passes the proper reachable interface when subscribing to events by keeping track of which interface was used when retrieving a device description
+fixed: gcc 4.2.3 errors (Ubuntu 8.04)
+changed: removed all NPT_Integer references
+fixed: didl parsing of resource with size > 2GB
+changed: didl resource duration is now unsigned
+added: support for SCons 1.0 (0.98.5)
+fixed: support for files > 4GB
+fixed: SIGPIPE errors on both Ubuntu and MacOSX
+fixed: potential memory leaks reported by valgrind
+changed: updated to use Neptune 1.0.1
+
+Platinum 0.4.1
+--------------
+fixed: crash caused by typo when fixing gcc warnings, was adding the wrong http handler
+changed: don't use an outside lock for requests in PltHttpClientTask which can cause delay and hang out when queuing requests in a row like when updating state (Thanks Andy B.!)
+added: copyright 2008
+
+Platinum 0.4.0
+--------------
+added: new PlatinumApps project for XCode
+added: apple iphone target
+fixed: fixing scons build, automatic stripping in release mode now
+fixed: potential crash due to trying to use connector of a client that didn't exist anymore
+added: support for Vs2008
+fixed: leopard support with both 10.4 and 10.5 sdk installed
+fixed: gcc 4 warnings
+changed: renamed fopen_s to fopen_wrapper
+fixed: Fix for unbuffered file streams on OSX (was callign setvbuf after seek)
+added: Support for SO_REUSEPORT on OSX
+added: Set NOSIGPIPE flag
+
+Platinum 0.3.9
+--------------
+added: Xbox360 support!
+fixed: warning appearing with gcc4 on macosx
+fixed: leaks when getting ip addresses
+added: new ring buffer stream and tests
+changed: Browse to pass a flag instead of UPnP browse text flag
+changed: Browse prototype
+changed: switched to static crt
+added: can now pass http port to FileMediaServerTest
+added: more mediatypes (avi, divx) support
+fixed: content-type not being set properly if file extension was uppercase
+fixed: MediaCrawler prototypes due to changes to Browse signature
+added: MediaConnect project
+added: arm-unknown-linux config (iphone support)
+added: RingBufferStream class
+fixed: NPT_Xml now writes the xml header
+changed: listen task now passed to Start/Stop function to have ctrlpoint, device remove themselves from it
+changed: working on better subscriber support in ctrlpoints (switching to references)
+removed: embedded devices support until we have a better idea on how to support it (is it DLNA compliant anyway?)
+added: a PresentationUrl element to description only if present otherwise Intel UPnP DeviceSpy is confused!
+added: avi & divx extension support to content-type
+added: custom http chunk decoder even though we don't support HTTP 1.1 yet
+fixed: server not reading socket info properly when receiving datagrams which would cause a device to respond to M-SEARCH requests on the wrong udp port (and Xbox360s to not discover our server!)
+fixed: Http Server handlers seem to trigger only on the path of a url NOT including the query which means that SCPD Urls with queries currently don't work! For now we switch to not use queries in SCPD urls
+changed: now announce and respond to search requests on loopback adapter
+fixed: Task manager thread was not sleeping enough! now 100ms
+added: ContentDirectorywSearchSCPD.xml SCPD (Xbox 360 needs Search !)
+updated: latest Neptune
+added: jpg content-type
+fixed: now don't allow to start if specified port for server is in use already
+added: more mimetype to class support
+added: can now pass a port for the file server of PLT_FileMediaServer
+changed: Device host and ctrl points now get their own task manager so that when they stop, all tasks stop so there's no need to keep track of running tasks
+changed: ctrl point now issue a search at least on localhost if no interfaces were found
+fixed: UPnP devices and ctrl points are now freed when stopped (removed)
+fixed: UPnP devices and ctrl points can be restarted (reused) now
+added: better support for icons
+fixed: EventSubscribers now have their own task and try to reuse the socket (Connection Keep-Alive) when possible
+changed: Service uses NPT_List instead of NPT_Arrays to improve manipulation of state vars
+added: Can now use Connection keep-alive with HTTP/1.0 clients
+added: State variables can now be moderated. Service has a task that monitors if vars have changed and send updates if it's time (according to moderation)
+added: Service now supports the "LastChange" state variable
+changed: PLT_SsdpInitMulticastIterator joins group on any interface
+fixed: possible lock when stopping all tasks (lock, notify tasks to stop, unlock then wait for list to be empty)
+added: some dlna support
+changed: moved File Media server from PLT_MediaServer to PLT_FileMediaServer
+added: placeholder for Search in PLT_MediaServer
+changed: removed MediaRenderer and MediaServer projects, now all is in Platinum project
+changed: moved MediaConnect source in Source/Devices
+fixed: build to not include ../ in path.. hopefully fixing gcc 3.3.5 errors
+added: MediaServer now sets variable rate
+fixed: bug where subscribers were deleted all the time after first notification
+fixed: eventing of moderated state variable changes
+fixed: temporary hack for XBMC support of Xbox360, we urlencoded the ? to that the 360 doesn't strip out the query and then the query ends being parsed as part of the path
+changed: didl now forces an empty upnp:artist
+added: Search action to look for ContainerID instead of ObjectId in xml since that's what the xbox 360 sends!
+changed: refactored to use NPT_HttpRequestContext instead of NPT_SocketInfo
+added: new macosx target (universal)
+fixed: use of NPT_CONFIG_THREAD_STACK_SIZE for xbox
+added: can now reset the connector of a NPT_HttpClient
+changed: Updates missing headers only if they're really missing (user_agent, connection, ..)
+changed: Updated NPT_MessageQueue to reflect new blocking way
+changed: Neptune Http server now uses reuse_address when binding
+fixed: single quote in urls
+changed: now can abort NPT_HttpServer
+fixed: If a request is forwarded, don't try to send the body if there's no content length...
+fixed: UPnP Renderer now receives moderated events properly
+fixed: Platinum scons Build, added MediaConnect target
+improved: HttpClientSocketTask now uses keep-alive so if the server is 1.1 or 1.0 with Connection: Keep-alive, it reuses the socket, useful for eventing
+added: Split up MediaConnect support and services into separate class, now CUPnPServer derives from PLT_MediaConnect.
+refactored: move httpserver in start/stop so that it actually stops and cleans up when the device is stopped
+fixed: now starts a thread only when there's a need to event state variable changes to subscribers instead of in the ctor. Useful since the class is also used by ctrl points and they don't need to notify.
+fixed: check that the body stream of a request is rewindable before trying to send a request on a keep-alive socket. If it fails, we wouldn't be able to resend it, so instead, we close the socket and reopen a new one.
+added: new downloader class
+fixed: potential deadlock when stopping upnp while devices are running
+changed: made file server port public in PLT_FileMediaServer so that we can update/query it without recreating a new class (no need for setter/getter)
+
+Platinum 0.3.8
+---------------
+
+fixed: crash in MicroMediaController (ctrlpoint really) when devices go away and a new one reappear. The control point was not removing subscribers from its list for the removed device.
+added: Visual Studio 2005 project files
+changed: switched to using new Neptune Logging system
+changed: PLT_DeviceHost now appends the ip address to friendly name if asked
+
+Platinum 0.3.7
+---------------
+changed: removed projects in the works from solution
+changed: dont restrict an interface to have the MULTICAST flag to send multicast data. If it's not multicast, it just won't send it. Cygwin doesn't report MULTICAST flag properly on interfaces that are multicast so that's why.
+fixed: clear SyncMediaBrowser cache for a device when it disappears
+changed: put back interface matching in proxy using netmask
+fixed: linux build
+fixed: workaround Windows Media Player bug that replaces back slashes to forward slashes in a url query !
+fixed: duplicate headers in crawler response
+changed: fileserver now defaults to serving root "/" with all children so that crawler can use /foo.wma
+changed: made ProcessFileRequest overridable for Crawler
+changed: Mega update:
+ - revamped to use http handlers from Neptune
+ - extensive switch to using address instead of pointers for NPT_HttpRequest & NPT_HttpResponse
+ - using eventhandlers now in devicehost (static for desc & scpds + dynamic for control/event) and controlpoint (event notifications)
+ - fixed host advertising twice byebye on exit
+ - Moved DeviceHost and Ctrlpoint Start/Stop into protected. It's PLT_UPnP now that starts and stop a device (via Add/Remove..)
+ - Created templated PLT_HttpRequestHandler
+fixed: 10 secs to get a M-SEARCH response is fine
+fixed: make it possible to pass an address to send the response back from a search, this is necessary when the udp.connect didn't actually find out which local interface to use
+fixed: now advertises on all interfaces even in broadcast
+fixed: setting MX to 1 in proxy, setting extra header to make sure we don't loop more
+changed: new ssdp proxy using broadcast instead of unicast, no need to keep track of unicasters anymore
+changed: when using broadcast mode, try to use interface broadcast address instead of 255.255.255.255
+changed: made presentation url public (so it can be overridden from the outside)
+hacked: device icons
+changed: better advertising in broadcast mode (less verbose)
+fixed: crash when a device disappears while trying to unsubscribe
+fixed: subscribers being added twice
+fixed: no need to set random seed in task, must be done in threads instead (using thread id)
+changed: added a media cache to cache data responses from servers to speed up
+fixed: better event support (fixed a couple of bugs), unsubscribe on device remove, still need to implement subscription renewal
+changed: improved NPT_Directory to read size & type with 1 call
+fixed: assuming forward unix style delimiters in resource urls was wrong, we want to keep whatever we're passed, it may matter
+changed: now can specify to keep file extension in item title
+changed: can now put a list of UUIDs to ignore in a ctrl point
+changed: now sends a search on localhost if no valid interfaces were found
+changed: now supports broadcast announcements for devices (mainly used by XBOX)
+fixed: changed callbackurls list to be NPT_List<NPT_String> instead of NPT_List<NPT_String*> for event subscribers to fix a weird crash
+fixed: SsdpListenTask takes a true UdpSocket if broadcast mode set
+changed: adding support of NPT_StringFinder for NPT_List<NPT_String> containers
+changed: using a HttpUrl for base urls instead of string
+changed: StreamHandler interface, now passing socket info to ModifyResource
+
+Platinum 0.3.6
+---------------
+- fixed list of devices not being cleared when ctrl point is stopped
+- fixed setting bad content length when serving a file with a byte-range request causing
+- filemediaserver now exposes one resource per network interface and put the proper one first (one the browse request was received on)
+- start listening for ssdp when upnp starts and stops when it stops
+- reversing back adding the Search method to ContentDirectory service
+- rewrite of action processing after finding a major flaw due to parallel processing of multiple calls to the same action. Now each invocation of an action gets its own sets of arguments (in and out).
+
+Platinum 0.3.5
+---------------
+Fixes/Changes:
+- updated directory structure so that everything falls under Build/Targets (even scons based stuff)
+- Fixing ip address being 0.0.0.0 in media resources under cygwin in some cases
+- switching to using HTTP/1.0 for http responses
+- scons build output to Targets top level folder now
+- fixed bug where files with no extensions were not advertised (linux)
+- now strips the executables in Targets folder only in release build
+- Fixed cygwin bug where devices wouldn't be detected when started after a Control Point. Was advertising on disconnected interfaces.
+- Fixed logging wrong ip address, now defaults to 127.0.0.1 if no valid one found
+- fixed bug in server socket task
+- added back HttpClientTests to solution
+- fixed bug in client socket task
+- switch to using NPT_StringOutputStream instead of PLT_OutputStringStream
+- improved PLT_Downloader
+- started working on a SQLite abstraction layer for a better Media Server (work in progress)
+
+Platinum 0.3.2
+---------------
+Fixes/Changes:
+- Tasks and TaskManager rewrote. No more housekeeping thread to cleanup tasks. Tasks are automatically cleaned up when done.
+- Stopping a ControlPoint will also stop the SSDP search tasks.
+- HttpServer can limit the number of connections (threads) it can handle at once.
+- Didl processing rewrote. Didl objects are more C++ oriented now.
+- Some progress in regards to DLNA validation. HTTP Server is 1.0 only (connections are closed immediately once all data has been sent. No more keep-alive support).
+- Started working on Ozone (Sqlite3 abstraction layer)
+
+Platinum 0.3.1
+---------------
+Fixes/Changes:
+- Fixed LightSample Test
+- Fixed MediaRenderer Test
+- Removed old source and project files to avoid confusion
+
+Platinum 0.3.00
+---------------
+Fixes/Changes:
+- Added MacOSX support.
+- Fixed socket abortion problem on Linux (using a pipe).
+- Complete rewrite to use threads instead of interrupt driven round-robin. The benefit is that throughput is now greatly improved (for streaming especially).
+- Addded a new App: MediaCrawler
+- Split up AV MediaServer code. Now the FileMediaServer is one implementation of the AV MediaServer. More to follow.
+- Added README, CHANGELOG, LICENSE files
+
+Known issues:
+- AV MediaServer Search not implemented yet.
+- Http server does not use a thread pool. This can be a problem with hungry ControlPoints like the Intel Tools AV MediaController.
+
+Platinum 0.2.00
+---------------
+Fixes/Changes:
+- Added support for Linux, Xbox, cygwin platforms (using Scons http://scons.org)
+- Now using timeouts on sockets. Fixed search not being repeatly sent.
+- Moved Neptune under ThirdParty folder
+
+Known issues:
+- Aborting on some platforms (linux/xbox) is not immediate. Sockets cannot be easily aborted by simply calling closesocket.
+
+Platinum 0.1.00
+---------------
+Initial Release
diff --git a/lib/libUPnP/Platinum/Extras/neptune-logging.properties b/lib/libUPnP/Platinum/Extras/neptune-logging.properties
new file mode 100644
index 0000000..e630440
--- /dev/null
+++ b/lib/libUPnP/Platinum/Extras/neptune-logging.properties
@@ -0,0 +1,13 @@
+### configure the root logger
+.level = FINE
+.handlers = ConsoleHandler,UdpHandler,FileHandler
+.ConsoleHandler.colors = off
+.ConsoleHandler.filter = 14
+.UdpHandler.hostname=239.255.255.100
+.FileHandler.filename = platinum.log
+
+### configure the platinum logger
+#platinum.level = FINE
+#platinum.handlers = FileHandler
+#platinum.FileHandler.filename = platinum.log
+#platinum.FileHandler.filter = 28 \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Extras/platinum-120x120.jpg b/lib/libUPnP/Platinum/Extras/platinum-120x120.jpg
new file mode 100644
index 0000000..06c0e03
--- /dev/null
+++ b/lib/libUPnP/Platinum/Extras/platinum-120x120.jpg
Binary files differ
diff --git a/lib/libUPnP/Platinum/Extras/platinum-120x120.png b/lib/libUPnP/Platinum/Extras/platinum-120x120.png
new file mode 100644
index 0000000..7f81ea8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Extras/platinum-120x120.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Extras/platinum-48x48.jpg b/lib/libUPnP/Platinum/Extras/platinum-48x48.jpg
new file mode 100644
index 0000000..b92b439
--- /dev/null
+++ b/lib/libUPnP/Platinum/Extras/platinum-48x48.jpg
Binary files differ
diff --git a/lib/libUPnP/Platinum/Extras/platinum-48x48.png b/lib/libUPnP/Platinum/Extras/platinum-48x48.png
new file mode 100644
index 0000000..1a6086f
--- /dev/null
+++ b/lib/libUPnP/Platinum/Extras/platinum-48x48.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/LICENSE.txt b/lib/libUPnP/Platinum/LICENSE.txt
new file mode 100644
index 0000000..979ed5c
--- /dev/null
+++ b/lib/libUPnP/Platinum/LICENSE.txt
@@ -0,0 +1,375 @@
+Platinum UPnP SDK
+-----------------
+This software is provided under the following license:
+
+Plutinosoft, LLC provides its Platinum UPnP SDK under a dual
+license model designed to meet the development and distribution
+needs of both commercial distributors (such as OEMs, ISVs and VARs)
+and open source projects.
+
+For OEMs, ISVs, VARs and Other Distributors of Commercial Applications:
+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.
+
+For developers of Free Open Source Software ("FOSS") applications
+under the GPL that want to combine and distribute those FOSS
+applications with Platinum software, Plutinosoft's Platinum
+open source software licensed under the GPL version 2, or (at your option)
+any later version, is the best option.
+
+Note that Platinum SDK links with Neptune C++ Runtime
+(http://sourceforge.net/projects/neptune), which is licensed under the
+terms of the BSD license. This license is compatible with the GNU GPL.
+
+Platinum is copyrighted by Plutinosoft, LLC.
+http://www.plutinosoft.com
+
+For all commercial license inquiries, please contact us at
+licensing@plutinosoft.com
+
+-------------------------------------------------------------------------
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
diff --git a/lib/libUPnP/Platinum/README.md b/lib/libUPnP/Platinum/README.md
new file mode 100644
index 0000000..6a1c11f
--- /dev/null
+++ b/lib/libUPnP/Platinum/README.md
@@ -0,0 +1,131 @@
+#PLATINUM UPNP SDK [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Build Status](https://travis-ci.org/plutinosoft/Platinum.svg?branch=master)](https://travis-ci.org/plutinosoft/Platinum)
+
+This toolkit consists of 2 modules:
+* Neptune : a C++ Runtime Library
+* Platinum: a modular UPnP Framework [Platinum depends on Neptune]
+
+Unless you intend to use Neptune independently from Platinum, it is recommended that you build binaries directly from the Platinum root directory. All the dependent binaries will be rebuilt automatically (including Neptune).
+
+#Building SDK and Sample Applications
+
+## Windows:
+Open the Visual Studio 2010 solution located @ Build\Targets\x86-microsoft-win32-vs2010\Platinum.sln
+
+## Mac, iOS:
+First install carthage (https://github.com/Carthage/Carthage)
+```
+> brew update || brew install carthage
+```
+Build Neptune & Platinum frameworks
+```
+> carthage bootstrap
+> carthage build --no-skip-current
+```
+
+Both Neptune and Platinum frameworks binaries can be found under Carthage/Build folders which you can link with your applications.
+Follow the instructions on the [carthage page](https://github.com/Carthage/Carthage).
+If you are building for iOS, special [instructions here](https://github.com/Carthage/Carthage#if-youre-building-for-ios).
+
+If you are interested in building sample apps or tests, you can also open the XCode project file located @ Build/Targets/universal-apple-macosx/Platinum.xcodeproj.
+
+## Linux, Cygwin, etc ...
+Open a shell, go to the Platinum root directory and type 'scons' (http://scons.org).
+```
+> brew update || brew install scons
+> git submodule update --init
+> scons target={TARGET} build_config={Debug|Release}
+```
+The output of the scons build will be found under Build/Targets/{TARGET}/{Debug|Release}.
+Additionally, the output is copied under Targets/{TARGET}/{Debug|Release} for convenience when applicable.
+
+#Running Sample Applications
+
+## FileMediaServerTest
+This is an example of a UPnP MediaServer. Given a path, it allows a UPnP ControlPoint to browse the content of the directory and its sub-directories. Additionally, files can be streamed (Note that only files with known mimetypes are advertised).
+
+```
+FileMediaServerTest [-f <friendly_name>] <path>
+ -f : optional upnp server friendly name
+ <path> : local path to serve
+```
+
+Once started, type 'q' to quit.
+
+## MediaRendererTest
+This is an example shell of a UPnP MediaRenderer. It is to be contolled by a UPnP ControlPoint. This is just a SHELL, this won't play anything yet. You need to hook up the playback functionality yourself.
+
+```
+MediaRendererTest [-f <friendly_name>]
+ -f : optional upnp server friendly name
+```
+
+Once started, type 'q' to quit.
+
+## MediaCrawler
+This is a combo UPnP MediaServer + ControlPoint. It browses content from other MediaServers it finds on the network and present them under one single aggregated view. This is useful for some devices that need to select one single MediaServer at boot time (i.e. Roku).
+
+Once started, type 'q' to quit.
+
+## MicroMediaController
+This is a ControlPoint (synchronous) that lets you browse any MediaServer using a shell-like interface. Once started, a command prompt lets you enter commands such as:
+```
+ quit - shutdown
+ exit - same as quit
+ setms - select a media server to become the active media server
+ getms - print the friendly name of the active media server
+ ls - list the contents of the current directory on the active
+ media server
+ cd - traverse down one level in the content tree on the active
+ media server
+ cd .. - traverse up one level in the content tree on the active
+ media server
+ pwd - print the path from the root to your current position in the
+ content tree on the active media server
+```
+
+Experimental MediaRenderer commands (not yet full implemented):
+```
+ setmr - select a media renderer to become the active media renderer
+ getmr - print the friendly name of the active media renderer
+ open - set the uri on the active media renderer
+ play - play the active uri on the active media renderer
+ stop - stop the active uri on the active media renderer
+```
+
+## MediaConnect
+This is a derived implementation of the FileMediaServerTest with the only difference that it makes it visible to a XBox 360.
+
+## MediaServerCocoaTest
+A basic cocoa test server app showing how to use the Platinum framework on Mac OSX.
+
+#Language Bindings
+
+## Objective-C
+Under Source/Extras/ObjectiveC
+
+## C++/CLR
+Under Source/Extras/Managed
+
+## Android Java/JNI
+To build the JNI shared library, you will need to install the Android NDK and set up the proper environment variables such as ANDROID_NDK_ROOT.
+```
+> scons target=arm-android-linux build_config=Release
+> cd Source/Platform/Android/module/platinum
+> ndk-build NDK_DEBUG=0
+```
+
+This will create the libplatinum-jni.so files under the Source/Platform/Android/module/platinum/libs folder.
+You can then import eclipse Android .project located @ Source/Platform/Android/modules/platinum to create the jar file @ Source/Platform/Android/modules/platinum/bin/platinum.jar
+
+To Test the Platinum jni layer, import into eclipse both Android projects located @ Source/Platform/Android/samples/sample-upnp & Source/Platform/Android/modules/platinum.
+
+#Contributing
+
+We're glad you're interested in Platinum, and we'd love to see where you take it.
+
+Any contributors to the master Platinum repository must sign the [Individual Contributor License Agreement (CLA)](https://docs.google.com/forms/d/1-SuyEu0LfYuhY3kKDDdfdYn5cmTU2lrQRSQSDHau4PI/viewform).
+It's a short form that covers our bases and makes sure you're eligible to contribute.
+
+When you have a change you'd like to see in the master repository, [send a pull request](https://github.com/plutinosoft/Platinum/pulls). Before we merge your request, we'll make sure you're in the list of people who have signed a CLA.
+
+Thanks!
diff --git a/lib/libUPnP/Platinum/SConstruct b/lib/libUPnP/Platinum/SConstruct
new file mode 100644
index 0000000..373e606
--- /dev/null
+++ b/lib/libUPnP/Platinum/SConstruct
@@ -0,0 +1 @@
+SConscript('Build/Boot.scons')
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist
new file mode 100644
index 0000000..789bf78
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowser-Info.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>NSMainNibFile</key>
+ <string>MainWindow</string>
+</dict>
+</plist>
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.h b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.h
new file mode 100755
index 0000000..d22cff1
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.h
@@ -0,0 +1,44 @@
+/*****************************************************************
+|
+| Platinum - Cocoa Touch Browser App
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+@interface CocoaTouchBrowserAppDelegate : NSObject <UIApplicationDelegate> {
+
+ UIWindow *window;
+ UINavigationController *navigationController;
+}
+
+@property (nonatomic, retain) IBOutlet UIWindow *window;
+@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
+
+@end
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.m b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.m
new file mode 100755
index 0000000..b7fb853
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/CocoaTouchBrowserAppDelegate.m
@@ -0,0 +1,73 @@
+/*****************************************************************
+|
+| Platinum - Cocoa Touch Browser
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#import "CocoaTouchBrowserAppDelegate.h"
+#import "RootViewController.h"
+
+
+@implementation CocoaTouchBrowserAppDelegate
+
+@synthesize window;
+@synthesize navigationController;
+
+
+#pragma mark -
+#pragma mark Application lifecycle
+
+- (void)applicationDidFinishLaunching:(UIApplication *)application {
+
+ // Override point for customization after app launch
+
+ [window addSubview:[navigationController view]];
+ [window makeKeyAndVisible];
+}
+
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Save data if appropriate
+}
+
+
+#pragma mark -
+#pragma mark Memory management
+
+- (void)dealloc {
+ [navigationController release];
+ [window release];
+ [super dealloc];
+}
+
+
+@end
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MainWindow.xib b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MainWindow.xib
new file mode 100755
index 0000000..41eefd3
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MainWindow.xib
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">768</int>
+ <string key="IBDocument.SystemVersion">10A288</string>
+ <string key="IBDocument.InterfaceBuilderVersion">715</string>
+ <string key="IBDocument.AppKitVersion">1010</string>
+ <string key="IBDocument.HIToolboxVersion">411.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">46</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="13"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="302016328">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUICustomObject" id="664661524"/>
+ <object class="IBUIWindow" id="380026005">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">1316</int>
+ <object class="NSPSMatrix" key="NSFrameMatrix"/>
+ <string key="NSFrameSize">{320, 480}</string>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ </object>
+ <object class="IBUINavigationController" id="701001926">
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ <object class="IBUINavigationBar" key="IBUINavigationBar" id="207850653">
+ <nil key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <string key="NSFrameSize">{0, 0}</string>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="IBUIViewControllers">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIViewController" id="619226028">
+ <object class="IBUINavigationItem" key="IBUINavigationItem" id="394667715">
+ <reference key="IBUINavigationBar"/>
+ </object>
+ <reference key="IBUIParentViewController" ref="701001926"/>
+ <string key="IBUINibName">RootViewController</string>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="664661524"/>
+ </object>
+ <int key="connectionID">4</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="380026005"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">navigationController</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="701001926"/>
+ </object>
+ <int key="connectionID">15</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="380026005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="664661524"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="302016328"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="701001926"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="207850653"/>
+ <reference ref="619226028"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">11</int>
+ <reference key="object" ref="207850653"/>
+ <reference key="parent" ref="701001926"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">13</int>
+ <reference key="object" ref="619226028"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="394667715"/>
+ </object>
+ <reference key="parent" ref="701001926"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">14</int>
+ <reference key="object" ref="394667715"/>
+ <reference key="parent" ref="619226028"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>11.IBPluginDependency</string>
+ <string>13.CustomClassName</string>
+ <string>13.IBPluginDependency</string>
+ <string>2.IBAttributePlaceholdersKey</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.CustomClassName</string>
+ <string>3.IBPluginDependency</string>
+ <string>9.IBEditorWindowLastContentRect</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIApplication</string>
+ <string>UIResponder</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>RootViewController</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <object class="NSMutableDictionary">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <string>{{673, 376}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>CocoaTouchBrowserAppDelegate</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>{{500, 343}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">15</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">RootViewController</string>
+ <string key="superclassName">UITableViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/RootViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">CocoaTouchBrowserAppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>navigationController</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UINavigationController</string>
+ <string>UIWindow</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/CocoaTouchBrowserAppDelegate.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">CocoaTouchBrowser.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.h b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.h
new file mode 100644
index 0000000..ee9f42d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.h
@@ -0,0 +1,101 @@
+/*****************************************************************
+|
+| Platinum - Media Browser Wrapper
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#import <Platinum/Platinum.h>
+
+/*----------------------------------------------------------------------
+| DiscoveryWrapper
++---------------------------------------------------------------------*/
+@interface DiscoveryWrapper : NSObject
+{
+ @public
+ PLT_DeviceDataReference device;
+ bool added;
+}
+@end
+
+/*----------------------------------------------------------------------
+| BrowseResponseWrapper
++---------------------------------------------------------------------*/
+@interface BrowseResponseWrapper : NSObject
+{
+ @public
+ NPT_Result res;
+ PLT_DeviceDataReference device;
+ PLT_BrowseInfo *info;
+ void *userdata;
+}
+@end
+
+/*----------------------------------------------------------------------
+| MediaBrowserDelegate interface
++---------------------------------------------------------------------*/
+@protocol MediaBrowserDelegate
+
+-(void) handleDiscovery: (DiscoveryWrapper*) wrapper;
+-(void) handleBrowseResponse: (BrowseResponseWrapper*) wrapper;
+
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserWrapper class
++---------------------------------------------------------------------*/
+class PLT_MediaBrowserWrapper : public PLT_MediaBrowser,
+ public PLT_MediaBrowserDelegate
+{
+public:
+ PLT_MediaBrowserWrapper(PLT_CtrlPointReference& control_point);
+ virtual ~PLT_MediaBrowserWrapper();
+
+ // public methods
+ virtual void SetWrapperDelegate(id delegate) { m_WrapperDelegate = delegate; }
+
+ // PLT_MediaBrowserDelegate methods
+ bool OnMSAdded(PLT_DeviceDataReference& device);
+ void OnMSRemoved(PLT_DeviceDataReference& device);
+ void OnBrowseResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_BrowseInfo* info,
+ void* userdata);
+
+private:
+ void NotifyAddedRemoved(PLT_DeviceDataReference& device,
+ bool added);
+
+private:
+ id m_WrapperDelegate;
+};
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.mm b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.mm
new file mode 100644
index 0000000..c853994
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/MediaBrowserWrapper.mm
@@ -0,0 +1,130 @@
+/*****************************************************************
+|
+| Platinum - Media Browser Wrapper
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#import "MediaBrowserWrapper.h"
+
+/*----------------------------------------------------------------------
+| DiscoveryWrapper implementation
++---------------------------------------------------------------------*/
+@implementation DiscoveryWrapper
+@end
+
+/*----------------------------------------------------------------------
+| BrowseResponseWrapper implementation
++---------------------------------------------------------------------*/
+@implementation BrowseResponseWrapper
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserWrapper::PLT_MediaBrowserWrapper
++---------------------------------------------------------------------*/
+PLT_MediaBrowserWrapper::PLT_MediaBrowserWrapper(PLT_CtrlPointReference& control_point) :
+ PLT_MediaBrowser(control_point)
+{
+ PLT_MediaBrowser::SetDelegate(this);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserWrapper::~PLT_MediaBrowserWrapper
++---------------------------------------------------------------------*/
+PLT_MediaBrowserWrapper::~PLT_MediaBrowserWrapper()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserWrapper::OnMSAdded
++---------------------------------------------------------------------*/
+bool
+PLT_MediaBrowserWrapper::OnMSAdded(PLT_DeviceDataReference& device)
+{
+ NotifyAddedRemoved(device, true);
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserWrapper::OnMSRemoved
++---------------------------------------------------------------------*/
+void
+PLT_MediaBrowserWrapper::OnMSRemoved(PLT_DeviceDataReference& device)
+{
+ NotifyAddedRemoved(device, false);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserWrapper::NotifyAddedRemoved
++---------------------------------------------------------------------*/
+void
+PLT_MediaBrowserWrapper::NotifyAddedRemoved(PLT_DeviceDataReference& device,
+ bool added)
+{
+ if ([m_WrapperDelegate respondsToSelector:@selector(handleDiscovery:)]) {
+ DiscoveryWrapper* wrapper = [[DiscoveryWrapper alloc] init];
+ wrapper->device = device;
+ wrapper->added = added;
+
+ // trigger the handling of the message on the main thread
+ [m_WrapperDelegate performSelectorOnMainThread: @selector(handleDiscovery:)
+ withObject: wrapper
+ waitUntilDone: YES];
+ [wrapper release];
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserWrapper::OnBrowseResult
++---------------------------------------------------------------------*/
+void
+PLT_MediaBrowserWrapper::OnBrowseResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_BrowseInfo* info,
+ void* userdata)
+{
+ if ([m_WrapperDelegate respondsToSelector:@selector(handleBrowseResponse:)]) {
+ BrowseResponseWrapper* wrapper = [[BrowseResponseWrapper alloc] init];
+ wrapper->res = res;
+ wrapper->device = device;
+ wrapper->info = info;
+ wrapper->userdata = userdata;
+
+ // trigger the handling of the message on the main thread
+ [m_WrapperDelegate performSelectorOnMainThread: @selector(handleBrowseResponse:)
+ withObject: wrapper
+ waitUntilDone: YES];
+ [wrapper release];
+ }
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.h b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.h
new file mode 100755
index 0000000..e2f6a8d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.h
@@ -0,0 +1,38 @@
+/*****************************************************************
+|
+| Platinum - Cocoa Touch Browser App
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+@interface RootViewController : UITableViewController {
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.m b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.m
new file mode 100755
index 0000000..b75870a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.m
@@ -0,0 +1,179 @@
+/*****************************************************************
+|
+| Platinum - Cocoa Touch Browser App
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#import "RootViewController.h"
+
+
+@implementation RootViewController
+
+/*
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
+ // self.navigationItem.rightBarButtonItem = self.editButtonItem;
+}
+*/
+
+/*
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+}
+*/
+/*
+- (void)viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+}
+*/
+/*
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+}
+*/
+/*
+- (void)viewDidDisappear:(BOOL)animated {
+ [super viewDidDisappear:animated];
+}
+*/
+
+/*
+ // Override to allow orientations other than the default portrait orientation.
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ // Return YES for supported orientations.
+ return (interfaceOrientation == UIInterfaceOrientationPortrait);
+}
+ */
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ // Release anything that can be recreated in viewDidLoad or on demand.
+ // e.g. self.myOutlet = nil;
+}
+
+
+#pragma mark Table view methods
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return 1;
+}
+
+
+// Customize the number of rows in the table view.
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return 0;
+}
+
+
+// Customize the appearance of table view cells.
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+
+ static NSString *CellIdentifier = @"Cell";
+
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+ if (cell == nil) {
+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
+ }
+
+ // Configure the cell.
+
+ return cell;
+}
+
+
+
+/*
+// Override to support row selection in the table view.
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+
+ // Navigation logic may go here -- for example, create and push another view controller.
+ // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
+ // [self.navigationController pushViewController:anotherViewController animated:YES];
+ // [anotherViewController release];
+}
+*/
+
+
+/*
+// Override to support conditional editing of the table view.
+- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
+ // Return NO if you do not want the specified item to be editable.
+ return YES;
+}
+*/
+
+
+/*
+// Override to support editing the table view.
+- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
+
+ if (editingStyle == UITableViewCellEditingStyleDelete) {
+ // Delete the row from the data source.
+ [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
+ }
+ else if (editingStyle == UITableViewCellEditingStyleInsert) {
+ // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
+ }
+}
+*/
+
+
+/*
+// Override to support rearranging the table view.
+- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
+}
+*/
+
+
+/*
+// Override to support conditional rearranging of the table view.
+- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
+ // Return NO if you do not want the item to be re-orderable.
+ return YES;
+}
+*/
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.xib b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.xib
new file mode 100755
index 0000000..98c7f8c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/RootViewController.xib
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.03">
+ <data>
+ <int key="IBDocument.SystemTarget">768</int>
+ <string key="IBDocument.SystemVersion">9G55</string>
+ <string key="IBDocument.InterfaceBuilderVersion">677</string>
+ <string key="IBDocument.AppKitVersion">949.43</string>
+ <string key="IBDocument.HIToolboxVersion">353.00</string>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="9"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="500153577">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUITableView" id="747164330">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrameSize">{320, 416}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ <object class="IBUISimulatedNavigationBarMetrics" key="IBUISimulatedTopBarMetrics">
+ <bool key="IBUIPrompted">NO</bool>
+ </object>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+ <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+ <float key="IBUIRowHeight">4.400000e+01</float>
+ <float key="IBUISectionHeaderHeight">2.200000e+01</float>
+ <float key="IBUISectionFooterHeight">2.200000e+01</float>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">tableView</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="747164330"/>
+ </object>
+ <int key="connectionID">10</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="747164330"/>
+ </object>
+ <int key="connectionID">11</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">dataSource</string>
+ <reference key="source" ref="747164330"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">12</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="747164330"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">13</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <object class="NSArray" key="object" id="231031770">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="231031770"/>
+ <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="500153577"/>
+ <reference key="parent" ref="231031770"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="747164330"/>
+ <reference key="parent" ref="231031770"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>9.IBEditorWindowLastContentRect</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>RootViewController</string>
+ <string>UIResponder</string>
+ <string>{{236, 337}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">13</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">RootViewController</string>
+ <string key="superclassName">UITableViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/RootViewController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">RootViewController</string>
+ <string key="superclassName">UITableViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">tableView</string>
+ <string key="NS.object.0">UITableView</string>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBUserSource</string>
+ <string key="minorKey"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.LastKnownRelativeProjectPath">CocoaTouchBrowser.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
diff --git a/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/main.m b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/main.m
new file mode 100755
index 0000000..02e3ea8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/CocoaTouchBrowser/main.m
@@ -0,0 +1,43 @@
+/*****************************************************************
+|
+| Platinum - Cocoa Touch Browser
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#import <UIKit/UIKit.h>
+
+int main(int argc, char *argv[]) {
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ int retVal = UIApplicationMain(argc, argv, nil, @"CocoaTouchBrowserAppDelegate");
+ [pool release];
+ return retVal;
+}
diff --git a/lib/libUPnP/Platinum/Source/Apps/FrameStreamer/main.cpp b/lib/libUPnP/Platinum/Source/Apps/FrameStreamer/main.cpp
new file mode 100644
index 0000000..fba4986
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/FrameStreamer/main.cpp
@@ -0,0 +1,249 @@
+/*****************************************************************
+|
+| Platinum - Frame Streamer
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Platinum.h"
+#include "PltFrameBuffer.h"
+#include "PltFrameStream.h"
+#include "PltFrameServer.h"
+
+#include <stdlib.h>
+
+NPT_SET_LOCAL_LOGGER("platinum.core.framestreamer")
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+struct Options {
+ const char* path;
+} Options;
+
+/*----------------------------------------------------------------------
+| StreamValidator:
++---------------------------------------------------------------------*/
+class StreamValidator : public PLT_StreamValidator
+{
+public:
+ StreamValidator(NPT_Reference<PLT_FrameBuffer>& buffer) : m_Buffer(buffer) {}
+ virtual ~StreamValidator() {}
+
+ // PLT_StreamValidator methods
+ bool OnNewRequestAccept(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ NPT_Reference<PLT_FrameBuffer>& buffer) {
+ NPT_COMPILER_UNUSED(request);
+ NPT_COMPILER_UNUSED(response);
+ NPT_COMPILER_UNUSED(context);
+ // TODO: should compare HTTP Header Accept and buffer mimetype
+ buffer = m_Buffer;
+ return true;
+ }
+
+ NPT_Reference<PLT_FrameBuffer> m_Buffer;
+};
+
+/*----------------------------------------------------------------------
+| FrameWriter
++---------------------------------------------------------------------*/
+class FrameWriter : public NPT_Thread
+{
+public:
+ FrameWriter(NPT_Reference<PLT_FrameBuffer>& frame_buffer,
+ const char* frame_folder) :
+ m_FrameBuffer(frame_buffer),
+ m_Aborted(false),
+ m_Folder(frame_folder)
+ {}
+
+ const char* GetPath(NPT_List<NPT_String>::Iterator& entry) {
+ if (!entry) return NULL;
+
+ if (!entry->EndsWith(".jpg", true)) {
+ return GetPath(++entry);
+ }
+
+ return *entry;
+ }
+
+ void Run() {
+ NPT_List<NPT_String> entries;
+ const char* frame_path = NULL;
+ NPT_DataBuffer frame;
+ NPT_List<NPT_String>::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();
+ if (!entry) {
+ // Wait a bit before continuing
+ 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
+ entries.Clear();
+ continue;
+ }
+
+ if (NPT_FAILED(m_FrameBuffer->SetNextFrame(frame.GetData(),
+ frame.GetDataSize()))) {
+ NPT_LOG_SEVERE_1("Failed to set next frame %s", frame_path);
+ goto failure;
+ }
+
+ // Wait before loading next frame
+ NPT_System::Sleep(m_Delay);
+
+ // look for next entry
+ ++entry;
+ }
+
+failure:
+ // one more time to unblock any pending readers
+ m_FrameBuffer->Abort();
+ }
+
+ NPT_Reference<PLT_FrameBuffer> m_FrameBuffer;
+ bool m_Aborted;
+ NPT_String m_Folder;
+ NPT_TimeInterval m_Delay;
+};
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit(char** args)
+{
+ fprintf(stderr, "usage: %s <images path>\n", args[0]);
+ fprintf(stderr, "<path> : local path to serve images from\n");
+ exit(1);
+}
+
+/*----------------------------------------------------------------------
+| ParseCommandLine
++---------------------------------------------------------------------*/
+static void
+ParseCommandLine(char** args)
+{
+ char** _args = args++;
+ const char* arg;
+
+ /* default values */
+ Options.path = NULL;
+
+ while ((arg = *args++)) {
+ if (Options.path == NULL) {
+ Options.path = arg;
+ } else {
+ fprintf(stderr, "ERROR: too many arguments\n");
+ PrintUsageAndExit(_args);
+ }
+ }
+
+ /* check args */
+ if (Options.path == NULL) {
+ fprintf(stderr, "ERROR: path missing\n");
+ PrintUsageAndExit(_args);
+ }
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int argc, char** argv)
+{
+ NPT_COMPILER_UNUSED(argc);
+
+ /* parse command line */
+ ParseCommandLine(argv);
+
+ // frame buffer
+ NPT_Reference<PLT_FrameBuffer> 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);
+ writer.Start();
+
+ // stream request validation
+ StreamValidator validator(frame_buffer);
+
+ // frame server receiving requests and serving frames
+ // read from frame buffer
+ NPT_Reference<PLT_FrameServer> device(
+ new PLT_FrameServer(
+ "frame",
+ validator,
+ NPT_IpAddress::Any,
+ 8099));
+
+ if (NPT_FAILED(device->Start()))
+ return 1;
+
+ char buf[256];
+ while (gets(buf))
+ {
+ if (*buf == 'q')
+ {
+ break;
+ }
+ }
+
+ writer.m_Aborted = true;
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Apps/MediaConnect/main.cpp b/lib/libUPnP/Platinum/Source/Apps/MediaConnect/main.cpp
new file mode 100644
index 0000000..993005f
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MediaConnect/main.cpp
@@ -0,0 +1,131 @@
+/*****************************************************************
+|
+| Platinum - Test UPnP A/V Media Connect
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltMediaConnect.h"
+#include "PltVersion.h"
+
+#include <stdlib.h>
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+struct Options {
+ const char* path;
+} Options;
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit(char** args)
+{
+ fprintf(stderr, "usage: %s <path>\n", args[0]);
+ fprintf(stderr, "<path> : local path to serve\n");
+ exit(1);
+}
+
+/*----------------------------------------------------------------------
+| ParseCommandLine
++---------------------------------------------------------------------*/
+static void
+ParseCommandLine(char** args)
+{
+ char** _args = args++;
+ const char* arg;
+
+ /* default values */
+ Options.path = NULL;
+
+ while ((arg = *args++)) {
+ if (Options.path == NULL) {
+ Options.path = arg;
+ } else {
+ fprintf(stderr, "ERROR: too many arguments\n");
+ PrintUsageAndExit(_args);
+ }
+ }
+
+ /* check args */
+ if (Options.path == NULL) {
+ fprintf(stderr, "ERROR: path missing\n");
+ PrintUsageAndExit(_args);
+ }
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+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<PLT_FileMediaConnectDelegate> delegate(
+ new PLT_FileMediaConnectDelegate("/", Options.path));
+ connect->SetDelegate((PLT_MediaServerDelegate*)delegate.AsPointer());
+
+ PLT_UPnP upnp;
+ PLT_DeviceHostReference device(connect);
+ upnp.AddDevice(device);
+ if (NPT_FAILED(upnp.Start()))
+ return 1;
+
+ char buf[256];
+ while (gets(buf))
+ {
+ if (*buf == 'q')
+ {
+ break;
+ }
+ }
+
+ upnp.Stop();
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.cpp b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.cpp
new file mode 100644
index 0000000..ed0c726
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.cpp
@@ -0,0 +1,566 @@
+/*****************************************************************
+|
+| Platinum - Media Crawler
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltVersion.h"
+#include "MediaCrawler.h"
+#include "PltLeaks.h"
+#include "PltMediaServer.h"
+#include "PltHttpServer.h"
+#include "PltDidl.h"
+#include "PltUtilities.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.apps.crawler")
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::CMediaCrawler
++---------------------------------------------------------------------*/
+CMediaCrawler::CMediaCrawler(PLT_CtrlPointReference& ctrlPoint,
+ const char* friendly_name,
+ bool show_ip,
+ const char* udn /* = NULL */,
+ unsigned int port /* = 0 */) :
+ PLT_MediaBrowser(ctrlPoint, NULL),
+ PLT_MediaServer(friendly_name, show_ip, udn, port)
+{
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::~CMediaCrawler
++---------------------------------------------------------------------*/
+CMediaCrawler::~CMediaCrawler()
+{
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::SplitObjectId
++---------------------------------------------------------------------*/
+NPT_Result
+CMediaCrawler::SplitObjectId(const NPT_String& object_id, NPT_String& server_uuid, NPT_String& server_object_id)
+{
+ // reset output params
+ server_uuid = "";
+ server_object_id = "";
+
+ if (object_id.GetLength() == 0 || object_id[0] != '0')
+ return NPT_ERROR_INVALID_FORMAT;
+
+ if (object_id.GetLength() > 1) {
+ if (object_id[1] != '/') return NPT_ERROR_INVALID_FORMAT;
+
+ server_uuid = object_id.SubString(2);
+
+ // look for next delimiter
+ int index = server_uuid.Find('/');
+ if (index >= 0) {
+ server_object_id = server_uuid.SubString(index+1);
+ server_uuid.SetLength(index);
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::FormatObjectId
++---------------------------------------------------------------------*/
+NPT_String
+CMediaCrawler::FormatObjectId(const NPT_String& server_uuid, const NPT_String& server_object_id)
+{
+ NPT_String object_id = NPT_String("0/") + server_uuid;
+ if (server_object_id.GetLength())
+ object_id += NPT_String("/") + server_object_id;
+
+ return object_id;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnBrowse
++---------------------------------------------------------------------*/
+NPT_Result
+CMediaCrawler::OnBrowse(PLT_ActionReference& action,
+ const PLT_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;
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::OnBrowseRoot
++---------------------------------------------------------------------*/
+NPT_Result
+CMediaCrawler::OnBrowseRoot(PLT_ActionReference& action)
+{
+ NPT_String browseFlagValue;
+ if (NPT_FAILED(action->GetArgumentValue("BrowseFlag", browseFlagValue))) {
+ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - invalid arguments.");
+ return NPT_FAILURE;
+ }
+
+ /* extract browseFlag */
+ BrowseFlags browseFlag;
+ if (NPT_FAILED(ParseBrowseFlag(browseFlagValue, browseFlag))) {
+ /* error */
+ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowseRoot - BrowseFlag value not allowed.");
+ action->SetError(402,"Invalid BrowseFlag arg.");
+ return NPT_FAILURE;
+ }
+
+ if (browseFlag == BROWSEMETADATA) {
+ PLT_MediaContainer item;
+ item.m_Title = "Root";
+ item.m_ParentID = "-1";
+ item.m_ObjectID = "0";
+ item.m_ChildrenCount = GetMediaServers().GetItemCount();
+ item.m_ObjectClass.type = "object.container";
+
+ /* convert item to didl */
+ NPT_String filter;
+ action->GetArgumentValue("Filter", filter);
+ NPT_String tmp;
+ NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, tmp));
+
+ /* add didl header and footer */
+ NPT_String didl = didl_header + tmp + didl_footer;
+
+ action->SetArgumentValue("Result", didl);
+ action->SetArgumentValue("NumberReturned", "1");
+ action->SetArgumentValue("TotalMatches", "1");
+
+ // update ID may be wrong here, it should be the one of the container?
+ action->SetArgumentValue("UpdateId", "1");
+ // TODO: We need to keep track of the overall updateID of the CDS
+ } else {
+ NPT_String startingInd;
+ NPT_String reqCount;
+ NPT_String filter;
+
+ NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd));
+ NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount));
+ NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));
+
+ NPT_Int32 start_index, req_count;
+ if (NPT_FAILED(startingInd.ToInteger(start_index)) ||
+ NPT_FAILED(reqCount.ToInteger(req_count))) {
+ return NPT_FAILURE;
+ }
+
+ NPT_Int32 cur_index = 0;
+ NPT_Int32 num_returned = 0;
+ NPT_Int32 total_matches = 0;
+ //unsigned long update_id = 0;
+ PLT_MediaContainer item;
+ NPT_String item_didl;
+ NPT_String didl = didl_header;
+
+ {
+ // populate a list of containers (one container per known servers)
+ const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers();
+ NPT_AutoLock lock((NPT_Mutex&)devices);
+
+ NPT_Lock<PLT_DeviceDataReferenceList>::Iterator entry = devices.GetFirstItem();
+ while (entry) {
+ PLT_DeviceDataReference device = (*entry);
+ item.m_Title = device->GetFriendlyName();
+ item.m_ObjectID = FormatObjectId(device->GetUUID(), "0");
+ item.m_ParentID = "0";
+ item.m_ObjectClass.type = "object.container";
+
+ // reset tmp didl
+ item_didl = "";
+ if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) {
+ NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, item_didl));
+
+ didl += item_didl;
+ num_returned++;
+ }
+ cur_index++;
+ total_matches++;
+
+ ++entry;
+ }
+ }
+
+ didl += didl_footer;
+
+ action->SetArgumentValue("Result", didl);
+ action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned));
+ action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches));
+ action->SetArgumentValue("UpdateId", "1");
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::OnBrowseDevice
++---------------------------------------------------------------------*/
+NPT_Result
+CMediaCrawler::OnBrowseDevice(PLT_ActionReference& action,
+ const char* server_uuid,
+ const char* server_object_id,
+ const NPT_HttpRequestContext& context)
+{
+ NPT_Result res;
+ PLT_DeviceDataReference device;
+
+ if (NPT_FAILED(FindServer(server_uuid, device))) {
+ /* error */
+ NPT_LOG_WARNING("CMediaCrawler::OnBrowseDevice - device not found.");
+ action->SetError(701, "No Such Object.");
+ return NPT_FAILURE;
+ }
+
+ // look for args and convert them
+ NPT_String browseFlagValue;
+ NPT_String startingInd;
+ NPT_String reqCount;
+ NPT_String filter;
+ NPT_String sort;
+
+ NPT_CHECK_SEVERE(action->GetArgumentValue("BrowseFlag", browseFlagValue));
+ NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd));
+ NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount));
+ NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));
+ NPT_CHECK_SEVERE(action->GetArgumentValue("SortCriteria", sort));
+
+ NPT_Int32 start_index, req_count;
+ if (NPT_FAILED(startingInd.ToInteger(start_index)) ||
+ NPT_FAILED(reqCount.ToInteger(req_count))) {
+ return NPT_FAILURE;
+ }
+
+ // create a container for our result
+ // this will be filled in by OnBrowseResponse
+ CMediaCrawlerBrowseInfoReference browse_info(new CMediaCrawlerBrowseInfo());
+ browse_info->shared_var.SetValue(0);
+
+ // send off the browse packet. Note that this will
+ // not block. The shared variable is used to block
+ // until the response has been received.
+ res = Browse(device,
+ server_object_id,
+ start_index,
+ req_count,
+ (browseFlagValue == "BrowseMetadata")?1:0,
+ filter,
+ sort,
+ new CMediaCrawlerBrowseInfoReference(browse_info));
+ NPT_CHECK_SEVERE(res);
+
+ // wait 10 secs for response
+ res = browse_info->shared_var.WaitUntilEquals(1, 10000);
+ NPT_CHECK_SEVERE(res);
+
+ // did the browse fail?
+ if (NPT_FAILED(browse_info->res)) {
+ action->SetError(browse_info->code, "");
+ return NPT_FAILURE;
+ }
+
+ action->SetArgumentValue("Result", UpdateDidl(server_uuid, browse_info->didl, &context.GetLocalAddress()));
+ action->SetArgumentValue("NumberReturned", browse_info->nr);
+ action->SetArgumentValue("TotalMatches", browse_info->tm);
+ action->SetArgumentValue("UpdateId", browse_info->uid);
+ action->SetArgumentValue("ObjectID", FormatObjectId(server_uuid, browse_info->object_id));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::OnBrowseResponse
++---------------------------------------------------------------------*/
+NPT_Result
+CMediaCrawler::OnBrowseResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_COMPILER_UNUSED(device);
+
+ if (!userdata) return NPT_FAILURE;
+
+ CMediaCrawlerBrowseInfoReference* info = (CMediaCrawlerBrowseInfoReference*) userdata;
+ (*info)->res = res;
+ (*info)->code = action->GetErrorCode();
+
+ if (NPT_FAILED(action->GetArgumentValue("ObjectID", (*info)->object_id))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("UpdateID", (*info)->uid))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("NumberReturned", (*info)->nr))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("TotalMatches", (*info)->tm))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("Result", (*info)->didl))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED((*info)->res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ goto done;
+
+bad_action:
+ if (NPT_SUCCEEDED((*info)->res)) (*info)->res = NPT_FAILURE;
+
+done:
+ (*info)->shared_var.SetValue(1);
+ delete info;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::UpdateDidl
++---------------------------------------------------------------------*/
+NPT_String
+CMediaCrawler::UpdateDidl(const char* server_uuid,
+ const NPT_String& didl,
+ const NPT_SocketAddress* req_local_address /* = NULL */)
+{
+ NPT_String new_didl;
+ NPT_String str;
+ NPT_XmlNode* node = NULL;
+ NPT_XmlWriter writer;
+ NPT_OutputStreamReference stream(new NPT_StringOutputStream(&new_didl));
+
+ NPT_LOG_FINE("Parsing Didl...");
+
+ NPT_XmlElementNode* tree = NULL;
+ NPT_XmlParser parser;
+ if (NPT_FAILED(parser.Parse(didl, node)) || !node || !node->AsElementNode()) {
+ goto cleanup;
+ }
+
+ tree = node->AsElementNode();
+
+ NPT_LOG_FINE("Processing Didl xml...");
+ if (tree->GetTag().Compare("DIDL-Lite", true)) {
+ goto cleanup;
+ }
+
+ // iterate through children
+ NPT_Result res;
+ for (NPT_List<NPT_XmlNode*>::Iterator children = tree->GetChildren().GetFirstItem(); children; children++) {
+ NPT_XmlElementNode* child = (*children)->AsElementNode();
+ if (!child) continue;
+
+ // object id remapping
+ NPT_XmlAttribute* attribute_id;
+ res = PLT_XmlHelper::GetAttribute(child, "id", attribute_id);
+ if (NPT_SUCCEEDED(res) && attribute_id) {
+ attribute_id->SetValue(FormatObjectId(server_uuid, attribute_id->GetValue()));
+ }
+
+ // parent ID remapping
+ NPT_XmlAttribute* attribute_parent_id;
+ res = PLT_XmlHelper::GetAttribute(child, "parentID", attribute_parent_id);
+ if (NPT_SUCCEEDED(res)) {
+ attribute_parent_id->SetValue(attribute_parent_id->GetValue().Compare("-1")?FormatObjectId(server_uuid, attribute_parent_id->GetValue()):"0");
+ }
+
+ // resources remapping
+ NPT_Array<NPT_XmlElementNode*> resources;
+ PLT_XmlHelper::GetChildren(child, resources, "res");
+ if (resources.GetItemCount() > 0) {
+ for (unsigned int i=0; i<resources.GetItemCount(); i++) {
+ NPT_XmlElementNode* resource = resources[i];
+ NPT_XmlAttribute* attribute_prot;
+ const NPT_String* url;
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(resource, "protocolInfo", attribute_prot)) && (url = resource->GetText())) {
+ // special case for Windows Media Connect
+ // When a browse is done on the same machine, WMC uses localhost
+ // instead of the IP for all resources urls which means we cannot advertise that
+ // since it would be useless for a remote device
+ // so we try to replace it with the right IP address by looking at which interface we received the
+ // initial browse request on to make sure the remote device will be able to access the modified resource
+ // urls (in case the local PC has more than 1 NICs)
+
+ // replace the url
+ NPT_List<NPT_XmlNode*>& nodes = resource->GetChildren();
+ NPT_HttpUrl http_url(NPT_Uri::PercentDecode(*url));
+ if ((http_url.GetHost() == "localhost" || http_url.GetHost() == "127.0.0.1") && req_local_address) {
+ if (req_local_address->GetIpAddress().AsLong()) {
+ http_url.SetHost(req_local_address->GetIpAddress().ToString());
+
+ // replace text
+ nodes.Apply(NPT_ObjectDeleter<NPT_XmlNode>());
+ nodes.Clear();
+ resource->AddText(http_url.ToString());
+ url = resource->GetText();
+ }
+ }
+
+ CStreamHandler* handler = NULL;
+ res = NPT_ContainerFind(m_StreamHandlers, CStreamHandlerFinder(attribute_prot->GetValue(), *url), handler);
+ if (NPT_SUCCEEDED(res)) {
+ handler->ModifyResource(resource);
+ }
+ }
+ }
+ }
+ }
+
+ // serialize modified node into new didl
+ writer.Serialize(*node, *stream);
+ delete node;
+ return new_didl;
+
+cleanup:
+ delete node;
+ return didl;
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::ProcessFileRequest
++---------------------------------------------------------------------*/
+NPT_Result
+CMediaCrawler::ProcessFileRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, "CMediaCrawler::ProcessFileRequest:", &request);
+
+ if (request.GetMethod().Compare("GET", true) && request.GetMethod().Compare("HEAD", true)) {
+ response.SetStatus(500, "Internal Server Error");
+ return NPT_SUCCESS;
+ }
+
+ // add the user agent header, some stupid media servers like YME needs it
+ if (!request.GetHeaders().GetHeader(NPT_HTTP_HEADER_USER_AGENT)) {
+ request.GetHeaders().SetHeader(NPT_HTTP_HEADER_USER_AGENT,
+ "Platinum/" PLT_PLATINUM_SDK_VERSION_STRING);
+ }
+
+ // File requested
+ NPT_HttpResponse* out_response = NULL;
+ NPT_HttpUrlQuery query(request.GetUrl().GetQuery());
+ const char* url = query.GetField("url");
+ if (url) {
+ // look for handler
+ CStreamHandler* handler = NULL;
+ NPT_ContainerFind(m_StreamHandlers, CStreamHandlerFinder(NULL, url), handler);
+ if (handler && NPT_SUCCEEDED(handler->ProcessFileRequest(request, out_response)) && out_response) {
+ // copy response code and reason
+ response.SetStatus(out_response->GetStatusCode(), out_response->GetReasonPhrase());
+
+ // copy headers
+ NPT_List<NPT_HttpHeader*>::Iterator headers = out_response->GetHeaders().GetHeaders().GetFirstItem();
+ while (headers) {
+ response.GetHeaders().SetHeader((*headers)->GetName(), (*headers)->GetValue());
+ ++headers;
+ }
+ response.SetEntity(new NPT_HttpEntity(response.GetHeaders()));
+
+ // update inputstream
+ NPT_HttpEntity* out_entity;
+ if ((out_entity = out_response->GetEntity()) != NULL) {
+ NPT_InputStreamReference inputstream;
+ out_entity->GetInputStream(inputstream);
+ if (!inputstream.IsNull()) {
+ // set the stream but do not update the content length
+ response.GetEntity()->SetInputStream(inputstream, false);
+ }
+ }
+
+ delete out_response;
+ return NPT_SUCCESS;
+ }
+ }
+
+ response.SetStatus(404, "File Not Found");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| CMediaCrawler::AddStreamHandler
++---------------------------------------------------------------------*/
+NPT_Result
+CMediaCrawler::AddStreamHandler(CStreamHandler* handler)
+{
+ // make sure we don't have a metadatahandler registered for the same extension
+ // PLT_StreamHandler* prev_handler;
+ // NPT_Result ret = NPT_ContainerFind(m_StreamHandlers, PLT_StreamHandlerFinder(handler->GetExtension()), prev_handler);
+ // if (NPT_SUCCEEDED(ret)) {
+ // return NPT_ERROR_INVALID_PARAMETERS;
+ // }
+
+ m_StreamHandlers.Add(handler);
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.h b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.h
new file mode 100644
index 0000000..5aba341
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/MediaCrawler.h
@@ -0,0 +1,118 @@
+/*****************************************************************
+|
+| Platinum - Media Crawler
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _CRAWLER_H_
+#define _CRAWLER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Platinum.h"
+#include "PltMediaConnect.h"
+#include "PltSyncMediaBrowser.h"
+#include "StreamHandler.h"
+
+/*----------------------------------------------------------------------
+| CMediaCrawler
++---------------------------------------------------------------------*/
+class CMediaCrawler : public PLT_MediaBrowser,
+ public PLT_MediaServer
+
+{
+public:
+ CMediaCrawler(PLT_CtrlPointReference& ctrlPoint,
+ const char* friendly_name = "Platinum Crawler",
+ bool show_ip = false,
+ const char* udn = NULL,
+ unsigned int port = 0);
+ virtual ~CMediaCrawler();
+
+ NPT_Result AddStreamHandler(CStreamHandler* handler);
+
+protected:
+ // PLT_MediaServer methods
+ NPT_Result OnBrowse(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+
+ // PLT_MediaBrowser methods
+ NPT_Result OnBrowseResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata);
+
+ // File Server Listener methods
+ NPT_Result ProcessFileRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+private:
+ // methods
+ NPT_Result OnBrowseRoot(PLT_ActionReference& action);
+ NPT_Result OnBrowseDevice(PLT_ActionReference& action,
+ const char* server_uuid,
+ const char* server_object_id,
+ const NPT_HttpRequestContext& context);
+
+ NPT_Result SplitObjectId(const NPT_String& object_id,
+ NPT_String& server_uuid,
+ NPT_String& server_object_id);
+ NPT_String FormatObjectId(const NPT_String& server_uuid,
+ const NPT_String& server_object_id);
+
+ NPT_String UpdateDidl(const char* server_uuid,
+ const NPT_String& didl,
+ const NPT_SocketAddress* req_local_address = NULL);
+
+ // members
+ NPT_List<CStreamHandler*> m_StreamHandlers;
+};
+
+/*----------------------------------------------------------------------
+| CMediaCrawlerBrowseInfo
++---------------------------------------------------------------------*/
+struct CMediaCrawlerBrowseInfo {
+ NPT_SharedVariable shared_var;
+ NPT_Result res;
+ int code;
+ NPT_String object_id;
+ NPT_String didl;
+ NPT_String nr;
+ NPT_String tm;
+ NPT_String uid;
+};
+
+typedef NPT_Reference<CMediaCrawlerBrowseInfo> CMediaCrawlerBrowseInfoReference;
+
+#endif /* _CRAWLER_H_ */
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/StreamHandler.h b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/StreamHandler.h
new file mode 100644
index 0000000..1f03fde
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/StreamHandler.h
@@ -0,0 +1,113 @@
+/*****************************************************************
+|
+| Platinum - Stream Handler
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_STREAM_HANDLER_H_
+#define _PLT_STREAM_HANDLER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class CMediaCrawler;
+
+/*----------------------------------------------------------------------
+| CStreamHandler
++---------------------------------------------------------------------*/
+class CStreamHandler
+{
+public:
+ CStreamHandler(CMediaCrawler* crawler) : m_MediaCrawler(crawler) {}
+ virtual ~CStreamHandler() {}
+
+ // overridables
+ virtual bool HandleResource(const char* prot_info, const char* url) = 0;
+ virtual NPT_Result ModifyResource(NPT_XmlElementNode* resource, NPT_SocketInfo* info = NULL) = 0;
+ virtual NPT_Result ProcessFileRequest(NPT_HttpRequest& request, NPT_HttpResponse*& response) = 0;
+
+protected:
+ CMediaCrawler* m_MediaCrawler;
+};
+
+/*----------------------------------------------------------------------
+| CStreamHandlerFinder
++---------------------------------------------------------------------*/
+class CStreamHandlerFinder
+{
+public:
+ // methods
+ CStreamHandlerFinder(const char* prot_info, const char* url) : m_ProtInfo(prot_info), m_Url(url) {}
+ bool operator()(CStreamHandler* const & handler) const {
+ return handler->HandleResource(m_ProtInfo, m_Url);
+ }
+
+private:
+ // members
+ NPT_String m_ProtInfo;
+ NPT_String m_Url;
+};
+
+/*----------------------------------------------------------------------
+| CPassThroughStreamHandler
++---------------------------------------------------------------------*/
+class CPassThroughStreamHandler : public CStreamHandler
+{
+public:
+ CPassThroughStreamHandler(CMediaCrawler* crawler) : CStreamHandler(crawler) {}
+ virtual ~CPassThroughStreamHandler() {}
+
+ // overridables
+ virtual bool HandleResource(const char* /*prot_info*/, const char* /*url*/) {
+ return true;
+ }
+
+ virtual NPT_Result ModifyResource(NPT_XmlElementNode* resource,
+ NPT_SocketInfo* info = NULL) {
+ NPT_COMPILER_UNUSED(resource);
+ NPT_COMPILER_UNUSED(info);
+ return NPT_SUCCESS;
+ }
+
+ virtual NPT_Result ProcessFileRequest(NPT_HttpRequest& request,
+ NPT_HttpResponse*& response) {
+ NPT_HttpClient client;
+ return client.SendRequest(request, response);
+ }
+
+};
+
+#endif /* _PLT_STREAM_HANDLER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/main.cpp b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/main.cpp
new file mode 100644
index 0000000..80a1a23
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MediaCrawler/main.cpp
@@ -0,0 +1,83 @@
+/*****************************************************************
+|
+| Platinum - main
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "MediaCrawler.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int main(void)
+{
+ // setup Neptune logging
+ NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=58");
+
+ PLT_UPnP upnp;
+ PLT_CtrlPointReference ctrlPoint(new PLT_CtrlPoint());
+ upnp.AddCtrlPoint(ctrlPoint);
+
+ CMediaCrawler* crawler =
+ new CMediaCrawler(ctrlPoint,
+ "Sylvain: Platinum: Crawler");
+ 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
+ ctrlPoint->Discover(NPT_HttpUrl("255.255.255.255", 1900, "*"), "upnp:rootdevice", 1);
+
+ char buf[256];
+ while (gets(buf)) {
+ if (*buf == 'q')
+ break;
+ }
+
+ upnp.Stop();
+
+ delete handler;
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.cpp b/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.cpp
new file mode 100644
index 0000000..5c2e7fb
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.cpp
@@ -0,0 +1,869 @@
+/*****************************************************************
+|
+| Platinum - Miccro Media Controller
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMicroMediaController.h"
+#include "PltLeaks.h"
+#include "PltDownloader.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+//NPT_SET_LOCAL_LOGGER("platinum.tests.micromediacontroller")
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::PLT_MicroMediaController
++---------------------------------------------------------------------*/
+PLT_MicroMediaController::PLT_MicroMediaController(PLT_CtrlPointReference& ctrlPoint) :
+ PLT_SyncMediaBrowser(ctrlPoint),
+ PLT_MediaController(ctrlPoint)
+{
+ // create the stack that will be the directory where the
+ // user is currently browsing.
+ // push the root directory onto the directory stack.
+ m_CurBrowseDirectoryStack.Push("0");
+
+ PLT_MediaController::SetDelegate(this);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::PLT_MicroMediaController
++---------------------------------------------------------------------*/
+PLT_MicroMediaController::~PLT_MicroMediaController()
+{
+}
+
+/*
+* Remove trailing white space from a string
+*/
+static void strchomp(char* str)
+{
+ if (!str) return;
+ char* e = str+NPT_StringLength(str)-1;
+
+ while (e >= str && *e) {
+ if ((*e != ' ') &&
+ (*e != '\t') &&
+ (*e != '\r') &&
+ (*e != '\n'))
+ {
+ *(e+1) = '\0';
+ break;
+ }
+ --e;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::ChooseIDFromTable
++---------------------------------------------------------------------*/
+/*
+ * Presents a list to the user, allows the user to choose one item.
+ *
+ * Parameters:
+ * PLT_StringMap: A map that contains the set of items from
+ * which the user should choose. The key should be a unique ID,
+ * and the value should be a string describing the item.
+ * returns a NPT_String with the unique ID.
+ */
+const char*
+PLT_MicroMediaController::ChooseIDFromTable(PLT_StringMap& table)
+{
+ printf("Select one of the following:\n");
+
+ NPT_List<PLT_StringMapEntry*> entries = table.GetEntries();
+ if (entries.GetItemCount() == 0) {
+ printf("None available\n");
+ } else {
+ // display the list of entries
+ NPT_List<PLT_StringMapEntry*>::Iterator entry = entries.GetFirstItem();
+ int count = 0;
+ while (entry) {
+ printf("%d)\t%s (%s)\n", ++count, (const char*)(*entry)->GetValue(), (const char*)(*entry)->GetKey());
+ ++entry;
+ }
+
+ int index, watchdog = 3;
+ char buffer[1024];
+
+ // wait for input
+ while (watchdog > 0) {
+ fgets(buffer, 1024, stdin);
+ strchomp(buffer);
+
+ if (1 != sscanf(buffer, "%d", &index)) {
+ printf("Please enter a number\n");
+ } else if (index < 0 || index > count) {
+ printf("Please choose one of the above, or 0 for none\n");
+ watchdog--;
+ index = 0;
+ } else {
+ watchdog = 0;
+ }
+ }
+
+ // find the entry back
+ if (index != 0) {
+ entry = entries.GetFirstItem();
+ while (entry && --index) {
+ ++entry;
+ }
+ if (entry) {
+ return (*entry)->GetKey();
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::PopDirectoryStackToRoot
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::PopDirectoryStackToRoot(void)
+{
+ NPT_String val;
+ while (NPT_SUCCEEDED(m_CurBrowseDirectoryStack.Peek(val)) && val.Compare("0")) {
+ m_CurBrowseDirectoryStack.Pop(val);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::OnMSAdded
++---------------------------------------------------------------------*/
+bool
+PLT_MicroMediaController::OnMSAdded(PLT_DeviceDataReference& device)
+{
+ // Issue special action upon discovering MediaConnect server
+ PLT_Service* service;
+ if (NPT_SUCCEEDED(device->FindServiceByType("urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:*", service))) {
+ PLT_ActionReference action;
+ PLT_SyncMediaBrowser::m_CtrlPoint->CreateAction(
+ device,
+ "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
+ "IsAuthorized",
+ action);
+ if (!action.IsNull()) {
+ action->SetArgumentValue("DeviceID", "");
+ PLT_SyncMediaBrowser::m_CtrlPoint->InvokeAction(action, 0);
+ }
+
+ PLT_SyncMediaBrowser::m_CtrlPoint->CreateAction(
+ device,
+ "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
+ "IsValidated",
+ action);
+ if (!action.IsNull()) {
+ action->SetArgumentValue("DeviceID", "");
+ PLT_SyncMediaBrowser::m_CtrlPoint->InvokeAction(action, 0);
+ }
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::OnMRAdded
++---------------------------------------------------------------------*/
+bool
+PLT_MicroMediaController::OnMRAdded(PLT_DeviceDataReference& device)
+{
+ NPT_String uuid = device->GetUUID();
+
+ // test if it's a media renderer
+ PLT_Service* service;
+ if (NPT_SUCCEEDED(device->FindServiceByType("urn:schemas-upnp-org:service:AVTransport:*", service))) {
+ NPT_AutoLock lock(m_MediaRenderers);
+ m_MediaRenderers.Put(uuid, device);
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::OnMRRemoved
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::OnMRRemoved(PLT_DeviceDataReference& device)
+{
+ NPT_String uuid = device->GetUUID();
+
+ {
+ NPT_AutoLock lock(m_MediaRenderers);
+ m_MediaRenderers.Erase(uuid);
+ }
+
+ {
+ NPT_AutoLock lock(m_CurMediaRendererLock);
+
+ // if it's the currently selected one, we have to get rid of it
+ if (!m_CurMediaRenderer.IsNull() && m_CurMediaRenderer == device) {
+ m_CurMediaRenderer = NULL;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::OnMRStateVariablesChanged
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::OnMRStateVariablesChanged(PLT_Service* service,
+ NPT_List<PLT_StateVariable*>* vars)
+{
+ NPT_String uuid = service->GetDevice()->GetUUID();
+ NPT_List<PLT_StateVariable*>::Iterator var = vars->GetFirstItem();
+ while (var) {
+ printf("Received state var \"%s:%s:%s\" changes: \"%s\"\n",
+ (const char*)uuid,
+ (const char*)service->GetServiceID(),
+ (const char*)(*var)->GetName(),
+ (const char*)(*var)->GetValue());
+ ++var;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::ChooseIDGetCurMediaServerFromTable
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::GetCurMediaServer(PLT_DeviceDataReference& server)
+{
+ NPT_AutoLock lock(m_CurMediaServerLock);
+
+ if (m_CurMediaServer.IsNull()) {
+ printf("No server selected, select one with setms\n");
+ } else {
+ server = m_CurMediaServer;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::GetCurMediaRenderer
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::GetCurMediaRenderer(PLT_DeviceDataReference& renderer)
+{
+ NPT_AutoLock lock(m_CurMediaRendererLock);
+
+ if (m_CurMediaRenderer.IsNull()) {
+ printf("No renderer selected, select one with setmr\n");
+ } else {
+ renderer = m_CurMediaRenderer;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::DoBrowse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MicroMediaController::DoBrowse(const char* object_id, /* = NULL */
+ bool metadata /* = false */)
+{
+ NPT_Result res = NPT_FAILURE;
+ PLT_DeviceDataReference device;
+
+ GetCurMediaServer(device);
+ if (!device.IsNull()) {
+ NPT_String cur_object_id;
+ m_CurBrowseDirectoryStack.Peek(cur_object_id);
+
+ // send off the browse packet and block
+ res = BrowseSync(
+ device,
+ object_id?object_id:(const char*)cur_object_id,
+ m_MostRecentBrowseResults,
+ metadata);
+ }
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_getms
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_getms()
+{
+ PLT_DeviceDataReference device;
+ GetCurMediaServer(device);
+ if (!device.IsNull()) {
+ printf("Current media server: %s\n", (const char*)device->GetFriendlyName());
+ } else {
+ // this output is taken care of by the GetCurMediaServer call
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_getmr
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_getmr()
+{
+ PLT_DeviceDataReference device;
+ GetCurMediaRenderer(device);
+ if (!device.IsNull()) {
+ printf("Current media renderer: %s\n", (const char*)device->GetFriendlyName());
+ } else {
+ // this output is taken care of by the GetCurMediaRenderer call
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::ChooseDevice
++---------------------------------------------------------------------*/
+PLT_DeviceDataReference
+PLT_MicroMediaController::ChooseDevice(const NPT_Lock<PLT_DeviceMap>& deviceList)
+{
+ PLT_StringMap namesTable;
+ PLT_DeviceDataReference* result = NULL;
+ NPT_String chosenUUID;
+ NPT_AutoLock lock(m_MediaServers);
+
+ // create a map with the device UDN -> device Name
+ const NPT_List<PLT_DeviceMapEntry*>& entries = deviceList.GetEntries();
+ NPT_List<PLT_DeviceMapEntry*>::Iterator entry = entries.GetFirstItem();
+ while (entry) {
+ PLT_DeviceDataReference device = (*entry)->GetValue();
+ NPT_String name = device->GetFriendlyName();
+ namesTable.Put((*entry)->GetKey(), name);
+
+ ++entry;
+ }
+
+ // ask user to choose
+ chosenUUID = ChooseIDFromTable(namesTable);
+ if (chosenUUID.GetLength()) {
+ deviceList.Get(chosenUUID, result);
+ }
+
+ return result?*result:PLT_DeviceDataReference(); // return empty reference if not device was selected
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_setms
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_setms()
+{
+ NPT_AutoLock lock(m_CurMediaServerLock);
+
+ PopDirectoryStackToRoot();
+ m_CurMediaServer = ChooseDevice(GetMediaServersMap());
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_setmr
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_setmr()
+{
+ NPT_AutoLock lock(m_CurMediaRendererLock);
+
+ m_CurMediaRenderer = ChooseDevice(m_MediaRenderers);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_ls
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_ls()
+{
+ DoBrowse();
+
+ if (!m_MostRecentBrowseResults.IsNull()) {
+ printf("There were %d results\n", m_MostRecentBrowseResults->GetItemCount());
+
+ NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
+ while (item) {
+ if ((*item)->IsContainer()) {
+ printf("Container: %s (%s)\n", (*item)->m_Title.GetChars(), (*item)->m_ObjectID.GetChars());
+ } else {
+ printf("Item: %s (%s)\n", (*item)->m_Title.GetChars(), (*item)->m_ObjectID.GetChars());
+ }
+ ++item;
+ }
+
+ m_MostRecentBrowseResults = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_info
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_info()
+{
+ NPT_String object_id;
+ PLT_StringMap tracks;
+ PLT_DeviceDataReference device;
+
+ // issue a browse
+ DoBrowse();
+
+ if (!m_MostRecentBrowseResults.IsNull()) {
+ // create a map item id -> item title
+ NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
+ while (item) {
+ if (!(*item)->IsContainer()) {
+ tracks.Put((*item)->m_ObjectID, (*item)->m_Title);
+ }
+ ++item;
+ }
+
+ // let the user choose which one
+ object_id = ChooseIDFromTable(tracks);
+
+ if (object_id.GetLength()) {
+ // issue a browse with metadata
+ DoBrowse(object_id, true);
+
+ // look back for the PLT_MediaItem in the results
+ PLT_MediaObject* track = NULL;
+ if (!m_MostRecentBrowseResults.IsNull() &&
+ NPT_SUCCEEDED(NPT_ContainerFind(*m_MostRecentBrowseResults, PLT_MediaItemIDFinder(object_id), track))) {
+
+ // display info
+ printf("Title: %s \n", track->m_Title.GetChars());
+ printf("OjbectID: %s\n", track->m_ObjectID.GetChars());
+ printf("Class: %s\n", track->m_ObjectClass.type.GetChars());
+ printf("Creator: %s\n", track->m_Creator.GetChars());
+ printf("Date: %s\n", track->m_Date.GetChars());
+ for (NPT_List<PLT_AlbumArtInfo>::Iterator iter = track->m_ExtraInfo.album_arts.GetFirstItem();
+ iter;
+ iter++) {
+ printf("Art Uri: %s\n", (*iter).uri.GetChars());
+ printf("Art Uri DLNA Profile: %s\n", (*iter).dlna_profile.GetChars());
+ }
+ for (NPT_Cardinal i=0;i<track->m_Resources.GetItemCount(); i++) {
+ printf("\tResource[%d].uri: %s\n", i, track->m_Resources[i].m_Uri.GetChars());
+ printf("\tResource[%d].profile: %s\n", i, track->m_Resources[i].m_ProtocolInfo.ToString().GetChars());
+ printf("\tResource[%d].duration: %d\n", i, track->m_Resources[i].m_Duration);
+ printf("\tResource[%d].size: %d\n", i, (int)track->m_Resources[i].m_Size);
+ printf("\n");
+ }
+ printf("Didl: %s\n", (const char*)track->m_Didl);
+ } else {
+ printf("Couldn't find the track\n");
+ }
+ }
+
+ m_MostRecentBrowseResults = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_download
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_download()
+{
+ NPT_String object_id;
+ PLT_StringMap tracks;
+ PLT_DeviceDataReference device;
+
+ // issue a browse
+ DoBrowse();
+
+ if (!m_MostRecentBrowseResults.IsNull()) {
+ // create a map item id -> item title
+ NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
+ while (item) {
+ if (!(*item)->IsContainer()) {
+ tracks.Put((*item)->m_ObjectID, (*item)->m_Title);
+ }
+ ++item;
+ }
+
+ // let the user choose which one
+ object_id = ChooseIDFromTable(tracks);
+
+ if (object_id.GetLength()) {
+ // issue a browse with metadata
+ DoBrowse(object_id, true);
+
+ // look back for the PLT_MediaItem in the results
+ PLT_MediaObject* track = NULL;
+ if (!m_MostRecentBrowseResults.IsNull() &&
+ NPT_SUCCEEDED(NPT_ContainerFind(*m_MostRecentBrowseResults, PLT_MediaItemIDFinder(object_id), track))) {
+
+ if (track->m_Resources.GetItemCount() > 0) {
+ printf("\tResource[0].uri: %s\n", track->m_Resources[0].m_Uri.GetChars());
+ printf("\n");
+ NPT_HttpUrl url(track->m_Resources[0].m_Uri.GetChars());
+ if (url.IsValid()) {
+ // Extract filename from URL
+ NPT_String filename = NPT_FilePath::BaseName(url.GetPath(true).GetChars(), false);
+ NPT_String extension = NPT_FilePath::FileExtension(url.GetPath(true).GetChars());
+ printf("Downloading %s%s\n", filename.GetChars(), extension.GetChars());
+
+ for (int i=0; i<3; i++) {
+ NPT_String filepath = NPT_String::Format("%s_%d%s", filename.GetChars(), i, extension.GetChars());
+
+ // Open file for writing
+ NPT_File file(filepath);
+ file.Open(NPT_FILE_OPEN_MODE_WRITE | NPT_FILE_OPEN_MODE_CREATE | NPT_FILE_OPEN_MODE_TRUNCATE);
+ NPT_OutputStreamReference output;
+ file.GetOutputStream(output);
+
+ // trigger 3 download
+ PLT_Downloader* downloader = new PLT_Downloader(url, output);
+ NPT_TimeInterval delay(5.);
+ m_DownloadTaskManager.StartTask(downloader, &delay);
+ }
+ }
+ } else {
+ printf("No resources found");
+ }
+ } else {
+ printf("Couldn't find the track\n");
+ }
+ }
+
+ m_MostRecentBrowseResults = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_cd
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_cd(const char* command)
+{
+ NPT_String newobject_id;
+ PLT_StringMap containers;
+
+ // if command has parameter, push it to stack and return
+ NPT_String id = command;
+ NPT_List<NPT_String> args = id.Split(" ");
+ if (args.GetItemCount() >= 2) {
+ args.Erase(args.GetFirstItem());
+ id = NPT_String::Join(args, " ");
+ m_CurBrowseDirectoryStack.Push(id);
+ return;
+ }
+
+ // list current directory to let user choose
+ DoBrowse();
+
+ if (!m_MostRecentBrowseResults.IsNull()) {
+ NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
+ while (item) {
+ if ((*item)->IsContainer()) {
+ containers.Put((*item)->m_ObjectID, (*item)->m_Title);
+ }
+ ++item;
+ }
+
+ newobject_id = ChooseIDFromTable(containers);
+ if (newobject_id.GetLength()) {
+ m_CurBrowseDirectoryStack.Push(newobject_id);
+ }
+
+ m_MostRecentBrowseResults = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_cdup
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_cdup()
+{
+ // we don't want to pop the root off now....
+ NPT_String val;
+ m_CurBrowseDirectoryStack.Peek(val);
+ if (val.Compare("0")) {
+ m_CurBrowseDirectoryStack.Pop(val);
+ } else {
+ printf("Already at root\n");
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_pwd
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_pwd()
+{
+ NPT_Stack<NPT_String> tempStack;
+ NPT_String val;
+
+ while (NPT_SUCCEEDED(m_CurBrowseDirectoryStack.Peek(val))) {
+ m_CurBrowseDirectoryStack.Pop(val);
+ tempStack.Push(val);
+ }
+
+ while (NPT_SUCCEEDED(tempStack.Peek(val))) {
+ tempStack.Pop(val);
+ printf("%s/", (const char*)val);
+ m_CurBrowseDirectoryStack.Push(val);
+ }
+ printf("\n");
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_open
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_open()
+{
+ NPT_String object_id;
+ PLT_StringMap tracks;
+ PLT_DeviceDataReference device;
+
+ GetCurMediaRenderer(device);
+ if (!device.IsNull()) {
+ // get the protocol info to try to see in advance if a track would play on the device
+
+ // issue a browse
+ DoBrowse();
+
+ if (!m_MostRecentBrowseResults.IsNull()) {
+ // create a map item id -> item title
+ NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
+ while (item) {
+ if (!(*item)->IsContainer()) {
+ tracks.Put((*item)->m_ObjectID, (*item)->m_Title);
+ }
+ ++item;
+ }
+
+ // let the user choose which one
+ object_id = ChooseIDFromTable(tracks);
+ if (object_id.GetLength()) {
+ // look back for the PLT_MediaItem in the results
+ PLT_MediaObject* track = NULL;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(*m_MostRecentBrowseResults, PLT_MediaItemIDFinder(object_id), track))) {
+ if (track->m_Resources.GetItemCount() > 0) {
+ // look for best resource to use by matching each resource to a sink advertised by renderer
+ NPT_Cardinal resource_index = 0;
+ if (NPT_FAILED(FindBestResource(device, *track, resource_index))) {
+ printf("No matching resource\n");
+ return;
+ }
+
+ // invoke the setUri
+ printf("Issuing SetAVTransportURI with url=%s & didl=%s",
+ (const char*)track->m_Resources[resource_index].m_Uri,
+ (const char*)track->m_Didl);
+ SetAVTransportURI(device, 0, track->m_Resources[resource_index].m_Uri, track->m_Didl, NULL);
+ } else {
+ printf("Couldn't find the proper resource\n");
+ }
+
+ } else {
+ printf("Couldn't find the track\n");
+ }
+ }
+
+ m_MostRecentBrowseResults = NULL;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_play
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_play()
+{
+ PLT_DeviceDataReference device;
+ GetCurMediaRenderer(device);
+ if (!device.IsNull()) {
+ Play(device, 0, "1", NULL);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_seek
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_seek(const char* command)
+{
+ PLT_DeviceDataReference device;
+ GetCurMediaRenderer(device);
+ if (!device.IsNull()) {
+ // remove first part of command ("seek")
+ NPT_String target = command;
+ NPT_List<NPT_String> args = target.Split(" ");
+ if (args.GetItemCount() < 2) return;
+
+ args.Erase(args.GetFirstItem());
+ target = NPT_String::Join(args, " ");
+
+ Seek(device, 0, (target.Find(":")!=-1)?"REL_TIME":"X_DLNA_REL_BYTE", target, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_stop
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_stop()
+{
+ PLT_DeviceDataReference device;
+ GetCurMediaRenderer(device);
+ if (!device.IsNull()) {
+ Stop(device, 0, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_mute
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_mute()
+{
+ PLT_DeviceDataReference device;
+ GetCurMediaRenderer(device);
+ if (!device.IsNull()) {
+ SetMute(device, 0, "Master", true, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_unmute
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_unmute()
+{
+ PLT_DeviceDataReference device;
+ GetCurMediaRenderer(device);
+ if (!device.IsNull()) {
+ SetMute(device, 0, "Master", false, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::HandleCmd_help
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::HandleCmd_help()
+{
+ printf("\n\nNone of the commands take arguments. The commands with a * \n");
+ printf("signify ones that will prompt the user for more information once\n");
+ printf("the command is called\n\n");
+ printf("The available commands are:\n\n");
+ printf(" quit - shutdown the Control Point\n");
+ printf(" exit - same as quit\n");
+
+ printf(" setms - * select a media server to become the active media server\n");
+ printf(" getms - print the friendly name of the active media server\n");
+ printf(" ls - list the contents of the current directory on the active \n");
+ printf(" media server\n");
+ printf(" info - display media info\n");
+ printf(" down - download media to current directory\n");
+ printf(" cd - * traverse down one level in the content tree on the active\n");
+ printf(" media server\n");
+ printf(" cd .. - traverse up one level in the content tree on the active\n");
+ printf(" media server\n");
+ printf(" pwd - print the path from the root to your current position in the \n");
+ printf(" content tree on the active media server\n");
+ printf(" setmr - * select a media renderer to become the active media renderer\n");
+ printf(" getmr - print the friendly name of the active media renderer\n");
+ printf(" open - set the uri on the active media renderer\n");
+ printf(" play - play the active uri on the active media renderer\n");
+ printf(" stop - stop the active uri on the active media renderer\n");
+ printf(" seek - issue a seek command\n");
+ printf(" mute - mute the active media renderer\n");
+ printf(" unmute - unmute the active media renderer\n");
+
+ printf(" help - print this help message\n\n");
+}
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController::ProcessCommandLoop
++---------------------------------------------------------------------*/
+void
+PLT_MicroMediaController::ProcessCommandLoop()
+{
+ char command[2048];
+ bool abort = false;
+
+ command[0] = '\0';
+ while (!abort) {
+ printf("command> ");
+ fflush(stdout);
+ fgets(command, 2048, stdin);
+ strchomp(command);
+
+ if (0 == strcmp(command, "quit") || 0 == strcmp(command, "exit")) {
+ abort = true;
+ } else if (0 == strcmp(command, "setms")) {
+ HandleCmd_setms();
+ } else if (0 == strcmp(command, "getms")) {
+ HandleCmd_getms();
+ } else if (0 == strncmp(command, "ls", 2)) {
+ HandleCmd_ls();
+ } else if (0 == strcmp(command, "info")) {
+ HandleCmd_info();
+ } else if (0 == strcmp(command, "down")) {
+ HandleCmd_download();
+ } else if (0 == strcmp(command, "cd")) {
+ HandleCmd_cd(command);
+ } else if (0 == strcmp(command, "cd ..")) {
+ HandleCmd_cdup();
+ } else if (0 == strcmp(command, "pwd")) {
+ HandleCmd_pwd();
+ } else if (0 == strcmp(command, "setmr")) {
+ HandleCmd_setmr();
+ } else if (0 == strcmp(command, "getmr")) {
+ HandleCmd_getmr();
+ } else if (0 == strcmp(command, "open")) {
+ HandleCmd_open();
+ } else if (0 == strcmp(command, "play")) {
+ HandleCmd_play();
+ } else if (0 == strcmp(command, "stop")) {
+ HandleCmd_stop();
+ } else if (0 == strncmp(command, "seek", 4)) {
+ HandleCmd_seek(command);
+ } else if (0 == strcmp(command, "mute")) {
+ HandleCmd_mute();
+ } else if (0 == strcmp(command, "unmute")) {
+ HandleCmd_mute();
+ } else if (0 == strcmp(command, "help")) {
+ HandleCmd_help();
+ } else if (0 == strcmp(command, "")) {
+ // just prompt again
+ } else {
+ printf("Unrecognized command: %s\n", command);
+ HandleCmd_help();
+ }
+ }
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.h b/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.h
new file mode 100644
index 0000000..c5b17bf
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/PltMicroMediaController.h
@@ -0,0 +1,176 @@
+/*****************************************************************
+|
+| Platinum - Micro Media Controller
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _MICRO_MEDIA_CONTROLLER_H_
+#define _MICRO_MEDIA_CONTROLLER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Platinum.h"
+#include "PltMediaServer.h"
+#include "PltSyncMediaBrowser.h"
+#include "PltMediaController.h"
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| definitions
++---------------------------------------------------------------------*/
+typedef NPT_Map<NPT_String, NPT_String> PLT_StringMap;
+typedef NPT_Lock<PLT_StringMap> PLT_LockStringMap;
+typedef NPT_Map<NPT_String, NPT_String>::Entry PLT_StringMapEntry;
+
+/*----------------------------------------------------------------------
+| PLT_MediaItemIDFinder
++---------------------------------------------------------------------*/
+class PLT_MediaItemIDFinder
+{
+public:
+ // methods
+ PLT_MediaItemIDFinder(const char* object_id) : m_ObjectID(object_id) {}
+
+ bool operator()(const PLT_MediaObject* const & item) const {
+ return item->m_ObjectID.Compare(m_ObjectID, true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_ObjectID;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MicroMediaController
++---------------------------------------------------------------------*/
+class PLT_MicroMediaController : public PLT_SyncMediaBrowser,
+ public PLT_MediaController,
+ public PLT_MediaControllerDelegate
+{
+public:
+ PLT_MicroMediaController(PLT_CtrlPointReference& ctrlPoint);
+ virtual ~PLT_MicroMediaController();
+
+ void ProcessCommandLoop();
+
+ // PLT_MediaBrowserDelegate methods
+ bool OnMSAdded(PLT_DeviceDataReference& device);
+
+ // PLT_MediaControllerDelegate methods
+ bool OnMRAdded(PLT_DeviceDataReference& device);
+ void OnMRRemoved(PLT_DeviceDataReference& device);
+ void OnMRStateVariablesChanged(PLT_Service* /* service */,
+ NPT_List<PLT_StateVariable*>* /* vars */);
+
+ // PLT_HttpClientTask method
+ NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response);
+
+private:
+ const char* ChooseIDFromTable(PLT_StringMap& table);
+ void PopDirectoryStackToRoot(void);
+ NPT_Result DoBrowse(const char* object_id = NULL, bool metdata = false);
+
+ void GetCurMediaServer(PLT_DeviceDataReference& server);
+ void GetCurMediaRenderer(PLT_DeviceDataReference& renderer);
+
+ PLT_DeviceDataReference ChooseDevice(const NPT_Lock<PLT_DeviceMap>& deviceList);
+
+ // Command Handlers
+ void HandleCmd_scan(const char* ip);
+ void HandleCmd_getms();
+ void HandleCmd_setms();
+ void HandleCmd_ls();
+ void HandleCmd_info();
+ void HandleCmd_cd(const char* command);
+ void HandleCmd_cdup();
+ void HandleCmd_pwd();
+ void HandleCmd_help();
+ void HandleCmd_getmr();
+ void HandleCmd_setmr();
+ void HandleCmd_download();
+ void HandleCmd_open();
+ void HandleCmd_play();
+ void HandleCmd_seek(const char* command);
+ void HandleCmd_stop();
+ void HandleCmd_mute();
+ void HandleCmd_unmute();
+
+private:
+ /* Tables of known devices on the network. These are updated via the
+ * OnMSAddedRemoved and OnMRAddedRemoved callbacks. Note that you should first lock
+ * before accessing them using the NPT_Map::Lock function.
+ */
+ NPT_Lock<PLT_DeviceMap> m_MediaServers;
+ NPT_Lock<PLT_DeviceMap> m_MediaRenderers;
+
+ /* Currently selected media server as well as
+ * a lock. If you ever want to hold both the m_CurMediaRendererLock lock and the
+ * m_CurMediaServerLock lock, make sure you grab the server lock first.
+ */
+ PLT_DeviceDataReference m_CurMediaServer;
+ NPT_Mutex m_CurMediaServerLock;
+
+ /* Currently selected media renderer as well as
+ * a lock. If you ever want to hold both the m_CurMediaRendererLock lock and the
+ * m_CurMediaServerLock lock, make sure you grab the server lock first.
+ */
+ PLT_DeviceDataReference m_CurMediaRenderer;
+ NPT_Mutex m_CurMediaRendererLock;
+
+ /* Most recent results from a browse request. The results come back in a
+ * callback instead of being returned to the calling function, so this
+ * variable is necessary in order to give the results back to the calling
+ * function.
+ */
+ PLT_MediaObjectListReference m_MostRecentBrowseResults;
+
+ /* When browsing through the tree on a media server, this is the stack
+ * symbolizing the current position in the tree. The contents of the
+ * stack are the object ID's of the nodes. Note that the object id: "0" should
+ * always be at the bottom of the stack.
+ */
+ NPT_Stack<NPT_String> m_CurBrowseDirectoryStack;
+
+ /* Semaphore on which to block when waiting for a response from over
+ * the network
+ */
+ NPT_SharedVariable m_CallbackResponseSemaphore;
+
+ /* Task Manager managing download tasks */
+ PLT_TaskManager m_DownloadTaskManager;
+};
+
+#endif /* _MICRO_MEDIA_CONTROLLER_H_ */
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/main.cpp b/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/main.cpp
new file mode 100644
index 0000000..4813db0
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MicroMediaController/main.cpp
@@ -0,0 +1,136 @@
+/*****************************************************************
+|
+| Platinum - main
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMicroMediaController.h"
+#include "PltFileMediaServer.h"
+#include "PltMediaRenderer.h"
+#include "PltXbox360.h"
+#include "PltVersion.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+//#define HAS_RENDERER 1
+//#define HAS_SERVER 1
+//#define SIMULATE_XBOX_360 1
+//#define SIMULATE_PS3 1
+//#define BROADCAST_EXTRA 1
+
+/*----------------------------------------------------------------------
+| 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;
+
+ // 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("/Users/sylvain/Documents/AudioFileTests",
+ "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
+ // override default headers
+ PLT_Constants::GetInstance().SetDefaultUserAgent("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";
+
+ // 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, NPT_TimeInterval(10.), NPT_TimeInterval(10.));
+ ctrlPoint->Search(
+ NPT_HttpUrl("239.255.255.250", 1900, "*"),
+ "urn:schemas-upnp-org:service:ContentDirectory:1", 2, NPT_TimeInterval(10.), NPT_TimeInterval(10.));
+
+#endif
+
+ // start to process commands
+ controller.ProcessCommandLoop();
+
+ // stop everything
+ upnp.Stop();
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.h b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.h
new file mode 100644
index 0000000..4c061b4
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.h
@@ -0,0 +1,17 @@
+//
+// AppDelegate.h
+// MobileMediaServer
+//
+// Created by Sylvain Rebaud on 3/10/15.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.m b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.m
new file mode 100644
index 0000000..49e7db5
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/AppDelegate.m
@@ -0,0 +1,45 @@
+//
+// AppDelegate.m
+// MobileMediaServer
+//
+// Created by Sylvain Rebaud on 3/10/15.
+//
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Override point for customization after application launch.
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/LaunchScreen.xib b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/LaunchScreen.xib
new file mode 100644
index 0000000..92aedf8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/LaunchScreen.xib
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14D127a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
+ <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
+ </dependencies>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB">
+ <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
+ <rect key="frame" x="20" y="439" width="441" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="MobileMediaServer" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
+ <rect key="frame" x="20" y="140" width="441" height="43"/>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+ <constraints>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
+ <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
+ <constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
+ <constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
+ <constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
+ </constraints>
+ <nil key="simulatedStatusBarMetrics"/>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <point key="canvasLocation" x="548" y="455"/>
+ </view>
+ </objects>
+</document>
diff --git a/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/Main.storyboard b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/Main.storyboard
new file mode 100644
index 0000000..f56d2f3
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/Main.storyboard
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="tne-QT-ifu">
+ <objects>
+ <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
+ <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+ <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+ </objects>
+ </scene>
+ </scenes>
+</document>
diff --git a/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.h b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.h
new file mode 100644
index 0000000..9f253ab
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.h
@@ -0,0 +1,14 @@
+//
+// ViewController.h
+// MobileMediaServer
+//
+// Created by Sylvain Rebaud on 3/10/15.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ViewController : UIViewController
+
+@end
+
diff --git a/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.mm b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.mm
new file mode 100644
index 0000000..33d715c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/ViewController.mm
@@ -0,0 +1,70 @@
+//
+// ViewController.m
+// MobileMediaServer
+//
+// Created by Sylvain Rebaud on 3/10/15.
+//
+//
+
+#import "ViewController.h"
+#import <Neptune/Neptune.h>
+#import <Platinum/PltUPnPObject.h>
+#import <Platinum/PltMediaServerObject.h>
+
+@interface ViewController () <PLT_MediaServerDelegateObject>
+
+@property (nonatomic) PLT_UPnPObject* upnp;
+
+@end
+
+@implementation ViewController
+
++ (void)initialize {
+ NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.outputs=1;.ConsoleHandler.filter=61");
+}
+
+- (void)awakeFromNib {
+ self.upnp = [[PLT_UPnPObject alloc] init];
+
+ // create server and add ourselves as the delegate
+ PLT_MediaServerObject* server = [[PLT_MediaServerObject alloc] init];
+ server.delegate = self;
+
+ [self.upnp addDevice:server];
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Do any additional setup after loading the view, typically from a nib.
+ [self.upnp start];
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+#pragma mark - PLT_MediaServerDelegateObject
+
+- (NPT_Result)onBrowseMetadata:(PLT_MediaServerBrowseCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+- (NPT_Result)onBrowseDirectChildren:(PLT_MediaServerBrowseCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+- (NPT_Result)onSearchContainer:(PLT_MediaServerSearchCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+- (NPT_Result)onFileRequest:(PLT_MediaServerFileRequestCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/main.m b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/main.m
new file mode 100644
index 0000000..31847c9
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Apps/MobileMediaServer/main.m
@@ -0,0 +1,16 @@
+//
+// main.m
+// MobileMediaServer
+//
+// Created by Sylvain Rebaud on 3/10/15.
+//
+//
+
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltAction.cpp b/lib/libUPnP/Platinum/Source/Core/PltAction.cpp
new file mode 100644
index 0000000..78ff4b2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltAction.cpp
@@ -0,0 +1,505 @@
+/*****************************************************************
+|
+| Platinum - Service Action
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltAction.h"
+#include "PltService.h"
+#include "PltUtilities.h"
+
+#define REMOVE_WMP_DATATYPE_EXTENSION
+
+NPT_SET_LOCAL_LOGGER("platinum.core.action")
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::PLT_ActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc::PLT_ActionDesc(const char* name, PLT_Service* service) :
+ m_Name(name),
+ m_Service(service)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::~PLT_ActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc::~PLT_ActionDesc()
+{
+ m_ArgumentDescs.Apply(NPT_ObjectDeleter<PLT_ArgumentDesc>());
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ActionDesc::GetSCPDXML(NPT_XmlElementNode* node)
+{
+ NPT_XmlElementNode* action = new NPT_XmlElementNode("action");
+ NPT_CHECK_SEVERE(node->AddChild(action));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(action, "name", m_Name));
+
+ NPT_XmlElementNode* argumentList = new NPT_XmlElementNode("argumentList");
+ NPT_CHECK_SEVERE(action->AddChild(argumentList));
+
+ // no arguments is ok
+ if (!m_ArgumentDescs.GetItemCount()) return NPT_SUCCESS;
+
+ return m_ArgumentDescs.ApplyUntil(
+ PLT_GetSCPDXMLIterator<PLT_ArgumentDesc>(argumentList),
+ NPT_UntilResultNotEquals(NPT_SUCCESS));
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::GetService
++---------------------------------------------------------------------*/
+PLT_Service*
+PLT_ActionDesc::GetService()
+{
+ return m_Service;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc::GetArgumentDesc
++---------------------------------------------------------------------*/
+PLT_ArgumentDesc*
+PLT_ActionDesc::GetArgumentDesc(const char* name)
+{
+ PLT_ArgumentDesc* arg_desc = NULL;
+ NPT_ContainerFind(m_ArgumentDescs, PLT_ArgumentDescNameFinder(name), arg_desc);
+ return arg_desc;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::PLT_Action(PLT_ActionDesc& action_desc) :
+ m_ActionDesc(action_desc),
+ m_ErrorCode(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::PLT_Action(PLT_ActionDesc& action_desc,
+ PLT_DeviceDataReference& root_device) :
+ m_ActionDesc(action_desc),
+ m_ErrorCode(0),
+ m_RootDevice(root_device)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::~PLT_Action
++---------------------------------------------------------------------*/
+PLT_Action::~PLT_Action()
+{
+ m_Arguments.Apply(NPT_ObjectDeleter<PLT_Argument>());
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, NPT_String& value)
+{
+ PLT_Argument* arg = GetArgument(name);
+ if (arg == NULL) {
+ return NPT_FAILURE;
+ }
+ value = arg->GetValue();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, NPT_UInt32& value)
+{
+ NPT_String tmp_value;
+ NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+ return tmp_value.ToInteger(value);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, NPT_Int32& value)
+{
+ NPT_String tmp_value;
+ NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+ return tmp_value.ToInteger(value);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::GetArgumentValue(const char* name, bool& value)
+{
+ NPT_String tmp_value;
+ NPT_CHECK_WARNING(GetArgumentValue(name, tmp_value));
+ if (tmp_value == "1" ||
+ !tmp_value.Compare("TRUE", true) ||
+ !tmp_value.Compare("YES", true)) {
+ value = true;
+ } else if (tmp_value == "0" ||
+ !tmp_value.Compare("FALSE", true) ||
+ !tmp_value.Compare("NO", true)) {
+ value = false;
+ } else {
+ return NPT_FAILURE;
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetArgument
++---------------------------------------------------------------------*/
+PLT_Argument*
+PLT_Action::GetArgument(const char* name)
+{
+ PLT_Argument* argument = NULL;
+ NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(name), argument);
+ return argument;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentValue(const char* name,
+ const char* value)
+{
+ // look for this argument in our argument list
+ // and replace the value if we found it
+ PLT_Arguments::Iterator iter = NULL;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(name), iter))) {
+ NPT_Result res = (*iter)->SetValue(value);
+
+ // remove argument from list if failed
+ // so that when we verify arguments later,
+ // we don't use a previously set value
+ if (NPT_FAILED(res)) m_Arguments.Erase(iter);
+ return res;
+ }
+
+ // since we didn't find it, create a clone
+ PLT_Argument* arg;
+ NPT_CHECK_SEVERE(PLT_Argument::CreateArgument(m_ActionDesc, name, value, arg));
+
+ // insert it at the right position
+ for (NPT_Cardinal i=0;
+ i<m_Arguments.GetItemCount();
+ i++) {
+ iter = m_Arguments.GetItem(i);
+ if ((*iter)->GetPosition() > arg->GetPosition()) {
+ return m_Arguments.Insert(iter, arg);
+ }
+ }
+
+ return m_Arguments.Add(arg);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::VerifyArgumentValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::VerifyArgumentValue(const char* name, const char* value)
+{
+ NPT_String str;
+ NPT_CHECK_SEVERE(GetArgumentValue(name, str));
+
+ return str.Compare(value, true)?NPT_FAILURE:NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::VerifyArguments
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::VerifyArguments(bool input)
+{
+ NPT_Cardinal count = 0;
+
+ // Check we have all the required parameters (in or out)
+ for(unsigned int i=0; i<m_ActionDesc.GetArgumentDescs().GetItemCount(); i++) {
+ PLT_ArgumentDesc* arg_desc = m_ActionDesc.GetArgumentDescs()[i];
+
+ // only input arguments are needed
+ if (arg_desc->GetDirection().Compare(input?"in":"out", true))
+ continue;
+
+ // look for this argument in the list we received
+ PLT_Argument* arg = NULL;
+ if (NPT_FAILED(NPT_ContainerFind(m_Arguments, PLT_ArgumentNameFinder(arg_desc->GetName()), arg))) {
+ NPT_LOG_WARNING_2("Argument %s for action %s not found",
+ (const char*) arg_desc->GetName(),
+ (const char*) m_ActionDesc.GetName());
+ return NPT_FAILURE;
+ }
+ ++count;
+ }
+
+ SetError(0, "");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentOutFromStateVariable(PLT_ArgumentDesc* arg_desc)
+{
+ // only output arguments can use a state variable
+ if (arg_desc->GetDirection().Compare("out", true)) {
+ return NPT_FAILURE;
+ }
+
+ PLT_StateVariable* variable = arg_desc->GetRelatedStateVariable();
+ if (!variable) return NPT_FAILURE;
+
+ // assign the value to an argument
+ NPT_CHECK_SEVERE(SetArgumentValue(arg_desc->GetName(), variable->GetValue()));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentOutFromStateVariable(const char* name)
+{
+ // look for this argument in the action list of arguments
+ PLT_ArgumentDesc* arg_desc = NULL;
+ NPT_CHECK_SEVERE(NPT_ContainerFind(m_ActionDesc.GetArgumentDescs(),
+ PLT_ArgumentDescNameFinder(name), arg_desc));
+
+ return SetArgumentOutFromStateVariable(arg_desc);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetArgumentsOutFromStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetArgumentsOutFromStateVariable()
+{
+ // go through the list of the action output arguments
+ for(unsigned int i=0; i<m_ActionDesc.GetArgumentDescs().GetItemCount(); i++) {
+ PLT_ArgumentDesc* arg_desc = m_ActionDesc.GetArgumentDescs()[i];
+
+ // only output arguments are needed
+ if (arg_desc->GetDirection().Compare("out", true))
+ continue;
+
+ NPT_CHECK_SEVERE(SetArgumentOutFromStateVariable(arg_desc));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::SetError
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::SetError(unsigned int code, const char* description)
+{
+ m_ErrorCode = code;
+ m_ErrorDescription = description;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetError
++---------------------------------------------------------------------*/
+const char*
+PLT_Action::GetError(unsigned int* code /* = NULL */)
+{
+ if (code) *code = m_ErrorCode;
+ return m_ErrorDescription;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::GetErrorCode
++---------------------------------------------------------------------*/
+unsigned int
+PLT_Action::GetErrorCode()
+{
+ return m_ErrorCode;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::FormatSoapRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapRequest(NPT_OutputStream& stream)
+{
+ NPT_String str;
+ NPT_Result res;
+ NPT_XmlElementNode* body = NULL;
+ NPT_XmlElementNode* request = NULL;
+ NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+ body = new NPT_XmlElementNode("s", "Body");
+ NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);
+
+ request = new NPT_XmlElementNode("u", m_ActionDesc.GetName());
+ NPT_CHECK_LABEL_SEVERE(res = request->SetNamespaceUri("u", m_ActionDesc.GetService()->GetServiceType()), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = body->AddChild(request), cleanup);
+
+ for(unsigned int i=0; i<m_Arguments.GetItemCount(); i++) {
+ PLT_Argument* argument = m_Arguments[i];
+ if (argument->GetDesc().GetDirection().Compare("in", true) == 0) {
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(
+ request,
+ argument->GetDesc().GetName(),
+ argument->GetValue()), cleanup);
+ }
+ }
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+ delete envelope;
+
+ return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+ delete envelope;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::FormatSoapResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapResponse(NPT_OutputStream& stream)
+{
+ if (m_ErrorCode) {
+ return FormatSoapError(m_ErrorCode, m_ErrorDescription, stream);
+ }
+
+ NPT_String str;
+ NPT_Result res;
+ NPT_XmlElementNode* body = NULL;
+ NPT_XmlElementNode* response = NULL;
+ NPT_XmlElementNode* node = NULL;
+ NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+ body = new NPT_XmlElementNode("s", "Body");
+ NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);
+
+ response = new NPT_XmlElementNode("u", m_ActionDesc.GetName() + "Response");
+ NPT_CHECK_LABEL_SEVERE(response->SetNamespaceUri("u", m_ActionDesc.GetService()->GetServiceType()), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = body->AddChild(response), cleanup);
+
+ for(unsigned int i=0; i<m_Arguments.GetItemCount(); i++) {
+ PLT_Argument* argument = m_Arguments[i];
+ if (argument->GetDesc().GetDirection().Compare("out", true) == 0) {
+ node = new NPT_XmlElementNode(argument->GetDesc().GetName());
+ NPT_CHECK_LABEL_SEVERE(res = node->AddText(argument->GetValue()), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = response->AddChild(node), cleanup);
+
+#ifndef REMOVE_WMP_DATATYPE_EXTENSION
+ PLT_StateVariable* var = argument->GetDesc().GetRelatedStateVariable();
+ if (var) {
+ node->SetNamespaceUri("dt", "urn:schemas-microsoft-com:datatypes");
+ node->SetAttribute("dt", "dt", var->GetDataType());
+ }
+#endif
+ }
+ }
+
+ // this will xmlescape any values that contain xml characters
+ NPT_CHECK_LABEL_SEVERE(PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+ delete envelope;
+
+ return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+ delete envelope;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Action::FormatSoapError
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Action::FormatSoapError(unsigned int code, NPT_String desc, NPT_OutputStream& stream)
+{
+ NPT_String str;
+ NPT_Result res;
+ NPT_XmlElementNode* body = NULL;
+ NPT_XmlElementNode* fault = NULL;
+ NPT_XmlElementNode* detail = NULL;
+ NPT_XmlElementNode* UPnPError = NULL;
+ NPT_XmlElementNode* envelope = new NPT_XmlElementNode("s", "Envelope");
+
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetNamespaceUri("s", "http://schemas.xmlsoap.org/soap/envelope/"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = envelope->SetAttribute("s", "encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"), cleanup);
+
+ body = new NPT_XmlElementNode("s", "Body");
+ NPT_CHECK_LABEL_SEVERE(res = envelope->AddChild(body), cleanup);
+
+ fault = new NPT_XmlElementNode("s", "Fault");
+ NPT_CHECK_LABEL_SEVERE(res = body->AddChild(fault), cleanup);
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(fault, "faultcode", "s:Client"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(fault, "faultstring", "UPnPError"), cleanup);
+
+ detail = new NPT_XmlElementNode("detail");
+ NPT_CHECK_LABEL_SEVERE(res = fault->AddChild(detail), cleanup);
+
+ UPnPError = new NPT_XmlElementNode("UPnPError");
+ NPT_CHECK_LABEL_SEVERE(res = UPnPError->SetNamespaceUri("", "urn:schemas-upnp-org:control-1-0"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = detail->AddChild(UPnPError), cleanup);
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(UPnPError, "errorCode", NPT_String::FromInteger(code)), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(UPnPError, "errorDescription", desc), cleanup);
+
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*envelope, str), cleanup);
+ delete envelope;
+
+ return stream.Write((const char*)str, str.GetLength());
+
+cleanup:
+ delete envelope;
+ return res;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltAction.h b/lib/libUPnP/Platinum/Source/Core/PltAction.h
new file mode 100644
index 0000000..f457f3d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltAction.h
@@ -0,0 +1,321 @@
+/*****************************************************************
+|
+| Platinum - Service Action
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Service Action
+ */
+
+#ifndef _PLT_ACTION_H_
+#define _PLT_ACTION_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltArgument.h"
+#include "PltDeviceData.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_Service;
+
+/*----------------------------------------------------------------------
+| PLT_ActionDesc
++---------------------------------------------------------------------*/
+/**
+ The PLT_ActionDesc class provides information about a UPnP Service given action.
+ This description has a name, a set of arguments and is associated to a service.
+ */
+class PLT_ActionDesc
+{
+public:
+ /**
+ Constructor
+ @param name the action name
+ @param service the UPnP service the action is associated with
+ */
+ PLT_ActionDesc(const char* name, PLT_Service* service);
+ ~PLT_ActionDesc();
+
+ /**
+ Return an array of arguments
+ @return array of arguments
+ */
+ NPT_Array<PLT_ArgumentDesc*>& GetArgumentDescs() {
+ return m_ArgumentDescs;
+ }
+
+ /**
+ Return the action name.
+ @return action name.
+ */
+ const NPT_String& GetName() const { return m_Name;}
+
+ /**
+ Look for an argument given a name.
+ @param name argument name
+ @return PLT_ArgumentDesc pointer
+ */
+ PLT_ArgumentDesc* GetArgumentDesc(const char* name);
+
+ /**
+ Serialize action information to xml into an existing xml tree
+ @param node the xml Element to serialize action information
+ */
+ NPT_Result GetSCPDXML(NPT_XmlElementNode* node);
+
+ /**
+ Return the service the action is associated with
+ */
+ PLT_Service* GetService();
+
+protected:
+ //members
+ NPT_String m_Name;
+ PLT_Service* m_Service;
+ NPT_Array<PLT_ArgumentDesc*> m_ArgumentDescs;
+};
+
+/*----------------------------------------------------------------------
+| PLT_Action
++---------------------------------------------------------------------*/
+/**
+ The PLT_Action class provides a mechanism to call or verify the validity of a
+ specific UPNP service action.
+ Given a service, a UPnP Control Point would use this class to serialize a soap
+ request. On the other side, a UPnP Device would use this class to verify
+ a soap request and the validity of the action arguments.
+ */
+class PLT_Action
+{
+public:
+ /**
+ Constructor
+ @param action_desc the action description
+ If you intend to send an action, you need to use the second constructor
+ and pass the root device of the device you wish to control.
+ */
+ PLT_Action(PLT_ActionDesc& action_desc);
+
+ /**
+ Constructor
+ @param action_desc the action description
+ @param root_device a reference to the root device of the service the action
+ is associated with. This insures that the device won't be deleted if it goes
+ away while we're waiting for a response for this action. This is important because
+ we only keep a reference to the PLT_ActionDesc which is own by the service operated
+ by the device (or embedded device).
+ */
+ PLT_Action(PLT_ActionDesc& action_desc, PLT_DeviceDataReference& root_device);
+ ~PLT_Action();
+
+ /**
+ Return the action description
+ @return the action description
+ */
+ PLT_ActionDesc& GetActionDesc() { return m_ActionDesc; }
+
+ /**
+ Retrieve the string value of an argument given an argument name.
+ @param name the argument name
+ @param value the string value to retrieve
+ @return error if the argument is not found or if the type does not correspond.
+ */
+ NPT_Result GetArgumentValue(const char* name, NPT_String& value);
+
+ /**
+ Retrieve the value of an argument given an argument name.
+ @param name the argument name
+ @param value the unsigned int value to retrieve
+ @return error if the argument is not found or if the type does not correspond.
+ */
+ NPT_Result GetArgumentValue(const char* name, NPT_UInt32& value);
+
+ /**
+ Retrieve the value of an argument given an argument name.
+ @param name the argument name
+ @param value the int value to retrieve
+ @return error if the argument is not found or if the type does not correspond.
+ */
+ NPT_Result GetArgumentValue(const char* name, NPT_Int32& value);
+
+ /**
+ Retrieve the value of an argument given an argument name.
+ @param name the argument name
+ @param value the bool value to retrieve
+ @return error if the argument is not found or if the type does not correspond.
+ */
+ NPT_Result GetArgumentValue(const char* name, bool& value);
+
+ /**
+ Verify a value is valid for a given argument.
+ @param name the argument name
+ @param value the value to verify
+ */
+ NPT_Result VerifyArgumentValue(const char* name, const char* value);
+
+ /**
+ Verify that all required arguments are set.
+ @param input boolean indicating whether input or output parameters
+ should be verified
+ */
+ NPT_Result VerifyArguments(bool input);
+
+ /**
+ Set the output argument value from the associated current state variable value.
+ @param name the state variable name
+ */
+ NPT_Result SetArgumentOutFromStateVariable(const char* name);
+
+ /**
+ Set all the output argument values associated with state variables.
+ */
+ NPT_Result SetArgumentsOutFromStateVariable();
+
+ /**
+ Set an argument value
+ @param name the argument name
+ @param value the argument value
+ */
+ NPT_Result SetArgumentValue(const char* name, const char* value);
+
+ /**
+ Set the error code and description in case of failure.
+ @param code the code for the error
+ @param description a short description
+ */
+ NPT_Result SetError(unsigned int code, const char* description);
+
+ /**
+ Return the error description and code for the failed action.
+ @param code optional pointer to receive the code
+ @return the error short description
+ */
+ const char* GetError(unsigned int* code = NULL);
+
+ /**
+ Return the error code for the failed action.
+ @return the error code.
+ */
+ unsigned int GetErrorCode();
+
+ /**
+ Called by a control point when serializing an action.
+ @param stream the stream to serialize the action to
+ */
+ NPT_Result FormatSoapRequest(NPT_OutputStream& stream);
+
+ /**
+ Called by a device when serializing a response to an action.
+ @param stream the stream to serialize the action to
+ */
+ NPT_Result FormatSoapResponse(NPT_OutputStream& stream);
+
+ /**
+ Helper method for a device to serialize an action invocation error.
+ @param code optional pointer to receive the code
+ @param desc the error short description
+ @param stream the stream to serialize to
+ */
+ static NPT_Result FormatSoapError(unsigned int code,
+ NPT_String desc,
+ NPT_OutputStream& stream);
+
+private:
+ // methods
+ NPT_Result SetArgumentOutFromStateVariable(PLT_ArgumentDesc* arg_desc);
+ PLT_Argument* GetArgument(const char* name);
+
+protected:
+ // members
+ PLT_ActionDesc& m_ActionDesc;
+ PLT_Arguments m_Arguments;
+ unsigned int m_ErrorCode;
+ NPT_String m_ErrorDescription;
+
+ // keep reference of service root device to prevent it
+ // from being released during action lifetime
+ PLT_DeviceDataReference m_RootDevice;
+};
+
+typedef NPT_Reference<PLT_Action> PLT_ActionReference;
+
+/*----------------------------------------------------------------------
+| PLT_GetSCPDXMLIterator
++---------------------------------------------------------------------*/
+/**
+ The PLT_GetSCPDXMLIterator class provides a recursive way to serialize
+ an SCPD into an xml tree.
+ */
+template <class T>
+class PLT_GetSCPDXMLIterator
+{
+public:
+ PLT_GetSCPDXMLIterator<T>(NPT_XmlElementNode* node) :
+ m_Node(node) {}
+
+ NPT_Result operator()(T* const & data) const {
+ return data->GetSCPDXML(m_Node);
+ }
+
+private:
+ NPT_XmlElementNode* m_Node;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ActionDescNameFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ActionDescNameFinder class provides a mechanism to find a PLT_ActionDesc
+ given an action name.
+ */
+class PLT_ActionDescNameFinder
+{
+public:
+ // methods
+ PLT_ActionDescNameFinder(const char* name) :
+ m_Name(name) {}
+ virtual ~PLT_ActionDescNameFinder() {}
+
+ bool operator()(const PLT_ActionDesc* const & action_desc) const {
+ return action_desc->GetName().Compare(m_Name, true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_Name;
+};
+
+#endif /* _PLT_ACTION_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltArgument.cpp b/lib/libUPnP/Platinum/Source/Core/PltArgument.cpp
new file mode 100644
index 0000000..be35821
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltArgument.cpp
@@ -0,0 +1,156 @@
+/*****************************************************************
+|
+| Platinum - Action Argument
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltArgument.h"
+#include "PltStateVariable.h"
+#include "PltUtilities.h"
+#include "PltAction.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.argument")
+
+/*----------------------------------------------------------------------
+| PLT_ArgumentDesc::PLT_ArgumentDesc
++---------------------------------------------------------------------*/
+PLT_ArgumentDesc::PLT_ArgumentDesc(const char* name,
+ NPT_Ordinal position,
+ const char* direction,
+ PLT_StateVariable* variable,
+ bool has_ret) :
+ m_Name(name),
+ m_Position(position),
+ m_Direction(direction),
+ m_RelatedStateVariable(variable),
+ m_HasReturnValue(has_ret)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_ArgumentDesc::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ArgumentDesc::GetSCPDXML(NPT_XmlElementNode* node)
+{
+ NPT_XmlElementNode* argument = new NPT_XmlElementNode("argument");
+ NPT_CHECK_SEVERE(node->AddChild(argument));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "name", m_Name));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "direction", m_Direction));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(argument, "relatedStateVariable", m_RelatedStateVariable->GetName()));
+
+ if (m_HasReturnValue) {
+ NPT_CHECK_SEVERE(argument->AddChild(new NPT_XmlElementNode("retval")));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Argument::CreateArgument
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Argument::CreateArgument(PLT_ActionDesc& action_desc,
+ const char* name,
+ const char* value,
+ PLT_Argument*& arg)
+{
+ // reset output params first
+ arg = NULL;
+
+ PLT_ArgumentDesc* arg_desc = action_desc.GetArgumentDesc(name);
+ if (!arg_desc) {
+ NPT_LOG_WARNING_2("Invalid argument %s for action %s",
+ name,
+ (const char*)action_desc.GetName());
+ return NPT_ERROR_NO_SUCH_NAME;
+ }
+
+ NPT_Result res;
+ PLT_Argument* new_arg = new PLT_Argument(*arg_desc);
+ if (NPT_FAILED(res = new_arg->SetValue(value))) {
+ delete new_arg;
+
+ NPT_LOG_WARNING_3("Invalid value of %s for argument %s of action %s",
+ value,
+ name,
+ (const char*)action_desc.GetName());
+ return res;
+ }
+
+ arg = new_arg;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Argument::PLT_Argument
++---------------------------------------------------------------------*/
+PLT_Argument::PLT_Argument(PLT_ArgumentDesc& arg_desc) :
+ m_ArgDesc(arg_desc)
+{
+
+}
+
+/*----------------------------------------------------------------------
+| PLT_Argument::SetValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Argument::SetValue(const char* value)
+{
+ NPT_CHECK_SEVERE(ValidateValue(value));
+
+ m_Value = value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Argument::GetValue
++---------------------------------------------------------------------*/
+const NPT_String&
+PLT_Argument::GetValue()
+{
+ return m_Value;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Argument::ValidateValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Argument::ValidateValue(const char* value)
+{
+ if (m_ArgDesc.GetRelatedStateVariable()) {
+ return m_ArgDesc.GetRelatedStateVariable()->ValidateValue(value);
+ }
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltArgument.h b/lib/libUPnP/Platinum/Source/Core/PltArgument.h
new file mode 100644
index 0000000..4730e28
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltArgument.h
@@ -0,0 +1,168 @@
+/*****************************************************************
+|
+| Platinum - Action Argument
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Service Action Argument
+ */
+
+#ifndef _PLT_ARGUMENT_H_
+#define _PLT_ARGUMENT_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_StateVariable;
+class PLT_Argument;
+class PLT_ActionDesc;
+typedef NPT_Array<PLT_Argument*> PLT_Arguments;
+
+/*----------------------------------------------------------------------
+| PLT_ArgumentDesc
++---------------------------------------------------------------------*/
+/**
+ The PLT_ArgumentDesc class provides information about a given argument of a
+ UPnP Service given action.
+ It has a name, a position, a direction (in/out), a PLT_StateVariable state
+ variable association and whether it is the return value of the action or not.
+ */
+class PLT_ArgumentDesc
+{
+public:
+ PLT_ArgumentDesc(const char* name,
+ NPT_Ordinal position,
+ const char* direction = "in",
+ PLT_StateVariable* variable = NULL,
+ bool has_ret = false);
+
+ // accessor methods
+ NPT_Result GetSCPDXML(NPT_XmlElementNode* node);
+ const NPT_String& GetName() const { return m_Name; }
+ const NPT_String& GetDirection() const { return m_Direction; }
+ NPT_Ordinal GetPosition() { return m_Position; }
+ PLT_StateVariable* GetRelatedStateVariable() { return m_RelatedStateVariable; }
+ bool HasReturnValue() { return m_HasReturnValue; }
+
+protected:
+ NPT_String m_Name;
+ NPT_Ordinal m_Position;
+ NPT_String m_Direction;
+ PLT_StateVariable* m_RelatedStateVariable;
+ bool m_HasReturnValue;
+};
+
+/*----------------------------------------------------------------------
+| PLT_Argument
++---------------------------------------------------------------------*/
+/**
+ The PLT_Argument class provides a mechanism to set or verify the validity of a
+ specific UPNP service action argument.
+ Typically, only a PLT_Action uses this class. Since an argument can be
+ associated to a state variable, the argument is automatically updated when
+ the associated state variable is changed
+ */
+class PLT_Argument
+{
+public:
+ PLT_Argument(PLT_ArgumentDesc& arg_desc);
+
+ // class methods
+ static NPT_Result CreateArgument(PLT_ActionDesc& action_desc,
+ const char* arg_name,
+ const char* arg_value,
+ PLT_Argument*& arg);
+
+ // accessor methods
+ PLT_ArgumentDesc& GetDesc() { return m_ArgDesc; }
+ NPT_Ordinal GetPosition() { return m_ArgDesc.GetPosition(); }
+ NPT_Result SetValue(const char* value);
+ const NPT_String& GetValue();
+
+private:
+ NPT_Result ValidateValue(const char* value);
+
+protected:
+ PLT_ArgumentDesc& m_ArgDesc;
+ NPT_String m_Value;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ArgumentNameFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ArgumentNameFinder class provides a mechanism to find a PLT_Argument given
+ an argument name.
+ */
+class PLT_ArgumentNameFinder
+{
+public:
+ // methods
+ PLT_ArgumentNameFinder(const char* name) : m_Name(name) {}
+
+ bool operator()(PLT_Argument* const & argument) const {
+ return argument->GetDesc().GetName().Compare(m_Name, true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_Name;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ArgumentDescNameFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ArgumentDescNameFinder class provides a mechanism to find a PLT_ArgumentDesc given
+ an argument name.
+ */
+class PLT_ArgumentDescNameFinder
+{
+public:
+ // methods
+ PLT_ArgumentDescNameFinder(const char* name) : m_Name(name) {}
+
+ bool operator()(PLT_ArgumentDesc* const & arg_desc) const {
+ return arg_desc->GetName().Compare(m_Name, true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_Name;
+};
+
+#endif /* _PLT_ARGUMENT_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltConstants.cpp b/lib/libUPnP/Platinum/Source/Core/PltConstants.cpp
new file mode 100755
index 0000000..8da87d0
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltConstants.cpp
@@ -0,0 +1,62 @@
+/*****************************************************************
+|
+| Platinum - UPnP Constants
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltConstants.h"
+#include "PltHttp.h"
+
+static PLT_Constants Constants;
+
+/*----------------------------------------------------------------------
+| PLT_Constants::PLT_Constant
++---------------------------------------------------------------------*/
+PLT_Constants::PLT_Constants()
+{
+ SetDefaultUserAgent(PLT_HTTP_DEFAULT_USER_AGENT);
+ SetDefaultDeviceLease(NPT_TimeInterval(1800.));
+ SetDefaultSubscribeLease(NPT_TimeInterval(1800.));
+ SetAnnounceMulticastTimeToLive(2);
+ SetSearchMulticastTimeToLive(2);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Constants::GetInstance
++---------------------------------------------------------------------*/
+PLT_Constants&
+PLT_Constants::GetInstance()
+{
+ return Constants;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltConstants.h b/lib/libUPnP/Platinum/Source/Core/PltConstants.h
new file mode 100755
index 0000000..d674ea8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltConstants.h
@@ -0,0 +1,87 @@
+/*****************************************************************
+|
+| Platinum - UPnP Constants
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Constants
+ */
+
+#ifndef _PLT_UPNP_CONSTANTS_H_
+#define _PLT_UPNP_CONSTANTS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_Constants
++---------------------------------------------------------------------*/
+/**
+ The PLT_Constants class provides a way to globally set or get certain
+ UPnP constants.
+ */
+class PLT_Constants
+{
+public:
+ // class methods
+ static PLT_Constants& GetInstance();
+
+ PLT_Constants();
+ ~PLT_Constants() {};
+
+ void SetDefaultDeviceLease(NPT_TimeInterval lease) { m_DefaultDeviceLease = new NPT_TimeInterval(lease); }
+ NPT_Reference<NPT_TimeInterval> GetDefaultDeviceLease() { return m_DefaultDeviceLease; }
+
+ void SetDefaultSubscribeLease(NPT_TimeInterval lease) { m_DefaultSubscribeLease = new NPT_TimeInterval(lease); }
+ NPT_Reference<NPT_TimeInterval> GetDefaultSubscribeLease() { return m_DefaultSubscribeLease; }
+
+ void SetDefaultUserAgent(const char* agent) { m_DefaultUserAgent = new NPT_String(agent); }
+ NPT_Reference<NPT_String> GetDefaultUserAgent() { return m_DefaultUserAgent; }
+
+ void SetSearchMulticastTimeToLive(NPT_UInt32 ttl) { m_SearchMulticastTimeToLive = ttl; }
+ NPT_UInt32 GetSearchMulticastTimeToLive() { return m_SearchMulticastTimeToLive; }
+
+ void SetAnnounceMulticastTimeToLive(NPT_UInt32 ttl) { m_AnnounceMulticastTimeToLive = ttl; }
+ NPT_UInt32 GetAnnounceMulticastTimeToLive() { return m_AnnounceMulticastTimeToLive; }
+
+private:
+ // members
+ NPT_Reference<NPT_TimeInterval> m_DefaultDeviceLease;
+ NPT_Reference<NPT_TimeInterval> m_DefaultSubscribeLease;
+ NPT_Reference<NPT_String> m_DefaultUserAgent;
+ NPT_UInt32 m_SearchMulticastTimeToLive;
+ NPT_UInt32 m_AnnounceMulticastTimeToLive;
+};
+
+#endif /* _PLT_UPNP_CONSTANTS_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
new file mode 100644
index 0000000..7d476d1
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.cpp
@@ -0,0 +1,1875 @@
+/*****************************************************************
+|
+| Platinum - Control Point
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltCtrlPoint.h"
+#include "PltUPnP.h"
+#include "PltDeviceData.h"
+#include "PltUtilities.h"
+#include "PltCtrlPointTask.h"
+#include "PltSsdp.h"
+#include "PltHttpServer.h"
+#include "PltConstants.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.ctrlpoint")
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointListenerOnDeviceAddedIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnDeviceAddedIterator
+{
+public:
+ PLT_CtrlPointListenerOnDeviceAddedIterator(PLT_DeviceDataReference& device) :
+ m_Device(device) {}
+
+ NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+ return listener->OnDeviceAdded(m_Device);
+ }
+
+private:
+ PLT_DeviceDataReference& m_Device;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointListenerOnDeviceRemovedIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnDeviceRemovedIterator
+{
+public:
+ PLT_CtrlPointListenerOnDeviceRemovedIterator(PLT_DeviceDataReference& device) :
+ m_Device(device) {}
+
+ NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+ return listener->OnDeviceRemoved(m_Device);
+ }
+
+private:
+ PLT_DeviceDataReference& m_Device;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointListenerOnActionResponseIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnActionResponseIterator
+{
+public:
+ PLT_CtrlPointListenerOnActionResponseIterator(NPT_Result res,
+ PLT_ActionReference& action,
+ void* userdata) :
+ m_Res(res), m_Action(action), m_Userdata(userdata) {}
+
+ NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+ return listener->OnActionResponse(m_Res, m_Action, m_Userdata);
+ }
+
+private:
+ NPT_Result m_Res;
+ PLT_ActionReference& m_Action;
+ void* m_Userdata;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointListenerOnEventNotifyIterator class
++---------------------------------------------------------------------*/
+class PLT_CtrlPointListenerOnEventNotifyIterator
+{
+public:
+ PLT_CtrlPointListenerOnEventNotifyIterator(PLT_Service* service,
+ NPT_List<PLT_StateVariable*>* vars) :
+ m_Service(service), m_Vars(vars) {}
+
+ NPT_Result operator()(PLT_CtrlPointListener*& listener) const {
+ return listener->OnEventNotify(m_Service, m_Vars);
+ }
+
+private:
+ PLT_Service* m_Service;
+ NPT_List<PLT_StateVariable*>* m_Vars;
+};
+
+/*----------------------------------------------------------------------
+| PLT_AddGetSCPDRequestIterator class
++---------------------------------------------------------------------*/
+class PLT_AddGetSCPDRequestIterator
+{
+public:
+ PLT_AddGetSCPDRequestIterator(PLT_CtrlPointGetSCPDsTask& task,
+ PLT_DeviceDataReference& device) :
+ m_Task(task), m_Device(device) {}
+
+ NPT_Result operator()(PLT_Service*& service) const {
+ // look for the host and port of the device
+ NPT_String scpd_url = service->GetSCPDURL(true);
+
+ NPT_LOG_FINER_3("Queueing SCPD request for service \"%s\" of device \"%s\" @ %s",
+ (const char*)service->GetServiceID(),
+ (const char*)service->GetDevice()->GetFriendlyName(),
+ (const char*)scpd_url);
+
+ // verify url before queuing just in case
+ NPT_HttpUrl url(scpd_url);
+ if (!url.IsValid()) {
+ NPT_LOG_SEVERE_3("Invalid SCPD url \"%s\" for service \"%s\" of device \"%s\"!",
+ (const char*)scpd_url,
+ (const char*)service->GetServiceID(),
+ (const char*)service->GetDevice()->GetFriendlyName());
+ return NPT_ERROR_INVALID_SYNTAX;
+ }
+
+ // Create request and attach service to it
+ PLT_CtrlPointGetSCPDRequest* request =
+ new PLT_CtrlPointGetSCPDRequest((PLT_DeviceDataReference&)m_Device, scpd_url, "GET", NPT_HTTP_PROTOCOL_1_1);
+ return m_Task.AddSCPDRequest(request);
+ }
+
+private:
+ PLT_CtrlPointGetSCPDsTask& m_Task;
+ PLT_DeviceDataReference m_Device;
+};
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriberRemoverIterator class
++---------------------------------------------------------------------*/
+// Note: The PLT_CtrlPoint::m_Lock must be acquired prior to using any
+// function such as Apply on this iterator
+class PLT_EventSubscriberRemoverIterator
+{
+public:
+ PLT_EventSubscriberRemoverIterator(PLT_CtrlPoint* ctrl_point) :
+ m_CtrlPoint(ctrl_point) {}
+ ~PLT_EventSubscriberRemoverIterator() {}
+
+ NPT_Result operator()(PLT_Service*& service) const {
+ PLT_EventSubscriberReference sub;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(m_CtrlPoint->m_Subscribers,
+ PLT_EventSubscriberFinderByService(service), sub))) {
+ NPT_LOG_INFO_1("Removed subscriber \"%s\"", (const char*)sub->GetSID());
+ m_CtrlPoint->m_Subscribers.Remove(sub);
+ }
+
+ return NPT_SUCCESS;
+ }
+
+private:
+ PLT_CtrlPoint* m_CtrlPoint;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ServiceReadyIterator class
++---------------------------------------------------------------------*/
+class PLT_ServiceReadyIterator
+{
+public:
+ PLT_ServiceReadyIterator() {}
+
+ NPT_Result operator()(PLT_Service*& service) const {
+ return service->IsValid()?NPT_SUCCESS:NPT_FAILURE;
+ }
+};
+
+/*----------------------------------------------------------------------
+| PLT_DeviceReadyIterator class
++---------------------------------------------------------------------*/
+class PLT_DeviceReadyIterator
+{
+public:
+ PLT_DeviceReadyIterator() {}
+ NPT_Result operator()(PLT_DeviceDataReference& device) const {
+ NPT_Result res = device->m_Services.ApplyUntil(
+ PLT_ServiceReadyIterator(),
+ NPT_UntilResultNotEquals(NPT_SUCCESS));
+ if (NPT_FAILED(res)) return res;
+
+ res = device->m_EmbeddedDevices.ApplyUntil(
+ PLT_DeviceReadyIterator(),
+ NPT_UntilResultNotEquals(NPT_SUCCESS));
+ if (NPT_FAILED(res)) return res;
+
+ // a device must have at least one service or embedded device
+ // otherwise it's not ready
+ if (device->m_Services.GetItemCount() == 0 &&
+ device->m_EmbeddedDevices.GetItemCount() == 0) {
+ return NPT_FAILURE;
+ }
+
+ return NPT_SUCCESS;
+ }
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::PLT_CtrlPoint
++---------------------------------------------------------------------*/
+PLT_CtrlPoint::PLT_CtrlPoint(const char* search_criteria /* = "upnp:rootdevice" */) :
+ m_EventHttpServer(NULL),
+ m_TaskManager(NULL),
+ m_Lock(true),
+ m_SearchCriteria(search_criteria),
+ m_Started(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::~PLT_CtrlPoint
++---------------------------------------------------------------------*/
+PLT_CtrlPoint::~PLT_CtrlPoint()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::IgnoreUUID
++---------------------------------------------------------------------*/
+void
+PLT_CtrlPoint::IgnoreUUID(const char* uuid)
+{
+ if (!m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) {
+ m_UUIDsToIgnore.Add(uuid);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Start(PLT_SsdpListenTask* task)
+{
+ if (m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ m_TaskManager = new PLT_TaskManager();
+
+ m_EventHttpServer = new PLT_HttpServer();
+ m_EventHttpServer->AddRequestHandler(new PLT_HttpRequestHandler(this), "/", true, true);
+ m_EventHttpServer->Start();
+
+ // house keeping task
+ m_TaskManager->StartTask(new PLT_CtrlPointHouseKeepingTask(this));
+
+ // add ourselves as an listener to SSDP multicast advertisements
+ task->AddListener(this);
+
+ //
+ // use next line instead for DLNA testing, faster frequency for M-SEARCH
+ //return m_SearchCriteria.GetLength()?Search(NPT_HttpUrl("239.255.255.250", 1900, "*"), m_SearchCriteria, 1, 5000):NPT_SUCCESS;
+ //
+
+ m_Started = true;
+
+ return m_SearchCriteria.GetLength()?Search(NPT_HttpUrl("239.255.255.250", 1900, "*"), m_SearchCriteria):NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::GetPort
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::GetPort(NPT_UInt16& port)
+{
+ if (!m_Started) return NPT_ERROR_INVALID_STATE;
+
+ port = m_EventHttpServer->GetPort();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Stop(PLT_SsdpListenTask* task)
+{
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ m_Started = false;
+
+ task->RemoveListener(this);
+
+ m_EventHttpServer->Stop();
+ m_TaskManager->Abort();
+
+ // force remove all devices
+ NPT_List<PLT_DeviceDataReference>::Iterator iter = m_RootDevices.GetFirstItem();
+ while (iter) {
+ NotifyDeviceRemoved(*iter);
+ ++iter;
+ }
+
+ // we can safely clear everything without a lock
+ // as there are no more tasks pending
+ m_RootDevices.Clear();
+ m_Subscribers.Clear();
+
+ m_EventHttpServer = NULL;
+ m_TaskManager = NULL;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::AddListener
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::AddListener(PLT_CtrlPointListener* listener)
+{
+ NPT_AutoLock lock(m_Lock);
+ if (!m_ListenerList.Contains(listener)) {
+ m_ListenerList.Add(listener);
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::RemoveListener
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::RemoveListener(PLT_CtrlPointListener* listener)
+{
+ NPT_AutoLock lock(m_Lock);
+ m_ListenerList.Remove(listener);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::CreateSearchTask
++---------------------------------------------------------------------*/
+PLT_SsdpSearchTask*
+PLT_CtrlPoint::CreateSearchTask(const NPT_HttpUrl& url,
+ const char* target,
+ NPT_Cardinal mx,
+ NPT_TimeInterval frequency,
+ const NPT_IpAddress& address)
+{
+ // make sure mx is at least 1
+ if (mx<1) mx=1;
+
+ // create socket
+ NPT_Reference<NPT_UdpMulticastSocket> socket(new NPT_UdpMulticastSocket(NPT_SOCKET_FLAG_CANCELLABLE));
+ socket->SetInterface(address);
+ socket->SetTimeToLive(PLT_Constants::GetInstance().GetSearchMulticastTimeToLive());
+
+ // bind to something > 1024 and different than 1900
+ int retries = 20;
+ do {
+ int random = NPT_System::GetRandomInteger();
+ int port = (unsigned short)(1024 + (random % 15000));
+ if (port == 1900) continue;
+
+ if (NPT_SUCCEEDED(socket->Bind(
+ NPT_SocketAddress(NPT_IpAddress::Any, port),
+ false)))
+ break;
+
+ } while (--retries);
+
+ if (retries == 0) {
+ NPT_LOG_SEVERE("Couldn't bind socket for Search Task");
+ return NULL;
+ }
+
+ // create request
+ NPT_HttpRequest* request = new NPT_HttpRequest(url, "M-SEARCH", NPT_HTTP_PROTOCOL_1_1);
+ PLT_UPnPMessageHelper::SetMX(*request, mx);
+ PLT_UPnPMessageHelper::SetST(*request, target);
+ PLT_UPnPMessageHelper::SetMAN(*request, "\"ssdp:discover\"");
+ request->GetHeaders().SetHeader(NPT_HTTP_HEADER_USER_AGENT, *PLT_Constants::GetInstance().GetDefaultUserAgent());
+
+ // create task
+ PLT_SsdpSearchTask* task = new PLT_SsdpSearchTask(
+ socket.AsPointer(),
+ this,
+ request,
+ (frequency.ToMillis()>0 && frequency.ToMillis()<5000)?NPT_TimeInterval(5.):frequency); /* repeat no less than every 5 secs */
+ socket.Detach();
+
+ return task;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::Search
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Search(const NPT_HttpUrl& url,
+ const char* target,
+ NPT_Cardinal mx /* = 5 */,
+ NPT_TimeInterval frequency /* = NPT_TimeInterval(50.) */,
+ NPT_TimeInterval initial_delay /* = NPT_TimeInterval(0.) */)
+{
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ NPT_List<NPT_NetworkInterface*> if_list;
+ NPT_List<NPT_NetworkInterface*>::Iterator net_if;
+ NPT_List<NPT_NetworkInterfaceAddress>::Iterator net_if_addr;
+
+ NPT_CHECK_SEVERE(PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list, true));
+
+ for (net_if = if_list.GetFirstItem();
+ net_if;
+ net_if++) {
+ // make sure the interface is at least broadcast or multicast
+ if (!((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) &&
+ !((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_BROADCAST)) {
+ continue;
+ }
+
+ for (net_if_addr = (*net_if)->GetAddresses().GetFirstItem();
+ net_if_addr;
+ net_if_addr++) {
+ // create task
+ PLT_SsdpSearchTask* task = CreateSearchTask(url,
+ target,
+ mx,
+ frequency,
+ (*net_if_addr).GetPrimaryAddress());
+ m_TaskManager->StartTask(task, &initial_delay);
+ }
+ }
+
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::Discover
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Discover(const NPT_HttpUrl& url,
+ const char* target,
+ NPT_Cardinal mx, /* = 5 */
+ NPT_TimeInterval frequency /* = NPT_TimeInterval(50.) */,
+ NPT_TimeInterval initial_delay /* = NPT_TimeInterval(0.) */)
+{
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ // make sure mx is at least 1
+ if (mx<1) mx = 1;
+
+ // create socket
+ NPT_UdpSocket* socket = new NPT_UdpSocket(NPT_SOCKET_FLAG_CANCELLABLE);
+
+ // create request
+ NPT_HttpRequest* request = new NPT_HttpRequest(url, "M-SEARCH", NPT_HTTP_PROTOCOL_1_1);
+ PLT_UPnPMessageHelper::SetMX(*request, mx);
+ PLT_UPnPMessageHelper::SetST(*request, target);
+ PLT_UPnPMessageHelper::SetMAN(*request, "\"ssdp:discover\"");
+ request->GetHeaders().SetHeader(NPT_HTTP_HEADER_USER_AGENT, *PLT_Constants::GetInstance().GetDefaultUserAgent());
+
+ // force HOST to be the regular multicast address:port
+ // Some servers do care (like WMC) otherwise they won't respond to us
+ request->GetHeaders().SetHeader(NPT_HTTP_HEADER_HOST, "239.255.255.250:1900");
+
+ // create task
+ PLT_ThreadTask* task = new PLT_SsdpSearchTask(
+ socket,
+ this,
+ request,
+ (frequency.ToMillis()>0 && frequency.ToMillis()<5000)?NPT_TimeInterval(5.):frequency); /* repeat no less than every 5 secs */
+ return m_TaskManager->StartTask(task, &initial_delay);
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::DoHouseKeeping
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::DoHouseKeeping()
+{
+ NPT_List<PLT_DeviceDataReference> devices_to_remove;
+
+ // remove expired devices
+ {
+ NPT_AutoLock lock(m_Lock);
+
+ PLT_DeviceDataReference head, device;
+ while (NPT_SUCCEEDED(m_RootDevices.PopHead(device))) {
+ NPT_TimeStamp last_update = device->GetLeaseTimeLastUpdate();
+ NPT_TimeInterval lease_time = device->GetLeaseTime();
+
+ // check if device lease time has expired or if failed to renew subscribers
+ // TODO: UDA 1.1 says that root device and all embedded devices must have expired
+ // before we can assume they're all no longer unavailable (we may have missed the root device renew)
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ if (now > last_update + NPT_TimeInterval((double)lease_time*2)) {
+ devices_to_remove.Add(device);
+ } else {
+ // add the device back to our list since it is still alive
+ m_RootDevices.Add(device);
+
+ // keep track of first device added back to list
+ // to know we checked all devices in initial list
+ if (head.IsNull()) head = device;
+ }
+
+ // have we exhausted initial list?
+ if (!head.IsNull() && head == *m_RootDevices.GetFirstItem())
+ break;
+ };
+ }
+
+ // remove old devices
+ {
+ NPT_AutoLock lock(m_Lock);
+
+ for (NPT_List<PLT_DeviceDataReference>::Iterator device =
+ devices_to_remove.GetFirstItem();
+ device;
+ device++) {
+ RemoveDevice(*device);
+ }
+ }
+
+ // renew subscribers of subscribed device services
+ NPT_List<PLT_ThreadTask*> tasks;
+ {
+ NPT_AutoLock lock(m_Lock);
+
+ NPT_List<PLT_EventSubscriberReference>::Iterator sub = m_Subscribers.GetFirstItem();
+ while (sub) {
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+
+ // time to renew if within 90 secs of expiration
+ if (now > (*sub)->GetExpirationTime() - NPT_TimeStamp(90.)) {
+ PLT_ThreadTask* task = RenewSubscriber(*sub);
+ if (task) tasks.Add(task);
+ }
+ sub++;
+ }
+ }
+
+ // Queue up all tasks now outside of lock, in case they
+ // block because the task manager has maxed out number of running tasks
+ // and to avoid a deadlock with tasks trying to acquire the lock in the response
+ NPT_List<PLT_ThreadTask*>::Iterator task = tasks.GetFirstItem();
+ while (task) {
+ PLT_ThreadTask* _task = *task++;
+ m_TaskManager->StartTask(_task);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::FindDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::FindDevice(const char* uuid,
+ PLT_DeviceDataReference& device,
+ bool return_root /* = false */)
+{
+ NPT_List<PLT_DeviceDataReference>::Iterator iter = m_RootDevices.GetFirstItem();
+ while (iter) {
+ // device uuid found immediately as root device
+ if ((*iter)->GetUUID().Compare(uuid) == 0) {
+ device = *iter;
+ return NPT_SUCCESS;
+ } else if (NPT_SUCCEEDED((*iter)->FindEmbeddedDevice(uuid, device))) {
+ // we found the uuid as an embedded device of this root
+ // return root if told, otherwise return found embedded device
+ if (return_root) device = (*iter);
+ return NPT_SUCCESS;
+ }
+ ++iter;
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::FindActionDesc
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::FindActionDesc(PLT_DeviceDataReference& device,
+ const char* service_type,
+ const char* action_name,
+ PLT_ActionDesc*& action_desc)
+{
+ if (device.IsNull()) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // 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_CtrlPoint::CreateAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::CreateAction(PLT_DeviceDataReference& device,
+ const char* service_type,
+ const char* action_name,
+ PLT_ActionReference& action)
+{
+ if (device.IsNull()) return NPT_ERROR_INVALID_PARAMETERS;
+
+ NPT_AutoLock lock(m_Lock);
+
+ PLT_ActionDesc* action_desc;
+ NPT_CHECK_SEVERE(FindActionDesc(device,
+ service_type,
+ action_name,
+ action_desc));
+
+ PLT_DeviceDataReference root_device;
+ NPT_CHECK_SEVERE(FindDevice(device->GetUUID(), root_device, true));
+
+ action = new PLT_Action(*action_desc, root_device);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ if (request.GetMethod().Compare("NOTIFY") == 0) {
+ return ProcessHttpNotify(request, context, response);
+ }
+
+ NPT_LOG_SEVERE("CtrlPoint received bad http request\r\n");
+ response.SetStatus(412, "Precondition Failed");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::DecomposeLastChangeVar
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::DecomposeLastChangeVar(NPT_List<PLT_StateVariable*>& vars)
+{
+ // parse LastChange var into smaller vars
+ PLT_StateVariable* lastChangeVar = NULL;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(vars,
+ PLT_StateVariableNameFinder("LastChange"),
+ lastChangeVar))) {
+ vars.Remove(lastChangeVar);
+ PLT_Service* var_service = lastChangeVar->GetService();
+ NPT_String text = lastChangeVar->GetValue();
+
+ NPT_XmlNode* xml = NULL;
+ NPT_XmlParser parser;
+ if (NPT_FAILED(parser.Parse(text, xml)) || !xml || !xml->AsElementNode()) {
+ delete xml;
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+
+ NPT_XmlElementNode* node = xml->AsElementNode();
+ if (!node->GetTag().Compare("Event", true)) {
+ // look for the instance with attribute id = 0
+ NPT_XmlElementNode* instance = NULL;
+ for (NPT_Cardinal i=0; i<node->GetChildren().GetItemCount(); i++) {
+ NPT_XmlElementNode* child;
+ if (NPT_FAILED(PLT_XmlHelper::GetChild(node, child, i)))
+ continue;
+
+ if (!child->GetTag().Compare("InstanceID", true)) {
+ // extract the "val" attribute value
+ NPT_String value;
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(child, "val", value)) &&
+ !value.Compare("0")) {
+ instance = child;
+ break;
+ }
+ }
+ }
+
+ // did we find an instance with id = 0 ?
+ if (instance != NULL) {
+ // all the children of the Instance node are state variables
+ for (NPT_Cardinal j=0; j<instance->GetChildren().GetItemCount(); j++) {
+ NPT_XmlElementNode* var_node;
+ if (NPT_FAILED(PLT_XmlHelper::GetChild(instance, var_node, j)))
+ continue;
+
+ // look for the state variable in this service
+ const NPT_String* value = var_node->GetAttribute("val");
+ PLT_StateVariable* var = var_service->FindStateVariable(var_node->GetTag());
+ if (value != NULL && var != NULL) {
+ // get the value and set the state variable
+ // if it succeeded, add it to the list of vars we'll event
+ if (NPT_SUCCEEDED(var->SetValue(*value))) {
+ vars.Add(var);
+ NPT_LOG_FINE_2("LastChange var change for (%s): %s",
+ (const char*)var->GetName(),
+ (const char*)var->GetValue());
+ }
+ }
+ }
+ }
+ }
+ delete xml;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessEventNotification
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessEventNotification(PLT_EventSubscriberReference subscriber,
+ PLT_EventNotification* notification,
+ NPT_List<PLT_StateVariable*> &vars)
+{
+ NPT_XmlElementNode* xml = NULL;
+ PLT_Service* service = subscriber->GetService();
+ PLT_DeviceData* device = service->GetDevice();
+
+ NPT_String uuid = device->GetUUID();
+ NPT_String service_id = service->GetServiceID();
+
+ // callback uri for this sub
+ NPT_String callback_uri = "/" + uuid + "/" + service_id;
+
+ if (notification->m_RequestUrl.GetPath().Compare(callback_uri, true)) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
+ }
+
+ // if the sequence number is less than our current one, we got it out of order
+ // so we disregard it
+ if (subscriber->GetEventKey() && notification->m_EventKey < subscriber->GetEventKey()) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
+ }
+
+ // parse body
+ if (NPT_FAILED(PLT_XmlHelper::Parse(notification->m_XmlBody, xml))) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
+ }
+
+ // check envelope
+ if (xml->GetTag().Compare("propertyset", true)) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
+ }
+
+ // check property set
+ // keep a vector of the state variables that changed
+ NPT_XmlElementNode* property;
+ PLT_StateVariable* var;
+ for (NPT_List<NPT_XmlNode*>::Iterator children = xml->GetChildren().GetFirstItem();
+ children;
+ children++) {
+ NPT_XmlElementNode* child = (*children)->AsElementNode();
+ if (!child) continue;
+
+ // check property
+ if (child->GetTag().Compare("property", true)) continue;
+
+ if (NPT_FAILED(PLT_XmlHelper::GetChild(child, property))) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
+ }
+
+ var = service->FindStateVariable(property->GetTag());
+ if (var == NULL) continue;
+
+ if (NPT_FAILED(var->SetValue(property->GetText() ? property->GetText()->GetChars() : "")))
+ {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, failure);
+ }
+
+ vars.Add(var);
+ }
+
+ // update sequence
+ subscriber->SetEventKey(notification->m_EventKey);
+
+ // Look if a state variable LastChange was received and decompose it into
+ // independent state variable updates
+ DecomposeLastChangeVar(vars);
+
+ delete xml;
+ return NPT_SUCCESS;
+
+failure:
+ NPT_LOG_SEVERE("CtrlPoint failed to process event notification");
+ delete xml;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::AddPendingEventNotification
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::AddPendingEventNotification(PLT_EventNotification *notification)
+{
+ // Only keep a maximum of 20 pending notifications
+ while (m_PendingNotifications.GetItemCount() > 20) {
+ PLT_EventNotification *garbage = NULL;
+ m_PendingNotifications.PopHead(garbage);
+ delete garbage;
+ }
+
+ m_PendingNotifications.Add(notification);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessPendingEventNotifications
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessPendingEventNotifications()
+{
+ NPT_Cardinal count = m_PendingNotifications.GetItemCount();
+ while (count--) {
+ NPT_List<PLT_StateVariable*> vars;
+ PLT_Service *service = NULL;
+ PLT_EventNotification *notification;
+
+ if (NPT_SUCCEEDED(m_PendingNotifications.PopHead(notification))) {
+ PLT_EventSubscriberReference sub;
+
+ // look for the subscriber with that sid
+ if (NPT_FAILED(NPT_ContainerFind(m_Subscribers,
+ PLT_EventSubscriberFinderBySID(notification->m_SID),
+ sub))) {
+ m_PendingNotifications.Add(notification);
+ continue;
+ }
+
+ // keep track of service for listeners later
+ service = sub->GetService();
+
+ // Reprocess notification
+ NPT_LOG_WARNING_1("Reprocessing delayed notification for subscriber %s", (const char*)notification->m_SID);
+ NPT_Result result = ProcessEventNotification(sub, notification, vars);
+ delete notification;
+
+ if (NPT_FAILED(result)) continue;
+ }
+
+ // notify listeners
+ if (service && vars.GetItemCount()) {
+ m_ListenerList.Apply(PLT_CtrlPointListenerOnEventNotifyIterator(service, &vars));
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessHttpNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessHttpNotify(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_AutoLock lock(m_Lock);
+
+ NPT_List<PLT_StateVariable*> vars;
+ PLT_Service* service = NULL;
+ PLT_EventSubscriberReference sub;
+ NPT_Result result;
+
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINER, "PLT_CtrlPoint::ProcessHttpNotify:", &request);
+
+ // Create notification from request
+ PLT_EventNotification* notification = PLT_EventNotification::Parse(request, context, response);
+ NPT_CHECK_POINTER_LABEL_WARNING(notification, bad_request);
+
+ // Give a last change to process pending notifications before throwing them out
+ // by AddPendingNotification
+ ProcessPendingEventNotifications();
+
+ // look for the subscriber with that sid
+ if (NPT_FAILED(NPT_ContainerFind(m_Subscribers,
+ PLT_EventSubscriberFinderBySID(notification->m_SID),
+ sub))) {
+ NPT_LOG_WARNING_1("Subscriber %s not found, delaying notification process.\n", (const char*)notification->m_SID);
+ AddPendingEventNotification(notification);
+ return NPT_SUCCESS;
+ }
+
+ // Process notification for subscriber
+ service = sub->GetService();
+ result = ProcessEventNotification(sub, notification, vars);
+ delete notification;
+
+ NPT_CHECK_LABEL_WARNING(result, bad_request);
+
+ // Notify listeners
+ if (vars.GetItemCount()) {
+ m_ListenerList.Apply(PLT_CtrlPointListenerOnEventNotifyIterator(service, &vars));
+ }
+
+ return NPT_SUCCESS;
+
+bad_request:
+ NPT_LOG_SEVERE("CtrlPoint received bad event notify request\r\n");
+ if (response.GetStatusCode() == 200) {
+ response.SetStatus(412, "Precondition Failed");
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessSsdpSearchResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSsdpSearchResponse(NPT_Result res,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_CHECK_SEVERE(res);
+ NPT_CHECK_POINTER_SEVERE(response);
+
+ NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+ NPT_String protocol = response->GetProtocol();
+
+ NPT_String prefix = NPT_String::Format("PLT_CtrlPoint::ProcessSsdpSearchResponse from %s:%d",
+ (const char*)context.GetRemoteAddress().GetIpAddress().ToString() ,
+ context.GetRemoteAddress().GetPort());
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINER, prefix, response);
+
+ // any 2xx responses are ok
+ if (response->GetStatusCode()/100 == 2) {
+ const NPT_String* st = response->GetHeaders().GetHeaderValue("st");
+ const NPT_String* usn = response->GetHeaders().GetHeaderValue("usn");
+ const NPT_String* ext = response->GetHeaders().GetHeaderValue("ext");
+ NPT_CHECK_POINTER_SEVERE(st);
+ NPT_CHECK_POINTER_SEVERE(usn);
+ NPT_CHECK_POINTER_SEVERE(ext);
+
+ NPT_String uuid;
+
+ // if we get an advertisement other than uuid
+ // verify it's formatted properly
+ if (usn != st) {
+ NPT_List<NPT_String> components = usn->Split("::");
+ if (components.GetItemCount() != 2)
+ return NPT_FAILURE;
+
+ if (st->Compare(*components.GetItem(1), true))
+ return NPT_FAILURE;
+
+ uuid = components.GetItem(0)->SubString(5);
+ } else {
+ uuid = usn->SubString(5);
+ }
+
+ if (m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) {
+ NPT_LOG_FINE_1("CtrlPoint received a search response from ourselves (%s)\n", (const char*)uuid);
+ return NPT_SUCCESS;
+ }
+
+ return ProcessSsdpMessage(*response, context, uuid);
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::OnSsdpPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::OnSsdpPacket(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context)
+{
+ return ProcessSsdpNotify(request, context);
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessSsdpNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSsdpNotify(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context)
+{
+ // get the address of who sent us some data back
+ NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+ NPT_String method = request.GetMethod();
+ NPT_String uri = request.GetUrl().GetPath(true);
+ NPT_String protocol = request.GetProtocol();
+
+ if (method.Compare("NOTIFY") == 0) {
+ const NPT_String* nts = PLT_UPnPMessageHelper::GetNTS(request);
+ const NPT_String* nt = PLT_UPnPMessageHelper::GetNT(request);
+ const NPT_String* usn = PLT_UPnPMessageHelper::GetUSN(request);
+
+ NPT_String prefix = NPT_String::Format("PLT_CtrlPoint::ProcessSsdpNotify from %s:%d (%s)",
+ context.GetRemoteAddress().GetIpAddress().ToString().GetChars(),
+ context.GetRemoteAddress().GetPort(),
+ usn?usn->GetChars():"unknown");
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINER, prefix, &request);
+
+ if ((uri.Compare("*") != 0) || (protocol.Compare("HTTP/1.1") != 0))
+ return NPT_FAILURE;
+
+ NPT_CHECK_POINTER_SEVERE(nts);
+ NPT_CHECK_POINTER_SEVERE(nt);
+ NPT_CHECK_POINTER_SEVERE(usn);
+
+ NPT_String uuid;
+
+ // if we get an advertisement other than uuid
+ // verify it's formatted properly
+ if (*usn != *nt) {
+ NPT_List<NPT_String> components = usn->Split("::");
+ if (components.GetItemCount() != 2)
+ return NPT_FAILURE;
+
+ if (nt->Compare(*components.GetItem(1), true))
+ return NPT_FAILURE;
+
+ uuid = components.GetItem(0)->SubString(5);
+ } else {
+ uuid = usn->SubString(5);
+ }
+
+ if (m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) {
+ NPT_LOG_FINE_1("Received a NOTIFY request from ourselves (%s)\n", (const char*)uuid);
+ return NPT_SUCCESS;
+ }
+
+ // if it's a byebye, remove the device and return right away
+ if (nts->Compare("ssdp:byebye", true) == 0) {
+ NPT_LOG_INFO_1("Received a byebye NOTIFY request from %s\n", (const char*)uuid);
+
+ NPT_AutoLock lock(m_Lock);
+
+ // look for root device
+ PLT_DeviceDataReference root_device;
+ FindDevice(uuid, root_device, true);
+
+ if (!root_device.IsNull()) RemoveDevice(root_device);
+ return NPT_SUCCESS;
+ }
+
+ return ProcessSsdpMessage(request, context, uuid);
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::AddDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::AddDevice(PLT_DeviceDataReference& data)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ return NotifyDeviceReady(data);
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::NotifyDeviceReady
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::NotifyDeviceReady(PLT_DeviceDataReference& data)
+{
+ m_ListenerList.Apply(PLT_CtrlPointListenerOnDeviceAddedIterator(data));
+
+ /* recursively add embedded devices */
+ NPT_Array<PLT_DeviceDataReference> embedded_devices =
+ data->GetEmbeddedDevices();
+ for (NPT_Cardinal i=0;i<embedded_devices.GetItemCount();i++) {
+ NotifyDeviceReady(embedded_devices[i]);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::RemoveDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::RemoveDevice(PLT_DeviceDataReference& data)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ NotifyDeviceRemoved(data);
+ CleanupDevice(data);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::NotifyDeviceRemoved
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::NotifyDeviceRemoved(PLT_DeviceDataReference& data)
+{
+ m_ListenerList.Apply(PLT_CtrlPointListenerOnDeviceRemovedIterator(data));
+
+ /* recursively add embedded devices */
+ NPT_Array<PLT_DeviceDataReference> embedded_devices =
+ data->GetEmbeddedDevices();
+ for (NPT_Cardinal i=0;i<embedded_devices.GetItemCount();i++) {
+ NotifyDeviceRemoved(embedded_devices[i]);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::CleanupDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::CleanupDevice(PLT_DeviceDataReference& data)
+{
+ if (data.IsNull()) return NPT_ERROR_INVALID_PARAMETERS;
+
+ NPT_LOG_INFO_1("Removing %s from device list\n", (const char*)data->GetUUID());
+
+ // Note: This must take the lock prior to being called
+ // we can't take the lock here because this function
+ // will be recursively called if device contains embedded devices
+
+ /* recursively remove embedded devices */
+ NPT_Array<PLT_DeviceDataReference> embedded_devices = data->GetEmbeddedDevices();
+ for (NPT_Cardinal i=0;i<embedded_devices.GetItemCount();i++) {
+ CleanupDevice(embedded_devices[i]);
+ }
+
+ /* remove from list */
+ m_RootDevices.Remove(data);
+
+ /* unsubscribe from services */
+ data->m_Services.Apply(PLT_EventSubscriberRemoverIterator(this));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessSsdpMessage
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSsdpMessage(const NPT_HttpMessage& message,
+ const NPT_HttpRequestContext& context,
+ NPT_String& uuid)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_AutoLock lock(m_Lock);
+
+ // check if we should ignore our own UUID
+ if (m_UUIDsToIgnore.Find(NPT_StringFinder(uuid))) return NPT_SUCCESS;
+
+ const NPT_String* url = PLT_UPnPMessageHelper::GetLocation(message);
+ NPT_CHECK_POINTER_SEVERE(url);
+
+ // Fix for Connect360 which uses localhost in device description url
+ NPT_HttpUrl location(*url);
+ if (location.GetHost().ToLowercase() == "localhost" ||
+ location.GetHost().ToLowercase() == "127.0.0.1") {
+ location.SetHost(context.GetRemoteAddress().GetIpAddress().ToString());
+ }
+
+ // be nice and assume a default lease time if not found even though it's required
+ NPT_TimeInterval leasetime;
+ if (NPT_FAILED(PLT_UPnPMessageHelper::GetLeaseTime(message, leasetime))) {
+ leasetime = *PLT_Constants::GetInstance().GetDefaultSubscribeLease();
+ }
+
+ // check if device (or embedded device) is already known
+ PLT_DeviceDataReference data;
+ if (NPT_SUCCEEDED(FindDevice(uuid, data))) {
+
+// // in case we missed the byebye and the device description has changed (ip or port)
+// // reset base and assumes device is the same (same number of services and embedded devices)
+// // FIXME: The right way is to remove the device and rescan it though but how do we know it changed?
+// PLT_DeviceReadyIterator device_tester;
+// if (NPT_SUCCEEDED(device_tester(data)) && data->GetDescriptionUrl().Compare(location.ToString(), true)) {
+// NPT_LOG_INFO_2("Old device \"%s\" detected @ new location %s",
+// (const char*)data->GetFriendlyName(),
+// (const char*)location.ToString());
+// data->SetURLBase(location);
+// }
+
+ // renew expiration time
+ data->SetLeaseTime(leasetime);
+ NPT_LOG_FINE_1("Device \"%s\" expiration time renewed..",
+ (const char*)data->GetFriendlyName());
+
+ return NPT_SUCCESS;
+ }
+
+ // start inspection
+ return InspectDevice(location, uuid, leasetime);
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::InspectDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::InspectDevice(const NPT_HttpUrl& location,
+ const char* uuid,
+ NPT_TimeInterval leasetime)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // check if already inspecting device
+ NPT_String pending_uuid;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(m_PendingInspections,
+ NPT_StringFinder(uuid),
+ pending_uuid))) {
+ return NPT_SUCCESS;
+ }
+
+ NPT_LOG_INFO_2("Inspecting device \"%s\" detected @ %s",
+ uuid,
+ (const char*)location.ToString());
+
+ if (!location.IsValid()) {
+ NPT_LOG_INFO_1("Invalid device description url: %s",
+ (const char*) location.ToString());
+ return NPT_FAILURE;
+ }
+
+ // remember that we're now inspecting the device
+ m_PendingInspections.Add(uuid);
+
+ // Start a task to retrieve the description
+ PLT_CtrlPointGetDescriptionTask* task = new PLT_CtrlPointGetDescriptionTask(
+ location,
+ this,
+ leasetime,
+ uuid);
+
+ // Add a delay to make sure that we received late NOTIFY bye-bye
+ NPT_TimeInterval delay(.5f);
+ m_TaskManager->StartTask(task, &delay);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::FetchDeviceSCPDs
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::FetchDeviceSCPDs(PLT_CtrlPointGetSCPDsTask* task,
+ PLT_DeviceDataReference& device,
+ NPT_Cardinal level)
+{
+ if (level == 5 && device->m_EmbeddedDevices.GetItemCount()) {
+ NPT_LOG_FATAL("Too many embedded devices depth! ");
+ return NPT_FAILURE;
+ }
+
+ ++level;
+
+ // fetch embedded devices services scpds first
+ for (NPT_Cardinal i = 0;
+ i<device->m_EmbeddedDevices.GetItemCount();
+ i++) {
+ NPT_CHECK_SEVERE(FetchDeviceSCPDs(task, device->m_EmbeddedDevices[i], level));
+ }
+
+ // Get SCPD of device services now and bail right away if one fails
+ return device->m_Services.ApplyUntil(
+ PLT_AddGetSCPDRequestIterator(*task, device),
+ NPT_UntilResultNotEquals(NPT_SUCCESS));
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessGetDescriptionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessGetDescriptionResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response,
+ NPT_TimeInterval leasetime,
+ NPT_String uuid)
+{
+ NPT_COMPILER_UNUSED(request);
+
+ NPT_AutoLock lock(m_Lock);
+
+ PLT_CtrlPointGetSCPDsTask* task = NULL;
+ NPT_String desc;
+ PLT_DeviceDataReference root_device;
+ PLT_DeviceDataReference device;
+
+ // Add a delay, some devices need it (aka Rhapsody)
+ NPT_TimeInterval delay(0.1f);
+
+ NPT_String prefix = NPT_String::Format("PLT_CtrlPoint::ProcessGetDescriptionResponse @ %s (result = %d, status = %d)",
+ (const char*)request.GetUrl().ToString(),
+ res,
+ response?response->GetStatusCode():0);
+
+ // Remove pending inspection
+ m_PendingInspections.Remove(uuid);
+
+ // verify response was ok
+ NPT_CHECK_LABEL_FATAL(res, bad_response);
+ NPT_CHECK_POINTER_LABEL_FATAL(response, bad_response);
+
+ // log response
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINER, prefix, response);
+
+ // get response body
+ res = PLT_HttpHelper::GetBody(*response, desc);
+ NPT_CHECK_SEVERE(res);
+
+ // create new root device
+ NPT_CHECK_SEVERE(PLT_DeviceData::SetDescription(root_device, leasetime, request.GetUrl(), desc, context));
+
+ // make sure root device was not previously queried
+ if (NPT_FAILED(FindDevice(root_device->GetUUID(), device))) {
+ m_RootDevices.Add(root_device);
+
+ NPT_LOG_INFO_3("Device \"%s\" is now known as \"%s\" (%s)",
+ (const char*)root_device->GetUUID(),
+ (const char*)root_device->GetFriendlyName(),
+ (const char*)root_device->GetDescriptionUrl(NULL));
+
+ // create one single task to fetch all scpds one after the other
+ task = new PLT_CtrlPointGetSCPDsTask(this, root_device);
+ NPT_CHECK_LABEL_SEVERE(res = FetchDeviceSCPDs(task, root_device, 0),
+ cleanup);
+
+ // if device has embedded devices, we want to delay fetching scpds
+ // just in case there's a chance all the initial NOTIFY bye-bye have
+ // not all been received yet which would cause to remove the devices
+ // as we're adding them
+ if (root_device->m_EmbeddedDevices.GetItemCount() > 0) {
+ delay = 1.f;
+ }
+ NPT_CHECK_LABEL_SEVERE(res = m_TaskManager->StartTask(task, &delay),
+ failure);
+ }
+
+ return NPT_SUCCESS;
+
+bad_response:
+ NPT_LOG_SEVERE_2("Bad Description response @ %s: %s",
+ (const char*)request.GetUrl().ToString(),
+ (const char*)desc);
+
+cleanup:
+ if (task) delete task;
+
+failure:
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessGetSCPDResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessGetSCPDResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response,
+ PLT_DeviceDataReference& device)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_AutoLock lock(m_Lock);
+
+ PLT_DeviceReadyIterator device_tester;
+ NPT_String scpd;
+ PLT_DeviceDataReference root_device;
+ PLT_Service* service;
+
+ NPT_String prefix = NPT_String::Format("PLT_CtrlPoint::ProcessGetSCPDResponse for a service of device \"%s\" @ %s (result = %d, status = %d)",
+ (const char*)device->GetFriendlyName(),
+ (const char*)request.GetUrl().ToString(),
+ res,
+ response?response->GetStatusCode():0);
+
+ // verify response was ok
+ NPT_CHECK_LABEL_FATAL(res, bad_response);
+ NPT_CHECK_POINTER_LABEL_FATAL(response, bad_response);
+
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINER, prefix, response);
+
+ // make sure root device hasn't disappeared
+ NPT_CHECK_LABEL_WARNING(FindDevice(device->GetUUID(), root_device, true),
+ bad_response);
+
+ res = device->FindServiceBySCPDURL(request.GetUrl().ToRequestString(), service);
+ NPT_CHECK_LABEL_SEVERE(res, bad_response);
+
+ // get response body
+ res = PLT_HttpHelper::GetBody(*response, scpd);
+ NPT_CHECK_LABEL_FATAL(res, bad_response);
+
+ // DIAL support
+ if (root_device->GetType().Compare("urn:dial-multiscreen-org:device:dial:1") == 0) {
+ AddDevice(root_device);
+ return NPT_SUCCESS;
+ }
+
+ // set the service scpd
+ res = service->SetSCPDXML(scpd);
+ NPT_CHECK_LABEL_SEVERE(res, bad_response);
+
+ // if root device is ready, notify listeners about it and embedded devices
+ if (NPT_SUCCEEDED(device_tester(root_device))) {
+ AddDevice(root_device);
+ }
+
+ return NPT_SUCCESS;
+
+bad_response:
+ NPT_LOG_SEVERE_2("Bad SCPD response for device \"%s\":%s",
+ (const char*)device->GetFriendlyName(),
+ (const char*)scpd);
+
+ if (!root_device.IsNull()) RemoveDevice(root_device);
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::RenewSubscriber
++---------------------------------------------------------------------*/
+PLT_ThreadTask*
+PLT_CtrlPoint::RenewSubscriber(PLT_EventSubscriberReference subscriber)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ PLT_DeviceDataReference root_device;
+ if (NPT_FAILED(FindDevice(subscriber->GetService()->GetDevice()->GetUUID(),
+ root_device,
+ true))) {
+ return NULL;
+ }
+
+ NPT_LOG_FINE_3("Renewing subscriber \"%s\" for service \"%s\" of device \"%s\"",
+ (const char*)subscriber->GetSID(),
+ (const char*)subscriber->GetService()->GetServiceID(),
+ (const char*)subscriber->GetService()->GetDevice()->GetFriendlyName());
+
+ // create the request
+ NPT_HttpRequest* request = new NPT_HttpRequest(
+ subscriber->GetService()->GetEventSubURL(true),
+ "SUBSCRIBE",
+ NPT_HTTP_PROTOCOL_1_1);
+
+ PLT_UPnPMessageHelper::SetSID(*request, subscriber->GetSID());
+ PLT_UPnPMessageHelper::SetTimeOut(*request,
+ (NPT_Int32)PLT_Constants::GetInstance().GetDefaultSubscribeLease()->ToSeconds());
+
+ // Prepare the request
+ // create a task to post the request
+ return new PLT_CtrlPointSubscribeEventTask(
+ request,
+ this,
+ root_device,
+ subscriber->GetService());
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::Subscribe
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::Subscribe(PLT_Service* service,
+ bool cancel,
+ void* userdata)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ NPT_HttpRequest* request = NULL;
+
+ // make sure service is subscribable
+ if (!service->IsSubscribable()) return NPT_FAILURE;
+
+ // event url
+ NPT_HttpUrl url(service->GetEventSubURL(true));
+
+ // look for the corresponding root device & sub
+ PLT_DeviceDataReference root_device;
+ PLT_EventSubscriberReference sub;
+ NPT_CHECK_WARNING(FindDevice(service->GetDevice()->GetUUID(),
+ root_device,
+ true));
+
+ // look for the subscriber with that service to decide if it's a renewal or not
+ NPT_ContainerFind(m_Subscribers,
+ PLT_EventSubscriberFinderByService(service),
+ sub);
+
+ if (cancel == false) {
+ // renewal?
+ if (!sub.IsNull()) {
+ PLT_ThreadTask* task = RenewSubscriber(sub);
+ return m_TaskManager->StartTask(task);
+ }
+
+ NPT_LOG_INFO_2("Subscribing to service \"%s\" of device \"%s\"",
+ (const char*)service->GetServiceID(),
+ (const char*)service->GetDevice()->GetFriendlyName());
+
+ // prepare the callback url
+ NPT_String uuid = service->GetDevice()->GetUUID();
+ NPT_String service_id = service->GetServiceID();
+ NPT_String callback_uri = "/" + uuid + "/" + service_id;
+
+ // create the request
+ request = new NPT_HttpRequest(url, "SUBSCRIBE", NPT_HTTP_PROTOCOL_1_1);
+ // specify callback url using ip of interface used when
+ // retrieving device description
+ NPT_HttpUrl callbackUrl(
+ service->GetDevice()->m_LocalIfaceIp.ToString(),
+ m_EventHttpServer->GetPort(),
+ callback_uri);
+
+ // set the required headers for a new subscription
+ PLT_UPnPMessageHelper::SetNT(*request, "upnp:event");
+ PLT_UPnPMessageHelper::SetCallbacks(*request,
+ "<" + callbackUrl.ToString() + ">");
+ PLT_UPnPMessageHelper::SetTimeOut(*request,
+ (NPT_Int32)PLT_Constants::GetInstance().GetDefaultSubscribeLease()->ToSeconds());
+ } else {
+ NPT_LOG_INFO_3("Unsubscribing subscriber \"%s\" for service \"%s\" of device \"%s\"",
+ (const char*)(!sub.IsNull()?sub->GetSID().GetChars():"unknown"),
+ (const char*)service->GetServiceID(),
+ (const char*)service->GetDevice()->GetFriendlyName());
+
+ // cancellation
+ if (sub.IsNull()) return NPT_FAILURE;
+
+ // create the request
+ request = new NPT_HttpRequest(url, "UNSUBSCRIBE", NPT_HTTP_PROTOCOL_1_1);
+ PLT_UPnPMessageHelper::SetSID(*request, sub->GetSID());
+
+ // remove from list now
+ m_Subscribers.Remove(sub, true);
+ }
+
+ // verify we have request to send just in case
+ NPT_CHECK_POINTER_FATAL(request);
+
+ // Prepare the request
+ // create a task to post the request
+ PLT_ThreadTask* task = new PLT_CtrlPointSubscribeEventTask(
+ request,
+ this,
+ root_device,
+ service,
+ userdata);
+ m_TaskManager->StartTask(task);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessSubscribeResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessSubscribeResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response,
+ PLT_Service* service,
+ void* /* userdata */)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_AutoLock lock(m_Lock);
+
+ const NPT_String* sid = NULL;
+ NPT_Int32 seconds = -1;
+ PLT_EventSubscriberReference sub;
+ bool subscription = (request.GetMethod().ToUppercase() == "SUBSCRIBE");
+
+ NPT_String prefix = NPT_String::Format("PLT_CtrlPoint::ProcessSubscribeResponse %ubscribe for service \"%s\" (result = %d, status code = %d)",
+ (const char*)subscription?"S":"Uns",
+ (const char*)service->GetServiceID(),
+ res,
+ response?response->GetStatusCode():0);
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINER, prefix, response);
+
+ // if there's a failure or it's a response to a cancellation
+ // we get out (any 2xx status code ok)
+ if (NPT_FAILED(res) || response == NULL || response->GetStatusCode()/100 != 2) {
+ goto failure;
+ }
+
+ if (subscription) {
+ if (!(sid = PLT_UPnPMessageHelper::GetSID(*response)) ||
+ NPT_FAILED(PLT_UPnPMessageHelper::GetTimeOut(*response, seconds))) {
+ NPT_CHECK_LABEL_SEVERE(res = NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // Look for subscriber
+ NPT_ContainerFind(m_Subscribers,
+ PLT_EventSubscriberFinderBySID(*sid),
+ sub);
+
+ NPT_LOG_INFO_5("%s subscriber \"%s\" for service \"%s\" of device \"%s\" (timeout = %d)",
+ !sub.IsNull()?"Updating timeout for":"Creating new",
+ (const char*)*sid,
+ (const char*)service->GetServiceID(),
+ (const char*)service->GetDevice()->GetFriendlyName(),
+ seconds);
+
+ // create new subscriber if sid never seen before
+ // or update subscriber expiration otherwise
+ if (sub.IsNull()) {
+ sub = new PLT_EventSubscriber(m_TaskManager, service, *sid, seconds);
+ m_Subscribers.Add(sub);
+ } else {
+ sub->SetTimeout(seconds);
+ }
+
+ // Process any pending notifcations for that subscriber we got a bit too early
+ ProcessPendingEventNotifications();
+
+ return NPT_SUCCESS;
+ }
+
+ goto remove_sub;
+
+failure:
+ NPT_LOG_SEVERE_4(
+ "%subscription failed of sub \"%s\" for service \"%s\" of device \"%s\"",
+ (const char*)subscription ? "S" : "Uns", (const char*)(sid ? sid->GetChars() : "Unknown"),
+ (const char*)service->GetServiceID(), (const char*)service->GetDevice()->GetFriendlyName());
+ res = NPT_FAILED(res) ? res : NPT_FAILURE;
+
+remove_sub:
+ // in case it was a renewal look for the subscriber with that service and remove it from the list
+ if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers,
+ PLT_EventSubscriberFinderByService(service),
+ sub))) {
+ m_Subscribers.Remove(sub);
+ }
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::InvokeAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::InvokeAction(PLT_ActionReference& action,
+ void* userdata)
+{
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ PLT_Service* service = action->GetActionDesc().GetService();
+
+ // create the request
+ NPT_HttpUrl url(service->GetControlURL(true));
+ NPT_HttpRequest* request = new NPT_HttpRequest(url, "POST", NPT_HTTP_PROTOCOL_1_1);
+
+ // create a memory stream for our request body
+ NPT_MemoryStreamReference stream(new NPT_MemoryStream);
+ action->FormatSoapRequest(*stream);
+
+ // set the request body
+ NPT_HttpEntity* entity = NULL;
+ PLT_HttpHelper::SetBody(*request, (NPT_InputStreamReference)stream, &entity);
+
+ entity->SetContentType("text/xml; charset=\"utf-8\"");
+ NPT_String service_type = service->GetServiceType();
+ NPT_String action_name = action->GetActionDesc().GetName();
+ request->GetHeaders().SetHeader("SOAPAction", "\"" + service_type + "#" + action_name + "\"");
+
+ // create a task to post the request
+ PLT_CtrlPointInvokeActionTask* task = new PLT_CtrlPointInvokeActionTask(
+ request,
+ this,
+ action,
+ userdata);
+
+ // queue the request
+ m_TaskManager->StartTask(task);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ProcessActionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ProcessActionResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& /*context*/,
+ NPT_HttpResponse* response,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_COMPILER_UNUSED(request);
+
+ NPT_String service_type;
+ NPT_String str;
+ NPT_XmlElementNode* xml = NULL;
+ NPT_String name;
+ NPT_String soap_action_name;
+ NPT_XmlElementNode* soap_action_response;
+ NPT_XmlElementNode* soap_body;
+ NPT_XmlElementNode* fault;
+ const NPT_String* attr = NULL;
+ PLT_ActionDesc& action_desc = action->GetActionDesc();
+
+ // reset the error code and desc
+ action->SetError(0, "");
+
+ // check context validity
+ if (NPT_FAILED(res) || response == NULL) {
+ PLT_Service* service = action_desc.GetService();
+ NPT_COMPILER_UNUSED(service);
+ NPT_LOG_WARNING_4("Failed to reach %s for %s.%s (%d)",
+ request.GetUrl().ToString().GetChars(),
+ service->GetDevice()->GetUUID().GetChars(),
+ service->GetServiceName().GetChars(),
+ res);
+ goto failure;
+ }
+
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINER, "PLT_CtrlPoint::ProcessActionResponse:", response);
+
+ NPT_LOG_FINER("Reading/Parsing Action Response Body...");
+ if (NPT_FAILED(PLT_HttpHelper::ParseBody(*response, xml))) {
+ goto failure;
+ }
+
+ NPT_LOG_FINER("Analyzing Action Response Body...");
+
+ // read envelope
+ if (xml->GetTag().Compare("Envelope", true))
+ goto failure;
+
+ // check namespace
+ if (!xml->GetNamespace() || xml->GetNamespace()->Compare("http://schemas.xmlsoap.org/soap/envelope/"))
+ goto failure;
+
+ // check encoding
+ attr = xml->GetAttribute("encodingStyle", "http://schemas.xmlsoap.org/soap/envelope/");
+ if (!attr || attr->Compare("http://schemas.xmlsoap.org/soap/encoding/"))
+ goto failure;
+
+ // read action
+ soap_body = PLT_XmlHelper::GetChild(xml, "Body");
+ if (soap_body == NULL)
+ goto failure;
+
+ // check if an error occurred
+ fault = PLT_XmlHelper::GetChild(soap_body, "Fault");
+ if (fault != NULL) {
+ // we have an error
+ ParseFault(action, fault);
+ goto failure;
+ }
+
+ if (NPT_FAILED(PLT_XmlHelper::GetChild(soap_body, soap_action_response)))
+ goto failure;
+
+ // verify action name is identical to SOAPACTION header
+ if (soap_action_response->GetTag().Compare(action_desc.GetName() + "Response", true))
+ goto failure;
+
+ // verify namespace
+ if (!soap_action_response->GetNamespace() ||
+ soap_action_response->GetNamespace()->Compare(action_desc.GetService()->GetServiceType()))
+ goto failure;
+
+ // read all the arguments if any
+ for (NPT_List<NPT_XmlNode*>::Iterator args = soap_action_response->GetChildren().GetFirstItem();
+ args;
+ args++) {
+ NPT_XmlElementNode* child = (*args)->AsElementNode();
+ if (!child) continue;
+
+ action->SetArgumentValue(child->GetTag(),
+ child->GetText() ? child->GetText()->GetChars() : "");
+ if (NPT_FAILED(res)) goto failure;
+ }
+
+ // create a buffer for our response body and call the service
+ res = action->VerifyArguments(false);
+ if (NPT_FAILED(res)) goto failure;
+
+ goto cleanup;
+
+failure:
+ // override res with failure if necessary
+ if (NPT_SUCCEEDED(res)) res = NPT_FAILURE;
+ // fallthrough
+
+cleanup:
+ {
+ NPT_AutoLock lock(m_Lock);
+ m_ListenerList.Apply(PLT_CtrlPointListenerOnActionResponseIterator(res, action, userdata));
+ }
+
+ delete xml;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint::ParseFault
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPoint::ParseFault(PLT_ActionReference& action,
+ NPT_XmlElementNode* fault)
+{
+ NPT_XmlElementNode* detail = fault->GetChild("detail");
+ if (detail == NULL) return NPT_FAILURE;
+
+ NPT_XmlElementNode *upnp_error, *error_code, *error_desc;
+ upnp_error = detail->GetChild("upnp_error");
+
+ // WMP12 Hack
+ if (upnp_error == NULL) {
+ upnp_error = detail->GetChild("UPnPError", NPT_XML_ANY_NAMESPACE);
+ if (upnp_error == NULL) return NPT_FAILURE;
+ }
+
+ error_code = upnp_error->GetChild("errorCode", NPT_XML_ANY_NAMESPACE);
+ error_desc = upnp_error->GetChild("errorDescription", NPT_XML_ANY_NAMESPACE);
+ NPT_Int32 code = 501;
+ NPT_String desc;
+ if (error_code && error_code->GetText()) {
+ NPT_String value = *error_code->GetText();
+ value.ToInteger(code);
+ }
+ if (error_desc && error_desc->GetText()) {
+ desc = *error_desc->GetText();
+ }
+ action->SetError(code, desc);
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.h b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.h
new file mode 100644
index 0000000..401c863
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltCtrlPoint.h
@@ -0,0 +1,254 @@
+/*****************************************************************
+|
+| Platinum - Control Point
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP ControlPoint
+ */
+
+#ifndef _PLT_CONTROL_POINT_H_
+#define _PLT_CONTROL_POINT_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltService.h"
+#include "PltSsdp.h"
+#include "PltDeviceData.h"
+#include "PltHttpServer.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_CtrlPointHouseKeepingTask;
+class PLT_SsdpSearchTask;
+class PLT_SsdpListenTask;
+class PLT_CtrlPointGetSCPDsTask;
+class PLT_CtrlPointGetSCPDRequest;
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointListener class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPointListener class is an interface used to receive notifications when
+ devices are found or removed from the network, actions responses and events
+ are being received.
+ */
+class PLT_CtrlPointListener
+{
+public:
+ virtual ~PLT_CtrlPointListener() {}
+
+ virtual NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device) = 0;
+ virtual NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device) = 0;
+ virtual NPT_Result OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata) = 0;
+ virtual NPT_Result OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars) = 0;
+};
+
+typedef NPT_List<PLT_CtrlPointListener*> PLT_CtrlPointListenerList;
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPoint class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPoint class implements the base functionality of a UPnP ControlPoint.
+ It searches and inpects devices, invoke actions on services and subscribes to
+ events.
+ */
+class PLT_CtrlPoint : public PLT_SsdpPacketListener,
+ public PLT_SsdpSearchResponseListener,
+ public NPT_HttpRequestHandler
+{
+public:
+ PLT_CtrlPoint(const char* search_criteria = "upnp:rootdevice"); // pass NULL to prevent repeated automatic search
+ ~PLT_CtrlPoint() override;
+
+ /**
+ Returns the port used by the internal HTTP server for all incoming event notifications.
+ @return port
+ */
+ virtual NPT_Result GetPort(NPT_UInt16& port);
+
+ // delegation
+ virtual NPT_Result AddListener(PLT_CtrlPointListener* listener);
+ virtual NPT_Result RemoveListener(PLT_CtrlPointListener* listener);
+
+ // discovery
+ virtual void IgnoreUUID(const char* uuid);
+ virtual NPT_Result Search(const NPT_HttpUrl& url = NPT_HttpUrl("239.255.255.250", 1900, "*"),
+ const char* target = "upnp:rootdevice",
+ NPT_Cardinal mx = 5,
+ NPT_TimeInterval frequency = NPT_TimeInterval(50.), // pass NPT_TimeInterval(0.) for one time only
+ NPT_TimeInterval initial_delay = NPT_TimeInterval(0.));
+ virtual NPT_Result Discover(const NPT_HttpUrl& url = NPT_HttpUrl("239.255.255.250", 1900, "*"),
+ const char* target = "ssdp:all",
+ NPT_Cardinal mx = 5,
+ NPT_TimeInterval frequency = NPT_TimeInterval(50.), // pass NPT_TimeInterval(0.) for one time only
+ NPT_TimeInterval initial_delay = NPT_TimeInterval(0.));
+ virtual NPT_Result InspectDevice(const NPT_HttpUrl& location,
+ const char* uuid,
+ NPT_TimeInterval leasetime = *PLT_Constants::GetInstance().GetDefaultDeviceLease());
+
+ // actions
+ virtual NPT_Result FindActionDesc(PLT_DeviceDataReference& device,
+ const char* service_type,
+ const char* action_name,
+ PLT_ActionDesc*& action_desc);
+ virtual NPT_Result CreateAction(PLT_DeviceDataReference& device,
+ const char* service_type,
+ const char* action_name,
+ PLT_ActionReference& action);
+ virtual NPT_Result InvokeAction(PLT_ActionReference& action,
+ void* userdata = NULL);
+
+ // events
+ virtual NPT_Result Subscribe(PLT_Service* service,
+ bool cancel = false,
+ void* userdata = NULL);
+
+ // NPT_HttpRequestHandler methods
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ // PLT_SsdpSearchResponseListener methods
+ NPT_Result ProcessSsdpSearchResponse(NPT_Result res,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) override;
+ // PLT_SsdpPacketListener method
+ NPT_Result OnSsdpPacket(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context) override;
+
+protected:
+
+ // State Variable Handling
+ virtual NPT_Result DecomposeLastChangeVar(NPT_List<PLT_StateVariable*>& vars);
+
+ // methods
+ virtual NPT_Result Start(PLT_SsdpListenTask* task);
+ virtual NPT_Result Stop(PLT_SsdpListenTask* task);
+
+ // SSDP & HTTP Notifications handling
+ virtual NPT_Result ProcessSsdpNotify(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context);
+ virtual NPT_Result ProcessSsdpMessage(const NPT_HttpMessage& message,
+ const NPT_HttpRequestContext& context,
+ NPT_String& uuid);
+ virtual NPT_Result ProcessGetDescriptionResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response,
+ NPT_TimeInterval leasetime,
+ NPT_String uuid);
+ virtual NPT_Result ProcessGetSCPDResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response,
+ PLT_DeviceDataReference& device);
+ virtual NPT_Result ProcessActionResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response,
+ PLT_ActionReference& action,
+ void* userdata);
+ virtual NPT_Result ProcessSubscribeResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response,
+ PLT_Service* service,
+ void* userdata);
+ virtual NPT_Result ProcessHttpNotify(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+ // Device management
+ virtual NPT_Result AddDevice(PLT_DeviceDataReference& data);
+ virtual NPT_Result RemoveDevice(PLT_DeviceDataReference& data);
+
+private:
+ // methods
+ PLT_ThreadTask* RenewSubscriber(PLT_EventSubscriberReference subscriber);
+
+ NPT_Result AddPendingEventNotification(PLT_EventNotification *notification);
+ NPT_Result ProcessPendingEventNotifications();
+ NPT_Result ProcessEventNotification(PLT_EventSubscriberReference subscriber,
+ PLT_EventNotification* notification,
+ NPT_List<PLT_StateVariable*> &vars);
+
+ NPT_Result DoHouseKeeping();
+ NPT_Result FetchDeviceSCPDs(PLT_CtrlPointGetSCPDsTask* task,
+ PLT_DeviceDataReference& device,
+ NPT_Cardinal level);
+
+ // Device management
+ NPT_Result FindDevice(const char* uuid, PLT_DeviceDataReference& device, bool return_root = false);
+ NPT_Result NotifyDeviceReady(PLT_DeviceDataReference& data);
+ NPT_Result NotifyDeviceRemoved(PLT_DeviceDataReference& data);
+ NPT_Result CleanupDevice(PLT_DeviceDataReference& data);
+
+ NPT_Result ParseFault(PLT_ActionReference& action, NPT_XmlElementNode* fault);
+ PLT_SsdpSearchTask* CreateSearchTask(const NPT_HttpUrl& url,
+ const char* target,
+ NPT_Cardinal mx,
+ NPT_TimeInterval frequency,
+ const NPT_IpAddress& address);
+
+private:
+ friend class NPT_Reference<PLT_CtrlPoint>;
+ friend class PLT_UPnP;
+ friend class PLT_UPnP_CtrlPointStartIterator;
+ friend class PLT_UPnP_CtrlPointStopIterator;
+ friend class PLT_EventSubscriberRemoverIterator;
+ friend class PLT_CtrlPointGetDescriptionTask;
+ friend class PLT_CtrlPointGetSCPDsTask;
+ friend class PLT_CtrlPointInvokeActionTask;
+ friend class PLT_CtrlPointHouseKeepingTask;
+ friend class PLT_CtrlPointSubscribeEventTask;
+
+ NPT_List<NPT_String> m_UUIDsToIgnore;
+ PLT_CtrlPointListenerList m_ListenerList;
+ PLT_HttpServerReference m_EventHttpServer;
+ PLT_TaskManagerReference m_TaskManager;
+ NPT_Mutex m_Lock;
+ NPT_List<PLT_DeviceDataReference> m_RootDevices;
+ NPT_List<PLT_EventSubscriberReference> m_Subscribers;
+ NPT_String m_SearchCriteria;
+ bool m_Started;
+ NPT_List<PLT_EventNotification *> m_PendingNotifications;
+ NPT_List<NPT_String> m_PendingInspections;
+};
+
+typedef NPT_Reference<PLT_CtrlPoint> PLT_CtrlPointReference;
+
+#endif /* _PLT_CONTROL_POINT_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.cpp b/lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.cpp
new file mode 100644
index 0000000..7d2e5ba
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.cpp
@@ -0,0 +1,213 @@
+/*****************************************************************
+|
+| Platinum - Control Point Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDeviceHost.h"
+#include "PltCtrlPointTask.h"
+#include "PltCtrlPoint.h"
+#include "PltDatagramStream.h"
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetDescriptionTask::PLT_CtrlPointGetDescriptionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointGetDescriptionTask::PLT_CtrlPointGetDescriptionTask(const NPT_HttpUrl& url,
+ PLT_CtrlPoint* ctrl_point,
+ NPT_TimeInterval leasetime,
+ NPT_String uuid) :
+ PLT_HttpClientSocketTask(new NPT_HttpRequest(url, "GET", NPT_HTTP_PROTOCOL_1_1)),
+ m_CtrlPoint(ctrl_point),
+ m_LeaseTime(leasetime),
+ m_UUID(uuid)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetDescriptionTask::~PLT_CtrlPointGetDescriptionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointGetDescriptionTask::~PLT_CtrlPointGetDescriptionTask()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetDescriptionTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPointGetDescriptionTask::ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(request);
+ return m_CtrlPoint->ProcessGetDescriptionResponse(
+ res,
+ request,
+ context,
+ response,
+ m_LeaseTime,
+ m_UUID);
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetSCPDsTask::PLT_CtrlPointGetSCPDsTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointGetSCPDsTask::PLT_CtrlPointGetSCPDsTask(PLT_CtrlPoint* ctrl_point,
+ PLT_DeviceDataReference& root_device) :
+ PLT_HttpClientSocketTask(),
+ m_CtrlPoint(ctrl_point),
+ m_RootDevice(root_device)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetSCPDsTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPointGetSCPDsTask::ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(context);
+ return m_CtrlPoint->ProcessGetSCPDResponse(
+ res,
+ request,
+ context,
+ response,
+ ((PLT_CtrlPointGetSCPDRequest&)request).m_Device);
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointInvokeActionTask::PLT_CtrlPointInvokeActionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointInvokeActionTask::PLT_CtrlPointInvokeActionTask(NPT_HttpRequest* request,
+ PLT_CtrlPoint* ctrl_point,
+ PLT_ActionReference& action,
+ void* userdata) :
+ PLT_HttpClientSocketTask(request),
+ m_CtrlPoint(ctrl_point),
+ m_Action(action),
+ m_Userdata(userdata)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointInvokeActionTask::~PLT_CtrlPointInvokeActionTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointInvokeActionTask::~PLT_CtrlPointInvokeActionTask()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointInvokeActionTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPointInvokeActionTask::ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(request);
+ NPT_COMPILER_UNUSED(context);
+
+ return m_CtrlPoint->ProcessActionResponse(res, request, context, response, m_Action, m_Userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointHouseKeepingTask::PLT_CtrlPointHouseKeepingTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointHouseKeepingTask::PLT_CtrlPointHouseKeepingTask(PLT_CtrlPoint* ctrl_point,
+ NPT_TimeInterval timer) :
+ m_CtrlPoint(ctrl_point),
+ m_Timer(timer)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointHouseKeepingTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_CtrlPointHouseKeepingTask::DoRun()
+{
+ while (!IsAborting((NPT_Timeout)m_Timer.ToSeconds()*1000)) {
+ if (m_CtrlPoint) {
+ m_CtrlPoint->DoHouseKeeping();
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointSubscribeEventTask::PLT_CtrlPointSubscribeEventTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointSubscribeEventTask::PLT_CtrlPointSubscribeEventTask(NPT_HttpRequest* request,
+ PLT_CtrlPoint* ctrl_point,
+ PLT_DeviceDataReference &device,
+ PLT_Service* service,
+ void* userdata) :
+ PLT_HttpClientSocketTask(request),
+ m_CtrlPoint(ctrl_point),
+ m_Service(service),
+ m_Device(device),
+ m_Userdata(userdata)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointSubscribeEventTask::~PLT_CtrlPointSubscribeEventTask
++---------------------------------------------------------------------*/
+PLT_CtrlPointSubscribeEventTask::~PLT_CtrlPointSubscribeEventTask()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointSubscribeEventTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_CtrlPointSubscribeEventTask::ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(request);
+ NPT_COMPILER_UNUSED(context);
+
+ return m_CtrlPoint->ProcessSubscribeResponse(
+ res,
+ request,
+ context,
+ response,
+ m_Service,
+ m_Userdata);
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.h b/lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.h
new file mode 100644
index 0000000..15ac887
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltCtrlPointTask.h
@@ -0,0 +1,225 @@
+/*****************************************************************
+|
+| Platinum - Control Point Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP ControlPoint Tasks
+ */
+
+#ifndef _PLT_CONTROL_POINT_TASK_H_
+#define _PLT_CONTROL_POINT_TASK_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpClientTask.h"
+#include "PltDatagramStream.h"
+#include "PltDeviceData.h"
+#include "PltCtrlPoint.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_Action;
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetDescriptionTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPointGetDescriptionTask class fetches the description xml document
+ from a UPnP device
+ */
+class PLT_CtrlPointGetDescriptionTask : public PLT_HttpClientSocketTask
+{
+public:
+ PLT_CtrlPointGetDescriptionTask(const NPT_HttpUrl& url,
+ PLT_CtrlPoint* ctrl_point,
+ NPT_TimeInterval leasetime,
+ NPT_String uuid);
+ ~PLT_CtrlPointGetDescriptionTask() override;
+
+protected:
+ // PLT_HttpClientSocketTask methods
+ NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) override;
+
+protected:
+ PLT_CtrlPoint* m_CtrlPoint;
+ NPT_TimeInterval m_LeaseTime;
+ NPT_String m_UUID;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetSCPDRequest class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPointGetSCPDRequest class is used by a PLT_CtrlPointGetSCPDsTask task
+ to fetch a specific SCPD xml document for a given service of a given device.
+ */
+class PLT_CtrlPointGetSCPDRequest : public NPT_HttpRequest
+{
+public:
+ PLT_CtrlPointGetSCPDRequest(PLT_DeviceDataReference& device,
+ const char* url,
+ const char* method = "GET",
+ const char* protocol = NPT_HTTP_PROTOCOL_1_1) : // 1.1 for pipelining
+ NPT_HttpRequest(url, method, protocol), m_Device(device) {}
+ ~PLT_CtrlPointGetSCPDRequest() override {}
+
+ // members
+ PLT_DeviceDataReference m_Device;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetSCPDsTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPointGetSCPDsTask class fetches the SCPD xml document of one or more
+ services for a given device.
+ */
+class PLT_CtrlPointGetSCPDsTask : public PLT_HttpClientSocketTask
+{
+public:
+ PLT_CtrlPointGetSCPDsTask(PLT_CtrlPoint* ctrl_point, PLT_DeviceDataReference& root_device);
+ ~PLT_CtrlPointGetSCPDsTask() override {}
+
+ NPT_Result AddSCPDRequest(PLT_CtrlPointGetSCPDRequest* request) {
+ return PLT_HttpClientSocketTask::AddRequest((NPT_HttpRequest*)request);
+ }
+
+ // override to prevent calling this directly
+ NPT_Result AddRequest(NPT_HttpRequest*) override {
+ // only queuing PLT_CtrlPointGetSCPDRequest allowed
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+
+protected:
+ // PLT_HttpClientSocketTask methods
+ NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) override;
+
+protected:
+ PLT_CtrlPoint* m_CtrlPoint;
+ PLT_DeviceDataReference m_RootDevice;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointInvokeActionTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPointInvokeActionTask class is used by a PLT_CtrlPoint to invoke
+ a specific action of a given service for a given device.
+ */
+class PLT_CtrlPointInvokeActionTask : public PLT_HttpClientSocketTask
+{
+public:
+ PLT_CtrlPointInvokeActionTask(NPT_HttpRequest* request,
+ PLT_CtrlPoint* ctrl_point,
+ PLT_ActionReference& action,
+ void* userdata);
+ ~PLT_CtrlPointInvokeActionTask() override;
+
+protected:
+ // PLT_HttpClientSocketTask methods
+ NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) override;
+
+protected:
+ PLT_CtrlPoint* m_CtrlPoint;
+ PLT_ActionReference m_Action;
+ void* m_Userdata;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointHouseKeepingTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPointHouseKeepingTask class is used by a PLT_CtrlPoint to keep
+ track of expired devices and autmatically renew event subscribers.
+ */
+class PLT_CtrlPointHouseKeepingTask : public PLT_ThreadTask
+{
+public:
+ PLT_CtrlPointHouseKeepingTask(PLT_CtrlPoint* ctrl_point,
+ NPT_TimeInterval timer = NPT_TimeInterval(5.));
+
+protected:
+ ~PLT_CtrlPointHouseKeepingTask() override {}
+
+ // PLT_ThreadTask methods
+ void DoRun() override;
+
+protected:
+ PLT_CtrlPoint* m_CtrlPoint;
+ NPT_TimeInterval m_Timer;
+};
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointSubscribeEventTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_CtrlPointSubscribeEventTask class is used to subscribe, renew or cancel
+ a subscription for a given service of a given device.
+ */
+class PLT_CtrlPointSubscribeEventTask : public PLT_HttpClientSocketTask
+{
+public:
+ PLT_CtrlPointSubscribeEventTask(NPT_HttpRequest* request,
+ PLT_CtrlPoint* ctrl_point,
+ PLT_DeviceDataReference& device,
+ PLT_Service* service,
+ void* userdata = NULL);
+ ~PLT_CtrlPointSubscribeEventTask() override;
+
+protected:
+ // PLT_HttpClientSocketTask methods
+ NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) override;
+
+protected:
+ PLT_CtrlPoint* m_CtrlPoint;
+ PLT_Service* m_Service;
+ PLT_DeviceDataReference m_Device; // force to keep a reference to device owning m_Service
+ void* m_Userdata;
+};
+
+#endif /* _PLT_CONTROL_POINT_TASK_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDatagramStream.cpp b/lib/libUPnP/Platinum/Source/Core/PltDatagramStream.cpp
new file mode 100644
index 0000000..6138007
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltDatagramStream.cpp
@@ -0,0 +1,169 @@
+/*****************************************************************
+|
+| Platinum - Datagram Stream
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDatagramStream.h"
+#include "NptLogging.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.inputdatagramstream")
+
+/*----------------------------------------------------------------------
+| PLT_InputDatagramStream::PLT_InputDatagramStream
++---------------------------------------------------------------------*/
+PLT_InputDatagramStream::PLT_InputDatagramStream(NPT_UdpSocket* socket,
+ NPT_Size buffer_size) :
+ m_Socket(socket),
+ m_BufferOffset(0)
+{
+ m_Buffer.SetBufferSize(buffer_size);
+}
+
+/*----------------------------------------------------------------------
+| PLT_InputDatagramStream::~PLT_InputDatagramStream
++---------------------------------------------------------------------*/
+PLT_InputDatagramStream::~PLT_InputDatagramStream()
+{
+}
+
+/*----------------------------------------------------------------------
+| 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_OutputDatagramStream::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_InputDatagramStream::GetInfo(NPT_SocketInfo& info)
+{
+ info = m_Info;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_OutputDatagramStream::PLT_OutputDatagramStream
++---------------------------------------------------------------------*/
+PLT_OutputDatagramStream::PLT_OutputDatagramStream(NPT_UdpSocket* socket,
+ NPT_Size size,
+ const NPT_SocketAddress* address) :
+ m_Socket(socket),
+ m_Address(address?new NPT_SocketAddress(address->GetIpAddress(), address->GetPort()):NULL)
+{
+ m_Buffer.SetBufferSize(size);
+}
+
+/*----------------------------------------------------------------------
+| PLT_OutputDatagramStream::~PLT_OutputDatagramStream
++---------------------------------------------------------------------*/
+PLT_OutputDatagramStream::~PLT_OutputDatagramStream()
+{
+ delete m_Address;
+}
+
+/*----------------------------------------------------------------------
+| PLT_OutputDatagramStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_OutputDatagramStream::Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written /* = NULL */)
+{
+ // calculate if we need to increase the buffer
+ NPT_Int32 overflow = bytes_to_write - m_Buffer.GetBufferSize() + m_Buffer.GetDataSize();
+ if (overflow > 0) {
+ m_Buffer.Reserve(m_Buffer.GetBufferSize() + overflow);
+ }
+ // copy data in place at the end of what we have there already
+ NPT_CopyMemory(m_Buffer.UseData() + m_Buffer.GetDataSize(), buffer, bytes_to_write);
+ m_Buffer.SetDataSize(m_Buffer.GetDataSize() + bytes_to_write);
+
+ if (bytes_written) *bytes_written = bytes_to_write;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_OutputDatagramStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_OutputDatagramStream::Flush()
+{
+ // send buffer now
+ m_Socket->Send(m_Buffer, m_Address);
+
+ // reset buffer
+ m_Buffer.SetDataSize(0);
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDatagramStream.h b/lib/libUPnP/Platinum/Source/Core/PltDatagramStream.h
new file mode 100644
index 0000000..86ba105
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltDatagramStream.h
@@ -0,0 +1,117 @@
+/*****************************************************************
+|
+| Platinum - Datagram Stream
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ Datagram Input/Output Neptune streams
+ */
+
+#ifndef _PLT_DATAGRAM_H_
+#define _PLT_DATAGRAM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_InputDatagramStream
++---------------------------------------------------------------------*/
+/**
+ The PLT_InputDatagramStream class is a simple buffered input stream
+ used when reading SSDP packets on a UDP socket. It allows to use Neptune
+ HTTP parsing as if reading on a TCP socket.
+ */
+class PLT_InputDatagramStream : public NPT_InputStream
+{
+public:
+ // methods
+ PLT_InputDatagramStream(NPT_UdpSocket* socket,
+ NPT_Size buffer_size = 2000);
+ ~PLT_InputDatagramStream() override;
+
+ NPT_Result GetInfo(NPT_SocketInfo& info);
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = 0) override;
+
+ NPT_Result Seek(NPT_Position offset) override { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+ NPT_Result Skip(NPT_Size offset) override { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+ NPT_Result Tell(NPT_Position& offset) override{ NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+ NPT_Result GetSize(NPT_LargeSize& size) override { NPT_COMPILER_UNUSED(size); return NPT_FAILURE; }
+ NPT_Result GetAvailable(NPT_LargeSize& available) override { NPT_COMPILER_UNUSED(available); return NPT_FAILURE; }
+
+protected:
+ NPT_UdpSocket* m_Socket;
+ NPT_SocketInfo m_Info;
+ NPT_DataBuffer m_Buffer;
+ NPT_Position m_BufferOffset;
+};
+
+typedef NPT_Reference<PLT_InputDatagramStream> PLT_InputDatagramStreamReference;
+
+/*----------------------------------------------------------------------
+| PLT_OutputDatagramStream
++---------------------------------------------------------------------*/
+/**
+ The PLT_OutputDatagramStream class is a simple buffered output stream
+ used when writing SSDP packets on a UDP socket. It allows to use Neptune
+ HTTP client as if writing on a TCP socket.
+ */
+class PLT_OutputDatagramStream : public NPT_OutputStream
+{
+public:
+ // methods
+ PLT_OutputDatagramStream(NPT_UdpSocket* socket,
+ NPT_Size size = 4096,
+ const NPT_SocketAddress* address = NULL);
+ ~PLT_OutputDatagramStream() override;
+
+ // NPT_OutputStream methods
+ NPT_Result Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written = NULL) override;
+ NPT_Result Flush() override;
+
+ NPT_Result Seek(NPT_Position offset) override { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+ NPT_Result Tell(NPT_Position& offset) override { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+
+protected:
+ NPT_UdpSocket* m_Socket;
+ NPT_DataBuffer m_Buffer;
+ NPT_SocketAddress* m_Address;
+};
+
+typedef NPT_Reference<PLT_OutputDatagramStream> PLT_OutputDatagramStreamReference;
+
+#endif /* _PLT_DATAGRAM_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDeviceData.cpp b/lib/libUPnP/Platinum/Source/Core/PltDeviceData.cpp
new file mode 100644
index 0000000..a092b77
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltDeviceData.cpp
@@ -0,0 +1,830 @@
+/*****************************************************************
+|
+| Platinum - Device Data
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDeviceData.h"
+#include "PltService.h"
+#include "PltUPnP.h"
+#include "PltUtilities.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.devicedata")
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::PLT_DeviceData
++---------------------------------------------------------------------*/
+PLT_DeviceData::PLT_DeviceData(NPT_HttpUrl description_url,
+ const char* uuid,
+ NPT_TimeInterval lease_time,
+ const char* device_type,
+ const char* friendly_name) :
+ m_Manufacturer("Plutinosoft LLC"),
+ m_ManufacturerURL("http://www.plutinosoft.com"),
+ m_UUID(uuid),
+ m_URLDescription(description_url),
+ m_DeviceType(device_type),
+ m_FriendlyName(friendly_name),
+ m_BootId(0),
+ m_NextBootId(0)
+{
+ if (uuid == NULL || strlen(uuid) == 0) {
+ PLT_UPnPMessageHelper::GenerateGUID(m_UUID);
+ }
+
+ SetLeaseTime(lease_time);
+ SetURLBase(m_URLDescription);
+ UpdateConfigId();
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::~PLT_DeviceData
++---------------------------------------------------------------------*/
+PLT_DeviceData::~PLT_DeviceData()
+{
+ Cleanup();
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::Cleanup
++---------------------------------------------------------------------*/
+void
+PLT_DeviceData::Cleanup()
+{
+ m_Services.Apply(NPT_ObjectDeleter<PLT_Service>());
+ m_Services.Clear();
+ m_EmbeddedDevices.Clear();
+ m_Icons.Clear();
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::SetDescriptionUrl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetDescriptionUrl(NPT_HttpUrl& url)
+{
+ NPT_CHECK_FATAL(SetURLBase(url));
+ m_URLDescription = url;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::GetDescriptionUrl
++---------------------------------------------------------------------*/
+NPT_String
+PLT_DeviceData::GetDescriptionUrl(const char* ip_address)
+{
+ NPT_HttpUrl url = m_URLDescription;
+
+ // replace host with ip address specified
+ if (ip_address) url.SetHost(ip_address);
+ return url.ToString();
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::SetURLBase
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetURLBase(NPT_HttpUrl& url)
+{
+ // only http scheme supported
+ m_URLBase.SetScheme(url.GetScheme());
+
+ // update port if any
+ if (url.GetPort() != NPT_URL_INVALID_PORT) m_URLBase.SetPort(url.GetPort());
+
+ // update host if any
+ if (!url.GetHost().IsEmpty()) m_URLBase.SetHost(url.GetHost());
+
+ // update path
+ NPT_String path = url.GetPath();
+
+ // remove trailing file according to RFC 2396
+ if (!path.EndsWith("/")) {
+ int index = path.ReverseFind('/');
+ if (index < 0) return NPT_FAILURE;
+ path.SetLength(index+1);
+ }
+ m_URLBase.SetPath(path, true);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::GetURLBase
++---------------------------------------------------------------------*/
+NPT_HttpUrl
+PLT_DeviceData::GetURLBase()
+{
+ return m_URLBase;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::NormalizeURL
++---------------------------------------------------------------------*/
+NPT_HttpUrl
+PLT_DeviceData::NormalizeURL(const NPT_String& url)
+{
+ if (url.StartsWith("http://")) return NPT_HttpUrl(url);
+
+ NPT_HttpUrl norm_url = m_URLBase;
+ if (url.StartsWith("/")) {
+ norm_url.ParsePathPlus(url);
+ } else {
+ norm_url.ParsePathPlus(norm_url.GetPath() + url);
+ }
+
+ return norm_url;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::GetIconUrl
++---------------------------------------------------------------------*/
+NPT_String
+PLT_DeviceData::GetIconUrl(const char* mimetype,
+ NPT_Int32 maxsize,
+ NPT_Int32 maxdepth)
+{
+ PLT_DeviceIcon icon;
+
+ for (NPT_Cardinal i=0; i<m_Icons.GetItemCount(); i++) {
+ if ((mimetype && m_Icons[i].m_MimeType != mimetype) ||
+ (maxsize && m_Icons[i].m_Width > maxsize) ||
+ (maxsize && m_Icons[i].m_Height > maxsize) ||
+ (maxdepth && m_Icons[i].m_Depth > maxdepth))
+ continue;
+
+ // pick the biggest and better resolution we can
+ if (icon.m_Width >= m_Icons[i].m_Width ||
+ icon.m_Height >= m_Icons[i].m_Height ||
+ icon.m_Depth >= m_Icons[i].m_Depth ||
+ m_Icons[i].m_UrlPath.IsEmpty())
+ continue;
+
+ icon = m_Icons[i];
+ }
+
+ if (icon.m_UrlPath == "") return "";
+
+ return NormalizeURL(icon.m_UrlPath).ToString();
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::UpdateConfigId
++---------------------------------------------------------------------*/
+void
+PLT_DeviceData::UpdateConfigId()
+{
+ NPT_UInt32 nextConfigId = NPT_System::GetRandomInteger() & 0xFFFFFF;
+ if (m_ConfigId == nextConfigId) {
+ // prevent value to underflow
+ nextConfigId>0?--nextConfigId:++nextConfigId;
+ }
+
+ m_ConfigId = nextConfigId;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::SetBootId
++---------------------------------------------------------------------*/
+void
+PLT_DeviceData::SetBootId(NPT_UInt32 bootId)
+{
+ m_BootId = bootId;
+}
+
+/*----------------------------------------------------------------------
+ | PLT_DeviceData::SetNextBootId
+ +---------------------------------------------------------------------*/
+void
+PLT_DeviceData::SetNextBootId(NPT_UInt32 nextBootId)
+{
+ m_NextBootId = nextBootId;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::GenerateNextBootId
++---------------------------------------------------------------------*/
+NPT_UInt32
+PLT_DeviceData::GenerateNextBootId()
+{
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ NPT_UInt32 value = (NPT_UInt32)now.ToSeconds();
+ if (value == m_BootId) ++value;
+ return value;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::SetLeaseTime
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetLeaseTime(NPT_TimeInterval lease_time, NPT_TimeStamp lease_time_last_update /* = 0 */)
+{
+ // Enforce 10 seconds min lease time
+ m_LeaseTime = (lease_time.ToSeconds()>=10)?lease_time:*PLT_Constants::GetInstance().GetDefaultDeviceLease();
+
+ // get current time as last update time if none passed
+ if ((double)lease_time_last_update == 0.) {
+ NPT_System::GetCurrentTimeStamp(lease_time_last_update);
+ }
+ m_LeaseTimeLastUpdate = lease_time_last_update;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::GetLeaseTimeLastUpdate
++---------------------------------------------------------------------*/
+NPT_TimeStamp
+PLT_DeviceData::GetLeaseTimeLastUpdate()
+{
+ return m_LeaseTimeLastUpdate;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::operator const char*()
++---------------------------------------------------------------------*/
+PLT_DeviceData::operator const char*()
+{
+ NPT_StringOutputStreamReference stream(new NPT_StringOutputStream);
+ stream->WriteString("Device GUID: ");
+ stream->WriteString((const char*)m_UUID);
+
+ stream->WriteString("Device Type: ");
+ stream->WriteString((const char*)m_DeviceType);
+
+ stream->WriteString("Device Base Url: ");
+ stream->WriteString((const char*)GetURLBase().ToString());
+
+ stream->WriteString("Device Friendly Name: ");
+ stream->WriteString((const char*)m_FriendlyName);
+
+ m_Representation = stream->GetString();
+ return m_Representation;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::AddEmbeddedDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::AddEmbeddedDevice(PLT_DeviceDataReference& device)
+{
+ UpdateConfigId();
+
+ device->m_ParentUUID = m_UUID;
+ return m_EmbeddedDevices.Add(device);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::RemoveEmbeddedDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::RemoveEmbeddedDevice(PLT_DeviceDataReference& device)
+{
+ for (NPT_Cardinal i=0;
+ i<m_EmbeddedDevices.GetItemCount();
+ i++) {
+ if (m_EmbeddedDevices[i] == device) {
+ UpdateConfigId();
+ return m_EmbeddedDevices.Erase(i);
+ }
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::AddService
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::AddService(PLT_Service* service)
+{
+ if (service->GetServiceType() == "" ||
+ service->GetServiceID() == "" ||
+ service->GetSCPDURL() == "" ||
+ service->GetControlURL() == "" ||
+ service->GetEventSubURL() == "") {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ UpdateConfigId();
+ return m_Services.Add(service);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::RemoveService
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::RemoveService(PLT_Service* service)
+{
+ for (NPT_Cardinal i=0;
+ i<m_Services.GetItemCount();
+ i++) {
+ if (m_Services[i] == service) {
+ UpdateConfigId();
+ return m_Services.Erase(i);
+ }
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_GetDescriptionIterator class
++---------------------------------------------------------------------*/
+template <class T>
+class PLT_GetDescriptionIterator
+{
+public:
+ PLT_GetDescriptionIterator<T>(NPT_XmlElementNode* parent) :
+ m_Parent(parent) {}
+
+ NPT_Result operator()(T& data) const {
+ return data->GetDescription(m_Parent);
+ }
+
+private:
+ NPT_XmlElementNode* m_Parent;
+};
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::GetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::GetDescription(NPT_XmlElementNode* root, NPT_XmlElementNode** device_out)
+{
+ NPT_XmlElementNode* device = new NPT_XmlElementNode("device");
+ if (device_out) *device_out = device;
+
+ NPT_CHECK_SEVERE(root->AddChild(device));
+
+ // device properties
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "deviceType", m_DeviceType));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "friendlyName", m_FriendlyName));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "manufacturer", m_Manufacturer));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "manufacturerURL", m_ManufacturerURL));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelDescription", m_ModelDescription));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelName", m_ModelName));
+ if (!m_ModelNumber.IsEmpty()) NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelNumber", m_ModelNumber));
+ if (!m_SerialNumber.IsEmpty()) NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "serialNumber", m_SerialNumber));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelURL", m_ModelURL)); // moved after modelNumber to go around a bug in UCTT
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "UDN", "uuid:" + m_UUID));
+
+ if (!m_PresentationURL.IsEmpty()) {
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "presentationURL", m_PresentationURL));
+ }
+
+ // Extra info not in UPnP specs
+ NPT_CHECK(OnAddExtraInfo(device));
+
+ // DLNA support
+ if (!m_DlnaDoc.IsEmpty()) {
+ NPT_XmlElementNode* dlnadoc = new NPT_XmlElementNode("dlna", "X_DLNADOC");
+ NPT_CHECK_SEVERE(dlnadoc->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0"));
+ dlnadoc->AddText(m_DlnaDoc);
+ device->AddChild(dlnadoc);
+ }
+ if (!m_DlnaCap.IsEmpty()) {
+ NPT_XmlElementNode* dlnacap = new NPT_XmlElementNode("dlna", "X_DLNACAP");
+ NPT_CHECK_SEVERE(dlnacap->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0"));
+ dlnacap->AddText(m_DlnaCap);
+ device->AddChild(dlnacap);
+ }
+
+ // icons
+ if (m_Icons.GetItemCount()) {
+ NPT_XmlElementNode* icons = new NPT_XmlElementNode("iconList");
+ NPT_CHECK_SEVERE(device->AddChild(icons));
+ for (NPT_Cardinal i=0; i<m_Icons.GetItemCount(); i++) {
+ NPT_XmlElementNode* icon = new NPT_XmlElementNode("icon");
+ NPT_CHECK_SEVERE(icons->AddChild(icon));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "mimetype", m_Icons[i].m_MimeType));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "width", NPT_String::FromInteger(m_Icons[i].m_Width)));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "height", NPT_String::FromInteger(m_Icons[i].m_Height)));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "depth", NPT_String::FromInteger(m_Icons[i].m_Depth)));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "url", m_Icons[i].m_UrlPath));
+ }
+ }
+
+ // services
+ NPT_XmlElementNode* services = new NPT_XmlElementNode("serviceList");
+ NPT_CHECK_SEVERE(device->AddChild(services));
+ NPT_CHECK_SEVERE(m_Services.ApplyUntil(PLT_GetDescriptionIterator<PLT_Service*>(services),
+ NPT_UntilResultNotEquals(NPT_SUCCESS)));
+
+ // PS3 support
+ if (!m_AggregationFlags.IsEmpty()) {
+ NPT_XmlElementNode* aggr = new NPT_XmlElementNode("av", "aggregationFlags");
+ NPT_CHECK_SEVERE(aggr->SetNamespaceUri("av", "urn:schemas-sonycom:av"));
+ aggr->AddText(m_AggregationFlags);
+ device->AddChild(aggr);
+ }
+
+ // embedded devices
+ if (m_EmbeddedDevices.GetItemCount()) {
+ NPT_XmlElementNode* deviceList = new NPT_XmlElementNode("deviceList");
+ NPT_CHECK_SEVERE(device->AddChild(deviceList));
+
+ NPT_CHECK_SEVERE(m_EmbeddedDevices.ApplyUntil(
+ PLT_GetDescriptionIterator<PLT_DeviceDataReference>(deviceList),
+ NPT_UntilResultNotEquals(NPT_SUCCESS)));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::GetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::GetDescription(NPT_String& desc)
+{
+ NPT_Result res;
+ NPT_XmlElementNode* spec = NULL;
+ NPT_XmlElementNode* root = new NPT_XmlElementNode("root");
+
+ NPT_CHECK_LABEL_SEVERE(res = root->SetNamespaceUri("", "urn:schemas-upnp-org:device-1-0"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = root->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = root->SetAttribute("", "configId", NPT_String::FromInteger(m_ConfigId)), cleanup);
+
+ // add spec version
+ spec = new NPT_XmlElementNode("specVersion");
+ NPT_CHECK_LABEL_SEVERE(res = root->AddChild(spec), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "major", "1"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "minor", "1"), cleanup);
+
+ // get device xml
+ NPT_CHECK_LABEL_SEVERE(res = GetDescription(root), cleanup);
+
+ // serialize node
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*root, desc, true, 2), cleanup);
+
+cleanup:
+ delete root;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::SetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetDescription(PLT_DeviceDataReference& root_device,
+ NPT_TimeInterval leasetime,
+ NPT_HttpUrl description_url,
+ const char* description,
+ const NPT_HttpRequestContext& context)
+{
+ NPT_XmlParser parser;
+ NPT_XmlNode* tree = NULL;
+ NPT_Result res;
+ NPT_XmlElementNode* root = NULL;
+ NPT_String URLBase;
+ NPT_String configId;
+
+ // create new device if none passed
+ if (root_device.IsNull()) {
+ root_device = new PLT_DeviceData(description_url, "", leasetime);
+ }
+
+ res = parser.Parse(description, tree);
+ NPT_CHECK_LABEL_SEVERE(res, cleanup);
+
+ root = tree->AsElementNode();
+ if (!root ||
+ root->GetTag() != "root" ||
+ !root->GetNamespace() ||
+ *root->GetNamespace() != "urn:schemas-upnp-org:device-1-0") {
+ NPT_LOG_INFO_1("root namespace is invalid: %s",
+ (root&&root->GetNamespace())?root->GetNamespace()->GetChars():"null");
+ NPT_CHECK_LABEL_SEVERE(NPT_FAILURE, cleanup);
+ }
+
+ // look for optional URLBase element
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(root, "URLBase", URLBase))) {
+ NPT_HttpUrl url(URLBase);
+ // Some devices like Connect360 try to be funny - not so
+ if (url.GetHost().ToLowercase() == "localhost" ||
+ url.GetHost().ToLowercase() == "127.0.0.1") {
+ url.SetHost(context.GetRemoteAddress().GetIpAddress().ToString());
+ }
+ root_device->SetURLBase(url);
+ } else {
+ // No URLBase, derive from description url
+ root_device->SetURLBase(description_url);
+ }
+
+ // at least one root device child element is required
+ NPT_XmlElementNode* device;
+ if (!(device = PLT_XmlHelper::GetChild(root, "device"))) {
+ NPT_CHECK_LABEL_SEVERE(NPT_FAILURE, cleanup);
+ }
+
+ res = SetDescriptionDevice(root_device, device, context);
+
+ // reset configId if and set it back from root attribute
+ root_device->m_ConfigId = 0;
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(root, "configId", configId))) {
+ NPT_UInt32 value;
+ if (NPT_SUCCEEDED(configId.ToInteger32(value))) {
+ root_device->m_ConfigId = value;
+ }
+ }
+
+cleanup:
+ // delete the tree
+ delete tree;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::SetDescriptionDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::SetDescriptionDevice(PLT_DeviceDataReference& device,
+ NPT_XmlElementNode* device_node,
+ const NPT_HttpRequestContext& context)
+{
+ NPT_Result res;
+
+ device->m_LocalIfaceIp = context.GetLocalAddress().GetIpAddress();
+
+ NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node, "deviceType", device->m_DeviceType));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node, "UDN", device->m_UUID));
+
+ // remove uuid: prefix
+ if (device->m_UUID.StartsWith("uuid:")) {
+ device->m_UUID = ((const char*)device->m_UUID)+5;
+ }
+
+ // optional attributes
+ PLT_XmlHelper::GetChildText(device_node, "friendlyName", device->m_FriendlyName);
+ PLT_XmlHelper::GetChildText(device_node, "manufacturer", device->m_Manufacturer);
+ PLT_XmlHelper::GetChildText(device_node, "manufacturerURL", device->m_ManufacturerURL);
+ PLT_XmlHelper::GetChildText(device_node, "modelDescription", device->m_ModelDescription);
+ PLT_XmlHelper::GetChildText(device_node, "modelName", device->m_ModelName);
+ PLT_XmlHelper::GetChildText(device_node, "modelURL", device->m_ModelURL);
+ PLT_XmlHelper::GetChildText(device_node, "modelNumber", device->m_ModelNumber);
+ PLT_XmlHelper::GetChildText(device_node, "serialNumber", device->m_SerialNumber);
+ PLT_XmlHelper::GetChildText(device_node, "presentationURL", device->m_PresentationURL);
+
+ // enumerate icons
+ NPT_XmlElementNode* iconList = PLT_XmlHelper::GetChild(device_node, "iconList");
+ if (iconList) {
+ NPT_Array<NPT_XmlElementNode*> icons;
+ PLT_XmlHelper::GetChildren(iconList, icons, "icon");
+
+ for (NPT_Cardinal k=0 ; k<icons.GetItemCount(); k++) {
+ PLT_DeviceIcon icon;
+ NPT_String integer, height, depth;
+
+ PLT_XmlHelper::GetChildText(icons[k], "mimetype", icon.m_MimeType);
+ PLT_XmlHelper::GetChildText(icons[k], "url", icon.m_UrlPath);
+
+ if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "width", integer)))
+ NPT_ParseInteger32(integer, icon.m_Width);
+ if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "height", integer)))
+ NPT_ParseInteger32(integer, icon.m_Height);
+ if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "depth", integer)))
+ NPT_ParseInteger32(integer, icon.m_Depth);
+
+ device->m_Icons.Add(icon);
+ }
+ }
+
+ // enumerate device services
+ NPT_XmlElementNode* serviceList = PLT_XmlHelper::GetChild(device_node, "serviceList");
+ if (serviceList) {
+ NPT_Array<NPT_XmlElementNode*> services;
+ PLT_XmlHelper::GetChildren(serviceList, services, "service");
+ for( int k = 0 ; k < (int)services.GetItemCount(); k++) {
+ NPT_String type, id, url;
+ PLT_XmlHelper::GetChildText(services[k], "serviceType", type);
+ PLT_XmlHelper::GetChildText(services[k], "serviceId", id);
+ PLT_Service* service = new PLT_Service(device.AsPointer(), type, id, NULL);
+
+ PLT_XmlHelper::GetChildText(services[k], "SCPDURL", url);
+ service->SetSCPDURL(url);
+
+ PLT_XmlHelper::GetChildText(services[k], "controlURL", url);
+ service->SetControlURL(url);
+
+ PLT_XmlHelper::GetChildText(services[k], "eventSubURL", url);
+ service->SetEventSubURL(url);
+
+ if (NPT_FAILED(res = device->AddService(service))) {
+ delete service;
+ return res;
+ }
+ }
+ }
+
+ // enumerate embedded devices
+ NPT_XmlElementNode* deviceList = PLT_XmlHelper::GetChild(device_node, "deviceList");
+ if (deviceList) {
+ NPT_Array<NPT_XmlElementNode*> devices;
+ PLT_XmlHelper::GetChildren(deviceList, devices, "device");
+ for (int k = 0; k<(int)devices.GetItemCount(); k++) {
+ // create an embedded device with same url base and leasetime as parent
+ PLT_DeviceDataReference embedded_device(new PLT_DeviceData(device->m_URLDescription, "", device->m_LeaseTime));
+ NPT_CHECK_SEVERE(PLT_DeviceData::SetDescriptionDevice(embedded_device, devices[k], context));
+ device->AddEmbeddedDevice(embedded_device);
+ }
+ }
+
+ // TODO: Parse extra DLNA stuff
+
+ return NPT_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindEmbeddedDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindEmbeddedDevice(const char* uuid,
+ PLT_DeviceDataReference& device)
+{
+ NPT_Result res = NPT_ContainerFind(m_EmbeddedDevices,
+ PLT_DeviceDataFinder(uuid),
+ device);
+ if (NPT_SUCCEEDED(res)) return res;
+
+ for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
+ res = m_EmbeddedDevices[i]->FindEmbeddedDevice(
+ uuid,
+ device);
+ if (NPT_SUCCEEDED(res)) return res;
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindEmbeddedDeviceByType
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindEmbeddedDeviceByType(const char* type,
+ PLT_DeviceDataReference& device)
+{
+ NPT_Result res = NPT_ContainerFind(m_EmbeddedDevices,
+ PLT_DeviceDataFinderByType(type),
+ device);
+ if (NPT_SUCCEEDED(res)) return res;
+
+ for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
+ res = m_EmbeddedDevices[i]->FindEmbeddedDeviceByType(
+ type,
+ device);
+ if (NPT_SUCCEEDED(res)) return res;
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindServiceById
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceById(const char* id, PLT_Service*& service)
+{
+ // do not try to find it within embedded devices, since different
+ // embedded devices could have an identical service
+ return NPT_ContainerFind(m_Services,
+ PLT_ServiceIDFinder(id),
+ service);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindServiceByType
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByType(const char* type, PLT_Service*& service)
+{
+ // do not try to find it within embedded devices, since different
+ // embedded devices could have an identical service
+ return NPT_ContainerFind(m_Services,
+ PLT_ServiceTypeFinder(type),
+ service);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindServiceByName
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByName(const char* name, PLT_Service*& service)
+{
+ // do not try to find it within embedded devices, since different
+ // embedded devices could have an identical service
+ return NPT_ContainerFind(m_Services,
+ PLT_ServiceNameFinder(name),
+ service);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindServiceBySCPDURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceBySCPDURL(const char* url,
+ PLT_Service*& service,
+ bool recursive /* = false */)
+{
+ NPT_Result res = NPT_ContainerFind(
+ m_Services,
+ PLT_ServiceSCPDURLFinder(url),
+ service);
+ if (NPT_SUCCEEDED(res)) return res;
+
+ if (recursive) {
+ for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
+ res = m_EmbeddedDevices[i]->FindServiceBySCPDURL(
+ url,
+ service,
+ recursive);
+ if (NPT_SUCCEEDED(res)) return res;
+ }
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindServiceByControlURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByControlURL(const char* url,
+ PLT_Service*& service,
+ bool recursive /* = false */)
+{
+ NPT_Result res = NPT_ContainerFind(m_Services,
+ PLT_ServiceControlURLFinder(url),
+ service);
+ if (NPT_SUCCEEDED(res)) return res;
+
+ if (recursive) {
+ for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
+ res = m_EmbeddedDevices[i]->FindServiceByControlURL(
+ url,
+ service,
+ recursive);
+ if (NPT_SUCCEEDED(res)) return res;
+ }
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData::FindServiceByEventSubURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceData::FindServiceByEventSubURL(const char* url,
+ PLT_Service*& service,
+ bool recursive /* = false */)
+{
+ NPT_Result res = NPT_ContainerFind(m_Services,
+ PLT_ServiceEventSubURLFinder(url),
+ service);
+ if (NPT_SUCCEEDED(res)) return res;
+
+ if (recursive) {
+ for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
+ res = m_EmbeddedDevices[i]->FindServiceByEventSubURL(
+ url,
+ service,
+ recursive);
+ if (NPT_SUCCEEDED(res)) return res;
+ }
+ }
+
+ return NPT_FAILURE;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDeviceData.h b/lib/libUPnP/Platinum/Source/Core/PltDeviceData.h
new file mode 100644
index 0000000..364ede7
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltDeviceData.h
@@ -0,0 +1,260 @@
+/*****************************************************************
+|
+| Platinum - Device Data
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Device information
+ */
+
+#ifndef _PLT_DEVICE_DATA_H_
+#define _PLT_DEVICE_DATA_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltConstants.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_Service;
+class PLT_DeviceData;
+
+typedef NPT_Reference<PLT_DeviceData> PLT_DeviceDataReference;
+typedef NPT_List<PLT_DeviceDataReference> PLT_DeviceDataReferenceList;
+
+/*----------------------------------------------------------------------
+| PLT_DeviceIcon class
++---------------------------------------------------------------------*/
+/**
+ The PLT_DeviceIcon class represents a given instance of a UPnP device icon.
+ */
+class PLT_DeviceIcon
+{
+public:
+ PLT_DeviceIcon(const char* mimetype = "",
+ NPT_Int32 width = 0,
+ NPT_Int32 height = 0,
+ NPT_Int32 depth = 0,
+ const char* urlpath = "") :
+ m_MimeType(mimetype),
+ m_Width(width),
+ m_Height(height),
+ m_Depth(depth),
+ m_UrlPath(urlpath) {}
+ virtual ~PLT_DeviceIcon() {}
+
+ NPT_String m_MimeType;
+ NPT_Int32 m_Width;
+ NPT_Int32 m_Height;
+ NPT_Int32 m_Depth;
+ NPT_String m_UrlPath;
+};
+
+/*----------------------------------------------------------------------
+| PLT_DeviceData class
++---------------------------------------------------------------------*/
+/**
+ The PLT_DeviceData class holds information about a device being advertised or
+ found by a control point. It maintains a list of services and
+ embedded devices if any.
+ */
+class PLT_DeviceData
+{
+public:
+ PLT_DeviceData(
+ NPT_HttpUrl description_url = NPT_HttpUrl(NULL, 0, "/description.xml"),
+ const char* uuid = "",
+ NPT_TimeInterval lease_time = *PLT_Constants::GetInstance().GetDefaultDeviceLease(),
+ const char* device_type = "",
+ const char* friendly_name = "");
+
+ /* methods */
+ virtual NPT_Result GetDescription(NPT_String& desc);
+ virtual NPT_String GetDescriptionUrl(const char* ip_address = NULL);
+ virtual NPT_HttpUrl GetURLBase();
+ virtual NPT_HttpUrl NormalizeURL(const NPT_String& url);
+ virtual NPT_Result GetDescription(NPT_XmlElementNode* parent, NPT_XmlElementNode** device = NULL);
+ virtual NPT_String GetIconUrl(const char* mimetype = NULL, NPT_Int32 maxsize = 0, NPT_Int32 maxdepth = 0);
+
+ bool IsRoot() { return m_ParentUUID.IsEmpty(); }
+ const NPT_TimeInterval& GetLeaseTime() const { return m_LeaseTime; }
+ const NPT_String& GetUUID() const { return m_UUID; }
+ const NPT_String& GetFriendlyName() const { return m_FriendlyName; }
+ const NPT_String& GetType() const { return m_DeviceType; }
+ const NPT_String& GetModelDescription() const { return m_ModelDescription; }
+ const NPT_String& GetParentUUID() const { return m_ParentUUID; }
+ const NPT_IpAddress& GetLocalIP() const { return m_LocalIfaceIp; }
+
+ const NPT_Array<PLT_Service*>& GetServices() const { return m_Services; }
+ const NPT_Array<PLT_DeviceDataReference>& GetEmbeddedDevices() const { return m_EmbeddedDevices; }
+
+ NPT_Result FindEmbeddedDevice(const char* uuid, PLT_DeviceDataReference& device);
+ NPT_Result FindEmbeddedDeviceByType(const char* type, PLT_DeviceDataReference& device);
+ NPT_Result FindServiceById(const char* id, PLT_Service*& service);
+ NPT_Result FindServiceByType(const char* type, PLT_Service*& service);
+ NPT_Result FindServiceByName(const char* name, PLT_Service*& service);
+ NPT_Result FindServiceBySCPDURL(const char* url, PLT_Service*& service, bool recursive = false);
+ NPT_Result FindServiceByControlURL(const char* url, PLT_Service*& service, bool recursive = false);
+ NPT_Result FindServiceByEventSubURL(const char* url, PLT_Service*& service, bool recursive = false);
+
+ /* called by PLT_Device subclasses */
+ NPT_Result AddEmbeddedDevice(PLT_DeviceDataReference& device);
+ NPT_Result RemoveEmbeddedDevice(PLT_DeviceDataReference& device);
+ NPT_Result AddService(PLT_Service* service);
+ NPT_Result RemoveService(PLT_Service* service);
+
+ /* BOOTID UPnP 1/1 */
+ void SetBootId(NPT_UInt32 bootId);
+ void SetNextBootId(NPT_UInt32 nextBootId);
+ NPT_UInt32 GenerateNextBootId();
+
+ operator const char* ();
+
+protected:
+ virtual ~PLT_DeviceData();
+
+ virtual void Cleanup();
+ virtual NPT_Result OnAddExtraInfo(NPT_XmlElementNode* /*device_node*/) { return NPT_SUCCESS; }
+
+
+private:
+ /* called by PLT_CtrlPoint when an existing device location is updated */
+ NPT_Result SetDescriptionUrl(NPT_HttpUrl& url);
+ NPT_Result SetLeaseTime(NPT_TimeInterval lease_time, NPT_TimeStamp lease_time_last_update = 0.);
+ NPT_Result SetURLBase(NPT_HttpUrl& url_base);
+ NPT_TimeStamp GetLeaseTimeLastUpdate();
+ void UpdateConfigId();
+
+ /* class methods */
+ static NPT_Result SetDescription(PLT_DeviceDataReference& root_device,
+ NPT_TimeInterval leasetime,
+ NPT_HttpUrl description_url,
+ const char* description,
+ const NPT_HttpRequestContext& context);
+ static NPT_Result SetDescriptionDevice(PLT_DeviceDataReference& device,
+ NPT_XmlElementNode* device_node,
+ const NPT_HttpRequestContext& context);
+
+public:
+ NPT_String m_Manufacturer;
+ NPT_String m_ManufacturerURL;
+ NPT_String m_ModelDescription;
+ NPT_String m_ModelName;
+ NPT_String m_ModelNumber;
+ NPT_String m_ModelURL;
+ NPT_String m_SerialNumber;
+ NPT_String m_UPC;
+ NPT_String m_PresentationURL;
+ NPT_String m_DlnaDoc;
+ NPT_String m_DlnaCap;
+ NPT_String m_AggregationFlags;
+
+protected:
+ friend class NPT_Reference<PLT_DeviceData>;
+ friend class PLT_CtrlPoint;
+ friend class PLT_DeviceReadyIterator;
+ friend class PLT_DeviceHost;
+
+ //members
+ NPT_String m_ParentUUID;
+ NPT_String m_UUID;
+ NPT_HttpUrl m_URLDescription;
+ NPT_HttpUrl m_URLBase;
+ NPT_String m_DeviceType;
+ NPT_String m_FriendlyName;
+ NPT_TimeInterval m_LeaseTime;
+ NPT_TimeStamp m_LeaseTimeLastUpdate;
+ NPT_Array<PLT_Service*> m_Services;
+ NPT_Array<PLT_DeviceDataReference> m_EmbeddedDevices;
+ NPT_Array<PLT_DeviceIcon> m_Icons;
+
+ /* IP address of interface used when retrieving device description.
+ We need the info for the control point subscription callback */
+ NPT_IpAddress m_LocalIfaceIp;
+ NPT_String m_Representation;
+
+private:
+ NPT_UInt32 m_BootId;
+ NPT_UInt32 m_NextBootId;
+ NPT_UInt32 m_ConfigId;
+};
+
+/*----------------------------------------------------------------------
+| PLT_DeviceDataFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_DeviceDataFinder class returns a PLT_DeviceData instance given
+ a device UUID.
+ */
+class PLT_DeviceDataFinder
+{
+public:
+ // methods
+ PLT_DeviceDataFinder(const char* uuid) : m_UUID(uuid) {}
+ virtual ~PLT_DeviceDataFinder() {}
+
+ bool operator()(const PLT_DeviceDataReference& data) const {
+ return data->GetUUID().Compare(m_UUID, true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_UUID;
+};
+
+/*----------------------------------------------------------------------
+| PLT_DeviceDataFinderByType
++---------------------------------------------------------------------*/
+/**
+ The PLT_DeviceDataFinderByType class returns a PLT_DeviceData instance
+ given a device type.
+ */
+class PLT_DeviceDataFinderByType
+{
+public:
+ // methods
+ PLT_DeviceDataFinderByType(const char* type) : m_Type(type) {}
+ virtual ~PLT_DeviceDataFinderByType() {}
+
+ bool operator()(const PLT_DeviceDataReference& data) const {
+ return data->GetType().Compare(m_Type, true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_Type;
+};
+
+#endif /* _PLT_DEVICE_DATA_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
new file mode 100644
index 0000000..6f5f09f
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.cpp
@@ -0,0 +1,953 @@
+/*****************************************************************
+|
+| Platinum - Device Host
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltService.h"
+#include "PltDeviceHost.h"
+#include "PltUPnP.h"
+#include "PltUtilities.h"
+#include "PltSsdp.h"
+#include "PltHttpServer.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.devicehost")
+
+/*----------------------------------------------------------------------
+| externals
++---------------------------------------------------------------------*/
+extern NPT_UInt8 Platinum_120x120_jpg[16096];
+extern NPT_UInt8 Platinum_120x120_png[26577];
+extern NPT_UInt8 Platinum_48x48_jpg[3041];
+extern NPT_UInt8 Platinum_48x48_png[4681];
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::PLT_DeviceHost
++---------------------------------------------------------------------*/
+PLT_DeviceHost::PLT_DeviceHost(const char* description_path /* = "/" */,
+ const char* uuid /* = "" */,
+ const char* device_type /* = "" */,
+ const char* friendly_name /* = "" */,
+ bool show_ip /* = false */,
+ NPT_UInt16 port /* = 0 */,
+ bool port_rebind /* = false */) :
+ PLT_DeviceData(NPT_HttpUrl(NULL, 0, description_path),
+ uuid,
+ *PLT_Constants::GetInstance().GetDefaultDeviceLease(),
+ device_type,
+ friendly_name),
+ m_TaskManager(NULL),
+ m_HttpServer(NULL),
+ m_ExtraBroascast(false),
+ m_Port(port),
+ m_PortRebind(port_rebind),
+ m_ByeByeFirst(true),
+ m_Started(false)
+{
+ if (show_ip) {
+ NPT_List<NPT_IpAddress> ips;
+ PLT_UPnPMessageHelper::GetIPAddresses(ips);
+ if (ips.GetItemCount()) {
+ m_FriendlyName += " (" + ips.GetFirstItem()->ToString() + ")";
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::~PLT_DeviceHost
++---------------------------------------------------------------------*/
+PLT_DeviceHost::~PLT_DeviceHost()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::AddIcon
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::AddIcon(const PLT_DeviceIcon& icon,
+ const char* fileroot,
+ const char* urlroot /* = "/" */)
+{
+ // verify the url of the icon starts with the url root
+ if (!icon.m_UrlPath.StartsWith(urlroot)) return NPT_ERROR_INVALID_PARAMETERS;
+
+ NPT_HttpFileRequestHandler* icon_handler = new NPT_HttpFileRequestHandler(urlroot, fileroot);
+ m_HttpServer->AddRequestHandler(icon_handler, icon.m_UrlPath, false, true);
+ return m_Icons.Add(icon);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::AddIcon
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::AddIcon(const PLT_DeviceIcon& icon,
+ const void* data,
+ NPT_Size size,
+ bool copy /* = true */)
+{
+ NPT_HttpStaticRequestHandler* icon_handler =
+ new NPT_HttpStaticRequestHandler(
+ data,
+ size,
+ icon.m_MimeType,
+ copy);
+ m_HttpServer->AddRequestHandler(icon_handler, icon.m_UrlPath, false, true);
+ return m_Icons.Add(icon);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::SetupIcons
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SetupIcons()
+{
+ /*if (m_Icons.GetItemCount() == 0) {
+ AddIcon(
+ PLT_DeviceIcon("image/jpeg", 120, 120, 24, "/images/platinum-120x120.jpg"),
+ Platinum_120x120_jpg, sizeof(Platinum_120x120_jpg), false);
+ AddIcon(
+ PLT_DeviceIcon("image/jpeg", 48, 48, 24, "/images/platinum-48x48.jpg"),
+ Platinum_48x48_jpg, sizeof(Platinum_48x48_jpg), false);
+ AddIcon(
+ PLT_DeviceIcon("image/png", 120, 120, 24, "/images/platinum-120x120.png"),
+ Platinum_120x120_png, sizeof(Platinum_120x120_png), false);
+ AddIcon(
+ PLT_DeviceIcon("image/png", 48, 48, 24, "/images/platinum-48x48.png"),
+ Platinum_48x48_png, sizeof(Platinum_48x48_png), false);
+ }*/
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::SetupDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SetupDevice()
+{
+ NPT_CHECK_FATAL(SetupServices());
+ NPT_CHECK_WARNING(SetupIcons());
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::Start(PLT_SsdpListenTask* task)
+{
+ NPT_Result result;
+
+ if (m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ // setup
+ m_TaskManager = new PLT_TaskManager();
+ m_HttpServer = new PLT_HttpServer(NPT_IpAddress::Any, m_Port, m_PortRebind, 100); // limit to 100 clients max
+ if (NPT_FAILED(result = m_HttpServer->Start())) {
+ m_TaskManager = NULL;
+ m_HttpServer = NULL;
+ NPT_CHECK_FATAL(result);
+ }
+
+ // read back assigned port in case we passed 0 to randomly select one
+ m_Port = m_HttpServer->GetPort();
+ m_URLDescription.SetPort(m_Port);
+
+ // callback to initialize the device
+ if (NPT_FAILED(result = SetupDevice())) {
+ m_TaskManager = NULL;
+ m_HttpServer = NULL;
+ NPT_CHECK_FATAL(result);
+ }
+
+ // all other requests including description document
+ // and service control are dynamically handled
+ m_HttpServer->AddRequestHandler(new PLT_HttpRequestHandler(this), "/", true, true);
+
+ // we should not advertise right away
+ // spec says randomly less than 100ms
+ NPT_TimeInterval delay(((NPT_Int64)NPT_System::GetRandomInteger()%100)*1000000);
+
+ // calculate when we should send another announcement
+ // we announce a bit before half way through leasetime to make sure
+ // clients don't expire us.
+ NPT_Size leaseTime = (NPT_Size)GetLeaseTime().ToSeconds();
+ NPT_TimeInterval repeat;
+ repeat.SetSeconds(leaseTime?(int)((leaseTime >> 1) - 10):30);
+
+ PLT_ThreadTask* announce_task = new PLT_SsdpDeviceAnnounceTask(
+ this,
+ repeat,
+ m_ByeByeFirst,
+ m_ExtraBroascast);
+ m_TaskManager->StartTask(announce_task, &delay);
+
+ // register ourselves as a listener for SSDP search requests
+ task->AddListener(this);
+
+ m_Started = true;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::Stop(PLT_SsdpListenTask* task)
+{
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ // mark immediately we're stopping
+ m_Started = false;
+
+ // unregister ourselves as a listener for ssdp requests
+ task->RemoveListener(this);
+
+ // remove all our running tasks
+ m_TaskManager->Abort();
+
+ // stop our internal http server
+ m_HttpServer->Stop();
+
+ // announce we're leaving
+ NPT_List<NPT_NetworkInterface*> if_list;
+ PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list, true);
+ if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(this, PLT_ANNOUNCETYPE_BYEBYE, m_ExtraBroascast));
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+
+ // Cleanup all services and embedded devices
+ PLT_DeviceData::Cleanup();
+
+ m_HttpServer = NULL;
+ m_TaskManager = NULL;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::Announce
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::Announce(PLT_DeviceData* device,
+ NPT_HttpRequest& req,
+ NPT_UdpSocket& socket,
+ PLT_SsdpAnnounceType type)
+{
+ NPT_Result res = NPT_SUCCESS;
+
+ // target address
+ NPT_IpAddress ip;
+ NPT_CHECK_FATAL(ip.ResolveName(req.GetUrl().GetHost()));
+ NPT_SocketAddress addr(ip, req.GetUrl().GetPort());
+
+// // UPnP 1.1 BOOTID.UPNP.ORG header
+// PLT_UPnPMessageHelper::SetBootId(req, device->m_BootId);
+//
+// // UPnP 1.1 CONFIGID.UPNP.ORG header
+// if (device->m_ConfigId > 0) {
+// PLT_UPnPMessageHelper::SetConfigId(req, device->m_ConfigId);
+// }
+
+ // NTS header
+ NPT_String nts;
+ switch (type) {
+ case PLT_ANNOUNCETYPE_ALIVE:
+ nts = "ssdp:alive";
+ PLT_UPnPMessageHelper::SetLeaseTime(req, device->GetLeaseTime());
+ PLT_UPnPMessageHelper::SetServer(req, PLT_HTTP_DEFAULT_SERVER, false);
+ break;
+
+ case PLT_ANNOUNCETYPE_BYEBYE:
+ nts = "ssdp:byebye";
+ break;
+
+ case PLT_ANNOUNCETYPE_UPDATE:
+ nts = "ssdp:update";
+ // update requires valid UPNP 1.1 NEXTBOOTID.UPNP.ORG Header
+ if (device->m_NextBootId == 0) {
+ NPT_CHECK_FATAL(NPT_ERROR_INTERNAL);
+ }
+ PLT_UPnPMessageHelper::SetNextBootId(req, device->m_NextBootId);
+ break;
+
+ default:
+ break;
+ }
+ PLT_UPnPMessageHelper::SetNTS(req, nts);
+
+ NPT_LOG_FINER_3("Sending SSDP NOTIFY (%s) Request to %s (%s)", nts.GetChars(),
+ (const char*)req.GetUrl().ToString(),
+ (const char*)(PLT_UPnPMessageHelper::GetLocation(req)
+ ? PLT_UPnPMessageHelper::GetLocation(req)->GetChars()
+ : ""));
+
+ // upnp:rootdevice
+ if (device->m_ParentUUID.IsEmpty()) {
+ PLT_SsdpSender::SendSsdp(req,
+ NPT_String("uuid:" + device->m_UUID + "::upnp:rootdevice"),
+ "upnp:rootdevice",
+ socket,
+ true,
+ &addr);
+ }
+
+ // on byebye, don't sleep otherwise it hangs when we stop upnp
+ if (type != PLT_ANNOUNCETYPE_BYEBYE) {
+ NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY));
+ }
+
+ // uuid:device-UUID
+ PLT_SsdpSender::SendSsdp(req,
+ "uuid:" + device->m_UUID,
+ "uuid:" + device->m_UUID,
+ socket,
+ true,
+ &addr);
+
+ // on byebye, don't sleep otherwise it hangs when we stop upnp
+ if (type != PLT_ANNOUNCETYPE_BYEBYE) {
+ NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY));
+ }
+
+ // uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:ver
+ PLT_SsdpSender::SendSsdp(req,
+ NPT_String("uuid:" + device->m_UUID + "::" + device->m_DeviceType),
+ device->m_DeviceType,
+ socket,
+ true,
+ &addr);
+
+ // on byebye, don't sleep otherwise it hangs when we stop upnp
+ if (type != PLT_ANNOUNCETYPE_BYEBYE) {
+ NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY));
+ }
+
+ // services
+ for (int i=0; i < (int)device->m_Services.GetItemCount(); i++) {
+ // uuid:device-UUID::urn:schemas-upnp-org:service:serviceType:ver
+ PLT_SsdpSender::SendSsdp(req,
+ NPT_String("uuid:" + device->m_UUID + "::" + device->m_Services[i]->GetServiceType()),
+ device->m_Services[i]->GetServiceType(),
+ socket,
+ true,
+ &addr);
+
+ // on byebye, don't sleep otherwise it hangs when we stop upnp
+ if (type != PLT_ANNOUNCETYPE_BYEBYE) {
+ NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY));
+ }
+ }
+
+ // embedded devices
+ for (int j=0; j < (int)device->m_EmbeddedDevices.GetItemCount(); j++) {
+ Announce(device->m_EmbeddedDevices[j].AsPointer(),
+ req,
+ socket,
+ type);
+ }
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ // get the address of who sent us some data back*/
+ NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+ NPT_String method = request.GetMethod();
+ NPT_String protocol = request.GetProtocol();
+
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINER, "PLT_DeviceHost::SetupResponse:", &request);
+
+ if (method.Compare("POST") == 0) {
+ return ProcessHttpPostRequest(request, context, response);
+ } else if (method.Compare("SUBSCRIBE") == 0 || method.Compare("UNSUBSCRIBE") == 0) {
+ return ProcessHttpSubscriberRequest(request, context, response);
+ } else if (method.Compare("GET") == 0 || method.Compare("HEAD") == 0) {
+ // process SCPD requests
+ PLT_Service* service;
+ if (NPT_SUCCEEDED(FindServiceBySCPDURL(request.GetUrl().ToRequestString(), service, true))) {
+ return ProcessGetSCPD(service, request, context, response);
+ }
+
+ // process Description document requests
+ if (request.GetUrl().GetPath() == m_URLDescription.GetPath()) {
+ return ProcessGetDescription(request, context, response);
+ }
+
+ // process other requests
+ return ProcessHttpGetRequest(request, context, response);
+ }
+
+ response.SetStatus(405, "Bad Request");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::ProcessHttpGetRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessHttpGetRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(request);
+ NPT_COMPILER_UNUSED(context);
+ NPT_COMPILER_UNUSED(response);
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::ProcessGetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessGetDescription(NPT_HttpRequest& /*request*/,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_String doc;
+ NPT_CHECK_FATAL(GetDescription(doc));
+ NPT_LOG_FINEST_2("Returning description to %s: %s",
+ (const char*)context.GetRemoteAddress().GetIpAddress().ToString(),
+ (const char*)doc);
+
+ NPT_HttpEntity* entity;
+ PLT_HttpHelper::SetBody(response, doc, &entity);
+ entity->SetContentType("text/xml; charset=\"utf-8\"");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::ProcessGetSCPD
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessGetSCPD(PLT_Service* service,
+ NPT_HttpRequest& /*request*/,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(context);
+ NPT_CHECK_POINTER_FATAL(service);
+
+ NPT_String doc;
+ NPT_CHECK_FATAL(service->GetSCPDXML(doc));
+ NPT_LOG_FINEST_2("Returning SCPD to %s: %s",
+ (const char*)context.GetRemoteAddress().GetIpAddress().ToString(),
+ (const char*)doc);
+
+ NPT_HttpEntity* entity;
+ PLT_HttpHelper::SetBody(response, doc, &entity);
+ entity->SetContentType("text/xml; charset=\"utf-8\"");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::ProcessPostRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessHttpPostRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_Result res;
+ NPT_String service_type;
+ NPT_String str;
+ NPT_XmlElementNode* xml = NULL;
+ NPT_String soap_action_header;
+ PLT_Service* service;
+ NPT_XmlElementNode* soap_body;
+ NPT_XmlElementNode* soap_action;
+ PLT_ActionDesc* action_desc;
+ PLT_ActionReference action;
+ NPT_MemoryStreamReference resp(new NPT_MemoryStream);
+ NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+ NPT_String method = request.GetMethod();
+ NPT_String url = request.GetUrl().ToRequestString();
+ NPT_String protocol = request.GetProtocol();
+ NPT_List<NPT_String> components;
+ NPT_String soap_action_name;
+
+#if defined(PLATINUM_UPNP_SPECS_STRICT)
+ const NPT_String* attr;
+#endif
+
+ if (NPT_FAILED(FindServiceByControlURL(url, service, true)))
+ goto bad_request_find_service;
+
+ if (!request.GetHeaders().GetHeaderValue("SOAPAction"))
+ goto bad_request_soap_header_value;
+
+ // extract the soap action name from the header
+ soap_action_header = *request.GetHeaders().GetHeaderValue("SOAPAction");
+ soap_action_header.TrimLeft('"');
+ soap_action_header.TrimRight('"');
+
+ components = soap_action_header.Split("#");
+ if (components.GetItemCount() != 2)
+ goto bad_request_soap_action_header;
+
+ soap_action_name = *components.GetItem(1);
+
+ // read the xml body and parse it
+ if (NPT_FAILED(PLT_HttpHelper::ParseBody(request, xml)))
+ goto bad_request_body_parse_error;
+
+ // check envelope
+ if (xml->GetTag().Compare("Envelope", true))
+ goto bad_request_no_envelope;
+
+#if defined(PLATINUM_UPNP_SPECS_STRICT)
+ // check namespace
+ if (!xml->GetNamespace() || xml->GetNamespace()->Compare("http://schemas.xmlsoap.org/soap/envelope/"))
+ goto bad_request_upnp_not_strict;
+
+ // check encoding
+ attr = xml->GetAttribute("encodingStyle", "http://schemas.xmlsoap.org/soap/envelope/");
+ if (!attr || attr->Compare("http://schemas.xmlsoap.org/soap/encoding/"))
+ goto bad_request_bad_encoding;
+#endif
+
+ // read action
+ soap_body = PLT_XmlHelper::GetChild(xml, "Body");
+ if (soap_body == NULL)
+ goto bad_request_soap_body;
+
+ PLT_XmlHelper::GetChild(soap_body, soap_action);
+ if (soap_action == NULL)
+ goto bad_request_soap_action_body;
+
+ // verify action name is identical to SOAPACTION header*/
+ if (soap_action->GetTag().Compare(soap_action_name, true))
+ goto bad_request_action_mismatch;
+
+ // verify namespace
+ if (!soap_action->GetNamespace() || soap_action->GetNamespace()->Compare(service->GetServiceType()))
+ goto bad_request_bad_namespace;
+
+ // create a buffer for our response body and call the service
+ if ((action_desc = service->FindActionDesc(soap_action_name)) == NULL) {
+ // create a bastard soap response
+ PLT_Action::FormatSoapError(401, "Invalid Action", *resp);
+ goto error;
+ }
+
+ // create a new action object
+ action = new PLT_Action(*action_desc);
+
+ // read all the arguments if any
+ for (NPT_List<NPT_XmlNode*>::Iterator args = soap_action->GetChildren().GetFirstItem();
+ args;
+ args++) {
+ NPT_XmlElementNode* child = (*args)->AsElementNode();
+ if (!child) continue;
+
+ // Total HACK for xbox360 upnp uncompliance!
+ NPT_String name = child->GetTag();
+ if (action_desc->GetName() == "Browse" && name == "ContainerID") {
+ name = "ObjectID";
+ }
+
+ res = action->SetArgumentValue(name, child->GetText() ? child->GetText()->GetChars() : "");
+
+ // test if value was correct
+ if (res == NPT_ERROR_INVALID_PARAMETERS)
+ {
+ action->SetError(701, "Invalid Name");
+ goto error;
+ }
+ }
+
+ // verify all required arguments were passed
+ if (NPT_FAILED(action->VerifyArguments(true))) {
+ action->SetError(402, "Invalid or Missing Args");
+ goto error;
+ }
+
+ NPT_LOG_FINE_2("Processing action \"%s\" from %s",
+ (const char*)action->GetActionDesc().GetName(),
+ (const char*)context.GetRemoteAddress().GetIpAddress().ToString());
+
+ // call the virtual function, it's all good
+ if (NPT_FAILED(OnAction(action, PLT_HttpRequestContext(request, context)))) {
+ goto error;
+ }
+
+ // create the soap response now
+ action->FormatSoapResponse(*resp);
+ goto done;
+
+error:
+ if (!action.IsNull()) {
+ // set the error in case it wasn't done already
+ if (action->GetErrorCode() == 0) {
+ action->SetError(501, "Action Failed");
+ }
+ NPT_LOG_WARNING_3("Error while processing action %s: %d %s",
+ (const char*)action->GetActionDesc().GetName(),
+ action->GetErrorCode(),
+ action->GetError());
+
+ action->FormatSoapResponse(*resp);
+ }
+
+ response.SetStatus(500, "Internal Server Error");
+
+done:
+ NPT_LargeSize resp_body_size;
+ if (NPT_SUCCEEDED(resp->GetAvailable(resp_body_size))) {
+ NPT_HttpEntity* entity;
+ PLT_HttpHelper::SetBody(response,
+ (NPT_InputStreamReference)resp,
+ &entity);
+ entity->SetContentType("text/xml; charset=\"utf-8\"");
+ response.GetHeaders().SetHeader("Ext", ""); // should only be for M-POST but oh well
+ }
+
+ delete xml;
+ return NPT_SUCCESS;
+
+bad_request:
+ // generic 500 now unused
+ response.SetStatus(500, "Bad Request");
+ goto bad_request_end;
+
+bad_request_find_service:
+ response.SetStatus(500, "Bad Request: Service by URL");
+ goto bad_request_end;
+
+bad_request_soap_header_value:
+ response.SetStatus(500, "Bad Request: SOAP Header");
+ goto bad_request_end;
+
+bad_request_soap_action_header:
+ response.SetStatus(500, "Bad Request: SOAP Action in Header");
+ goto bad_request_end;
+
+bad_request_body_parse_error:
+ response.SetStatus(500, "Bad Request: Error Parsing XML Body");
+ goto bad_request_end;
+
+bad_request_no_envelope:
+ response.SetStatus(500, "Bad Request: SOAP Envelope");
+ goto bad_request_end;
+
+#if defined(PLATINUM_UPNP_SPECS_STRICT)
+bad_request_upnp_not_strict:
+ response.SetStatus(500, "Bad Request: SOAP not Strict");
+ goto bad_request_end;
+
+bad_request_bad_encoding:
+ response.SetStatus(500, "Bad Request: SOAP Encoding");
+ goto bad_request_end;
+#endif
+
+bad_request_soap_body:
+ response.SetStatus(500, "Bad Request: SOAP Body");
+ goto bad_request_end;
+
+bad_request_soap_action_body:
+ response.SetStatus(500, "Bad Request: SOAP Action in Body");
+ goto bad_request_end;
+
+bad_request_action_mismatch:
+ response.SetStatus(500, "Bad Request: SOAP Action Mismatch");
+ goto bad_request_end;
+
+bad_request_bad_namespace:
+ response.SetStatus(500, "Bad Request: Bad Namespace");
+ goto bad_request_end;
+
+bad_request_end:
+ delete xml;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::ProcessHttpSubscriberRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::ProcessHttpSubscriberRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+ NPT_String method = request.GetMethod();
+ NPT_String url = request.GetUrl().ToRequestString();
+ NPT_String protocol = request.GetProtocol();
+
+ const NPT_String* nt = PLT_UPnPMessageHelper::GetNT(request);
+ const NPT_String* callback_urls = PLT_UPnPMessageHelper::GetCallbacks(request);
+ const NPT_String* sid = PLT_UPnPMessageHelper::GetSID(request);
+
+ PLT_Service* service;
+ NPT_CHECK_LABEL_WARNING(FindServiceByEventSubURL(url, service, true), cleanup);
+
+ if (method.Compare("SUBSCRIBE") == 0) {
+ // Do we have a sid ?
+ if (sid) {
+ // make sure we don't have a callback nor a nt
+ if (nt || callback_urls) {
+ goto cleanup;
+ }
+
+ // default lease
+ NPT_Int32 timeout = *PLT_Constants::GetInstance().GetDefaultSubscribeLease().AsPointer();
+
+ // subscription renewed
+ // send the info to the service
+ service->ProcessRenewSubscription(context.GetLocalAddress(),
+ *sid,
+ timeout,
+ response);
+ return NPT_SUCCESS;
+ } else {
+ // new subscription ?
+ // verify nt is present and valid
+ if (!nt || nt->Compare("upnp:event", true)) {
+ response.SetStatus(412, "Precondition failed");
+ return NPT_SUCCESS;
+ }
+ // verify callback is present
+ if (!callback_urls) {
+ response.SetStatus(412, "Precondition failed");
+ return NPT_SUCCESS;
+ }
+
+ // default lease time
+ NPT_Int32 timeout = *PLT_Constants::GetInstance().GetDefaultSubscribeLease().AsPointer();
+
+ // send the info to the service
+ service->ProcessNewSubscription(m_TaskManager,
+ context.GetLocalAddress(),
+ *callback_urls,
+ timeout,
+ response);
+ return NPT_SUCCESS;
+ }
+ } else if (method.Compare("UNSUBSCRIBE") == 0) {
+ // Do we have a sid ?
+ if (sid && sid->GetLength() > 0) {
+ // make sure we don't have a callback nor a nt
+ if (nt || callback_urls) {
+ goto cleanup;
+ }
+
+ // subscription cancelled
+ // send the info to the service
+ service->ProcessCancelSubscription(context.GetLocalAddress(),
+ *sid,
+ response);
+ return NPT_SUCCESS;
+ }
+
+ response.SetStatus(412, "Precondition failed");
+ return NPT_SUCCESS;
+ }
+
+cleanup:
+ response.SetStatus(400, "Bad Request");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::OnSsdpPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::OnSsdpPacket(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context)
+{
+ // get the address of who sent us some data back*/
+ NPT_String ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
+ NPT_String method = request.GetMethod();
+ NPT_String url = request.GetUrl().ToRequestString(true);
+ NPT_String protocol = request.GetProtocol();
+ NPT_IpPort remote_port = context.GetRemoteAddress().GetPort();
+ const NPT_String* st = PLT_UPnPMessageHelper::GetST(request);
+
+ if (method.Compare("M-SEARCH") == 0) {
+ NPT_String prefix = NPT_String::Format("PLT_DeviceHost::OnSsdpPacket M-SEARCH for %s from %s:%d",
+ st?st->GetChars():"Unknown",
+ (const char*) ip_address, remote_port);
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, prefix, &request);
+
+ /*
+ // DLNA 7.2.3.5 support
+ if (remote_port < 1024 || remote_port == 1900) {
+ NPT_LOG_INFO_2("Ignoring M-SEARCH from %s:%d (invalid source port)",
+ (const char*) ip_address,
+ remote_port);
+ return NPT_FAILURE;
+ }
+ */
+
+ NPT_CHECK_POINTER_SEVERE(st);
+
+ if (url.Compare("*") || protocol.Compare("HTTP/1.1"))
+ return NPT_FAILURE;
+
+ const NPT_String* man = PLT_UPnPMessageHelper::GetMAN(request);
+ if (!man || man->Compare("\"ssdp:discover\"", true))
+ return NPT_FAILURE;
+
+ NPT_UInt32 mx;
+ NPT_CHECK_SEVERE(PLT_UPnPMessageHelper::GetMX(request, mx));
+
+ // create a task to respond to the request
+ NPT_TimeInterval timer((mx==0)?0.:(double)(NPT_System::GetRandomInteger()%(mx>5?5:mx)));
+ PLT_SsdpDeviceSearchResponseTask* task = new PLT_SsdpDeviceSearchResponseTask(this, context.GetRemoteAddress(), *st);
+ m_TaskManager->StartTask(task, &timer);
+ return NPT_SUCCESS;
+ } else {
+ NPT_String prefix = NPT_String::Format("Ignoring %s request from %s:%d",
+ method.GetChars(),
+ (const char*) ip_address, remote_port);
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, prefix, &request);
+ }
+
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::SendSsdpSearchResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::SendSsdpSearchResponse(PLT_DeviceData* device,
+ NPT_HttpResponse& response,
+ NPT_UdpSocket& socket,
+ const char* st,
+ const NPT_SocketAddress* addr /* = NULL */)
+{
+ // UPnP 1.1 BOOTID.UPNP.ORG header
+ PLT_UPnPMessageHelper::SetBootId(response, device->m_BootId);
+
+ // UPnP 1.1 CONFIGID.UPNP.ORG header
+ if (device->m_ConfigId > 0) {
+ PLT_UPnPMessageHelper::SetConfigId(response, device->m_ConfigId);
+ }
+
+ // ssdp:all or upnp:rootdevice
+ if (NPT_String::Compare(st, "ssdp:all") == 0 ||
+ NPT_String::Compare(st, "upnp:rootdevice") == 0) {
+
+ if (device->m_ParentUUID.IsEmpty()) {
+ NPT_LOG_FINE_1("Responding to a M-SEARCH request for %s", st);
+
+ // upnp:rootdevice
+ PLT_SsdpSender::SendSsdp(response,
+ NPT_String("uuid:" + device->m_UUID + "::upnp:rootdevice"),
+ "upnp:rootdevice",
+ socket,
+ false,
+ addr);
+ }
+ }
+
+ // uuid:device-UUID
+ if (NPT_String::Compare(st, "ssdp:all") == 0 ||
+ NPT_String::Compare(st, (const char*)("uuid:" + device->m_UUID)) == 0) {
+
+ NPT_LOG_FINE_1("Responding to a M-SEARCH request for %s", st);
+
+ // uuid:device-UUID
+ PLT_SsdpSender::SendSsdp(response,
+ "uuid:" + device->m_UUID,
+ "uuid:" + device->m_UUID,
+ socket,
+ false,
+ addr);
+ }
+
+ // urn:schemas-upnp-org:device:deviceType:ver
+ if (NPT_String::Compare(st, "ssdp:all") == 0 ||
+ NPT_String::Compare(st, (const char*)(device->m_DeviceType)) == 0) {
+
+ NPT_LOG_FINE_1("Responding to a M-SEARCH request for %s", st);
+
+ // uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:ver
+ PLT_SsdpSender::SendSsdp(response,
+ NPT_String("uuid:" + device->m_UUID + "::" + device->m_DeviceType),
+ device->m_DeviceType,
+ socket,
+ false,
+ addr);
+ }
+
+ // services
+ for (int i=0; i < (int)device->m_Services.GetItemCount(); i++) {
+ if (NPT_String::Compare(st, "ssdp:all") == 0 ||
+ NPT_String::Compare(st, (const char*)(device->m_Services[i]->GetServiceType())) == 0) {
+
+ NPT_LOG_FINE_1("Responding to a M-SEARCH request for %s", st);
+
+ // uuid:device-UUID::urn:schemas-upnp-org:service:serviceType:ver
+ PLT_SsdpSender::SendSsdp(response,
+ NPT_String("uuid:" + device->m_UUID + "::" + device->m_Services[i]->GetServiceType()),
+ device->m_Services[i]->GetServiceType(),
+ socket,
+ false,
+ addr);
+ }
+ }
+
+ // embedded devices
+ for (int j=0; j < (int)device->m_EmbeddedDevices.GetItemCount(); j++) {
+ SendSsdpSearchResponse(device->m_EmbeddedDevices[j].AsPointer(),
+ response,
+ socket,
+ st,
+ addr);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_DeviceHost::OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+ action->SetError(401, "Invalid Action");
+ return NPT_FAILURE;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.h b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.h
new file mode 100644
index 0000000..8cf6118
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltDeviceHost.h
@@ -0,0 +1,341 @@
+/*****************************************************************
+|
+| Platinum - Device Host
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Device
+ */
+
+#ifndef _PLT_DEVICE_HOST_H_
+#define _PLT_DEVICE_HOST_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltDeviceData.h"
+#include "PltSsdp.h"
+#include "PltTaskManager.h"
+#include "PltAction.h"
+#include "PltHttp.h"
+#include "PltHttpServer.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_SsdpDeviceAnnounceTask;
+class PLT_SsdpListenTask;
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost class
++---------------------------------------------------------------------*/
+/**
+ UPnP Device Host.
+ The PLT_DeviceHost class is a base class for implementing a UPnP Device. It handles
+ network announcements and responses to searches from ControlPoints. ControlPoint
+ action invocations are also received and delegated to derived classes. A
+ PLT_DeviceHost also takes care of eventing when services state variables change.
+ */
+class PLT_DeviceHost : public PLT_DeviceData,
+ public PLT_SsdpPacketListener,
+ public NPT_HttpRequestHandler
+{
+public:
+ /**
+ Creates a new instance of UPnP Device Host.
+ @param description_path Relative path for description url
+ @param uuid UPnP device unique id
+ @param device_type UPnP device type
+ @param friendly_name Name advertised for UPnP device
+ @param show_ip Flag to indicate if device IP should be appended to friendly name
+ @param port local port for the device host internal HTTP server, 0 for randomly
+ selected.
+ @param port_rebind Flag to indicate if device host should automatically try to look
+ for another port if failing to choose the one passed.
+ */
+ PLT_DeviceHost(const char* description_path = "/",
+ const char* uuid = "",
+ const char* device_type = "",
+ const char* friendly_name = "",
+ bool show_ip = false,
+ NPT_UInt16 port = 0,
+ bool port_rebind = false);
+ ~PLT_DeviceHost() override;
+
+ virtual void SetExtraBroadcast(bool broadcast) { m_ExtraBroascast = broadcast; }
+
+ /**
+ When a UPnP device comes up, the specifications require that a SSDP bye-bye
+ sequence is sent to force the removal of the device in case it wasn't sent
+ properly during the last shutdown.
+ @param bye_bye_first Boolean to indicate that SSDP bye-bye sequence should
+ be sent first or not.
+ */
+ virtual void SetByeByeFirst(bool bye_bye_first) { m_ByeByeFirst = bye_bye_first; }
+
+ /**
+ Returns the port used by the internal HTTP server for all incoming requests.
+ @return port
+ */
+ virtual NPT_UInt16 GetPort() { return m_Port; };
+
+ /**
+ Sets the lease time.
+ @param lease_time Lease Time
+ */
+ NPT_Result SetLeaseTime(NPT_TimeInterval lease_time) { return PLT_DeviceData::SetLeaseTime(lease_time); }
+
+protected:
+ /**
+ NPT_HttpRequestHandler method for setting up the response of an incoming
+ HTTP request.
+ @param request the request received
+ @param context the context of the request
+ @param response the response to set up
+ */
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ /**
+ Static method similar to Announce.
+ @param device the device to announce
+ @param request the SSDP pre formatted request
+ @param socket the network socket to use to send the request
+ @param type PLT_SsdpAnnounceType enum if the announce is a SSDP bye-bye, update or alive.
+ */
+ static NPT_Result Announce(PLT_DeviceData* device,
+ NPT_HttpRequest& request,
+ NPT_UdpSocket& socket,
+ PLT_SsdpAnnounceType type);
+ /**
+ Called during SSDP announce. The HTTP request is already configured with
+ the right method and host.
+ @param request the SSDP pre formatted request
+ @param socket the network socket to use to send the request
+ @param type PLT_SsdpAnnounceType enum if the announce is a SSDP bye-bye, update or alive.
+ */
+ NPT_Result Announce(NPT_HttpRequest& request,
+ NPT_UdpSocket& socket,
+ PLT_SsdpAnnounceType type) {
+ return Announce(this, request, socket, type);
+ }
+
+ /**
+ PLT_SsdpPacketListener method called when a M-SEARCH SSDP packet is received.
+ @param request SSDP packet
+ @param context the context of the request
+ */
+ NPT_Result OnSsdpPacket(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context) override;
+
+ /**
+ Static method similar to SendSsdpSearchResponse.
+ @param device the device to announce
+ @param response the SSDP pre formatted response
+ @param socket the network socket to use to send the request
+ @param st the original request search target
+ @param addr the remote address to send the response back to in case the socket
+ is not already connected.
+ */
+ static NPT_Result SendSsdpSearchResponse(PLT_DeviceData* device,
+ NPT_HttpResponse& response,
+ NPT_UdpSocket& socket,
+ const char* st,
+ const NPT_SocketAddress* addr = NULL);
+ /**
+ Called by PLT_SsdpDeviceSearchResponseTask when responding to a M-SEARCH
+ SSDP request.
+ @param response the SSDP pre formatted response
+ @param socket the network socket to use to send the request
+ @param st the original request search target
+ @param addr the remote address to send the response back to in case the socket
+ is not already connected.
+ */
+ virtual NPT_Result SendSsdpSearchResponse(NPT_HttpResponse& response,
+ NPT_UdpSocket& socket,
+ const char* st,
+ const NPT_SocketAddress* addr = NULL) {
+ return SendSsdpSearchResponse(this, response, socket, st, addr);
+ }
+
+public:
+ /**
+ Add UPnP icon information to serve from file system.
+ @param icon the icon information including url path
+ @param fileroot the file system root path
+ @param urlroot the url root path of the icon url to match to fileroot
+ Note: As an exemple, if the icon url path is "/images/icon1.jpg", the fileroot
+ is "/Users/joe/www" and the urlroot is "/", when a request is made for
+ "/images/icon1.jpg", the file is expected to be found at
+ "/Users/joe/www/images/icon1.jpg". If the urlroot were "/images", the file
+ would be expected to be found at "/Users/joe/www/icon1.jpg".
+ */
+ virtual NPT_Result AddIcon(const PLT_DeviceIcon& icon,
+ const char* fileroot,
+ const char* urlroot = "/");
+
+ /**
+ Add UPnP icon information to serve using static image.
+ @param icon the icon information including url path
+ @param data the image data
+ @param size the image data size
+ @param copy boolean to indicate the data should be copied internally
+ */
+ virtual NPT_Result AddIcon(const PLT_DeviceIcon& icon,
+ const void* data,
+ NPT_Size size,
+ bool copy = true);
+
+protected:
+ /**
+ Required method for setting up UPnP services of device host
+ (and any embedded). Called when device starts.
+ */
+ virtual NPT_Result SetupServices() = 0;
+
+ /**
+ Default implementation for registering device icon resources. Override to
+ use different ones. Called when device starts.
+ */
+ virtual NPT_Result SetupIcons();
+
+ /**
+ Default implementation for setting up device host. This calls SetupServices
+ and SetupIcons when device starts.
+ */
+ virtual NPT_Result SetupDevice();
+
+ /**
+ Called by PLT_TaskManager when the device is started.
+ @param task the SSDP listening task to attach to for receiving
+ SSDP M-SEARCH messages.
+ */
+ virtual NPT_Result Start(PLT_SsdpListenTask* task);
+
+ /**
+ Called by PLT_TaskManager when the device is stoped.
+ @param task the SSDP listening task to detach from to stop receiving
+ SSDP M-SEARCH messages.
+ */
+ virtual NPT_Result Stop(PLT_SsdpListenTask* task);
+
+ /**
+ This mehod is called when an action performed by a control point has been
+ received and needs to be answered.
+ @param action the action information to answer
+ @param context the context information including the HTTP request and
+ local and remote socket information (IP & port).
+ */
+ virtual NPT_Result OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+
+ /**
+ This method is called when a control point is requesting the device
+ description.
+ @param request the HTTP request
+ @param context the context information including local and remote socket information.
+ @param response the response to setup.
+ */
+ virtual NPT_Result ProcessGetDescription(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+ /**
+ This method is called when a control point is requesting a service SCPD.
+ @param service the service
+ @param request the HTTP request
+ @param context the context information including local and remote socket information.
+ @param response the response to setup.
+ */
+ virtual NPT_Result ProcessGetSCPD(PLT_Service* service,
+ NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+ /**
+ This method is called when a "GET" request for a resource other than the device
+ description, SCPD, or icons has been received.
+ @param request the HTTP request
+ @param context the context information including local and remote socket information.
+ @param response the response to setup.
+ */
+ virtual NPT_Result ProcessHttpGetRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+ /**
+ This method is called when a "POST" request has been received. This is usually
+ an UPnP service action invocation. This will deserialize the request and call
+ the OnAction method.
+ @param request the HTTP request
+ @param context the context information including local and remote socket information.
+ @param response the response to setup.
+ */
+ virtual NPT_Result ProcessHttpPostRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+ /**
+ This method is called when a request from a subscriber has been received. This is
+ for any new subscritions, existing subscrition renewal or cancellation.
+ @param request the HTTP request
+ @param context the context information including local and remote socket information.
+ @param response the response to setup.
+ */
+ virtual NPT_Result ProcessHttpSubscriberRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+protected:
+ friend class PLT_UPnP;
+ friend class PLT_UPnP_DeviceStartIterator;
+ friend class PLT_UPnP_DeviceStopIterator;
+ friend class PLT_Service;
+ friend class NPT_Reference<PLT_DeviceHost>;
+ friend class PLT_SsdpDeviceSearchResponseInterfaceIterator;
+ friend class PLT_SsdpDeviceSearchResponseTask;
+ friend class PLT_SsdpAnnounceInterfaceIterator;
+
+ PLT_TaskManagerReference m_TaskManager;
+ PLT_HttpServerReference m_HttpServer;
+ bool m_ExtraBroascast;
+ NPT_UInt16 m_Port;
+ bool m_PortRebind;
+ bool m_ByeByeFirst;
+ bool m_Started;
+};
+
+typedef NPT_Reference<PLT_DeviceHost> PLT_DeviceHostReference;
+
+#endif /* _PLT_DEVICE_HOST_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltEvent.cpp b/lib/libUPnP/Platinum/Source/Core/PltEvent.cpp
new file mode 100644
index 0000000..7bc699b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltEvent.cpp
@@ -0,0 +1,328 @@
+/*****************************************************************
+|
+| Platinum - Control/Event
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltEvent.h"
+#include "PltService.h"
+#include "PltUPnP.h"
+#include "PltDeviceData.h"
+#include "PltUtilities.h"
+#include "PltCtrlPointTask.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.event")
+
+/*----------------------------------------------------------------------
+| PLT_EventNotification::PLT_EventNotification
++---------------------------------------------------------------------*/
+PLT_EventNotification*
+PLT_EventNotification::Parse(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINER, "PLT_CtrlPoint::ProcessHttpNotify:", &request);
+
+ PLT_EventNotification *notification = new PLT_EventNotification();
+ notification->m_RequestUrl = request.GetUrl();
+
+ const NPT_String* sid = PLT_UPnPMessageHelper::GetSID(request);
+ const NPT_String* nt = PLT_UPnPMessageHelper::GetNT(request);
+ const NPT_String* nts = PLT_UPnPMessageHelper::GetNTS(request);
+
+ if (!sid || sid->GetLength() == 0) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, bad_request);
+ }
+ notification->m_SID = *sid;
+
+ if (!nt || nt->GetLength() == 0 || !nts || nts->GetLength() == 0) {
+ response.SetStatus(400, "Bad request");
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, bad_request);
+ }
+
+ if (nt->Compare("upnp:event", true) || nts->Compare("upnp:propchange", true)) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, bad_request);
+ }
+
+ // if the sequence number is less than our current one, we got it out of order
+ // so we disregard it
+ PLT_UPnPMessageHelper::GetSeq(request, notification->m_EventKey);
+
+ // parse body
+ if (NPT_FAILED(PLT_HttpHelper::GetBody(request, notification->m_XmlBody))) {
+ NPT_CHECK_LABEL_WARNING(NPT_FAILURE, bad_request);
+ }
+
+ return notification;
+
+bad_request:
+ NPT_LOG_SEVERE("CtrlPoint received bad event notify request\r\n");
+ if (response.GetStatusCode() == 200) {
+ response.SetStatus(412, "Precondition Failed");
+ }
+ delete notification;
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::PLT_EventSubscriber
++---------------------------------------------------------------------*/
+PLT_EventSubscriber::PLT_EventSubscriber(PLT_TaskManagerReference 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);
+}
+
+/*----------------------------------------------------------------------
+| 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_EventSubscriber::GetService
++---------------------------------------------------------------------*/
+PLT_Service*
+PLT_EventSubscriber::GetService()
+{
+ return m_Service;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::GetEventKey
++---------------------------------------------------------------------*/
+NPT_Ordinal
+PLT_EventSubscriber::GetEventKey()
+{
+ return m_EventKey;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::SetEventKey
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetEventKey(NPT_Ordinal value)
+{
+ m_EventKey = value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::GetLocalIf
++---------------------------------------------------------------------*/
+NPT_SocketAddress
+PLT_EventSubscriber::GetLocalIf()
+{
+ return m_LocalIf;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::SetLocalIf
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetLocalIf(NPT_SocketAddress value)
+{
+ m_LocalIf = value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::GetExpirationTime
++---------------------------------------------------------------------*/
+// a TimeStamp of 0 means no expiration
+NPT_TimeStamp
+PLT_EventSubscriber::GetExpirationTime()
+{
+ return m_ExpirationTime;
+}
+
+/*----------------------------------------------------------------------
+| 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;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::FindCallbackURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::FindCallbackURL(const char* callback_url)
+{
+ NPT_String res;
+ return NPT_ContainerFind(m_CallbackURLs,
+ NPT_StringFinder(callback_url),
+ res);
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::AddCallbackURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::AddCallbackURL(const char* callback_url)
+{
+ NPT_CHECK_POINTER_FATAL(callback_url);
+
+ NPT_LOG_FINE_2("Adding callback \"%s\" to subscriber %s",
+ callback_url,
+ m_SID.GetChars());
+ return m_CallbackURLs.Add(callback_url);
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber::Notify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::Notify(NPT_List<PLT_StateVariable*>& vars)
+{
+ // verify we have eventable variables
+ bool foundVars = false;
+ NPT_Reference<NPT_XmlElementNode> propertyset(new NPT_XmlElementNode("e", "propertyset"));
+ NPT_CHECK_SEVERE(propertyset->SetNamespaceUri(
+ "e",
+ "urn:schemas-upnp-org:event-1-0"));
+
+ NPT_List<PLT_StateVariable*>::Iterator var = vars.GetFirstItem();
+ while (var) {
+ if ((*var)->IsSendingEvents()) {
+ NPT_XmlElementNode* property = new NPT_XmlElementNode("e", "property");
+ NPT_CHECK_FATAL(propertyset->AddChild(property));
+ NPT_CHECK_FATAL(PLT_XmlHelper::AddChildText(property,
+ (*var)->GetName(),
+ (*var)->GetValue()));
+ foundVars = true;
+ }
+ ++var;
+ }
+
+ // no eventable state variables found!
+ if (foundVars == false) {
+ return NPT_FAILURE;
+ }
+
+ // format the body with the xml
+ NPT_String xml;
+ if (NPT_FAILED(PLT_XmlHelper::Serialize(*propertyset, xml))) {
+ NPT_CHECK_FATAL(NPT_FAILURE);
+ }
+ propertyset = NULL;
+
+ // parse the callback url
+ NPT_HttpUrl url(m_CallbackURLs[0]);
+ if (!url.IsValid()) {
+ NPT_CHECK_FATAL(NPT_FAILURE);
+ }
+ // format request
+ NPT_HttpRequest* request =
+ new NPT_HttpRequest(url,
+ "NOTIFY",
+ NPT_HTTP_PROTOCOL_1_1);
+ NPT_HttpEntity* entity;
+ PLT_HttpHelper::SetBody(*request, xml, &entity);
+
+ // add the extra headers
+ entity->SetContentType("text/xml; charset=\"utf-8\"");
+ PLT_UPnPMessageHelper::SetNT(*request, "upnp:event");
+ PLT_UPnPMessageHelper::SetNTS(*request, "upnp:propchange");
+ PLT_UPnPMessageHelper::SetSID(*request, m_SID);
+ PLT_UPnPMessageHelper::SetSeq(*request, m_EventKey);
+
+ // wrap around sequence to 1
+ if (++m_EventKey == 0) m_EventKey = 1;
+
+ // start the task now if not started already
+ if (!m_SubscriberTask) {
+ // TODO: the subscriber task should inform subscriber if
+ // a notification failed to be received so it can be removed
+ // from the list of subscribers inside the device host
+ NPT_Reference<PLT_HttpClientSocketTask> task(new PLT_HttpClientSocketTask(request, true));
+
+ // short connection time out in case subscriber is not alive
+ NPT_HttpClient::Config config;
+ config.m_ConnectionTimeout = 2000;
+ task->SetHttpClientConfig(config);
+
+ // add initial delay to make sure ctrlpoint receives response to subscription
+ // before our first NOTIFY. Also make sure task is not auto-destroy
+ // since we want to destroy it manually when the subscriber goes away.
+ NPT_TimeInterval delay(0.05f);
+ NPT_CHECK_FATAL(m_TaskManager->StartTask(task.AsPointer(), NULL /*&delay*/, false));
+
+ // Task successfully started, keep around for future notifications
+ m_SubscriberTask = task.AsPointer();
+ task.Detach();
+ } else {
+ m_SubscriberTask->AddRequest(request);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriberFinderByService::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_EventSubscriberFinderByService::operator()(PLT_EventSubscriberReference const & eventSub) const
+{
+ return (m_Service == eventSub->GetService());
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltEvent.h b/lib/libUPnP/Platinum/Source/Core/PltEvent.h
new file mode 100644
index 0000000..de754bb
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltEvent.h
@@ -0,0 +1,191 @@
+/*****************************************************************
+|
+| Platinum - Event
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Eventing
+ */
+
+#ifndef _PLT_EVENT_H_
+#define _PLT_EVENT_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpClientTask.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_StateVariable;
+class PLT_DeviceData;
+class PLT_Service;
+class PLT_TaskManager;
+class PLT_CtrlPoint;
+
+/*----------------------------------------------------------------------
+| PLT_EventNotification class
++---------------------------------------------------------------------*/
+/**
+ The PLT_EventNotification class represents an event notification for a given
+ service to a given subscriber
+ */
+class PLT_EventNotification
+{
+public:
+ ~PLT_EventNotification() {}
+
+ static PLT_EventNotification* Parse(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+
+ NPT_TimeStamp m_ReceptionTime;
+ NPT_HttpUrl m_RequestUrl;
+ NPT_String m_SID;
+ NPT_Ordinal m_EventKey;
+ NPT_String m_XmlBody;
+
+protected:
+ PLT_EventNotification() : m_EventKey(0) {}
+};
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriber class
++---------------------------------------------------------------------*/
+/**
+ The PLT_EventSubscriber class represents an event subscription for a given service
+ from a UPnP ControlPoint.
+ */
+class PLT_EventSubscriber
+{
+public:
+ PLT_EventSubscriber(PLT_TaskManagerReference task_manager,
+ PLT_Service* service,
+ const char* sid,
+ NPT_Timeout timeout_secs = -1);
+ ~PLT_EventSubscriber();
+
+ PLT_Service* GetService();
+ NPT_Ordinal GetEventKey();
+ NPT_Result SetEventKey(NPT_Ordinal value);
+ NPT_SocketAddress GetLocalIf();
+ NPT_Result SetLocalIf(NPT_SocketAddress value);
+ NPT_TimeStamp GetExpirationTime();
+ NPT_Result SetTimeout(NPT_Timeout seconds = -1);
+ const NPT_String& GetSID() const { return m_SID; }
+ NPT_Result FindCallbackURL(const char* callback_url);
+ NPT_Result AddCallbackURL(const char* callback_url);
+ NPT_Result Notify(NPT_List<PLT_StateVariable*>& vars);
+
+protected:
+ //members
+ PLT_TaskManagerReference m_TaskManager;
+ PLT_Service* m_Service;
+ NPT_Ordinal m_EventKey;
+ PLT_HttpClientSocketTask* m_SubscriberTask;
+ NPT_String m_SID;
+ NPT_SocketAddress m_LocalIf;
+ NPT_Array<NPT_String> m_CallbackURLs;
+ NPT_TimeStamp m_ExpirationTime;
+};
+
+typedef NPT_Reference<PLT_EventSubscriber> PLT_EventSubscriberReference;
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriberFinderBySID
++---------------------------------------------------------------------*/
+/**
+ The PLT_EventSubscriberFinderBySID class returns an instance of a PLT_EventSubscriber
+ given its subscriber ID.
+ */
+class PLT_EventSubscriberFinderBySID
+{
+public:
+ // methods
+ PLT_EventSubscriberFinderBySID(const char* sid) : m_SID(sid) {}
+
+ bool operator()(PLT_EventSubscriberReference const & sub) const {
+ return m_SID.Compare(sub->GetSID(), true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_SID;
+};
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriberFinderByCallbackURL
++---------------------------------------------------------------------*/
+/**
+ The PLT_EventSubscriberFinderByCallbackURL class returns an instance of a
+ PLT_EventSubscriber given its subscriber callback url.
+ */
+class PLT_EventSubscriberFinderByCallbackURL
+{
+public:
+ // methods
+ PLT_EventSubscriberFinderByCallbackURL(const char* callback_url) :
+ m_CallbackURL(callback_url) {}
+
+ bool operator()(PLT_EventSubscriberReference const & sub) const {
+ return NPT_SUCCEEDED(sub->FindCallbackURL(m_CallbackURL));
+ }
+
+private:
+ // members
+ NPT_String m_CallbackURL;
+};
+
+/*----------------------------------------------------------------------
+| PLT_EventSubscriberFinderByService
++---------------------------------------------------------------------*/
+/**
+ The PLT_EventSubscriberFinderByService class returns an instance of a
+ PLT_EventSubscriber given a UPnP service.
+ */
+class PLT_EventSubscriberFinderByService
+{
+public:
+ // methods
+ PLT_EventSubscriberFinderByService(PLT_Service* service) : m_Service(service) {}
+ virtual ~PLT_EventSubscriberFinderByService() {}
+ bool operator()(PLT_EventSubscriberReference const & eventSub) const;
+
+private:
+ // members
+ PLT_Service* m_Service;
+};
+
+#endif /* _PLT_EVENT_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttp.cpp b/lib/libUPnP/Platinum/Source/Core/PltHttp.cpp
new file mode 100644
index 0000000..41159be
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttp.cpp
@@ -0,0 +1,352 @@
+/*****************************************************************
+|
+| Platinum - HTTP Protocol Helper
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltHttp.h"
+#include "PltDatagramStream.h"
+#include "PltVersion.h"
+#include "PltUtilities.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http")
+
+/*----------------------------------------------------------------------
+| external references
++---------------------------------------------------------------------*/
+extern NPT_String HttpServerHeader;
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaderFinder
++---------------------------------------------------------------------*/
+class NPT_HttpHeaderFinder
+{
+ public:
+ // methods
+ NPT_HttpHeaderFinder(const char* name) : m_Name(name) {}
+ bool operator()(const NPT_HttpHeader* const & header) const {
+ if (header->GetName().Compare(m_Name, true)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private:
+ // members
+ NPT_String m_Name;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaderLogger
++---------------------------------------------------------------------*/
+class NPT_HttpHeaderLogger
+{
+public:
+ // methods
+ NPT_HttpHeaderLogger(NPT_LoggerReference& logger, int level) :
+ m_Logger(logger), m_Level(level) {}
+ NPT_Result operator()(NPT_HttpHeader*& header) const {
+ NPT_COMPILER_UNUSED(header);
+
+ NPT_LOG_L2(m_Logger, m_Level, "%s: %s",
+ (const char*)header->GetName(),
+ (const char*)header->GetValue());
+ return NPT_SUCCESS;
+ }
+
+ NPT_LoggerReference& m_Logger;
+ int m_Level;
+};
+
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::GetContentType
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetContentType(const NPT_HttpMessage& message,
+ NPT_String& type)
+{
+ type = "";
+
+ const NPT_String* val =
+ message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_TYPE);
+ NPT_CHECK_POINTER(val);
+
+ type = *val;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::GetContentLength
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetContentLength(const NPT_HttpMessage& message,
+ NPT_LargeSize& len)
+{
+ len = 0;
+
+ const NPT_String* val =
+ message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH);
+ NPT_CHECK_POINTER(val);
+
+ return val->ToInteger64(len);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::SetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetBody(NPT_HttpMessage& message,
+ NPT_String& text,
+ NPT_HttpEntity** entity /* = NULL */)
+{
+ return SetBody(message, (const char*)text, text.GetLength(), entity);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::SetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetBody(NPT_HttpMessage& message,
+ const char* text,
+ NPT_HttpEntity** entity /* = NULL */)
+{
+ return SetBody(message, (const char*)text, NPT_StringLength(text), entity);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpMessage::SetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetBody(NPT_HttpMessage& message,
+ const void* body,
+ NPT_LargeSize len,
+ NPT_HttpEntity** entity /* = NULL */)
+{
+ if (len == 0) return NPT_SUCCESS;
+
+ // dump the body in a memory stream
+ NPT_MemoryStreamReference stream(new NPT_MemoryStream);
+ stream->Write(body, (NPT_Size)len);
+
+ // set content length
+ return SetBody(message, (NPT_InputStreamReference)stream, entity);
+}
+
+/*----------------------------------------------------------------------
+| NPT_HttpMessage::SetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::SetBody(NPT_HttpMessage& message,
+ NPT_InputStreamReference stream,
+ NPT_HttpEntity** entity /* = NULL */)
+{
+ // get the entity
+ NPT_HttpEntity* _entity = message.GetEntity();
+ if (_entity == NULL) {
+ // no entity yet, create one
+ message.SetEntity(_entity = new NPT_HttpEntity());
+ }
+
+ if (entity) *entity =_entity;
+
+ // set the entity body
+ return _entity->SetInputStream(stream, true);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::GetBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetBody(const NPT_HttpMessage& message, NPT_String& body)
+{
+ NPT_Result res;
+ NPT_InputStreamReference stream;
+
+ // get stream
+ NPT_HttpEntity* entity = message.GetEntity();
+ if (!entity ||
+ NPT_FAILED(entity->GetInputStream(stream)) ||
+ stream.IsNull()) {
+ return NPT_FAILURE;
+ }
+
+ // extract body
+ NPT_StringOutputStream* output_stream = new NPT_StringOutputStream(&body);
+ res = NPT_StreamToStreamCopy(*stream,
+ *output_stream,
+ 0,
+ entity->GetContentLength());
+ delete output_stream;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::ParseBody
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::ParseBody(const NPT_HttpMessage& message,
+ NPT_XmlElementNode*& tree)
+{
+ // reset tree
+ tree = NULL;
+
+ // read body
+ NPT_String body;
+ NPT_CHECK_WARNING(GetBody(message, body));
+
+ return PLT_XmlHelper::Parse(body, tree);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::IsConnectionKeepAlive
++---------------------------------------------------------------------*/
+bool
+PLT_HttpHelper::IsConnectionKeepAlive(NPT_HttpMessage& message)
+{
+ const NPT_String* connection =
+ message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
+
+ // the DLNA says that all HTTP 1.0 requests should be closed immediately by the server
+ NPT_String protocol = message.GetProtocol();
+ if (protocol.Compare(NPT_HTTP_PROTOCOL_1_0, true) == 0) return false;
+
+ // all HTTP 1.1 requests without a Connection header
+ // or with a keep-alive Connection header should be kept alive if possible
+ return (!connection || connection->Compare("keep-alive", true) == 0);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::IsBodyStreamSeekable
++---------------------------------------------------------------------*/
+bool
+PLT_HttpHelper::IsBodyStreamSeekable(NPT_HttpMessage& message)
+{
+ NPT_HttpEntity* entity = message.GetEntity();
+ NPT_InputStreamReference stream;
+
+ if (!entity ||
+ NPT_FAILED(entity->GetInputStream(stream)) ||
+ stream.IsNull()) {
+ return true;
+ }
+
+ // try to get current position and seek there
+ NPT_Position position;
+ if (NPT_FAILED(stream->Tell(position)) ||
+ NPT_FAILED(stream->Seek(position))) {
+ return false;
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::GetHost
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpHelper::GetHost(const NPT_HttpRequest& request, NPT_String& value)
+{
+ value = "";
+
+ const NPT_String* val =
+ request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_HOST);
+ NPT_CHECK_POINTER(val);
+
+ value = *val;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::SetHost
++---------------------------------------------------------------------*/
+void
+PLT_HttpHelper::SetHost(NPT_HttpRequest& request, const char* host)
+{
+ request.GetHeaders().SetHeader(NPT_HTTP_HEADER_HOST, host);
+}
+
+/*----------------------------------------------------------------------
+| 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);
+ const NPT_String* dlna_friendly_name = request.GetHeaders().GetHeaderValue("FriendlyName.DLNA.ORG");
+ NPT_LOG_FINEST_2("agent: %s, server: %s", agent?agent->GetChars():"none", server?server->GetChars():"none");
+
+ 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_360;
+ } else if(dlna_friendly_name && (dlna_friendly_name->Find("XBOX-ONE", 0, true) >= 0)) {
+ return PLT_DEVICE_XBOX_ONE;
+ } 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 if (agent && (agent->Find("VLC", 0, true) >= 0 || agent->Find("VideoLan", 0, true) >= 0)) {
+ return PLT_DEVICE_VLC;
+ } else {
+ NPT_LOG_FINER_2("Unknown device signature (ua=%s, server=%s)", agent?agent->GetChars():"none", server?server->GetChars():"none");
+ }
+
+ return PLT_DEVICE_UNKNOWN;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper::SetBasicAuthorization
++---------------------------------------------------------------------*/
+void
+PLT_HttpHelper::SetBasicAuthorization(NPT_HttpRequest& request,
+ const char* username,
+ const char* password)
+{
+ NPT_String encoded;
+ NPT_String cred = NPT_String(username) + ":" + password;
+
+ NPT_Base64::Encode((const NPT_Byte *)cred.GetChars(), cred.GetLength(), encoded);
+ request.GetHeaders().SetHeader(NPT_HTTP_HEADER_AUTHORIZATION, NPT_String("Basic " + encoded));
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttp.h b/lib/libUPnP/Platinum/Source/Core/PltHttp.h
new file mode 100644
index 0000000..7c03c28
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttp.h
@@ -0,0 +1,214 @@
+/*****************************************************************
+|
+| Platinum - HTTP Helper
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ HTTP utilities
+ */
+
+#ifndef _PLT_HTTP_H_
+#define _PLT_HTTP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltVersion.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#if !defined(PLT_HTTP_DEFAULT_USER_AGENT)
+#define PLT_HTTP_DEFAULT_USER_AGENT "UPnP/1.0 DLNADOC/1.50 Platinum/" PLT_PLATINUM_SDK_VERSION_STRING
+#endif
+
+#if !defined(PLT_HTTP_DEFAULT_SERVER)
+#define PLT_HTTP_DEFAULT_SERVER "UPnP/1.0 DLNADOC/1.50 Platinum/" PLT_PLATINUM_SDK_VERSION_STRING
+#endif
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef enum {
+ PLT_DEVICE_UNKNOWN,
+ PLT_DEVICE_XBOX_360,
+ PLT_DEVICE_XBOX_ONE,
+ PLT_DEVICE_PS3,
+ PLT_DEVICE_WMP,
+ PLT_DEVICE_SONOS,
+ PLT_DEVICE_MAC,
+ PLT_DEVICE_WINDOWS,
+ PLT_DEVICE_VLC
+} PLT_DeviceSignature;
+
+/*----------------------------------------------------------------------
+| PLT_HttpHelper
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpHelper class is a set of utility functions for manipulating
+ HTTP headers, entities and messages.
+ */
+class PLT_HttpHelper {
+public:
+ static bool IsConnectionKeepAlive(NPT_HttpMessage& message);
+ static bool IsBodyStreamSeekable(NPT_HttpMessage& message);
+
+ static NPT_Result GetContentType(const NPT_HttpMessage& message, NPT_String& type);
+ static NPT_Result GetContentLength(const NPT_HttpMessage& message, NPT_LargeSize& len);
+
+ static NPT_Result GetHost(const NPT_HttpRequest& request, NPT_String& value);
+ static void SetHost(NPT_HttpRequest& request, const char* host);
+ static PLT_DeviceSignature GetDeviceSignature(const NPT_HttpRequest& request);
+
+ static NPT_Result SetBody(NPT_HttpMessage& message, NPT_String& text, NPT_HttpEntity** entity = NULL);
+ static NPT_Result SetBody(NPT_HttpMessage& message, const char* text, NPT_HttpEntity** entity = NULL);
+ static NPT_Result SetBody(NPT_HttpMessage& message, const void* body, NPT_LargeSize len, NPT_HttpEntity** entity = NULL);
+ static NPT_Result SetBody(NPT_HttpMessage& message, NPT_InputStreamReference stream, NPT_HttpEntity** entity = NULL);
+ static NPT_Result GetBody(const NPT_HttpMessage& message, NPT_String& body);
+ static NPT_Result ParseBody(const NPT_HttpMessage& message, NPT_XmlElementNode*& xml);
+
+ static void SetBasicAuthorization(NPT_HttpRequest& request, const char* username, const char* password);
+};
+
+/*----------------------------------------------------------------------
+| PLT_HttpRequestContext
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpRequestContext class holds information about the request sent, the
+ local & remote ip addresses and ports associated with a connection. It is used
+ mostly when processing a HTTP response.
+ */
+class PLT_HttpRequestContext : public NPT_HttpRequestContext {
+public:
+ // constructors and destructor
+ PLT_HttpRequestContext(const NPT_HttpRequest& request) :
+ m_Request(request) {}
+ PLT_HttpRequestContext(const NPT_HttpRequest& request, const NPT_HttpRequestContext& context) :
+ NPT_HttpRequestContext(&context.GetLocalAddress(), &context.GetRemoteAddress()),
+ m_Request(request) {}
+ virtual ~PLT_HttpRequestContext() {}
+
+ const NPT_HttpRequest& GetRequest() const { return m_Request; }
+ PLT_DeviceSignature GetDeviceSignature() { return PLT_HttpHelper::GetDeviceSignature(m_Request); }
+
+private:
+ const NPT_HttpRequest& m_Request;
+};
+
+/*----------------------------------------------------------------------
+| NPT_HttpHeaderPrinter
++---------------------------------------------------------------------*/
+class NPT_HttpHeaderPrinter
+{
+public:
+ // methods
+ NPT_HttpHeaderPrinter(NPT_OutputStreamReference& stream) :
+ m_Stream(stream) {}
+ NPT_Result operator()(NPT_HttpHeader*& header) const {
+ m_Stream->WriteString(header->GetName());
+ m_Stream->Write(": ", 2);
+ m_Stream->WriteString(header->GetValue());
+ m_Stream->Write("\r\n", 2, NULL);
+ return NPT_SUCCESS;
+ }
+
+private:
+ // members
+ NPT_OutputStreamReference& m_Stream;
+};
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#if defined(NPT_CONFIG_ENABLE_LOGGING)
+#define PLT_LOG_HTTP_REQUEST_L(_logger, _level, _prefix, _request) \
+do { \
+ if (!_request) break; \
+ NPT_LOG_GET_LOGGER((_logger)) \
+ if ((_logger).logger && (_level) >= (_logger).logger->GetLevel()) { \
+ NPT_StringOutputStreamReference stream(new NPT_StringOutputStream); \
+ NPT_OutputStreamReference output = stream; \
+ _request->GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output)); \
+ NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"%s\n%s %s %s\n%s", (const char*)_prefix, (const char*)_request->GetMethod(), (const char*)_request->GetUrl().ToRequestString(true), (const char*)_request->GetProtocol(), (const char*)stream->GetString())); \
+ } \
+} while (0)
+
+#define PLT_LOG_HTTP_RESPONSE_L(_logger, _level, _prefix, _response) \
+do { \
+ if (!_response) break; \
+ NPT_LOG_GET_LOGGER((_logger)) \
+ if ((_logger).logger && (_level) >= (_logger).logger->GetLevel()) { \
+ NPT_StringOutputStreamReference stream(new NPT_StringOutputStream); \
+ NPT_OutputStreamReference output = stream; \
+ _response->GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output)); \
+ NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"%s\n%s %d %s\n%s", (const char*)_prefix, (const char*)_response->GetProtocol(), _response->GetStatusCode(), (const char*)_response->GetReasonPhrase(), (const char*)stream->GetString())); \
+ } \
+} while (0)
+
+#define PLT_LOG_HTTP_REQUEST(_level,_prefix,_request) PLT_LOG_HTTP_REQUEST_L(_NPT_LocalLogger,(_level),(_prefix),(_request))
+
+#define PLT_LOG_HTTP_RESPONSE(_level,_prefix,_response) PLT_LOG_HTTP_RESPONSE_L(_NPT_LocalLogger,(_level),(_prefix),(_response))
+
+#else /* NPT_CONFIG_ENABLE_LOGGING */
+#define PLT_LOG_HTTP_REQUEST_L(_logger, _level, _prefix, _request)
+#define PLT_LOG_HTTP_RESPONSE_L(_logger, _level, _prefix, _response)
+#define PLT_LOG_HTTP_REQUEST(_level,_prefix,_request)
+#define PLT_LOG_HTTP_RESPONSE(_level,_prefix,_response)
+#endif /* NPT_CONFIG_ENABLE_LOGGING */
+
+/*----------------------------------------------------------------------
+| PLT_HttpRequestHandler
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpRequestHandler class delegates the handling of the response of a
+ received HTTP request by a HTTP Server.
+ */
+class PLT_HttpRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+ PLT_HttpRequestHandler(NPT_HttpRequestHandler* delegate) :
+ m_Delegate(delegate) {}
+ ~PLT_HttpRequestHandler() override {}
+
+ // NPT_HttpRequestHandler methods
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override {
+ return m_Delegate->SetupResponse(request, context, response);
+ }
+
+private:
+ NPT_HttpRequestHandler* m_Delegate;
+};
+
+#endif /* _PLT_HTTP_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.cpp b/lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.cpp
new file mode 100644
index 0000000..82c4acd
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.cpp
@@ -0,0 +1,190 @@
+/*****************************************************************
+|
+| Platinum - HTTP Client Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltHttpClientTask.h"
+#include "PltConstants.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http.clienttask")
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::PLT_HttpClientSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpClientSocketTask::PLT_HttpClientSocketTask(NPT_HttpRequest* request /* = NULL */,
+ bool wait_forever /* = false */) :
+ m_WaitForever(wait_forever)
+{
+ m_Client.SetUserAgent(*PLT_Constants::GetInstance().GetDefaultUserAgent());
+ m_Client.SetTimeouts(60000, 60000, 60000);
+ if (request) m_Requests.Push(request);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::~PLT_HttpClientSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpClientSocketTask::~PLT_HttpClientSocketTask()
+{
+ // delete any outstanding requests
+ NPT_HttpRequest* request;
+ while (NPT_SUCCEEDED(m_Requests.Pop(request, false))) {
+ delete request;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::SetHttpClientConfig
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClientSocketTask::SetHttpClientConfig(const NPT_HttpClient::Config& config)
+{
+ return m_Client.SetConfig(config);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::AddRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClientSocketTask::AddRequest(NPT_HttpRequest* request)
+{
+ return m_Requests.Push(request);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::GetNextRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClientSocketTask::GetNextRequest(NPT_HttpRequest*& request, NPT_Timeout timeout_ms)
+{
+ return m_Requests.Pop(request, timeout_ms);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::DoAbort
++---------------------------------------------------------------------*/
+void
+PLT_HttpClientSocketTask::DoAbort()
+{
+ m_Client.Abort();
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_HttpClientSocketTask::DoRun()
+{
+ NPT_HttpRequest* request = NULL;
+ NPT_HttpResponse* response = NULL;
+ NPT_HttpRequestContext context;
+ NPT_Result res;
+ NPT_TimeStamp watchdog;
+
+ NPT_System::GetCurrentTimeStamp(watchdog);
+
+ do {
+ // pop next request or wait for one for 100ms
+ while (NPT_SUCCEEDED(GetNextRequest(request, 100))) {
+ response = NULL;
+
+ if (IsAborting(0)) goto abort;
+
+ // send request
+ res = m_Client.SendRequest(*request, response, &context);
+
+ NPT_String prefix = NPT_String::Format("PLT_HttpClientSocketTask::DoRun (res = %d):", res);
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINER, prefix, response);
+
+ // process response
+ ProcessResponse(res, *request, context, response);
+
+ // cleanup
+ delete response;
+ response = NULL;
+ delete request;
+ request = NULL;
+ }
+
+ // DLNA requires that we abort unanswered/unused sockets after 60 secs
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ if (now > watchdog + NPT_TimeInterval(60.)) {
+ NPT_HttpConnectionManager::GetInstance()->Recycle(NULL);
+ watchdog = now;
+ }
+
+ } while (m_WaitForever && !IsAborting(0));
+
+abort:
+ if (request) delete request;
+ if (response) delete response;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpClientSocketTask::ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(request);
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_LOG_FINE_1("PLT_HttpClientSocketTask::ProcessResponse (result=%d)", res);
+ NPT_CHECK_WARNING(res);
+
+ NPT_CHECK_POINTER_WARNING(response);
+
+ // check if there's a body to read
+ NPT_HttpEntity* entity;
+ NPT_InputStreamReference body;
+ if (!(entity = response->GetEntity()) ||
+ NPT_FAILED(entity->GetInputStream(body)) ||
+ body.IsNull()) {
+ return NPT_SUCCESS;
+ }
+
+ // dump body into ether
+ // (if no content-length specified, read until disconnected)
+ NPT_NullOutputStream output;
+ NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(*body,
+ output,
+ 0,
+ entity->GetContentLength()));
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.h b/lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.h
new file mode 100644
index 0000000..62ac723
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttpClientTask.h
@@ -0,0 +1,121 @@
+/*****************************************************************
+|
+| Platinum - HTTP Client Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ HTTP Client tasks
+ */
+
+#ifndef _PLT_HTTP_CLIENT_TASK_H_
+#define _PLT_HTTP_CLIENT_TASK_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+#include "PltThreadTask.h"
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientSocketTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpClientSocketTask class is the base class used to send a HTTP request
+ asynchronously using a task (thread). It supports persistent connections
+ and HTTP pipelining with automatic fallback and reconnection when HTTP 1.0
+ is used.
+ */
+class PLT_HttpClientSocketTask : public PLT_ThreadTask
+{
+friend class PLT_ThreadTask;
+
+public:
+ PLT_HttpClientSocketTask(NPT_HttpRequest* request = NULL,
+ bool wait_forever = false);
+ ~PLT_HttpClientSocketTask() override;
+
+ virtual NPT_Result AddRequest(NPT_HttpRequest* request);
+ virtual NPT_Result SetHttpClientConfig(const NPT_HttpClient::Config& config);
+
+protected:
+ // PLT_ThreadTask methods
+ void DoAbort() override;
+ void DoRun() override;
+
+ virtual NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response);
+
+private:
+ NPT_Result GetNextRequest(NPT_HttpRequest*& request, NPT_Timeout timeout_ms);
+
+protected:
+ NPT_HttpClient m_Client;
+ bool m_WaitForever;
+ NPT_Queue<NPT_HttpRequest> m_Requests;
+};
+
+/*----------------------------------------------------------------------
+| PLT_HttpClientTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpClientTask class is a templatized version of PLT_HttpClientSocketTask
+ to support arbitrary delegation of HTTP response handling.
+ */
+template <class T>
+class PLT_HttpClientTask : public PLT_HttpClientSocketTask
+{
+public:
+ PLT_HttpClientTask<T>(const NPT_HttpUrl& url, T* data) :
+ PLT_HttpClientSocketTask(new NPT_HttpRequest(url,
+ "GET",
+ NPT_HTTP_PROTOCOL_1_1)),
+ m_Data(data) {}
+ protected:
+ ~PLT_HttpClientTask<T>() override {}
+
+protected:
+ // PLT_HttpClientSocketTask method
+ NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) override {
+ return m_Data->ProcessResponse(res, request, context, response);
+ }
+
+protected:
+ T* m_Data;
+};
+
+#endif /* _PLT_HTTP_CLIENT_TASK_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttpServer.cpp b/lib/libUPnP/Platinum/Source/Core/PltHttpServer.cpp
new file mode 100644
index 0000000..2557f62
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttpServer.cpp
@@ -0,0 +1,310 @@
+/*****************************************************************
+|
+| Platinum - HTTP Server
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltHttpServer.h"
+#include "PltHttp.h"
+#include "PltVersion.h"
+#include "PltUtilities.h"
+#include "PltProtocolInfo.h"
+#include "PltMimeType.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http.server")
+
+/*----------------------------------------------------------------------
+| PLT_HttpServer::PLT_HttpServer
++---------------------------------------------------------------------*/
+PLT_HttpServer::PLT_HttpServer(NPT_IpAddress address,
+ NPT_IpPort port,
+ bool allow_random_port_on_bind_failure, /* = false */
+ NPT_Cardinal max_clients, /* = 50 */
+ bool reuse_address) : /* = false */
+ NPT_HttpServer(address, port, true),
+ m_TaskManager(new PLT_TaskManager(max_clients)),
+ m_Address(address),
+ m_Port(port),
+ m_AllowRandomPortOnBindFailure(allow_random_port_on_bind_failure),
+ m_ReuseAddress(reuse_address),
+ m_Running(false),
+ m_Aborted(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServer::~PLT_HttpServer
++---------------------------------------------------------------------*/
+PLT_HttpServer::~PLT_HttpServer()
+{
+ Stop();
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServer::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServer::Start()
+{
+ NPT_Result res = NPT_FAILURE;
+
+ // we can't start an already running server or restart an aborted server
+ // because the socket is shared create a new instance
+ if (m_Running || m_Aborted) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ // if we're given a port for our http server, try it
+ if (m_Port) {
+ res = SetListenPort(m_Port, m_ReuseAddress);
+ // return right away if failed and not allowed to try again randomly
+ if (NPT_FAILED(res) && !m_AllowRandomPortOnBindFailure) {
+ NPT_CHECK_SEVERE(res);
+ }
+ }
+
+ // try random port now
+ if (!m_Port || NPT_FAILED(res)) {
+ int retries = 100;
+ do {
+ int random = NPT_System::GetRandomInteger();
+ int port = (unsigned short)(1024 + (random % 1024));
+ if (NPT_SUCCEEDED(SetListenPort(port, m_ReuseAddress))) {
+ break;
+ }
+ } while (--retries > 0);
+
+ if (retries == 0) NPT_CHECK_SEVERE(NPT_FAILURE);
+ }
+
+ // keep track of port server has successfully bound
+ m_Port = m_BoundPort;
+
+ // Tell server to try to listen to more incoming sockets
+ // (this could fail silently)
+ if (m_TaskManager->GetMaxTasks() > 20) {
+ m_Socket.Listen(m_TaskManager->GetMaxTasks());
+ }
+
+ // start a task to listen for incoming connections
+ PLT_HttpListenTask *task = new PLT_HttpListenTask(this, &m_Socket, false);
+ NPT_CHECK_SEVERE(m_TaskManager->StartTask(task));
+
+ NPT_SocketInfo info;
+ m_Socket.GetInfo(info);
+ NPT_LOG_INFO_2("HttpServer listening on %s:%d",
+ (const char*)info.local_address.GetIpAddress().ToString(),
+ m_Port);
+
+ m_Running = true;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServer::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServer::Stop()
+{
+ // we can't restart an aborted server
+ if (m_Aborted || !m_Running) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ // stop all other pending tasks
+ m_TaskManager->Abort();
+
+ m_Running = false;
+ m_Aborted = true;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServer::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServer::SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_String prefix = NPT_String::Format("PLT_HttpServer::SetupResponse %s request from %s for \"%s\"",
+ (const char*) request.GetMethod(),
+ (const char*) context.GetRemoteAddress().ToString(),
+ (const char*) request.GetUrl().ToString());
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, prefix, &request);
+
+ NPT_List<NPT_HttpRequestHandler*> handlers = FindRequestHandlers(request);
+ if (handlers.GetItemCount() == 0) return NPT_ERROR_NO_SUCH_ITEM;
+
+ // ask the handler to setup the response
+ NPT_Result result = (*handlers.GetFirstItem())->SetupResponse(request, context, response);
+
+ // DLNA compliance
+ PLT_UPnPMessageHelper::SetDate(response);
+ if (request.GetHeaders().GetHeader("Accept-Language")) {
+ response.GetHeaders().SetHeader("Content-Language", "en");
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| 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)) {
+ 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(NPT_File::GetInfo(file_path, &file_info)) &&
+ 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_HttpServer::ServeStream
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServer::ServeStream(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ NPT_InputStreamReference& body,
+ const char* content_type)
+{
+ if (body.IsNull()) return NPT_FAILURE;
+
+ // set date
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ response.GetHeaders().SetHeader("Date", NPT_DateTime(now).ToString(NPT_DateTime::FORMAT_RFC_1123), true);
+
+ // get entity
+ NPT_HttpEntity* entity = response.GetEntity();
+ NPT_CHECK_POINTER_FATAL(entity);
+
+ // set the content type
+ entity->SetContentType(content_type);
+
+ // check for range requests
+ const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE);
+
+ // setup entity body
+ NPT_CHECK(NPT_HttpFileRequestHandler::SetupResponseBody(response, body, range_spec));
+
+ // set some default headers
+ if (response.GetEntity()->GetTransferEncoding() != NPT_HTTP_TRANSFER_ENCODING_CHUNKED) {
+ // set but don't replace Accept-Range header only if body is seekable
+ NPT_Position offset;
+ if (NPT_SUCCEEDED(body->Tell(offset)) && NPT_SUCCEEDED(body->Seek(offset))) {
+ response.GetHeaders().SetHeader(NPT_HTTP_HEADER_ACCEPT_RANGES, "bytes", false);
+ }
+ }
+
+ // set getcontentFeatures.dlna.org
+ const NPT_String* value = request.GetHeaders().GetHeaderValue("getcontentFeatures.dlna.org");
+ if (value) {
+ PLT_HttpRequestContext tmp_context(request, context);
+ const char* dlna = PLT_ProtocolInfo::GetDlnaExtension(entity->GetContentType(),
+ &tmp_context);
+ if (dlna) response.GetHeaders().SetHeader("ContentFeatures.DLNA.ORG", dlna, false);
+ }
+
+ // transferMode.dlna.org
+ value = request.GetHeaders().GetHeaderValue("transferMode.dlna.org");
+ if (value) {
+ // Interactive mode not supported?
+ /*if (value->Compare("Interactive", true) == 0) {
+ response.SetStatus(406, "Not Acceptable");
+ return NPT_SUCCESS;
+ }*/
+
+ response.GetHeaders().SetHeader("TransferMode.DLNA.ORG", value->GetChars(), false);
+ } else {
+ response.GetHeaders().SetHeader("TransferMode.DLNA.ORG", "Streaming", false);
+ }
+
+ if (request.GetHeaders().GetHeaderValue("TimeSeekRange.dlna.org")) {
+ response.SetStatus(406, "Not Acceptable");
+ return NPT_SUCCESS;
+ }
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttpServer.h b/lib/libUPnP/Platinum/Source/Core/PltHttpServer.h
new file mode 100644
index 0000000..04c47fc
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttpServer.h
@@ -0,0 +1,100 @@
+/*****************************************************************
+|
+| Platinum - HTTP Server
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ HTTP Server
+ */
+
+#ifndef _PLT_HTTP_SERVER_H_
+#define _PLT_HTTP_SERVER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpServerTask.h"
+
+/*----------------------------------------------------------------------
+| PLT_HttpServer class
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpServer class provides an asynchronous way to handle multiple HTTP requests
+ concurrently. Pipelining requests and keep-alive connections are supported.
+ */
+class PLT_HttpServer : public NPT_HttpRequestHandler,
+ public NPT_HttpServer
+{
+public:
+ PLT_HttpServer(NPT_IpAddress address = NPT_IpAddress::Any,
+ NPT_IpPort port = 0,
+ bool allow_random_port_on_bind_failure = false,
+ NPT_Cardinal max_clients = 50,
+ bool reuse_address = false);
+ ~PLT_HttpServer() override;
+
+ // class methods
+ static NPT_Result ServeFile(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ NPT_String file_path);
+ static NPT_Result ServeStream(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ NPT_InputStreamReference& stream,
+ const char* content_type);
+
+ // NPT_HttpRequestHandler methods
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ // methods
+ virtual NPT_Result Start();
+ virtual NPT_Result Stop();
+ virtual unsigned int GetPort() { return m_Port; }
+
+private:
+ PLT_TaskManagerReference m_TaskManager;
+ NPT_Reference<NPT_HttpServer> m_Server;
+ NPT_IpAddress m_Address;
+ NPT_IpPort m_Port;
+ bool m_AllowRandomPortOnBindFailure;
+ bool m_ReuseAddress;
+ bool m_Running;
+ bool m_Aborted;
+};
+
+typedef NPT_Reference<PLT_HttpServer> PLT_HttpServerReference;
+
+#endif /* _PLT_HTTP_SERVER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.cpp b/lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.cpp
new file mode 100644
index 0000000..ed23d47
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.cpp
@@ -0,0 +1,443 @@
+/*****************************************************************
+|
+| Platinum - HTTP Server Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltHttpServerTask.h"
+#include "PltHttp.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http.servertask")
+
+/*----------------------------------------------------------------------
+| external references
++---------------------------------------------------------------------*/
+extern NPT_String HttpServerHeader;
+const char* const PLT_HTTP_DEFAULT_403_HTML = "<html><head><title>403 Forbidden</title></head><body><h1>Forbidden</h1><p>Access to this URL is forbidden.</p></html>";
+const char* const PLT_HTTP_DEFAULT_404_HTML = "<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></html>";
+const char* const PLT_HTTP_DEFAULT_500_HTML = "<html><head><title>500 Internal Error</title></head><body><h1>Internal Error</h1><p>The server encountered an unexpected condition which prevented it from fulfilling the request.</p></html>";
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::PLT_HttpServerSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpServerSocketTask::PLT_HttpServerSocketTask(NPT_Socket* socket,
+ bool stay_alive_forever) :
+ m_Socket(socket),
+ m_StayAliveForever(stay_alive_forever)
+{
+ // needed for PS3 that is some case will request data every 35 secs and
+ // won't like it if server disconnected too early
+ m_Socket->SetReadTimeout(60000);
+ m_Socket->SetWriteTimeout(600000);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::~PLT_HttpServerSocketTask
++---------------------------------------------------------------------*/
+PLT_HttpServerSocketTask::~PLT_HttpServerSocketTask()
+{
+ if (m_Socket) {
+ m_Socket->Cancel();
+ delete m_Socket;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_HttpServerSocketTask::DoRun()
+{
+ NPT_BufferedInputStreamReference buffered_input_stream;
+ NPT_HttpRequestContext context;
+ NPT_Result res = NPT_SUCCESS;
+ bool headers_only;
+ bool keep_alive = false;
+
+ // create a buffered input stream to parse HTTP request
+ NPT_InputStreamReference input_stream;
+ NPT_CHECK_LABEL_SEVERE(GetInputStream(input_stream), done);
+ NPT_CHECK_POINTER_LABEL_FATAL(input_stream.AsPointer(), done);
+ buffered_input_stream = new NPT_BufferedInputStream(input_stream);
+
+ while (!IsAborting(0)) {
+ NPT_HttpRequest* request = NULL;
+ NPT_HttpResponse* response = NULL;
+
+ // reset keep-alive to exit task on read failure
+ keep_alive = false;
+
+ // wait for a request
+ res = Read(buffered_input_stream, request, &context);
+ if (NPT_FAILED(res) || (request == NULL))
+ goto cleanup;
+
+ // process request and setup response
+ res = RespondToClient(*request, context, response);
+ if (NPT_FAILED(res) || (response == NULL))
+ goto cleanup;
+
+ // check if client requested keep-alive
+ keep_alive = PLT_HttpHelper::IsConnectionKeepAlive(*request);
+ headers_only = request->GetMethod() == NPT_HTTP_METHOD_HEAD;
+
+ // send response, pass keep-alive request from client
+ // (it can be overridden if response handler did not allow it)
+ res = Write(response, keep_alive, headers_only);
+
+ // on write error, reset keep_alive so we can close this connection
+ if (NPT_FAILED(res)) keep_alive = false;
+
+cleanup:
+ // cleanup
+ delete request;
+ delete response;
+
+ if (!keep_alive && !m_StayAliveForever) {
+ return;
+ }
+ }
+done:
+ return;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::GetInputStream(NPT_InputStreamReference& stream)
+{
+ return m_Socket->GetInputStream(stream);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::GetInfo(NPT_SocketInfo& info)
+{
+ return m_Socket->GetInfo(info);
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::Read
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::Read(NPT_BufferedInputStreamReference& buffered_input_stream,
+ NPT_HttpRequest*& request,
+ NPT_HttpRequestContext* context)
+{
+ NPT_SocketInfo info;
+ GetInfo(info);
+
+ // update context with socket info if needed
+ if (context) {
+ context->SetLocalAddress(info.local_address);
+ context->SetRemoteAddress(info.remote_address);
+ }
+
+ // put back in buffered mode to be able to parse HTTP request properly
+ buffered_input_stream->SetBufferSize(NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE);
+
+ // parse request
+ NPT_Result res = NPT_HttpRequest::Parse(*buffered_input_stream, &info.local_address, request);
+ if (NPT_FAILED(res) || !request) {
+ // only log if not timeout
+ res = NPT_FAILED(res)?res:NPT_FAILURE;
+ if (res != NPT_ERROR_TIMEOUT && res != NPT_ERROR_EOS) NPT_CHECK_WARNING(res);
+ return res;
+ }
+
+ // update context with socket info again
+ // to refresh the remote address in case it was a non connected udp socket
+ GetInfo(info);
+ if (context) {
+ context->SetLocalAddress(info.local_address);
+ context->SetRemoteAddress(info.remote_address);
+ }
+
+ // return right away if no body is expected
+ if (request->GetMethod() == NPT_HTTP_METHOD_GET ||
+ request->GetMethod() == NPT_HTTP_METHOD_HEAD) {
+ return NPT_SUCCESS;
+ }
+
+ // create an entity
+ NPT_HttpEntity* request_entity = new NPT_HttpEntity(request->GetHeaders());
+ request->SetEntity(request_entity);
+
+ NPT_MemoryStream* body_stream = new NPT_MemoryStream();
+ request_entity->SetInputStream((NPT_InputStreamReference)body_stream);
+
+ // unbuffer the stream to read body fast
+ buffered_input_stream->SetBufferSize(0);
+
+ // check for chunked Transfer-Encoding
+ if (request_entity->GetTransferEncoding() == "chunked") {
+ NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(
+ *NPT_InputStreamReference(new NPT_HttpChunkedInputStream(buffered_input_stream)).AsPointer(),
+ *body_stream));
+
+ request_entity->SetTransferEncoding(NULL);
+ } else if (request_entity->GetContentLength()) {
+ // a request with a body must always have a content length if not chunked
+ NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(
+ *buffered_input_stream.AsPointer(),
+ *body_stream,
+ 0,
+ request_entity->GetContentLength()));
+ } else {
+ request->SetEntity(NULL);
+ }
+
+ // rebuffer the stream
+ buffered_input_stream->SetBufferSize(NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::RespondToClient
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::RespondToClient(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse*& response)
+{
+ NPT_Result result = NPT_ERROR_NO_SUCH_ITEM;
+
+ // reset output params first
+ response = NULL;
+
+ // prepare the response body
+ NPT_HttpEntity* body = new NPT_HttpEntity();
+ response = new NPT_HttpResponse(200, "OK", NPT_HTTP_PROTOCOL_1_1);
+ response->SetEntity(body);
+
+ // ask to setup the response
+ result = SetupResponse(request, context, *response);
+
+ // handle result
+ if (result == NPT_ERROR_NO_SUCH_ITEM) {
+ body->SetInputStream(PLT_HTTP_DEFAULT_404_HTML);
+ body->SetContentType("text/html");
+ response->SetStatus(404, "Not Found");
+ } else if (result == NPT_ERROR_PERMISSION_DENIED) {
+ body->SetInputStream(PLT_HTTP_DEFAULT_403_HTML);
+ body->SetContentType("text/html");
+ response->SetStatus(403, "Forbidden");
+ } else if (result == NPT_ERROR_TERMINATED) {
+ // mark that we want to exit
+ delete response;
+ response = NULL;
+ } else if (NPT_FAILED(result)) {
+ body->SetInputStream(PLT_HTTP_DEFAULT_500_HTML);
+ body->SetContentType("text/html");
+ response->SetStatus(500, "Internal Error");
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask::SendResponseHeaders
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::SendResponseHeaders(NPT_HttpResponse* response,
+ NPT_OutputStream& output_stream,
+ bool& keep_alive)
+{
+ // add any headers that may be missing
+ NPT_HttpHeaders& headers = response->GetHeaders();
+
+ // get the request entity to set additional headers
+ NPT_InputStreamReference body_stream;
+ NPT_HttpEntity* entity = response->GetEntity();
+ if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
+ // set the content length if known
+ if (entity->ContentLengthIsKnown()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH,
+ NPT_String::FromIntegerU(entity->GetContentLength()));
+ }
+
+ // content type
+ NPT_String content_type = entity->GetContentType();
+ if (!content_type.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
+ }
+
+ // content encoding
+ NPT_String content_encoding = entity->GetContentEncoding();
+ if (!content_encoding.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
+ }
+
+ // transfer encoding
+ const NPT_String& transfer_encoding = entity->GetTransferEncoding();
+ if (!transfer_encoding.IsEmpty()) {
+ headers.SetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING, transfer_encoding);
+ }
+
+ } else if (!headers.GetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH)) {
+ // force content length to 0 if there is no message body
+ // (necessary for 1.1 or 1.0 with keep-alive connections)
+ headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
+ }
+
+ const NPT_String* content_length = headers.GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH);
+ const NPT_String* transfer_encoding = headers.GetHeaderValue(NPT_HTTP_HEADER_TRANSFER_ENCODING);
+ const NPT_String* connection_header = headers.GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
+ if (keep_alive) {
+ if (connection_header && connection_header->Compare("close") == 0) {
+ keep_alive = false;
+ } else {
+ // the request says client supports keep-alive
+ // but override if response has content-length header or
+ // transfer chunked encoding
+ keep_alive = content_length ||
+ (transfer_encoding && transfer_encoding->Compare(NPT_HTTP_TRANSFER_ENCODING_CHUNKED) == 0);
+ }
+ }
+
+ // only write keep-alive header for 1.1 if it's close
+ NPT_String protocol = response->GetProtocol();
+ if (protocol.Compare(NPT_HTTP_PROTOCOL_1_0, true) == 0 || !keep_alive) {
+ headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, keep_alive?"keep-alive":"close", true);
+ }
+ headers.SetHeader(NPT_HTTP_HEADER_SERVER, PLT_HTTP_DEFAULT_SERVER, false); // set but don't replace
+
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINE, "PLT_HttpServerSocketTask::Write", response);
+
+ // create a memory stream to buffer the headers
+ NPT_MemoryStream header_stream;
+ response->Emit(header_stream);
+
+ // send the headers
+ NPT_CHECK_WARNING(output_stream.WriteFully(header_stream.GetData(), header_stream.GetDataSize()));
+
+ 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_HttpServerSocketTask::Write
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpServerSocketTask::Write(NPT_HttpResponse* response,
+ bool& keep_alive,
+ bool headers_only /* = false */)
+{
+ // get the socket output stream
+ NPT_OutputStreamReference output_stream;
+ NPT_CHECK_WARNING(m_Socket->GetOutputStream(output_stream));
+
+ // send headers
+ NPT_CHECK_WARNING(SendResponseHeaders(response, *output_stream, keep_alive));
+
+ // send the body
+ if (!headers_only) {
+ NPT_CHECK_WARNING(SendResponseBody(response, *output_stream));
+ }
+
+ // flush
+ output_stream->Flush();
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_HttpListenTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_HttpListenTask::DoRun()
+{
+ while (!IsAborting(0)) {
+ NPT_Socket* client = NULL;
+ NPT_Result result = m_Socket->WaitForNewClient(client, 5000, NPT_SOCKET_FLAG_CANCELLABLE);
+ if (NPT_FAILED(result)) {
+ // cleanup just in case
+ if (client) delete client;
+
+ // normal error
+ if (result == NPT_ERROR_TIMEOUT) continue;
+
+ // exit on other errors ?
+ NPT_LOG_WARNING_2("PLT_HttpListenTask exiting with %d (%s)", result, NPT_ResultText(result));
+ break;
+ } else {
+ PLT_ThreadTask* task = new PLT_HttpServerTask(m_Handler, client);
+ m_TaskManager->StartTask(task);
+ }
+ }
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.h b/lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.h
new file mode 100644
index 0000000..dc5cbd3
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltHttpServerTask.h
@@ -0,0 +1,163 @@
+/*****************************************************************
+|
+| Platinum - HTTP Server Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ HTTP Server Tasks
+ */
+
+#ifndef _PLT_HTTP_SERVER_TASK_H_
+#define _PLT_HTTP_SERVER_TASK_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+#include "PltDatagramStream.h"
+#include "PltThreadTask.h"
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerSocketTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpServerSocketTask class is a task used for handling one or more HTTP
+ requests from a client. It is created by a PLT_HttpListenTask instance upon
+ receiving a connection request. A PLT_HttpServer will handle the delegation for
+ setting up the HTTP response.
+ */
+class PLT_HttpServerSocketTask : public PLT_ThreadTask
+{
+ friend class PLT_ThreadTask;
+
+public:
+ PLT_HttpServerSocketTask(NPT_Socket* socket, bool stay_alive_forever = false);
+
+protected:
+ ~PLT_HttpServerSocketTask() override;
+
+protected:
+ // Request callback handler
+ virtual NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) = 0;
+
+ // overridables
+ virtual NPT_Result GetInputStream(NPT_InputStreamReference& stream);
+ virtual NPT_Result GetInfo(NPT_SocketInfo& info);
+
+ // PLT_ThreadTask methods
+ void DoAbort() override { if (m_Socket) m_Socket->Cancel(); }
+ void DoRun() override;
+
+private:
+ virtual NPT_Result Read(NPT_BufferedInputStreamReference& buffered_input_stream,
+ NPT_HttpRequest*& request,
+ NPT_HttpRequestContext* context = NULL);
+ virtual NPT_Result Write(NPT_HttpResponse* response,
+ bool& keep_alive,
+ bool headers_only = false);
+ virtual NPT_Result RespondToClient(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse*& response);
+ virtual NPT_Result SendResponseHeaders(NPT_HttpResponse* response,
+ NPT_OutputStream& output_stream,
+ bool& keep_alive);
+ virtual NPT_Result SendResponseBody(NPT_HttpResponse* response,
+ NPT_OutputStream& output_stream);
+
+protected:
+ NPT_Socket* m_Socket;
+ bool m_StayAliveForever;
+};
+
+/*----------------------------------------------------------------------
+| PLT_HttpServerTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpServerTask class is a version of PLT_HttpServerSocketTask that supports
+ delegation of HTTP request handling.
+ */
+class PLT_HttpServerTask : public PLT_HttpServerSocketTask
+{
+public:
+ PLT_HttpServerTask(NPT_HttpRequestHandler* handler,
+ NPT_Socket* socket,
+ bool keep_alive = false) :
+ PLT_HttpServerSocketTask(socket, keep_alive), m_Handler(handler) {}
+
+protected:
+ ~PLT_HttpServerTask() override {}
+
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override {
+ return m_Handler->SetupResponse(request, context, response);
+ }
+
+protected:
+ NPT_HttpRequestHandler* m_Handler;
+};
+
+/*----------------------------------------------------------------------
+| PLT_HttpListenTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_HttpListenTask class is used by a PLT_HttpServer to listen for incoming
+ connections and spawn a new task for handling each request.
+ */
+class PLT_HttpListenTask : public PLT_ThreadTask
+{
+public:
+ PLT_HttpListenTask(NPT_HttpRequestHandler* handler,
+ NPT_TcpServerSocket* socket,
+ bool owns_socket = true) :
+ m_Handler(handler), m_Socket(socket), m_OwnsSocket(owns_socket) {}
+
+protected:
+ ~PLT_HttpListenTask() override {
+ if (m_OwnsSocket && m_Socket) delete m_Socket;
+ }
+
+protected:
+ // PLT_ThreadTask methods
+ void DoAbort() override { if (m_Socket) m_Socket->Cancel(); }
+ void DoRun() override;
+
+protected:
+ NPT_HttpRequestHandler* m_Handler;
+ NPT_TcpServerSocket* m_Socket;
+ bool m_OwnsSocket;
+};
+
+#endif /* _PLT_HTTP_SERVER_TASK_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltIconsData.cpp b/lib/libUPnP/Platinum/Source/Core/PltIconsData.cpp
new file mode 100644
index 0000000..56b60b5
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltIconsData.cpp
@@ -0,0 +1,2580 @@
+/*****************************************************************
+|
+| Platinum - AV Media Server Device SCPDs
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 Platinum_120x120_jpg[16096] =
+{
+ 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00,
+ 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xDB, 0x00, 0x43, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xC0,
+ 0x00, 0x11, 0x08, 0x00, 0x81, 0x00, 0x81, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, 0xC4, 0x00,
+ 0x1F, 0x00, 0x00, 0x01, 0x04, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03,
+ 0x06, 0x07, 0x08, 0x02, 0x05, 0x09, 0x0A, 0x01, 0x00, 0x0B, 0xFF, 0xC4, 0x00, 0x49, 0x10, 0x00, 0x01, 0x03, 0x03, 0x02,
+ 0x04, 0x03, 0x04, 0x07, 0x04, 0x04, 0x0C, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x07, 0x21,
+ 0x00, 0x12, 0x31, 0x41, 0x08, 0x13, 0x51, 0x14, 0x61, 0x71, 0x81, 0x09, 0x15, 0x22, 0x32, 0x91, 0xA1, 0xB1, 0x23, 0x52,
+ 0xC1, 0xD1, 0x42, 0x72, 0xB2, 0xE1, 0x0A, 0x16, 0x17, 0x24, 0x34, 0x35, 0x62, 0x92, 0xB3, 0xD2, 0xF0, 0xF1, 0x25, 0x33,
+ 0x37, 0x45, 0x73, 0x74, 0x75, 0xFF, 0xC4, 0x00, 0x1A, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xFF, 0xC4, 0x00, 0x3B, 0x11, 0x01, 0x00,
+ 0x01, 0x03, 0x03, 0x03, 0x01, 0x06, 0x05, 0x03, 0x02, 0x06, 0x01, 0x05, 0x00, 0x00, 0x01, 0x11, 0x02, 0x21, 0x31, 0x00,
+ 0x03, 0x41, 0x12, 0x51, 0x61, 0x71, 0x22, 0x32, 0x81, 0x91, 0xB1, 0xF0, 0x04, 0x13, 0xA1, 0xC1, 0xD1, 0x42, 0xE1, 0xF1,
+ 0x52, 0x72, 0x05, 0x23, 0x62, 0x92, 0xB2, 0xD2, 0xA2, 0x14, 0x33, 0x34, 0x53, 0x83, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01,
+ 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00, 0xA3, 0xEA, 0x9A, 0x46, 0x7E, 0xD1, 0x3F, 0x2D, 0xBA, 0xFA, 0x9D, 0xBE,
+ 0x7F, 0x87, 0x1F, 0x5B, 0x22, 0x90, 0xFD, 0xC3, 0x30, 0xE7, 0xE5, 0xEA, 0x61, 0xD7, 0xB1, 0xA4, 0x15, 0x37, 0xD5, 0x5B,
+ 0x1C, 0xF7, 0x07, 0xF0, 0xC6, 0x00, 0xE0, 0x99, 0x40, 0xF0, 0x91, 0x78, 0xEF, 0x2F, 0x57, 0x6B, 0x73, 0x9F, 0x99, 0xA1,
+ 0x97, 0x37, 0x03, 0xAE, 0x76, 0xF8, 0x9E, 0xFB, 0x8C, 0x6D, 0x9F, 0x97, 0x4C, 0x9E, 0x19, 0x32, 0xCB, 0xCF, 0xBA, 0x5A,
+ 0x42, 0x3C, 0xCD, 0xFD, 0x6C, 0x97, 0xD1, 0xA1, 0xD5, 0x3B, 0xB7, 0x37, 0xC7, 0x7F, 0xE4, 0x7A, 0x1F, 0x99, 0xFC, 0xF8,
+ 0x86, 0xA6, 0xF2, 0x0C, 0x31, 0x8B, 0x19, 0xF9, 0xCF, 0xED, 0xA2, 0x13, 0x26, 0x6E, 0x79, 0x3B, 0xE8, 0x45, 0xCD, 0x38,
+ 0xFB, 0xDB, 0x9E, 0x9F, 0x0F, 0xC7, 0x3E, 0xBD, 0x8E, 0xDB, 0xF0, 0x99, 0x8B, 0x4F, 0x4A, 0x5B, 0xB0, 0x4F, 0x3C, 0x4C,
+ 0xFC, 0x7B, 0xF6, 0xD1, 0x6E, 0x71, 0xF2, 0xD0, 0x6B, 0x9F, 0x83, 0xF7, 0xBD, 0x49, 0xDF, 0xD7, 0xB8, 0xCF, 0x5F, 0x87,
+ 0xBB, 0x6E, 0x15, 0xCB, 0x4F, 0x9B, 0x7A, 0x7F, 0x19, 0xD3, 0x33, 0x89, 0xF0, 0xFF, 0x00, 0x67, 0xE5, 0xF4, 0x9D, 0x0F,
+ 0xF5, 0xA0, 0x49, 0x19, 0x39, 0x00, 0x6D, 0xBE, 0xE3, 0x3D, 0x32, 0x36, 0xDB, 0x61, 0x9F, 0x81, 0x07, 0xAF, 0x0B, 0xEE,
+ 0xD9, 0xF8, 0x6A, 0x8A, 0x2A, 0x49, 0x88, 0x26, 0x26, 0x4F, 0xA4, 0xCE, 0xAD, 0x5F, 0x85, 0x0D, 0x3A, 0x4E, 0xBC, 0x6B,
+ 0x56, 0x9A, 0x69, 0x04, 0x7A, 0xEC, 0x2B, 0x71, 0xFD, 0x40, 0xBB, 0xA8, 0x76, 0xD3, 0xF7, 0x14, 0xE6, 0x84, 0x98, 0xD4,
+ 0x36, 0x6A, 0xF2, 0x1D, 0x41, 0x99, 0xEC, 0x85, 0xD6, 0x13, 0x32, 0x51, 0x8D, 0x16, 0x69, 0x81, 0x09, 0x4F, 0xB0, 0x89,
+ 0x72, 0x9B, 0x44, 0x75, 0xBC, 0xD2, 0x56, 0x5C, 0x47, 0x2E, 0xEE, 0xF3, 0x49, 0x5C, 0x13, 0xD2, 0x32, 0x77, 0x01, 0x98,
+ 0xF3, 0x24, 0x46, 0x42, 0xF7, 0xD4, 0xEE, 0x46, 0xD6, 0xDD, 0x55, 0xB7, 0x42, 0xA8, 0xB5, 0x96, 0x60, 0x8E, 0x50, 0xB7,
+ 0xAE, 0x6D, 0x31, 0xAF, 0x43, 0x9E, 0x27, 0xBE, 0x86, 0x3B, 0x52, 0xC6, 0xD1, 0x9B, 0x8A, 0xF6, 0xD1, 0x6B, 0xD6, 0xF6,
+ 0xAF, 0xDD, 0x56, 0x45, 0xBF, 0x3A, 0xE0, 0xAB, 0x5B, 0x37, 0xCA, 0x2D, 0xF9, 0x6C, 0x5D, 0x94, 0xCA, 0x44, 0x57, 0x27,
+ 0x56, 0x53, 0x45, 0x95, 0x43, 0xA5, 0xD1, 0xDE, 0xA0, 0xD7, 0x9A, 0x84, 0xC4, 0xA9, 0x90, 0x21, 0x3C, 0x9A, 0x9D, 0x3A,
+ 0x72, 0xD8, 0xFA, 0xB4, 0xB9, 0x19, 0xE7, 0x5A, 0x97, 0xC7, 0x9F, 0xB7, 0xF8, 0xCA, 0xBA, 0x82, 0xB2, 0x05, 0xB4, 0x4C,
+ 0x4B, 0x7C, 0x3D, 0xCC, 0xB2, 0x45, 0xE3, 0x9D, 0x70, 0xD1, 0xF8, 0x95, 0xA8, 0x2A, 0x08, 0x58, 0xB5, 0xA2, 0x70, 0xDF,
+ 0x31, 0xCD, 0xCB, 0x73, 0xAF, 0x2C, 0xFA, 0x80, 0x88, 0xF0, 0x64, 0xAD, 0x4C, 0x6E, 0xD2, 0xC1, 0x29, 0x3B, 0x0E, 0x60,
+ 0x49, 0xC1, 0x29, 0x23, 0x9B, 0x9B, 0x19, 0x4A, 0x87, 0xAF, 0x50, 0x9D, 0xC8, 0xF5, 0x76, 0xF7, 0x1A, 0x80, 0x42, 0xEE,
+ 0x66, 0xE6, 0x6C, 0xC0, 0x52, 0x71, 0xF0, 0x73, 0x3A, 0xF5, 0x28, 0x07, 0xA5, 0x48, 0xF6, 0x7A, 0x5E, 0xAB, 0x65, 0x95,
+ 0x2E, 0x79, 0x27, 0x99, 0x49, 0xBC, 0x6A, 0x18, 0x91, 0x51, 0x1C, 0xEA, 0x3C, 0xD8, 0x03, 0xA1, 0xC8, 0xC0, 0x18, 0x39,
+ 0xCE, 0x46, 0xFB, 0x11, 0xE9, 0xD7, 0xAF, 0x6E, 0x35, 0xD5, 0xDC, 0x83, 0xB4, 0x94, 0xD8, 0xC0, 0x81, 0x49, 0x1D, 0xA1,
+ 0xEE, 0xF9, 0x67, 0x4E, 0x7B, 0x2A, 0x8B, 0x5E, 0xBF, 0xAE, 0xDB, 0x4A, 0xC0, 0xB3, 0x28, 0xD3, 0x6E, 0x8B, 0xDA, 0xFA,
+ 0xB8, 0xA9, 0x56, 0xA5, 0xA1, 0x6C, 0xD3, 0x7C, 0x91, 0x3A, 0xB5, 0x70, 0xD6, 0xA5, 0x37, 0x12, 0x9F, 0x4F, 0x60, 0xC9,
+ 0x71, 0x88, 0xED, 0x79, 0x8F, 0x38, 0x14, 0xF4, 0x99, 0x2F, 0x35, 0x16, 0x24, 0x74, 0xBB, 0x26, 0x4B, 0xCD, 0x30, 0xD3,
+ 0x8E, 0x27, 0x1D, 0xCD, 0xCE, 0x96, 0x1F, 0x64, 0x89, 0x96, 0xD3, 0x69, 0xFA, 0x71, 0x9C, 0x5B, 0xB4, 0xD4, 0x94, 0x8D,
+ 0x4B, 0x14, 0xD2, 0x2B, 0x52, 0x58, 0x82, 0x6E, 0x5F, 0xD2, 0x09, 0x56, 0x20, 0x67, 0x5B, 0xCD, 0x6F, 0xD3, 0x1B, 0xFB,
+ 0x40, 0xF5, 0x2E, 0xE9, 0xD1, 0xDD, 0x59, 0xB7, 0x45, 0xA3, 0xA8, 0xB6, 0x7A, 0xE9, 0xAA, 0xAC, 0xD1, 0x51, 0x54, 0xA5,
+ 0xD6, 0xE2, 0x2A, 0x2D, 0x66, 0x9B, 0x16, 0xAF, 0x48, 0xA8, 0xD3, 0x2B, 0x34, 0x79, 0x12, 0xE9, 0xB5, 0x5A, 0x5D, 0x4A,
+ 0x99, 0x36, 0x34, 0xC8, 0x73, 0xA1, 0xBE, 0xB6, 0xDC, 0x6D, 0xD2, 0x16, 0x1B, 0x79, 0x2E, 0x34, 0x99, 0xDB, 0xDE, 0xA6,
+ 0xA2, 0x69, 0xAB, 0xAA, 0x94, 0x91, 0xCC, 0xDE, 0xF1, 0x37, 0xE1, 0x02, 0xD7, 0x83, 0x0E, 0x9E, 0xDD, 0x54, 0xD7, 0x4D,
+ 0x35, 0xD3, 0x7A, 0x5B, 0x8B, 0x24, 0x5D, 0xA5, 0x22, 0x24, 0x7A, 0x88, 0xB9, 0xC6, 0x0D, 0x42, 0x8E, 0xCC, 0xCA, 0xB3,
+ 0xCF, 0x8D, 0xF7, 0xC7, 0x4E, 0xDE, 0x83, 0x07, 0x3E, 0x83, 0x60, 0x77, 0xEF, 0xC6, 0x8E, 0xE4, 0x60, 0x7F, 0xF8, 0xFE,
+ 0xF2, 0x7E, 0xFA, 0x26, 0xCC, 0x07, 0xCB, 0x17, 0xEF, 0x76, 0xF3, 0x0F, 0xC3, 0x41, 0xB9, 0x28, 0x0C, 0x1E, 0x6E, 0xA0,
+ 0x8E, 0xBB, 0xE0, 0x7C, 0x89, 0xCE, 0x3A, 0x0E, 0xFD, 0x08, 0xDF, 0x69, 0xEA, 0xA9, 0x11, 0x88, 0x99, 0x2C, 0x3F, 0xDE,
+ 0x33, 0x67, 0xE9, 0x6D, 0x13, 0x09, 0xDD, 0x78, 0x1C, 0x47, 0x08, 0x21, 0x98, 0x7B, 0x6B, 0x5E, 0xE4, 0xCC, 0x64, 0x76,
+ 0xDC, 0x6F, 0xD8, 0x80, 0x4F, 0x41, 0x8E, 0xA3, 0x71, 0xF2, 0xDB, 0x89, 0xBF, 0xDE, 0x0F, 0xE0, 0xFD, 0x25, 0xF3, 0xA9,
+ 0xEA, 0x2F, 0xD8, 0x3D, 0x6D, 0x3C, 0x44, 0xC5, 0xFB, 0xC7, 0x37, 0xEE, 0x2F, 0xB4, 0x9F, 0x51, 0xFE, 0xE9, 0xE1, 0x49,
+ 0xDC, 0xF9, 0x9A, 0x99, 0x7B, 0xD1, 0xF3, 0x75, 0x63, 0x97, 0x3B, 0x6F, 0xBD, 0x83, 0xE8, 0x08, 0x39, 0xF5, 0xD8, 0x93,
+ 0xF2, 0xCF, 0xA6, 0xDB, 0xEF, 0xC7, 0x62, 0x12, 0x5F, 0x30, 0x37, 0x2D, 0x01, 0xCD, 0xBD, 0x27, 0xEB, 0x31, 0xAC, 0xB1,
+ 0xDE, 0xFF, 0x00, 0x27, 0xF9, 0x8F, 0xD3, 0x43, 0xAA, 0x76, 0xD8, 0xCF, 0x7C, 0x1C, 0x91, 0xD3, 0xD7, 0x19, 0xED, 0xB7,
+ 0xA7, 0xAF, 0x71, 0xC2, 0xEA, 0x66, 0x66, 0xF8, 0xC4, 0x31, 0xF2, 0x8F, 0xAE, 0xA8, 0xA1, 0x89, 0x7D, 0x41, 0x21, 0x38,
+ 0xE7, 0x1C, 0xBF, 0x1D, 0x0E, 0xA9, 0xDE, 0xFD, 0xFA, 0x9C, 0x9D, 0xBA, 0x0F, 0x71, 0x39, 0xDF, 0xB9, 0xEE, 0x07, 0x0B,
+ 0xE2, 0xCF, 0x1F, 0x73, 0x6F, 0x1A, 0x3A, 0x19, 0x99, 0x31, 0x39, 0xB5, 0xEF, 0x0C, 0x5A, 0x43, 0xCE, 0x19, 0xBE, 0x74,
+ 0x32, 0xA6, 0xEE, 0x72, 0xAD, 0xB7, 0x03, 0xFB, 0x8E, 0x73, 0xE9, 0xBF, 0x0A, 0x7F, 0x9F, 0x5D, 0x5B, 0xB6, 0xF4, 0x89,
+ 0xD5, 0x3D, 0xD8, 0x0B, 0xBF, 0xD2, 0x37, 0xB5, 0xDB, 0x97, 0xED, 0x0E, 0x85, 0x72, 0x6F, 0xA9, 0x3B, 0xE4, 0x01, 0x9C,
+ 0x0F, 0x78, 0xDC, 0xE3, 0xA6, 0x77, 0xCE, 0x3F, 0x11, 0x87, 0x2F, 0x7E, 0xC7, 0xCB, 0x1A, 0xAA, 0x68, 0xA4, 0x60, 0x25,
+ 0x61, 0x7A, 0x81, 0x98, 0x23, 0x36, 0x3C, 0xC4, 0x62, 0x74, 0x0B, 0xB3, 0x39, 0x72, 0x79, 0x8F, 0x43, 0xD4, 0xEF, 0xF3,
+ 0x38, 0xEB, 0x80, 0x3B, 0x7B, 0xC6, 0xF8, 0xE1, 0x6A, 0xA0, 0x38, 0x26, 0xE4, 0x90, 0x5A, 0xE6, 0x0E, 0x7E, 0x30, 0xF6,
+ 0xBE, 0x9B, 0xF5, 0x0A, 0xA1, 0x6D, 0xB2, 0xA2, 0xA3, 0x80, 0x36, 0x19, 0xC6, 0x48, 0x19, 0x1D, 0x09, 0xE8, 0x08, 0x03,
+ 0xAF, 0x50, 0x73, 0xC4, 0x57, 0x54, 0x16, 0x61, 0xCE, 0x26, 0xDC, 0xDB, 0xFB, 0xE9, 0x2F, 0x49, 0x3F, 0x29, 0x39, 0xE2,
+ 0x1E, 0x7E, 0x87, 0x6D, 0x3F, 0xBC, 0x31, 0xEA, 0x24, 0xC4, 0x6B, 0x25, 0x56, 0xD4, 0xA7, 0x55, 0x57, 0x47, 0xBC, 0x9C,
+ 0xB6, 0xA9, 0x97, 0xF6, 0x9B, 0x54, 0x10, 0xF2, 0xDA, 0x78, 0xDD, 0x5A, 0x63, 0x5B, 0x35, 0x19, 0xD4, 0xF8, 0xCA, 0x42,
+ 0x92, 0xB3, 0x25, 0xFA, 0x15, 0x72, 0x54, 0xC6, 0x9B, 0x4A, 0xB9, 0xD6, 0x8A, 0x73, 0xC0, 0x0C, 0x24, 0x94, 0xF3, 0x52,
+ 0x1B, 0x8D, 0x74, 0x0B, 0x35, 0x52, 0x24, 0xDD, 0xEA, 0xA5, 0x6E, 0xF8, 0xA8, 0x59, 0x7B, 0xF7, 0x35, 0x8E, 0xF5, 0x43,
+ 0x45, 0x15, 0xE6, 0x92, 0xB6, 0x8D, 0xCA, 0x5C, 0x94, 0xEE, 0x10, 0x3C, 0x91, 0x34, 0x87, 0xC7, 0x8B, 0x1A, 0xF6, 0xA7,
+ 0xE1, 0xF3, 0xE9, 0x5F, 0xD3, 0xDD, 0x5A, 0xF0, 0xD3, 0x72, 0x3D, 0xA9, 0x0E, 0x33, 0x4D, 0xD5, 0x0B, 0x6E, 0xCE, 0xAB,
+ 0xD2, 0x2E, 0x18, 0xAB, 0x71, 0xA6, 0xD8, 0xAC, 0x4F, 0x6E, 0x93, 0x2A, 0x1B, 0x95, 0x03, 0x1D, 0xDE, 0x55, 0xB4, 0x97,
+ 0xC9, 0xE7, 0x7D, 0x00, 0x2D, 0xB7, 0x1C, 0x56, 0x42, 0x80, 0x5E, 0xFC, 0x55, 0x7E, 0x0E, 0xA3, 0x76, 0x98, 0xB0, 0x54,
+ 0x49, 0x0C, 0xC9, 0x0C, 0x52, 0xF9, 0xC9, 0xDA, 0x39, 0xD7, 0x99, 0x5E, 0xCB, 0x4D, 0x47, 0x48, 0xD5, 0x4B, 0x0D, 0x29,
+ 0xCC, 0xFF, 0x00, 0x49, 0x7C, 0xF6, 0x96, 0x53, 0x5E, 0x20, 0x2F, 0xAD, 0x44, 0x87, 0x5A, 0xAF, 0xD4, 0x5A, 0x88, 0xE2,
+ 0x56, 0xC2, 0xD1, 0x4E, 0xA9, 0xC6, 0xF2, 0xD5, 0x90, 0x63, 0xD5, 0x69, 0xEC, 0x49, 0x40, 0x46, 0x4E, 0x0A, 0x4B, 0xDE,
+ 0xD0, 0x12, 0x53, 0xB6, 0x47, 0x41, 0x93, 0xC7, 0x65, 0x29, 0x4A, 0x2C, 0x0A, 0x72, 0x48, 0x29, 0xDB, 0x98, 0x26, 0xE4,
+ 0xDF, 0x18, 0x75, 0xED, 0xAF, 0x45, 0x03, 0x52, 0xC8, 0xD5, 0x49, 0x1C, 0x34, 0xA8, 0xF8, 0xF2, 0xA6, 0x64, 0x88, 0xBC,
+ 0x30, 0x5F, 0xA9, 0xE5, 0xA5, 0x10, 0xA2, 0x0F, 0xEE, 0x93, 0x90, 0x3B, 0xF6, 0xEF, 0xD8, 0xFA, 0x1D, 0xFB, 0xF1, 0x6D,
+ 0x7C, 0xB5, 0x2D, 0xE4, 0x25, 0x3B, 0x98, 0xB6, 0x1C, 0x29, 0xAC, 0xFA, 0xCE, 0x95, 0xBC, 0xCD, 0xB1, 0x72, 0xF2, 0xA6,
+ 0x48, 0x4F, 0x8D, 0xBE, 0x0D, 0xFB, 0x67, 0x57, 0x35, 0x1B, 0x4A, 0xF5, 0x46, 0xCE, 0xD4, 0x2D, 0x2C, 0xAA, 0x2E, 0x97,
+ 0xA8, 0xDA, 0x7E, 0xB9, 0x57, 0xC5, 0x87, 0x35, 0x08, 0x0E, 0xA9, 0xBB, 0x96, 0xD3, 0x93, 0x4E, 0xAD, 0x84, 0x25, 0xA5,
+ 0xA5, 0x69, 0x79, 0x4F, 0xD1, 0x21, 0xD6, 0xDB, 0x53, 0x45, 0x0A, 0x0E, 0xB3, 0xE7, 0x20, 0x82, 0x09, 0xC6, 0x2D, 0x4D,
+ 0x4B, 0x4A, 0x53, 0x54, 0xD3, 0x54, 0x09, 0x94, 0x27, 0xA7, 0xCC, 0x9C, 0x4C, 0xD4, 0x76, 0xD2, 0xFC, 0xCA, 0x5A, 0x2A,
+ 0xA3, 0x70, 0x2A, 0xA6, 0xA5, 0x2A, 0x9B, 0x59, 0x13, 0x27, 0x25, 0x50, 0xCE, 0x6D, 0x6D, 0x11, 0xA8, 0xFA, 0xD7, 0xAA,
+ 0x9A, 0xCD, 0xAB, 0xF7, 0x4D, 0xFF, 0x00, 0xAC, 0x97, 0x3C, 0x9B, 0xBB, 0x54, 0x2B, 0xB1, 0xE1, 0x4E, 0xBF, 0xEB, 0x4F,
+ 0xA9, 0x20, 0x37, 0x71, 0xD4, 0x98, 0x6A, 0x4B, 0x16, 0xEC, 0x56, 0x50, 0x12, 0xD4, 0x78, 0x76, 0x85, 0xB0, 0xDD, 0xB9,
+ 0x42, 0x6E, 0x23, 0x69, 0xF2, 0xE2, 0xC9, 0x62, 0x73, 0x21, 0x21, 0x68, 0x58, 0x08, 0x4F, 0x70, 0xA4, 0xA7, 0xA0, 0xA7,
+ 0xA8, 0x31, 0x2C, 0x55, 0xD2, 0x3C, 0x01, 0x02, 0x77, 0x52, 0x64, 0x75, 0x25, 0x61, 0x47, 0x46, 0xD5, 0x26, 0xDD, 0x33,
+ 0x3C, 0xAA, 0x79, 0x9B, 0xCD, 0x4B, 0x54, 0xC6, 0x24, 0xF5, 0xD2, 0x0D, 0xCB, 0x52, 0x92, 0x30, 0xA2, 0x7A, 0x83, 0xB9,
+ 0x00, 0xEC, 0x37, 0x27, 0x23, 0x3B, 0xEC, 0x7E, 0x3B, 0x8E, 0x35, 0x2B, 0xEF, 0xF7, 0xF7, 0x7F, 0x97, 0x2E, 0xA6, 0x5E,
+ 0xEF, 0x7F, 0xBB, 0xFD, 0xA5, 0xB9, 0xD6, 0x4A, 0x92, 0x7D, 0x73, 0xB1, 0xD8, 0x91, 0xCA, 0x77, 0xDF, 0xB1, 0xE9, 0xDB,
+ 0xAE, 0x4F, 0xB8, 0x6C, 0x35, 0xE2, 0xC6, 0x49, 0xCC, 0xC4, 0xF6, 0x88, 0xED, 0xCD, 0xB3, 0x6D, 0x3E, 0xA6, 0xC5, 0xA0,
+ 0xE3, 0xED, 0x99, 0xF8, 0xE6, 0xFA, 0x19, 0x6F, 0x9E, 0x84, 0xFB, 0x86, 0xF8, 0xC0, 0xDF, 0x7C, 0x8D, 0xFD, 0x01, 0xCE,
+ 0x07, 0x5E, 0x9B, 0x01, 0x2D, 0x4B, 0xF2, 0x8C, 0xB3, 0xF0, 0xB8, 0x03, 0xDA, 0x3F, 0x9D, 0x4E, 0x92, 0xF3, 0x8F, 0xA0,
+ 0xFC, 0x47, 0xFC, 0xDC, 0x4C, 0xD5, 0xDE, 0x9F, 0xFB, 0x0F, 0xE7, 0x46, 0xA7, 0x95, 0xCC, 0x3D, 0xCF, 0xBF, 0x07, 0x6C,
+ 0x7B, 0x8F, 0x40, 0x32, 0x7A, 0x7B, 0xBA, 0xF5, 0xE3, 0xD1, 0xB5, 0xA2, 0x7C, 0xFF, 0x00, 0x6D, 0x74, 0xC1, 0x25, 0xC0,
+ 0xA5, 0x60, 0xA7, 0xA8, 0xE3, 0x29, 0x24, 0xF1, 0xC9, 0x7B, 0xB3, 0xA4, 0x15, 0x33, 0x24, 0x9C, 0xEC, 0x7D, 0x0F, 0x4E,
+ 0xA3, 0x61, 0xDB, 0x39, 0xDF, 0xAF, 0xC7, 0x85, 0xA2, 0xDE, 0xB3, 0xC5, 0xED, 0xF2, 0x8F, 0xD3, 0x48, 0x2A, 0x6E, 0x4E,
+ 0xCB, 0xC0, 0xDB, 0xA1, 0xC1, 0xEF, 0xD3, 0xE3, 0xEE, 0x19, 0xF4, 0xDF, 0x27, 0x83, 0xEF, 0xEF, 0xFB, 0xE8, 0x98, 0x33,
+ 0x7E, 0xD1, 0x8F, 0x23, 0xDE, 0xC7, 0x9D, 0x0E, 0xA9, 0x80, 0x83, 0xB8, 0xC1, 0xDC, 0x9C, 0xE0, 0x9C, 0x76, 0xC7, 0x51,
+ 0xF9, 0x74, 0x19, 0xCF, 0x06, 0x89, 0x7B, 0xBF, 0xE7, 0x43, 0xAE, 0x67, 0x30, 0xC0, 0x3B, 0x01, 0x9D, 0xCE, 0xF8, 0xE9,
+ 0xD7, 0x38, 0xEB, 0xD3, 0x04, 0x91, 0xB6, 0x31, 0x8E, 0x06, 0xD9, 0xE6, 0x39, 0xEF, 0x89, 0xED, 0x3C, 0x4E, 0x96, 0x65,
+ 0xF8, 0xE8, 0x67, 0x64, 0x13, 0xFD, 0x2D, 0x80, 0x04, 0x6F, 0xD0, 0xE7, 0xD7, 0xB1, 0x3E, 0x9B, 0xED, 0xC0, 0xDA, 0x7B,
+ 0xF6, 0xD3, 0x87, 0xF6, 0xF9, 0xE2, 0xD9, 0xBE, 0x9B, 0x55, 0x67, 0x14, 0xA6, 0x54, 0x32, 0x72, 0x93, 0x91, 0x82, 0x09,
+ 0xC6, 0xF9, 0x03, 0x07, 0xA6, 0xE3, 0x38, 0x1B, 0x8E, 0xF8, 0xE3, 0x9F, 0x75, 0xF7, 0xBC, 0x40, 0x7A, 0x4C, 0x76, 0xE5,
+ 0x9E, 0xFE, 0x35, 0x35, 0xFB, 0xB7, 0x98, 0x5B, 0x7C, 0x33, 0xCD, 0xB1, 0xAA, 0xC3, 0x7E, 0xDD, 0xB5, 0xFD, 0x33, 0xB9,
+ 0xEC, 0xDD, 0x5F, 0xB5, 0x8B, 0x82, 0xE1, 0xD2, 0xFB, 0x9A, 0x9B, 0x77, 0xC4, 0x6D, 0x1F, 0x68, 0xCE, 0x83, 0x4F, 0x5A,
+ 0xDA, 0xAF, 0x51, 0xDD, 0x46, 0xC1, 0xC8, 0xF5, 0xBB, 0x7A, 0x45, 0x56, 0x96, 0xEB, 0x2A, 0xE6, 0x43, 0x86, 0x4A, 0x32,
+ 0x3E, 0xC8, 0xC7, 0x15, 0x75, 0xD5, 0xB7, 0x55, 0x1B, 0xB4, 0xCC, 0xED, 0x55, 0xD5, 0x04, 0xFB, 0x54, 0x90, 0xD4, 0x31,
+ 0x93, 0xA6, 0x78, 0xB3, 0x39, 0xCE, 0xB9, 0x77, 0x09, 0xA1, 0xEC, 0x17, 0x0E, 0x69, 0xC2, 0x7C, 0xAE, 0x46, 0x18, 0xD5,
+ 0xD2, 0xF1, 0x1D, 0xAD, 0xF5, 0xDB, 0x22, 0xB8, 0xCD, 0xDB, 0xA6, 0xD5, 0x82, 0x9B, 0x1B, 0x5B, 0x2C, 0x88, 0xF7, 0x14,
+ 0x35, 0xC4, 0x6B, 0xCD, 0x69, 0xE6, 0xAB, 0x34, 0xD6, 0x66, 0xA0, 0x2E, 0x43, 0x88, 0x24, 0x33, 0xE4, 0xBC, 0xD7, 0x98,
+ 0xCA, 0x31, 0xCE, 0xF0, 0xC3, 0x8B, 0x0D, 0x80, 0x13, 0xDD, 0xF8, 0xAD, 0xDA, 0x68, 0x28, 0xAE, 0x81, 0x8D, 0xCA, 0x3A,
+ 0x84, 0xB8, 0x89, 0x37, 0x02, 0x6C, 0x7C, 0xE3, 0x29, 0x95, 0xF8, 0x7A, 0xC2, 0x92, 0x9A, 0xA9, 0xEB, 0xAB, 0x6E, 0xA6,
+ 0x16, 0xA6, 0x1A, 0x4E, 0x48, 0x85, 0x99, 0x18, 0x64, 0xCD, 0xF5, 0x4F, 0x68, 0x35, 0x77, 0x45, 0x52, 0x86, 0x85, 0x3A,
+ 0xA5, 0x17, 0x34, 0xD7, 0x4E, 0x9F, 0x59, 0x59, 0xCA, 0x96, 0xE4, 0x8A, 0x64, 0xD7, 0x5E, 0x59, 0xED, 0xCC, 0x56, 0xA5,
+ 0x73, 0x1D, 0xB7, 0x18, 0xC0, 0xC0, 0x03, 0x8C, 0xAA, 0x6A, 0x26, 0xFF, 0x00, 0xF2, 0xF6, 0x92, 0x00, 0x09, 0xA5, 0xC7,
+ 0xD6, 0xD3, 0x9B, 0xEB, 0x4E, 0xA6, 0xB6, 0xA6, 0xA4, 0x56, 0xA6, 0x63, 0x03, 0xC8, 0x78, 0xFD, 0x42, 0x09, 0xB6, 0xA6,
+ 0x06, 0xDF, 0x2E, 0x35, 0x82, 0x01, 0x27, 0x04, 0xE3, 0xAF, 0x63, 0xB7, 0xE9, 0x9F, 0x43, 0xC5, 0xF8, 0x96, 0x3B, 0x4D,
+ 0xB4, 0x69, 0x8F, 0x70, 0xD1, 0xD7, 0x35, 0xF8, 0xD2, 0x58, 0x95, 0x32, 0x0C, 0xD8, 0x32, 0x5B, 0x99, 0x02, 0x7D, 0x3E,
+ 0x53, 0xF0, 0xA7, 0xC0, 0x94, 0xC9, 0xE6, 0x6E, 0x4C, 0x29, 0x91, 0x56, 0xD4, 0x88, 0xCF, 0x37, 0x95, 0x04, 0xB8, 0xD3,
+ 0x88, 0x5E, 0x14, 0xA4, 0xF3, 0x72, 0xAD, 0x41, 0x53, 0x03, 0x1C, 0x24, 0x22, 0x4C, 0x8B, 0x61, 0x1B, 0x33, 0x6C, 0xF1,
+ 0x17, 0xC6, 0x91, 0x0D, 0x3E, 0x55, 0xE2, 0xC8, 0x58, 0xBB, 0x79, 0xB6, 0x62, 0xF6, 0x8D, 0x0D, 0x41, 0xA3, 0x26, 0x96,
+ 0x95, 0x84, 0x17, 0x56, 0xB7, 0x5D, 0x76, 0x44, 0x87, 0xDF, 0x71, 0xC9, 0x12, 0x24, 0xC9, 0x79, 0xC5, 0xBA, 0xF4, 0x89,
+ 0x32, 0x1E, 0x53, 0x8F, 0x48, 0x90, 0xFB, 0xCE, 0x2D, 0xE7, 0x9D, 0x75, 0xC5, 0x38, 0xEB, 0xAB, 0x5B, 0x8E, 0x2D, 0x4A,
+ 0x52, 0x94, 0x40, 0x29, 0x23, 0xCC, 0x0B, 0x2A, 0xAE, 0x65, 0xBB, 0x77, 0xBA, 0xFC, 0xA3, 0x4E, 0x39, 0xE6, 0xD1, 0x76,
+ 0x63, 0x9B, 0x44, 0x5E, 0xDE, 0x74, 0xF5, 0x43, 0xBC, 0x8D, 0x80, 0x0F, 0x6C, 0x6D, 0x9C, 0x1C, 0xF7, 0x04, 0x6F, 0xD3,
+ 0xD7, 0x6E, 0x2B, 0xEF, 0xE5, 0xA3, 0x5F, 0x0B, 0xFE, 0xFF, 0x00, 0xCC, 0x9F, 0xD3, 0x83, 0x46, 0x90, 0x5C, 0x8F, 0xFB,
+ 0x7E, 0xB9, 0xDF, 0x6F, 0x99, 0xED, 0xEB, 0xC1, 0xA3, 0x48, 0x7B, 0x4A, 0x7F, 0x7C, 0x7E, 0x29, 0xFE, 0x7C, 0x1A, 0x35,
+ 0x35, 0x19, 0x5B, 0xEC, 0xAF, 0x76, 0xD9, 0xC7, 0xA7, 0xC8, 0x83, 0xEB, 0xB7, 0x7E, 0xFC, 0x77, 0xA8, 0x31, 0x97, 0xC5,
+ 0xE3, 0xD6, 0x3F, 0xCF, 0x8D, 0x74, 0xC7, 0x90, 0xED, 0x3C, 0xFD, 0xF9, 0xD2, 0x66, 0x59, 0xDC, 0x67, 0x63, 0x9C, 0x8C,
+ 0xF6, 0x3D, 0x7A, 0x9E, 0xF9, 0xDB, 0x3E, 0xBD, 0x3A, 0x70, 0xC4, 0xBC, 0x64, 0x0B, 0xCD, 0xA5, 0xF0, 0x42, 0x27, 0x99,
+ 0xBF, 0x11, 0xA5, 0xA4, 0x55, 0x27, 0x24, 0xE4, 0x8F, 0x76, 0xFD, 0x07, 0xBC, 0xF6, 0xDC, 0x7E, 0x67, 0xDD, 0xC4, 0x35,
+ 0x25, 0xA1, 0x1F, 0x17, 0xF8, 0x62, 0xE7, 0x78, 0x6C, 0x73, 0xAA, 0xB5, 0xAF, 0x79, 0x3D, 0xE0, 0x06, 0x7E, 0x67, 0xCF,
+ 0xE1, 0xA1, 0x97, 0x28, 0xEE, 0x79, 0x8E, 0x3E, 0xEF, 0x43, 0x8C, 0x83, 0xD3, 0x19, 0x1D, 0x3A, 0x9E, 0xFB, 0xF6, 0xDF,
+ 0x84, 0xD6, 0xDA, 0x0C, 0xDE, 0x6E, 0x23, 0x7B, 0x16, 0xB9, 0x21, 0x99, 0xE6, 0x24, 0x74, 0x9E, 0x7B, 0x0C, 0x7C, 0x78,
+ 0x26, 0xDE, 0x3E, 0xB1, 0x7D, 0x02, 0xE5, 0x4D, 0xA6, 0x81, 0x2B, 0x5A, 0x42, 0x53, 0x95, 0x12, 0x4F, 0xDD, 0xE5, 0x07,
+ 0x99, 0x4A, 0xDC, 0x8C, 0x80, 0x32, 0x76, 0x3D, 0x31, 0xDC, 0x71, 0x9B, 0x54, 0x5D, 0xA9, 0x26, 0xD9, 0xCF, 0xEF, 0x69,
+ 0xE3, 0x12, 0xBA, 0x5D, 0x45, 0xAE, 0x2B, 0x88, 0xF5, 0xF9, 0x7C, 0x31, 0x16, 0x2F, 0x89, 0xB6, 0xD8, 0xD1, 0x7D, 0x5A,
+ 0xB9, 0x74, 0x7A, 0xB7, 0xE2, 0x02, 0x97, 0xA6, 0x97, 0x5D, 0x5F, 0x45, 0x2D, 0x7B, 0x80, 0x5A, 0x97, 0x5E, 0xA5, 0x51,
+ 0xD8, 0x89, 0x57, 0xA1, 0x5A, 0x55, 0xC3, 0x06, 0x9D, 0x51, 0x43, 0x17, 0x54, 0x6A, 0x7C, 0xB7, 0xAB, 0x56, 0xE4, 0x25,
+ 0x44, 0xAB, 0x53, 0x1C, 0x4D, 0x76, 0xAD, 0x4C, 0x8F, 0x6F, 0x85, 0xCC, 0x65, 0x95, 0x55, 0x43, 0xA5, 0x48, 0x4B, 0xAB,
+ 0x7A, 0x2A, 0x09, 0xA2, 0x91, 0xF6, 0xC1, 0x95, 0xAA, 0x09, 0x42, 0x56, 0x60, 0x6E, 0x5A, 0x2E, 0xC7, 0x77, 0xD7, 0x41,
+ 0x5D, 0x3B, 0x6D, 0x54, 0x95, 0x27, 0x55, 0x34, 0xD4, 0x43, 0x59, 0x28, 0x42, 0xC0, 0xB9, 0xF6, 0x64, 0x5F, 0x2E, 0xA3,
+ 0x4A, 0xED, 0x05, 0xD4, 0x30, 0xA5, 0xB4, 0x8E, 0x74, 0x29, 0x3C, 0xC8, 0x5A, 0x47, 0xF4, 0x54, 0x01, 0x49, 0xC8, 0xC8,
+ 0xDC, 0x1E, 0xA3, 0xB1, 0x04, 0x6D, 0xB9, 0xCD, 0xAC, 0xA8, 0xA9, 0x98, 0x9C, 0x43, 0x03, 0x2D, 0xB3, 0x01, 0x31, 0x89,
+ 0x96, 0xEF, 0x94, 0xDC, 0x3A, 0x8B, 0x11, 0x2B, 0x97, 0xCF, 0x3D, 0xBE, 0xFC, 0x3A, 0xAC, 0xBA, 0x87, 0x49, 0xF6, 0x88,
+ 0x72, 0x98, 0x71, 0xAE, 0x64, 0xAD, 0xB7, 0x12, 0xB0, 0x40, 0x50, 0x51, 0xE5, 0x3F, 0x67, 0x1B, 0x9E, 0xF9, 0xC9, 0xC0,
+ 0xDB, 0xAE, 0x3A, 0xF3, 0xD6, 0x48, 0x98, 0x65, 0xF8, 0x70, 0xFA, 0x0E, 0x5C, 0xC8, 0xCC, 0x76, 0xE7, 0x66, 0xF4, 0xB1,
+ 0x34, 0xB0, 0x17, 0x98, 0x6D, 0x57, 0x84, 0x99, 0x99, 0x71, 0x11, 0xA6, 0x1B, 0xD5, 0x99, 0x77, 0x27, 0x84, 0x5B, 0x46,
+ 0x93, 0x2D, 0xD5, 0x3B, 0x53, 0xD0, 0xCD, 0x51, 0xAC, 0xE9, 0x8B, 0x6E, 0x2C, 0xF3, 0xB8, 0x9B, 0x62, 0xAE, 0x86, 0xEE,
+ 0x3B, 0x44, 0x2F, 0x39, 0x21, 0xA4, 0xD2, 0xAA, 0x8A, 0xA7, 0xB2, 0x09, 0x28, 0x50, 0xA7, 0xA8, 0x00, 0xAF, 0x2C, 0x81,
+ 0x2D, 0x7D, 0x7F, 0x83, 0xA6, 0x95, 0xF6, 0xB6, 0x37, 0x6A, 0xDA, 0x89, 0x67, 0xA6, 0xAF, 0x68, 0xF3, 0x69, 0x82, 0xF3,
+ 0x9B, 0x44, 0x47, 0x35, 0x07, 0x4D, 0x68, 0x70, 0xA7, 0x88, 0x26, 0x08, 0x99, 0xB1, 0xF0, 0x93, 0x5A, 0xEB, 0x45, 0xD7,
+ 0x16, 0xFD, 0xB0, 0xEA, 0xF2, 0x54, 0xAD, 0x3F, 0xB7, 0x23, 0x12, 0x41, 0x49, 0x4B, 0x94, 0x9A, 0xCD, 0xD5, 0x48, 0x75,
+ 0xB2, 0x49, 0xCF, 0x33, 0x0A, 0x84, 0x1B, 0x56, 0x7D, 0x06, 0x09, 0x04, 0x71, 0x3B, 0x6F, 0xB4, 0x75, 0x5D, 0xFC, 0xBD,
+ 0xBC, 0xC2, 0xC9, 0x55, 0x74, 0x85, 0xB9, 0x22, 0x23, 0x88, 0x9D, 0x6B, 0x4D, 0xBA, 0xA5, 0xB4, 0xB2, 0xE3, 0xBA, 0xAF,
+ 0xAF, 0x89, 0x67, 0x8D, 0x58, 0x08, 0x4F, 0x7E, 0xCD, 0x39, 0x3F, 0xD1, 0x03, 0x63, 0x9C, 0x90, 0x07, 0xBF, 0x6C, 0x91,
+ 0xEB, 0xEF, 0xC9, 0xED, 0xB0, 0xCC, 0xFA, 0xC7, 0x6F, 0xB8, 0xFD, 0x53, 0x54, 0xF5, 0x1C, 0x5E, 0x61, 0x11, 0x22, 0x32,
+ 0x5C, 0xBA, 0x77, 0xED, 0xE7, 0x4B, 0x38, 0x42, 0xBE, 0xD2, 0x80, 0xCF, 0x4C, 0xF7, 0x39, 0xC0, 0xC6, 0x7B, 0x9F, 0x4F,
+ 0xD3, 0x81, 0xE2, 0xDC, 0xFC, 0x4C, 0xC6, 0x31, 0x7F, 0xAE, 0x9E, 0x87, 0x2A, 0x03, 0xA9, 0xE0, 0x00, 0xC7, 0xA3, 0xA7,
+ 0x0C, 0x4C, 0x5B, 0x03, 0x6B, 0xF7, 0x8E, 0x6D, 0xCB, 0x10, 0x49, 0xA4, 0xD4, 0xEE, 0xD8, 0x07, 0x18, 0x39, 0xFE, 0x1D,
+ 0x37, 0xF5, 0xCF, 0xE7, 0x8E, 0xFC, 0x3D, 0x2D, 0x0E, 0xB7, 0xC2, 0x7A, 0x93, 0xBE, 0x76, 0x39, 0x39, 0xF5, 0xD8, 0x7E,
+ 0xA7, 0x6E, 0x14, 0xF8, 0xB9, 0x9C, 0xC0, 0xF6, 0x98, 0x8D, 0x1A, 0x11, 0x72, 0xB3, 0xB0, 0xC7, 0x5E, 0xA7, 0x7F, 0x5F,
+ 0xE8, 0x8C, 0x6F, 0xF1, 0x3E, 0xEE, 0x1F, 0xC7, 0xEF, 0xEF, 0xD7, 0x47, 0xF7, 0xFE, 0xDF, 0x2D, 0x23, 0xED, 0x4E, 0x7E,
+ 0xFA, 0xBF, 0x04, 0xF0, 0x68, 0xD4, 0xC1, 0xED, 0x60, 0x67, 0x24, 0x67, 0x3D, 0x46, 0x37, 0x27, 0x3D, 0xBB, 0xED, 0xD7,
+ 0x71, 0x9C, 0x67, 0xD7, 0x8E, 0x86, 0x5E, 0x5F, 0x12, 0xAF, 0xAF, 0x27, 0xC0, 0xE3, 0xE1, 0xAE, 0x82, 0xAE, 0x0C, 0xDB,
+ 0x0F, 0x4C, 0xE4, 0xB2, 0xCD, 0xA2, 0x5E, 0xDE, 0x75, 0x87, 0xB6, 0x24, 0x6C, 0x0E, 0x09, 0x19, 0x00, 0xF5, 0x24, 0x7E,
+ 0x78, 0xDB, 0x1D, 0x3F, 0x2E, 0x08, 0x59, 0x89, 0xB4, 0x4E, 0x71, 0x01, 0x96, 0x78, 0xFD, 0xF1, 0x7D, 0x2E, 0xB2, 0x62,
+ 0x03, 0x33, 0x29, 0x56, 0x30, 0x58, 0xB3, 0xE1, 0xB7, 0x1A, 0xCB, 0xDA, 0x49, 0xDB, 0x3D, 0x72, 0x70, 0x00, 0x38, 0x4E,
+ 0x33, 0x92, 0x70, 0x41, 0xDF, 0x73, 0xB1, 0xEF, 0xBE, 0x76, 0xE1, 0x08, 0xE1, 0x1F, 0x46, 0x75, 0x3F, 0x99, 0xDB, 0x3E,
+ 0x41, 0x23, 0x9E, 0x73, 0xDA, 0xDF, 0x2D, 0x20, 0xF2, 0xD7, 0xCB, 0x93, 0x91, 0xB6, 0xC7, 0x7C, 0x60, 0x9E, 0xD8, 0xC6,
+ 0x09, 0x1D, 0x4E, 0x09, 0x19, 0x38, 0xDB, 0x85, 0x55, 0x40, 0x59, 0xBD, 0xF9, 0x2D, 0xE7, 0xEC, 0xF8, 0xEA, 0x7A, 0xDE,
+ 0x6E, 0xDE, 0x2F, 0x21, 0xE8, 0x71, 0x78, 0x94, 0xBC, 0x7A, 0xE9, 0x9F, 0x57, 0x90, 0xA4, 0xB4, 0xE0, 0xE6, 0xC6, 0x52,
+ 0x52, 0x71, 0xB6, 0x32, 0x0E, 0xC4, 0xE3, 0xDD, 0x9C, 0x1E, 0xE3, 0x1B, 0x0E, 0x30, 0x73, 0xE5, 0x57, 0xE3, 0xDF, 0xF6,
+ 0xB4, 0x59, 0xB4, 0x6A, 0x2E, 0xCE, 0x56, 0x16, 0x66, 0xE4, 0x5E, 0x4E, 0xE1, 0xDB, 0x11, 0x2F, 0x7D, 0x4A, 0xFE, 0x0D,
+ 0xBE, 0x90, 0xCD, 0x49, 0xF0, 0x23, 0xA9, 0xA9, 0xAE, 0xC0, 0xAC, 0x26, 0x8F, 0x6D, 0x55, 0x61, 0x22, 0xD8, 0xB8, 0x2B,
+ 0x13, 0xE9, 0x72, 0xAE, 0xDD, 0x39, 0xBB, 0xEC, 0x75, 0x87, 0x19, 0xFF, 0x00, 0x27, 0x7E, 0x23, 0x74, 0xCA, 0x3F, 0x32,
+ 0xAF, 0x6B, 0x06, 0x2C, 0x59, 0x12, 0x60, 0x50, 0x75, 0x0E, 0xD8, 0x43, 0x5A, 0x97, 0xA7, 0x34, 0xE7, 0x95, 0x1D, 0x2D,
+ 0x5C, 0xD6, 0xEC, 0x63, 0x4D, 0x44, 0x55, 0x5D, 0x0F, 0xFC, 0xBD, 0xE6, 0x1C, 0xED, 0xD6, 0x4D, 0x2D, 0x2C, 0xB0, 0xBC,
+ 0xCD, 0x2C, 0x05, 0x54, 0xCB, 0x10, 0x45, 0x41, 0x09, 0xB8, 0x1B, 0xB4, 0xC5, 0x67, 0x53, 0x33, 0x6B, 0x34, 0xD5, 0xFE,
+ 0xBA, 0x2A, 0x5F, 0x65, 0x5B, 0xB4, 0xFB, 0x95, 0x25, 0xFA, 0x73, 0xAF, 0x41, 0x16, 0x8F, 0x83, 0x0F, 0x0B, 0x1F, 0x48,
+ 0xA5, 0x1A, 0x5D, 0xEB, 0xE0, 0x7E, 0xEF, 0xB7, 0x3C, 0x3E, 0xEB, 0x7C, 0xBA, 0x12, 0x6F, 0x3B, 0x97, 0xC1, 0xEE, 0xA0,
+ 0x57, 0x19, 0xB8, 0x74, 0xCA, 0xB5, 0x4C, 0x98, 0x9F, 0x31, 0x57, 0xB7, 0x87, 0x1D, 0x4D, 0xA2, 0x32, 0xFA, 0xAA, 0x5A,
+ 0x5F, 0x55, 0x90, 0xA2, 0x69, 0xD3, 0x29, 0x34, 0xFA, 0xED, 0x12, 0x84, 0xFB, 0xC8, 0xA5, 0xD7, 0xAD, 0xFD, 0x38, 0x90,
+ 0x81, 0x4C, 0x46, 0x6D, 0x7B, 0x9B, 0x2C, 0x6E, 0x4D, 0x74, 0x5B, 0xA7, 0x72, 0x9E, 0x69, 0x88, 0x3A, 0x8B, 0x88, 0xE3,
+ 0xA8, 0x85, 0xF2, 0x89, 0xAC, 0xFF, 0x00, 0xFA, 0x8A, 0xF6, 0x5A, 0x69, 0xDD, 0x5D, 0xDD, 0xBC, 0x53, 0xB8, 0x09, 0x59,
+ 0x68, 0xE9, 0xAE, 0x95, 0x89, 0x09, 0x91, 0x59, 0x8F, 0x66, 0xA4, 0x27, 0x5C, 0x80, 0xF1, 0x31, 0xE0, 0x9B, 0x57, 0xF4,
+ 0x72, 0xEE, 0x9D, 0xA7, 0xFA, 0xA3, 0xA7, 0xF5, 0xEB, 0x02, 0xF2, 0x69, 0xA7, 0x24, 0xB7, 0x4C, 0xAB, 0xB2, 0xD3, 0xF0,
+ 0x2B, 0x10, 0x52, 0xE2, 0x9A, 0x15, 0x6B, 0x62, 0xB7, 0x01, 0xD9, 0x54, 0x4B, 0x9E, 0x8C, 0xB7, 0x12, 0x52, 0x9A, 0x9D,
+ 0x16, 0x6C, 0xB6, 0x5B, 0x51, 0x0C, 0x4A, 0x11, 0xA4, 0xA5, 0x6C, 0x23, 0x5A, 0x6A, 0xA2, 0xA0, 0xAC, 0x69, 0x7B, 0x23,
+ 0xDC, 0xE7, 0x0F, 0xC1, 0x27, 0x5D, 0x74, 0x6E, 0x6D, 0x6F, 0x53, 0x22, 0x41, 0x07, 0x51, 0x05, 0x54, 0xA5, 0xFD, 0xA9,
+ 0x8C, 0x11, 0x26, 0x1C, 0x8C, 0x26, 0xA1, 0xCF, 0x0D, 0x1E, 0x01, 0xF5, 0x2B, 0x58, 0x6E, 0xBB, 0x8F, 0x47, 0x69, 0x54,
+ 0xC9, 0x72, 0x5D, 0xD5, 0x8D, 0x53, 0xD0, 0x34, 0xC0, 0x8C, 0xC4, 0x75, 0xAF, 0xC9, 0x91, 0x42, 0x99, 0x7B, 0xC9, 0xB9,
+ 0x6A, 0x2A, 0xC2, 0x4E, 0x19, 0x89, 0x6A, 0xB6, 0xDB, 0xB3, 0x9D, 0x50, 0x0D, 0xB4, 0xCB, 0x71, 0xC2, 0xD4, 0x39, 0xD1,
+ 0x95, 0x4D, 0x34, 0x51, 0x46, 0xF0, 0xFB, 0x5D, 0x55, 0x51, 0x55, 0xE3, 0xD9, 0x69, 0xEA, 0xEA, 0x89, 0x3F, 0xD3, 0x96,
+ 0x78, 0xD6, 0x55, 0xD3, 0xB3, 0xB7, 0x57, 0xE6, 0x35, 0x15, 0x52, 0x53, 0xB9, 0x53, 0x38, 0xEA, 0x0A, 0x7A, 0x60, 0xA5,
+ 0x89, 0x59, 0x85, 0x91, 0xF4, 0x9D, 0x3D, 0xBC, 0x74, 0xF8, 0x09, 0xB9, 0x7C, 0x1B, 0x78, 0x85, 0xB9, 0x34, 0xEE, 0x43,
+ 0x0F, 0x2E, 0x8F, 0x4C, 0x91, 0x32, 0x45, 0x15, 0xE2, 0x8C, 0x34, 0xFD, 0x0E, 0xE6, 0x6E, 0x3D, 0xCF, 0x4E, 0x2C, 0xAC,
+ 0x24, 0x25, 0x48, 0x62, 0xA6, 0xED, 0xD5, 0x1C, 0x04, 0x92, 0x94, 0x96, 0x79, 0x49, 0xCF, 0x50, 0x36, 0xE2, 0x9A, 0xB6,
+ 0xE2, 0x11, 0x84, 0x98, 0x86, 0xAE, 0xA2, 0x4B, 0xBE, 0xF4, 0xF9, 0xBC, 0x13, 0xC3, 0xD9, 0xFC, 0xBD, 0xFA, 0x3F, 0x30,
+ 0xF6, 0x2B, 0x40, 0xF6, 0x5F, 0x67, 0xAA, 0x8A, 0xA1, 0x2A, 0x15, 0x6E, 0x34, 0xE3, 0x0A, 0xA7, 0x9A, 0x80, 0x86, 0x14,
+ 0xCF, 0xD9, 0xE5, 0xC0, 0xCF, 0xDD, 0xE8, 0x47, 0x51, 0xDB, 0x61, 0xD0, 0x7A, 0x8F, 0x53, 0xB6, 0x38, 0xAB, 0xDF, 0x33,
+ 0x62, 0xE1, 0xDF, 0x33, 0xC8, 0xE4, 0x26, 0xD3, 0x16, 0x70, 0x00, 0xFB, 0x2F, 0xE6, 0x35, 0x13, 0x34, 0xD1, 0x48, 0x82,
+ 0x37, 0x85, 0x89, 0xB6, 0x59, 0xC1, 0xF2, 0x35, 0x11, 0x1D, 0x50, 0x2A, 0xE5, 0x24, 0x67, 0x18, 0xDC, 0x1E, 0x9D, 0x77,
+ 0x1B, 0x1F, 0x76, 0xFF, 0x00, 0x91, 0x1C, 0x39, 0x3B, 0xFA, 0x7C, 0x71, 0xEB, 0x9E, 0x38, 0xCC, 0x5B, 0x4E, 0xAA, 0x13,
+ 0xFE, 0x92, 0xC4, 0xD5, 0x55, 0x2C, 0xB1, 0x88, 0x1E, 0xF6, 0x66, 0xF0, 0x91, 0x7D, 0x06, 0xF3, 0x6B, 0x42, 0x8F, 0xD9,
+ 0xC7, 0x72, 0xA3, 0xB9, 0xED, 0xD7, 0xA6, 0x32, 0x09, 0xDF, 0x7E, 0x98, 0xDF, 0x83, 0xBC, 0x5A, 0x0B, 0x62, 0x3F, 0x9B,
+ 0x44, 0x3D, 0xB5, 0x35, 0x74, 0xDA, 0x2A, 0x54, 0xB4, 0x74, 0xC5, 0x30, 0x72, 0x25, 0x80, 0x88, 0x8F, 0x3C, 0xE7, 0x5A,
+ 0xC7, 0xD6, 0x12, 0x0F, 0x50, 0x72, 0x48, 0xC1, 0xFD, 0xDE, 0xA4, 0xFA, 0xFA, 0xE3, 0x1B, 0x9E, 0x09, 0x15, 0x84, 0x82,
+ 0x2F, 0xE5, 0xFA, 0x72, 0x4F, 0x3C, 0x76, 0xD4, 0xF7, 0xBF, 0xF7, 0xFB, 0x35, 0xAC, 0x71, 0xFC, 0x13, 0x93, 0xBE, 0xC7,
+ 0x23, 0x3B, 0xE7, 0xDF, 0xB6, 0x4F, 0xAE, 0x07, 0xE1, 0xBF, 0x0F, 0x46, 0x83, 0x5B, 0xDE, 0xF0, 0x3F, 0x1D, 0xFE, 0x03,
+ 0xAE, 0x77, 0xDF, 0xB6, 0xDB, 0xF0, 0x68, 0xD2, 0x5E, 0x7A, 0xBF, 0x79, 0x5F, 0x97, 0x06, 0x8D, 0x4A, 0xE6, 0x56, 0x09,
+ 0xC1, 0xEB, 0xD7, 0x7C, 0xF4, 0xF7, 0xA7, 0x6F, 0x5E, 0x98, 0xDB, 0x6E, 0x9C, 0x57, 0x53, 0xDD, 0x7B, 0x12, 0x91, 0xF2,
+ 0x8B, 0xBC, 0xFA, 0x1A, 0x6A, 0xB9, 0xF4, 0xF8, 0x18, 0x34, 0x98, 0x94, 0x02, 0xB2, 0x4F, 0x4F, 0x4D, 0xFA, 0x03, 0x9D,
+ 0xBE, 0x5E, 0xEF, 0x9E, 0x78, 0x95, 0x5E, 0x5E, 0xD6, 0x52, 0x49, 0x98, 0x5C, 0xA7, 0x86, 0x7E, 0x7A, 0x51, 0x36, 0x3F,
+ 0x7F, 0xDA, 0xFF, 0x00, 0x2D, 0x3A, 0x2D, 0x88, 0xD2, 0x6B, 0xF5, 0x8A, 0x65, 0x0A, 0x95, 0x06, 0xA1, 0x58, 0xAC, 0xD5,
+ 0xE6, 0x46, 0x81, 0x4B, 0xA3, 0xD1, 0xE0, 0xCA, 0xAA, 0xD5, 0xAA, 0x73, 0x66, 0x49, 0x6E, 0x24, 0x48, 0x54, 0xFA, 0x6C,
+ 0x26, 0x9E, 0x99, 0x2E, 0x64, 0xA9, 0x52, 0x18, 0x8B, 0x1A, 0x34, 0x76, 0x5C, 0x75, 0xF9, 0x2F, 0xB2, 0xC3, 0x28, 0x5B,
+ 0xCE, 0xB6, 0x95, 0x32, 0xA6, 0xE9, 0x90, 0xBD, 0x80, 0x39, 0xBD, 0xAD, 0xEB, 0xFC, 0x6B, 0x4D, 0xBA, 0x7D, 0xEA, 0xAA,
+ 0x80, 0x22, 0x9F, 0x6A, 0x00, 0x92, 0x58, 0x58, 0xE0, 0xF5, 0xED, 0x8D, 0x58, 0x9B, 0xFF, 0x00, 0xC3, 0xAE, 0xA7, 0x69,
+ 0x8B, 0xB0, 0xA9, 0x9A, 0xA3, 0xA6, 0xDA, 0x83, 0xA6, 0x35, 0x7A, 0x93, 0x2A, 0x7A, 0x9B, 0x4E, 0xD4, 0x4B, 0x36, 0xBF,
+ 0x67, 0xCA, 0xA9, 0xA1, 0x09, 0x2A, 0x5A, 0xA9, 0x82, 0xB7, 0x02, 0x1B, 0x35, 0x02, 0xD0, 0x27, 0xCD, 0x44, 0x27, 0x9F,
+ 0x71, 0x90, 0x0F, 0x9E, 0x84, 0x0D, 0x82, 0x37, 0x04, 0xCF, 0x51, 0x29, 0x33, 0x4B, 0x19, 0x12, 0x46, 0xDE, 0x3A, 0xA1,
+ 0x9B, 0x16, 0x9D, 0x5D, 0x2E, 0xD5, 0x63, 0xD2, 0xD1, 0x5F, 0x0F, 0x42, 0x31, 0x85, 0x58, 0xBC, 0xC2, 0x37, 0xB1, 0x95,
+ 0xB3, 0x15, 0x66, 0xEB, 0xA2, 0x48, 0x80, 0xB7, 0x1A, 0x71, 0x1C, 0xA3, 0x2A, 0x19, 0x23, 0xA8, 0xED, 0x92, 0xA2, 0x77,
+ 0x1E, 0x9D, 0x37, 0xD8, 0xE0, 0x1E, 0x1A, 0x1C, 0x36, 0x7C, 0xC3, 0xE9, 0x66, 0x71, 0xC9, 0xA5, 0x56, 0xD7, 0x4A, 0xB4,
+ 0xF5, 0x54, 0x49, 0xEC, 0x96, 0x4E, 0x51, 0xEF, 0x4D, 0x66, 0x2A, 0x9B, 0x7C, 0x75, 0x5F, 0xAE, 0x7A, 0x33, 0x72, 0x9B,
+ 0x79, 0x0E, 0x37, 0xE6, 0x36, 0xA0, 0x72, 0x92, 0x9C, 0xE4, 0x75, 0xE6, 0xED, 0x9C, 0x75, 0x1D, 0x30, 0x7A, 0x60, 0x90,
+ 0x38, 0xC7, 0x72, 0x92, 0xA1, 0xC6, 0x21, 0xF5, 0x2E, 0x77, 0xE6, 0x07, 0x98, 0xED, 0x7D, 0x64, 0x89, 0x12, 0x44, 0x92,
+ 0x1E, 0x38, 0xD7, 0xEF, 0x0E, 0x7E, 0x29, 0x6F, 0x9F, 0x05, 0x77, 0xE5, 0xBF, 0x39, 0x35, 0x2B, 0xAD, 0xED, 0x17, 0x87,
+ 0x74, 0x37, 0x72, 0x24, 0x5A, 0x95, 0x19, 0x14, 0xFB, 0xEB, 0x44, 0x2E, 0x67, 0x5D, 0x01, 0xED, 0x51, 0xD1, 0xAA, 0xB3,
+ 0x2A, 0xF6, 0x8A, 0x24, 0xF8, 0xF9, 0x2F, 0x5D, 0x56, 0x8A, 0x4A, 0xAD, 0xCB, 0xC6, 0x9C, 0x24, 0xC6, 0xA9, 0xD3, 0xDD,
+ 0x71, 0xC5, 0xAD, 0x58, 0xD3, 0xB8, 0xEC, 0xCE, 0xD6, 0xEC, 0x57, 0xB3, 0x52, 0xF6, 0xF6, 0x16, 0x30, 0xDA, 0x22, 0x61,
+ 0x26, 0x12, 0xD7, 0x8A, 0x87, 0x1A, 0xFD, 0x98, 0x52, 0x69, 0x42, 0x86, 0x4E, 0xAE, 0x93, 0x20, 0x9F, 0xD5, 0xB7, 0xC5,
+ 0x47, 0xBD, 0x47, 0xBD, 0x42, 0x45, 0x54, 0xD5, 0xFD, 0x04, 0xFC, 0x2C, 0xF8, 0xE2, 0xF0, 0xD9, 0xE3, 0xF7, 0x4D, 0xAD,
+ 0xBD, 0x03, 0xF1, 0xAC, 0xCE, 0x9E, 0x5C, 0xB7, 0x94, 0xDA, 0x14, 0x0B, 0xAB, 0x4E, 0x35, 0x38, 0x21, 0x34, 0x3B, 0x3F,
+ 0x58, 0x2D, 0xEA, 0x84, 0x46, 0xD7, 0x49, 0xD4, 0x4B, 0x1A, 0xB5, 0x0D, 0xD8, 0x92, 0xB4, 0xE6, 0xFB, 0x72, 0x2A, 0x90,
+ 0x8B, 0x9A, 0x87, 0x06, 0x74, 0x28, 0x8A, 0x98, 0x99, 0x49, 0x84, 0xB5, 0x40, 0x79, 0xCA, 0x4C, 0x63, 0x73, 0x63, 0x73,
+ 0x6A, 0xAE, 0xBD, 0xAB, 0xD2, 0xDC, 0x0B, 0x8D, 0x2E, 0x22, 0x72, 0x77, 0x33, 0x4F, 0x36, 0xD7, 0x2D, 0x5B, 0x75, 0xED,
+ 0xFF, 0x00, 0xCC, 0xDB, 0x92, 0x1E, 0x94, 0xCB, 0x42, 0x98, 0x52, 0x44, 0x73, 0x4B, 0xC9, 0x0D, 0xF3, 0xAE, 0x92, 0xE8,
+ 0x7E, 0x80, 0xF8, 0x3A, 0xF0, 0xA4, 0xF4, 0x8A, 0x86, 0x9A, 0x44, 0xA0, 0x33, 0x72, 0x55, 0x9B, 0x75, 0xB5, 0x5C, 0x35,
+ 0x2B, 0x91, 0x57, 0x75, 0xD2, 0xE4, 0x37, 0x92, 0xD8, 0x72, 0x24, 0x3A, 0x94, 0xB7, 0xDF, 0x34, 0xDA, 0x7B, 0x88, 0x6D,
+ 0xA4, 0xBE, 0x98, 0x0D, 0xC4, 0x13, 0x02, 0x1A, 0x44, 0xB7, 0x24, 0x06, 0xDB, 0x4A, 0x70, 0x4D, 0xFD, 0xD2, 0xF4, 0xD5,
+ 0x49, 0x00, 0xDB, 0xA4, 0x63, 0xBA, 0x67, 0x01, 0x7F, 0xF1, 0x8D, 0x7B, 0x95, 0xD6, 0x4D, 0x4A, 0x93, 0xC0, 0x04, 0xCC,
+ 0xE0, 0x01, 0x86, 0xE7, 0x6E, 0x35, 0x4B, 0x3E, 0x97, 0x0F, 0x05, 0x2C, 0xF8, 0xB3, 0xD2, 0x28, 0x5A, 0xCD, 0xA5, 0xF4,
+ 0xBF, 0xAF, 0xEF, 0xDB, 0x02, 0x9A, 0xF3, 0x75, 0x0A, 0x55, 0x39, 0x84, 0xC8, 0xA9, 0x5C, 0x96, 0x9C, 0x77, 0x17, 0x35,
+ 0xC4, 0xC0, 0x69, 0x80, 0xA7, 0x66, 0x55, 0xED, 0xF7, 0x17, 0x29, 0xF6, 0xE0, 0xA0, 0x2D, 0xF9, 0x94, 0xA9, 0xF5, 0x36,
+ 0xE2, 0x25, 0xC9, 0x88, 0x8B, 0x1D, 0xEB, 0xD9, 0xAD, 0xDB, 0xA9, 0xDB, 0xAE, 0xD0, 0xC9, 0xCF, 0x98, 0x99, 0x6C, 0xB3,
+ 0x09, 0x19, 0x78, 0xD6, 0xFF, 0x00, 0x85, 0xDF, 0xFC, 0x9A, 0xE1, 0xF7, 0x57, 0xE4, 0xDF, 0x0F, 0x03, 0xCB, 0xE0, 0xF5,
+ 0xD7, 0x8B, 0x0A, 0xCF, 0x87, 0x6A, 0xDA, 0xAB, 0x0A, 0x10, 0xA2, 0xBA, 0xA6, 0x5C, 0x79, 0x58, 0xC2, 0x15, 0xB6, 0x16,
+ 0x50, 0xA4, 0x91, 0x82, 0x52, 0xA4, 0x9C, 0x85, 0xA3, 0x62, 0x95, 0x85, 0x24, 0xF4, 0xE3, 0xB2, 0x69, 0x4B, 0x9E, 0xBE,
+ 0x1B, 0x19, 0xFB, 0xB1, 0xE3, 0x5E, 0xBB, 0x56, 0xD5, 0x41, 0x53, 0x03, 0x7B, 0x09, 0x2D, 0xBB, 0x99, 0x93, 0x10, 0xFD,
+ 0x2D, 0x78, 0xB4, 0x67, 0xE8, 0x9E, 0xD7, 0x9D, 0x67, 0xD0, 0x4D, 0x5A, 0xD7, 0xAB, 0x56, 0x05, 0x2E, 0x3D, 0xAF, 0xA5,
+ 0xB0, 0xE5, 0xBD, 0x12, 0x93, 0x54, 0x4D, 0x41, 0x37, 0x06, 0xA3, 0xCB, 0xA2, 0xC6, 0x35, 0x1B, 0xB2, 0x15, 0x94, 0xD3,
+ 0x11, 0xDC, 0x8E, 0xB5, 0x5B, 0x14, 0xA4, 0x97, 0xE5, 0x49, 0x9C, 0xE3, 0x6C, 0xD4, 0x2A, 0x59, 0xA1, 0xD3, 0xFC, 0xC9,
+ 0xCD, 0xC9, 0x31, 0xA2, 0xAD, 0xEA, 0x69, 0xAA, 0x9A, 0x3F, 0xD5, 0x84, 0xB8, 0x71, 0x78, 0x31, 0x38, 0xB8, 0xAF, 0x31,
+ 0xAC, 0x6B, 0xFC, 0x4E, 0xD5, 0x1B, 0x94, 0xED, 0xB3, 0x57, 0x5E, 0x64, 0xF6, 0x69, 0x92, 0x29, 0x91, 0xBC, 0x8E, 0x13,
+ 0x01, 0x36, 0x22, 0x79, 0xB3, 0x7B, 0x69, 0x25, 0x6E, 0x86, 0xA2, 0xE3, 0x71, 0x5C, 0x71, 0x85, 0xA4, 0x38, 0x83, 0xCA,
+ 0xA1, 0xF6, 0x14, 0x02, 0x81, 0x47, 0xD9, 0x24, 0x82, 0x92, 0x0E, 0x7A, 0x11, 0x92, 0x08, 0xCF, 0x17, 0x03, 0x8A, 0xA2,
+ 0x66, 0x46, 0x6E, 0xF6, 0x89, 0xB3, 0x68, 0xFE, 0xDA, 0xB2, 0x8A, 0x2A, 0x64, 0x4A, 0x23, 0xDE, 0x82, 0xCF, 0xFD, 0x5D,
+ 0x8F, 0x81, 0x0F, 0x1E, 0x2B, 0xCD, 0x71, 0x85, 0x53, 0x5D, 0x6D, 0x89, 0x5F, 0xB3, 0x7D, 0xF7, 0x3C, 0xA8, 0xEC, 0xE0,
+ 0x97, 0xE4, 0xBA, 0x4E, 0x03, 0x51, 0xD9, 0x40, 0x53, 0xAF, 0x2F, 0xA1, 0xF2, 0xDB, 0x42, 0x97, 0xB9, 0x18, 0xCE, 0x38,
+ 0x03, 0xA7, 0x38, 0x79, 0x8B, 0x09, 0xF3, 0xEF, 0x66, 0xDC, 0x27, 0x89, 0xAB, 0x6E, 0xAA, 0x6F, 0x0A, 0x1E, 0xF5, 0x44,
+ 0x74, 0x9D, 0xA7, 0x92, 0xC9, 0x33, 0x6E, 0xD0, 0x69, 0xA0, 0xEC, 0xB4, 0xAC, 0x73, 0x21, 0x43, 0x72, 0xAF, 0x8E, 0xC7,
+ 0x94, 0x8C, 0x60, 0x29, 0x04, 0x10, 0x52, 0xA4, 0x10, 0x08, 0x20, 0xA4, 0x80, 0xA1, 0xB5, 0x0D, 0xB8, 0xC4, 0xB9, 0x21,
+ 0x96, 0x46, 0x42, 0xE7, 0x2F, 0xC7, 0x59, 0xFC, 0x9F, 0x4C, 0x68, 0x25, 0x3E, 0x0F, 0x43, 0xF8, 0x1C, 0x7A, 0xFA, 0x12,
+ 0x78, 0x3A, 0xA9, 0xEE, 0x7C, 0xF4, 0x69, 0x3F, 0x38, 0x7B, 0xBF, 0x03, 0xC2, 0xEB, 0xA7, 0xBF, 0xE8, 0xFF, 0x00, 0x1A,
+ 0x35, 0x27, 0x2E, 0x48, 0xF5, 0xC0, 0xCE, 0x7E, 0x1F, 0x8F, 0xF2, 0x1F, 0x1F, 0x5A, 0xD1, 0xAD, 0x6C, 0xB9, 0xE5, 0xB0,
+ 0x70, 0xA0, 0x3A, 0x92, 0xA3, 0xBE, 0x36, 0x18, 0xEB, 0xEF, 0xEB, 0xD3, 0xE1, 0x81, 0xBA, 0x49, 0xCE, 0x3B, 0x4F, 0xDB,
+ 0xF0, 0x98, 0xD3, 0x42, 0x06, 0x6E, 0xCC, 0x84, 0x90, 0x63, 0x23, 0x79, 0xBF, 0xA7, 0xC7, 0x4D, 0x8B, 0x43, 0xC4, 0x5D,
+ 0x1B, 0x42, 0xF5, 0x36, 0x15, 0xD1, 0x77, 0xD4, 0xAF, 0xDB, 0x56, 0x92, 0x95, 0xDB, 0x95, 0x2B, 0x6F, 0x53, 0xB4, 0xD5,
+ 0xC5, 0x26, 0xEF, 0xD2, 0xCB, 0xF6, 0xCF, 0xAE, 0xAA, 0xB5, 0x6F, 0x5C, 0xF1, 0x5B, 0x42, 0x83, 0x8F, 0x40, 0x71, 0x52,
+ 0x5E, 0x6A, 0x58, 0x6B, 0x9D, 0x4D, 0xC8, 0x89, 0x0D, 0x4B, 0x6D, 0x49, 0x50, 0x29, 0xCB, 0xF3, 0x69, 0xA2, 0xB6, 0x9D,
+ 0xCA, 0x5F, 0xCA, 0xAA, 0x90, 0x9A, 0x61, 0xAA, 0x9A, 0xA9, 0x5B, 0xB3, 0x32, 0x43, 0x11, 0x86, 0xC4, 0x26, 0xB2, 0xAF,
+ 0x72, 0xAD, 0xB2, 0xE9, 0xD0, 0x8D, 0x29, 0x50, 0xB4, 0x22, 0x44, 0x55, 0x04, 0xD3, 0x25, 0xA4, 0xB0, 0x5B, 0xD7, 0xD5,
+ 0x9F, 0x87, 0xBF, 0xA7, 0x67, 0x4A, 0x3C, 0x44, 0x69, 0xAA, 0x34, 0x5F, 0xC5, 0x95, 0xBB, 0xA3, 0x3E, 0x39, 0xF4, 0xF6,
+ 0xAB, 0x19, 0xA8, 0x95, 0x2A, 0xBE, 0x9E, 0xD4, 0x2D, 0xFB, 0x2B, 0x5B, 0x4B, 0x49, 0x42, 0x92, 0x8A, 0xC5, 0x73, 0x43,
+ 0xAF, 0x79, 0xD4, 0x08, 0x35, 0x4B, 0xAE, 0x30, 0x52, 0x9F, 0x4D, 0xC1, 0xA6, 0x17, 0x2D, 0xBB, 0x5C, 0x44, 0xA6, 0xC4,
+ 0xA8, 0x11, 0x84, 0xB5, 0x82, 0xA8, 0x3F, 0x0F, 0x45, 0x75, 0x75, 0xFE, 0x1B, 0x76, 0x91, 0x99, 0xE9, 0x18, 0xBF, 0x9A,
+ 0x2A, 0x4A, 0x89, 0x42, 0xC2, 0x8D, 0xEC, 0x10, 0x6B, 0x9F, 0xF2, 0xCE, 0xAE, 0xBD, 0x9A, 0xEA, 0xDB, 0x78, 0x47, 0xAE,
+ 0x83, 0x88, 0xEB, 0xA1, 0xAA, 0xA0, 0xB6, 0x2A, 0xA7, 0x1E, 0x35, 0xCA, 0x6F, 0x1F, 0xBA, 0x69, 0xE1, 0x46, 0xDA, 0x88,
+ 0xFE, 0xAA, 0x78, 0x39, 0xF1, 0x15, 0x4D, 0xBF, 0xEC, 0x27, 0x6A, 0xD4, 0xF8, 0x17, 0x4F, 0x87, 0x4D, 0x5F, 0x6A, 0xA5,
+ 0xA7, 0x9E, 0x2A, 0x34, 0x6E, 0x5D, 0x72, 0x43, 0x8C, 0x53, 0xC2, 0x6D, 0x0B, 0xCA, 0x05, 0x0E, 0xAF, 0xAA, 0x36, 0x2A,
+ 0x26, 0x06, 0xE9, 0xEE, 0x5C, 0x74, 0x58, 0xD3, 0x2A, 0xD4, 0x17, 0x65, 0x40, 0x6E, 0xA7, 0x2A, 0xE2, 0x87, 0x21, 0xCA,
+ 0xEB, 0x5A, 0x1D, 0x61, 0x59, 0xBD, 0x4F, 0x4A, 0x05, 0xF0, 0x33, 0x11, 0xD0, 0x2C, 0xCF, 0x88, 0x4B, 0x49, 0x11, 0xAE,
+ 0xED, 0xAD, 0xDA, 0xDA, 0x6A, 0xA3, 0x7C, 0x6E, 0x56, 0x53, 0xBB, 0xB5, 0xD3, 0x5D, 0x15, 0x20, 0x44, 0xB4, 0xFB, 0xB5,
+ 0x0B, 0x99, 0x24, 0x11, 0xBD, 0xB5, 0xCA, 0xE6, 0xE4, 0x43, 0xAA, 0xF2, 0xAC, 0x3C, 0xCA, 0x19, 0x7C, 0x25, 0x48, 0x75,
+ 0x4B, 0x4A, 0x10, 0x52, 0xB1, 0x91, 0xF6, 0xD4, 0x40, 0x19, 0x07, 0x39, 0x38, 0xFB, 0x39, 0x38, 0x3C, 0xA4, 0x1B, 0x11,
+ 0xA4, 0x83, 0xA8, 0x83, 0x3C, 0xFA, 0xCF, 0xDC, 0xFC, 0xF4, 0x14, 0xD5, 0x5A, 0x40, 0xD6, 0xB7, 0xA9, 0x5E, 0xDE, 0xF2,
+ 0xBC, 0x73, 0x13, 0xA1, 0xEA, 0x7A, 0x40, 0xFD, 0xD9, 0x05, 0xC8, 0xF4, 0x90, 0xCD, 0x6D, 0xF9, 0x68, 0x28, 0x62, 0x9F,
+ 0x4A, 0x42, 0xAA, 0xF3, 0x65, 0xB8, 0xE7, 0xD9, 0x4B, 0x51, 0xE1, 0xC2, 0x4B, 0xEF, 0xBE, 0xE3, 0xA4, 0xF2, 0x36, 0x94,
+ 0x36, 0xA0, 0xA5, 0xE0, 0x1D, 0x8E, 0x44, 0x57, 0xB6, 0x54, 0x5E, 0xD6, 0x0B, 0x53, 0x28, 0x71, 0x19, 0x00, 0x0B, 0xC1,
+ 0x7B, 0xF7, 0xD6, 0xCE, 0xC5, 0x24, 0x35, 0x55, 0x1C, 0xC3, 0x49, 0x07, 0x89, 0xA9, 0x6C, 0xF6, 0xE4, 0xBC, 0xB1, 0xA9,
+ 0xC9, 0x8B, 0x93, 0x51, 0xBC, 0x37, 0x69, 0xB7, 0x87, 0xCD, 0x1C, 0xAB, 0x5B, 0xF7, 0x75, 0x12, 0xAB, 0xA6, 0x30, 0x2A,
+ 0xAF, 0xCE, 0xAC, 0xDC, 0x74, 0x6A, 0xCD, 0xB6, 0xE3, 0x4F, 0x5C, 0xD7, 0x15, 0x52, 0xE7, 0x8F, 0x41, 0xA1, 0x9A, 0xB4,
+ 0x58, 0x95, 0x39, 0x34, 0x3B, 0x4A, 0x34, 0xE8, 0xB4, 0xC3, 0x3D, 0xB8, 0xCC, 0x46, 0xA8, 0xBF, 0x1E, 0x52, 0xE9, 0xC5,
+ 0xC8, 0x26, 0x34, 0x97, 0x7A, 0x0E, 0x93, 0x6B, 0x6B, 0x6E, 0xEF, 0xE5, 0x91, 0x55, 0x51, 0x55, 0xA6, 0x50, 0x20, 0xB8,
+ 0x7F, 0x55, 0xA2, 0x63, 0x8D, 0x67, 0xB5, 0xB3, 0x45, 0x26, 0xE6, 0xE7, 0x50, 0xD0, 0x74, 0x80, 0x85, 0x49, 0x4D, 0x14,
+ 0xC1, 0xD4, 0x53, 0x24, 0xC4, 0x59, 0x94, 0x20, 0xE6, 0x35, 0x7B, 0x34, 0x8F, 0xE9, 0x04, 0xD4, 0x5A, 0x53, 0x16, 0xDA,
+ 0xDC, 0xB8, 0xAB, 0x55, 0x24, 0xCD, 0x6D, 0xD6, 0x24, 0x46, 0x55, 0xC4, 0xE5, 0x46, 0x40, 0x66, 0x90, 0x64, 0x3D, 0x33,
+ 0x31, 0x22, 0xC6, 0xA8, 0xF3, 0x79, 0x69, 0x8E, 0xDA, 0x9D, 0x66, 0x12, 0xA3, 0x35, 0x19, 0xB4, 0xBD, 0x1D, 0xF1, 0x1D,
+ 0xB4, 0xB8, 0x1E, 0xD2, 0x8D, 0xA2, 0xBA, 0x66, 0x94, 0xAA, 0x41, 0x61, 0x06, 0x55, 0x17, 0x88, 0xBE, 0x4E, 0x90, 0xCF,
+ 0x26, 0xB2, 0xAA, 0x8D, 0xAA, 0xBA, 0xA3, 0xA4, 0x48, 0x65, 0x12, 0xEC, 0x5D, 0x92, 0xC3, 0x29, 0x74, 0xB9, 0x36, 0x6C,
+ 0x7A, 0x48, 0xF0, 0x11, 0xF4, 0xB0, 0xD9, 0xB0, 0x51, 0x06, 0xD3, 0xD4, 0xF9, 0xD3, 0x21, 0xD1, 0x27, 0xA2, 0x29, 0x5C,
+ 0xE9, 0x05, 0x2F, 0x31, 0x4D, 0x7E, 0x40, 0x61, 0x11, 0xA5, 0xC5, 0x9C, 0xBF, 0x29, 0xC9, 0x49, 0x90, 0x5C, 0x0B, 0x79,
+ 0x87, 0x90, 0x56, 0xA2, 0xA5, 0x79, 0x13, 0x5F, 0x52, 0x3C, 0x86, 0x39, 0xBF, 0x13, 0xF8, 0x5E, 0xA2, 0x4F, 0x66, 0xA2,
+ 0x7D, 0xA7, 0x19, 0x8B, 0xDD, 0xB3, 0x1C, 0x58, 0x8B, 0x5B, 0x5C, 0x3B, 0x9B, 0x15, 0x13, 0x55, 0x1E, 0xD0, 0x4C, 0xDE,
+ 0x51, 0x1E, 0x4E, 0x24, 0x86, 0x71, 0x7F, 0x8E, 0xBA, 0x67, 0x5F, 0xF0, 0xA3, 0xF4, 0x7F, 0xF8, 0x84, 0xB8, 0x06, 0xAC,
+ 0xB3, 0x1A, 0xD2, 0x7E, 0x75, 0x72, 0x47, 0xD6, 0x75, 0x89, 0x56, 0x75, 0xF0, 0xF5, 0xA7, 0x02, 0xE3, 0x96, 0xEA, 0x92,
+ 0xEB, 0xB2, 0x6B, 0xD4, 0x28, 0x33, 0xA2, 0x34, 0x2A, 0x12, 0x4E, 0x4C, 0xE9, 0x2C, 0x46, 0x81, 0x3E, 0x52, 0xD6, 0xB7,
+ 0x25, 0xBE, 0xEB, 0xEA, 0x2E, 0x9F, 0x3E, 0x77, 0xE9, 0xB3, 0x4A, 0x85, 0xA9, 0xAA, 0x1A, 0xA0, 0x46, 0x4A, 0x6A, 0x8B,
+ 0x9F, 0xA2, 0x7C, 0x4D, 0x66, 0x6E, 0xEE, 0xD0, 0x14, 0x95, 0x20, 0x60, 0x41, 0x8F, 0x98, 0xDB, 0xB1, 0x83, 0x8D, 0x5D,
+ 0x7B, 0x3A, 0x4E, 0x92, 0xD9, 0xD4, 0x0A, 0x45, 0x8B, 0x65, 0x4C, 0xB2, 0xE8, 0x36, 0xF5, 0x0A, 0x03, 0x74, 0xDA, 0x3D,
+ 0xBD, 0x47, 0x99, 0x4D, 0x8F, 0x02, 0x0C, 0x24, 0x79, 0x98, 0x66, 0x3C, 0x74, 0x3A, 0x50, 0xA0, 0xEA, 0x94, 0xEB, 0xAF,
+ 0x38, 0xB5, 0x38, 0xEC, 0xA7, 0xDC, 0x79, 0xF9, 0x2E, 0x3A, 0xF3, 0xAE, 0xAD, 0x50, 0xD1, 0xB8, 0xCA, 0xD1, 0x5D, 0xB2,
+ 0xA3, 0x6E, 0x79, 0xE0, 0x3E, 0x44, 0x07, 0x06, 0xB3, 0x65, 0x56, 0xA9, 0x57, 0x33, 0x96, 0x7B, 0xEB, 0x99, 0xDA, 0xFF,
+ 0x00, 0xF4, 0x42, 0xF8, 0x43, 0xD4, 0x8A, 0x9D, 0x5E, 0xFD, 0x9F, 0x73, 0xDD, 0xBA, 0x45, 0x6D, 0xBA, 0xE4, 0xBA, 0xDD,
+ 0xCD, 0x06, 0xD7, 0xAD, 0x5A, 0x70, 0x2D, 0x18, 0xAC, 0x2D, 0x4A, 0x95, 0x51, 0x95, 0x06, 0x45, 0xCF, 0x44, 0xAA, 0x26,
+ 0xD9, 0x88, 0xAC, 0xBB, 0x21, 0xC4, 0x47, 0x96, 0xAA, 0x6C, 0x30, 0xA3, 0xEC, 0x91, 0x63, 0x32, 0x94, 0xB2, 0x34, 0xA3,
+ 0x7B, 0x70, 0x9A, 0x5A, 0x0A, 0x9B, 0x70, 0xCD, 0xB9, 0xB6, 0x3F, 0xB6, 0x59, 0x9D, 0x6F, 0x4F, 0xE2, 0x77, 0x40, 0xA4,
+ 0x8A, 0xDB, 0x47, 0x51, 0xD4, 0xD9, 0x22, 0x49, 0x3A, 0x83, 0xB3, 0x7D, 0x78, 0xEA, 0xFA, 0x52, 0x75, 0xA7, 0xC1, 0xBE,
+ 0x95, 0x45, 0x8F, 0xE1, 0xFF, 0x00, 0xC1, 0x0E, 0x8F, 0x5B, 0x2D, 0x50, 0x2E, 0x29, 0xAA, 0x7A, 0x7E, 0xBB, 0x5F, 0x31,
+ 0x9C, 0xBD, 0xB5, 0x93, 0x5A, 0x59, 0xB5, 0xAA, 0xAE, 0xC5, 0x95, 0x77, 0x37, 0x75, 0x5C, 0x88, 0x76, 0xA1, 0xA7, 0xFA,
+ 0x15, 0x4D, 0xB8, 0xA3, 0xAA, 0x15, 0xBD, 0x45, 0xB4, 0xE2, 0x5B, 0x55, 0x4D, 0x69, 0xB8, 0xE9, 0x4E, 0xBC, 0xF3, 0x74,
+ 0x2D, 0x3B, 0xA1, 0xD4, 0x13, 0x73, 0x75, 0x15, 0x57, 0x46, 0xDF, 0x5E, 0xEB, 0xED, 0x6E, 0x53, 0x14, 0x52, 0x47, 0x49,
+ 0x28, 0x2B, 0x30, 0xD5, 0x09, 0xDE, 0x54, 0x42, 0xC2, 0x3D, 0xF4, 0x9B, 0xB5, 0x51, 0x55, 0x7B, 0xD5, 0xAD, 0x40, 0xD2,
+ 0x6D, 0x8C, 0x51, 0x42, 0x94, 0xAD, 0x3D, 0x23, 0x0D, 0x68, 0xE5, 0x13, 0x6E, 0x1B, 0x2C, 0x47, 0x17, 0xA2, 0x4A, 0x70,
+ 0x34, 0x10, 0xEB, 0xCE, 0x48, 0x74, 0x95, 0xB8, 0xF3, 0xCE, 0xAC, 0x2D, 0xE7, 0xDE, 0x75, 0x4A, 0x71, 0xE7, 0xDD, 0x5E,
+ 0x00, 0x53, 0xAF, 0x3C, 0xA7, 0x1D, 0x75, 0x60, 0x00, 0xA7, 0x16, 0xA2, 0x12, 0x91, 0xB0, 0x54, 0xBE, 0xC8, 0xCA, 0xDA,
+ 0xF3, 0xFD, 0x4C, 0xDE, 0x6F, 0xDB, 0x3F, 0x6E, 0x9E, 0x3B, 0xE2, 0x49, 0x22, 0xCE, 0x38, 0x3E, 0xF3, 0xA3, 0x83, 0xD9,
+ 0x03, 0xAE, 0x31, 0xDB, 0x1F, 0xAE, 0xC7, 0x86, 0xE7, 0xEF, 0xF6, 0xE3, 0xB6, 0x8D, 0x61, 0xE6, 0x8F, 0x77, 0xFB, 0xC3,
+ 0xF9, 0x70, 0xB4, 0x6A, 0x44, 0x72, 0x4A, 0xBF, 0x78, 0xF5, 0xE8, 0x06, 0x33, 0xD7, 0xDF, 0x9D, 0xFD, 0xE4, 0x8F, 0x5D,
+ 0xF8, 0xE8, 0xFB, 0xF1, 0xF2, 0x9F, 0xEF, 0xA3, 0xBD, 0xBC, 0x4C, 0xF2, 0xE1, 0x88, 0xB9, 0x13, 0x24, 0x8C, 0x99, 0xD6,
+ 0xBA, 0x4B, 0xBE, 0x62, 0x31, 0x9C, 0xE3, 0xD0, 0xE7, 0x04, 0x7B, 0xF7, 0xE8, 0x73, 0xD7, 0x20, 0xEF, 0xDF, 0x83, 0xE3,
+ 0xF7, 0xF7, 0xFE, 0x74, 0x6A, 0x2F, 0xBA, 0x68, 0x4C, 0x55, 0x9A, 0x71, 0x89, 0x4C, 0x21, 0xC4, 0x38, 0x95, 0x05, 0x05,
+ 0xA7, 0x9D, 0x2B, 0x07, 0xD7, 0x3B, 0x10, 0x7B, 0x82, 0x4A, 0x76, 0x1D, 0xF7, 0xE3, 0x9A, 0xBA, 0x0A, 0xAC, 0xCC, 0x5F,
+ 0xE5, 0x6E, 0xE4, 0xFE, 0x87, 0xE9, 0x65, 0x17, 0x6E, 0xC3, 0x16, 0xE2, 0xDF, 0xB3, 0xCF, 0xF1, 0x6D, 0x56, 0xEA, 0xC6,
+ 0x86, 0x5A, 0xB2, 0xDE, 0x53, 0xE8, 0xA6, 0xA2, 0x3B, 0xE1, 0x7C, 0xED, 0xBF, 0x0C, 0xAE, 0x2B, 0xCD, 0x38, 0x14, 0x56,
+ 0x97, 0x10, 0xE4, 0x75, 0x36, 0xA4, 0x29, 0x2A, 0xDD, 0x25, 0x04, 0x28, 0x28, 0x05, 0x27, 0x97, 0x23, 0x8C, 0x5D, 0x90,
+ 0xB8, 0xA1, 0x30, 0x33, 0x51, 0x38, 0xC4, 0x7A, 0xC3, 0x11, 0xAC, 0xDD, 0x9D, 0xB5, 0x98, 0x86, 0x66, 0x45, 0xA5, 0x3D,
+ 0x3A, 0x50, 0xF8, 0xC6, 0xA5, 0xAB, 0x7A, 0xE2, 0xD6, 0xCA, 0x15, 0x32, 0x2D, 0xB6, 0x35, 0x5E, 0xE5, 0xAD, 0xDB, 0x94,
+ 0xF5, 0x05, 0x51, 0xE0, 0x5E, 0x70, 0xED, 0xFB, 0xEA, 0x5D, 0xB4, 0xB0, 0x92, 0x84, 0xBD, 0x68, 0xD7, 0x2E, 0xFA, 0x3D,
+ 0x62, 0xB9, 0x6B, 0x48, 0x65, 0x27, 0xFC, 0xDD, 0xEA, 0x3D, 0x46, 0x39, 0x8A, 0xAC, 0x3B, 0x18, 0x36, 0xF2, 0x10, 0xB4,
+ 0x69, 0x4D, 0x5F, 0x88, 0x0E, 0x93, 0x75, 0x48, 0x7A, 0x7A, 0x82, 0xB6, 0x99, 0xCA, 0x35, 0x8B, 0x4B, 0xD3, 0x37, 0x09,
+ 0x18, 0x88, 0x74, 0x8D, 0xA8, 0x7D, 0xFA, 0x92, 0xD2, 0x39, 0x81, 0x90, 0xEA, 0x89, 0x42, 0xF6, 0x55, 0xC5, 0xC9, 0x9D,
+ 0x4A, 0x5A, 0x43, 0xAB, 0x96, 0xA6, 0x8C, 0xEA, 0x4D, 0x97, 0x71, 0x5E, 0xEE, 0xD1, 0x69, 0xF4, 0x8A, 0x1D, 0x42, 0xDD,
+ 0xA9, 0x50, 0xEE, 0x2B, 0xC6, 0xC5, 0x63, 0x54, 0xB4, 0xFE, 0x8D, 0x71, 0xDB, 0xD5, 0x96, 0x2A, 0x11, 0xE0, 0xEA, 0x7D,
+ 0x81, 0x29, 0xC4, 0xAE, 0xE3, 0xD3, 0xFB, 0xA6, 0x3A, 0x3E, 0xAA, 0xB8, 0x1C, 0x8E, 0x5E, 0x97, 0x01, 0xC8, 0xF0, 0xDD,
+ 0x7D, 0xA9, 0x10, 0x25, 0xCF, 0x4F, 0x15, 0x46, 0xE5, 0x14, 0x55, 0xD1, 0xBA, 0xBD, 0x3D, 0x34, 0xD3, 0x4D, 0x64, 0xAD,
+ 0x0C, 0x16, 0xA8, 0x9E, 0x46, 0xED, 0x30, 0x96, 0x8C, 0x43, 0xA3, 0x5F, 0x42, 0x2C, 0x94, 0x23, 0x42, 0xD3, 0x53, 0x4A,
+ 0x75, 0x5A, 0x7A, 0x8F, 0x76, 0x33, 0x4A, 0x8D, 0x22, 0x7B, 0x50, 0x5F, 0x5E, 0xD8, 0xF4, 0x4B, 0xE9, 0xC0, 0xAA, 0x58,
+ 0xBA, 0x71, 0x42, 0xB9, 0x6E, 0x4F, 0x07, 0x7A, 0x1F, 0x5F, 0xA6, 0xCD, 0xA6, 0x34, 0x9B, 0x73, 0x55, 0xBC, 0x2F, 0x56,
+ 0x20, 0x43, 0xB0, 0x6B, 0x88, 0x0C, 0x24, 0x32, 0x63, 0xD0, 0xFE, 0xA4, 0x95, 0x55, 0xA2, 0x3A, 0xE6, 0x42, 0x97, 0x4A,
+ 0x15, 0x65, 0xAA, 0x38, 0x0E, 0xB4, 0x82, 0x92, 0xD7, 0x28, 0xD6, 0xAF, 0xC0, 0x55, 0x53, 0xD4, 0x6E, 0x55, 0x5D, 0x15,
+ 0x5F, 0xAE, 0x97, 0xAF, 0xA8, 0x57, 0x17, 0x2A, 0xF0, 0xD9, 0x73, 0x3D, 0xB5, 0xC8, 0xED, 0x51, 0x5D, 0x65, 0x3F, 0x9B,
+ 0x50, 0xC0, 0xF4, 0xEE, 0xD3, 0xED, 0x5E, 0xA4, 0xF6, 0x6A, 0x16, 0x8A, 0x80, 0x0A, 0xBA, 0x84, 0xB5, 0xE2, 0xDA, 0xF3,
+ 0xC1, 0xF4, 0x97, 0xF8, 0xC4, 0xB8, 0xBC, 0x6D, 0xEA, 0xD4, 0xAD, 0x40, 0xAF, 0xD0, 0xE8, 0xB6, 0xDB, 0x92, 0xD9, 0x11,
+ 0xE2, 0x00, 0xEB, 0x71, 0xE3, 0xC1, 0xA5, 0x42, 0x80, 0xB9, 0x8D, 0x31, 0xED, 0xBE, 0x6C, 0xB7, 0xA6, 0xAD, 0x84, 0x43,
+ 0x44, 0x46, 0x8B, 0x31, 0xD3, 0x29, 0x15, 0x36, 0xD0, 0xD3, 0x92, 0x62, 0x95, 0xB9, 0xC6, 0xCE, 0xD9, 0xB7, 0xB4, 0x6D,
+ 0xFB, 0xA6, 0x3D, 0xB6, 0x2A, 0x60, 0x2A, 0x55, 0x26, 0xD2, 0x42, 0x40, 0xF3, 0x33, 0x63, 0xB6, 0x9A, 0x69, 0xD8, 0xD9,
+ 0xAB, 0x6F, 0xA8, 0xA9, 0xAA, 0xA2, 0x52, 0x18, 0x7A, 0xA2, 0xAB, 0x62, 0xC1, 0x24, 0x4F, 0xA5, 0xB5, 0x41, 0x2D, 0x99,
+ 0xD1, 0x60, 0x4D, 0xF3, 0x11, 0x48, 0xA1, 0xCA, 0x2C, 0x4D, 0x75, 0x31, 0x90, 0xB9, 0x33, 0x1D, 0x5C, 0x1E, 0x68, 0x8D,
+ 0x35, 0x4F, 0x6D, 0x97, 0x91, 0xC9, 0x22, 0x50, 0x8E, 0xA6, 0x19, 0x71, 0xDF, 0x22, 0x62, 0x10, 0xD4, 0xC1, 0x24, 0x3C,
+ 0xE2, 0xE2, 0x48, 0xF2, 0xA3, 0x56, 0xDD, 0x6D, 0x0C, 0xD2, 0x02, 0x3E, 0xC8, 0xAB, 0xD3, 0x68, 0x29, 0xF3, 0x9F, 0x68,
+ 0x6D, 0x39, 0x52, 0x23, 0x9D, 0x9E, 0xE8, 0xF7, 0x2C, 0xF9, 0xC5, 0xA1, 0x72, 0x44, 0x63, 0xB6, 0xAC, 0x7D, 0x17, 0x59,
+ 0xE7, 0x44, 0xA9, 0xBD, 0x52, 0xF6, 0x18, 0x08, 0x54, 0xE7, 0x45, 0x51, 0xC6, 0x98, 0xA6, 0xAD, 0xA6, 0xD8, 0x2E, 0xB0,
+ 0x85, 0x30, 0x11, 0x04, 0xCF, 0x4B, 0x6D, 0x24, 0xCD, 0x68, 0xB8, 0xDC, 0x38, 0x73, 0xD9, 0x8E, 0xB8, 0x88, 0x6D, 0x4D,
+ 0x17, 0x9F, 0x0E, 0x46, 0x4F, 0x61, 0xBB, 0xB7, 0x5D, 0xAB, 0x2F, 0x79, 0x62, 0xD6, 0xF1, 0x2B, 0x93, 0xCF, 0x1F, 0x17,
+ 0x4F, 0xBB, 0xCD, 0x29, 0x00, 0x88, 0xCD, 0x23, 0xDA, 0xD7, 0x66, 0xF3, 0x29, 0x6E, 0x03, 0x56, 0xD6, 0xCF, 0xF1, 0x65,
+ 0x77, 0x5B, 0xCD, 0xC6, 0x9B, 0x4D, 0xB8, 0xDB, 0x8A, 0x3F, 0x62, 0x96, 0xE8, 0xD1, 0x59, 0x7A, 0x4C, 0xA5, 0x21, 0x2D,
+ 0x72, 0x00, 0x56, 0xF3, 0x4B, 0x72, 0x3B, 0x65, 0x2D, 0x97, 0xA4, 0x3A, 0xA4, 0x2D, 0x98, 0xE8, 0x52, 0x98, 0x8A, 0x66,
+ 0x48, 0x41, 0x68, 0x27, 0x67, 0x6E, 0xA2, 0x69, 0x88, 0x58, 0x22, 0x09, 0xF8, 0xF1, 0xCF, 0x07, 0xD3, 0x47, 0xB2, 0xC5,
+ 0x35, 0x27, 0x2C, 0xD5, 0x57, 0x4E, 0x5B, 0x3C, 0x7A, 0x44, 0xF1, 0x7E, 0xFA, 0x95, 0xE9, 0x9F, 0x48, 0x25, 0xF5, 0x44,
+ 0x4C, 0x89, 0x0F, 0x5D, 0x72, 0x21, 0xBC, 0xA9, 0x30, 0x54, 0x61, 0x42, 0x6D, 0x49, 0x90, 0xF3, 0x12, 0x1B, 0x68, 0x29,
+ 0xB5, 0xAB, 0x91, 0xA0, 0x95, 0x43, 0xA8, 0x05, 0x07, 0x63, 0x29, 0x4C, 0x14, 0xAE, 0x62, 0x1F, 0x93, 0x26, 0x34, 0x7F,
+ 0xD8, 0x89, 0x7F, 0x0F, 0x4C, 0x20, 0x8C, 0xAB, 0x12, 0x45, 0xC4, 0x0B, 0x5C, 0x06, 0xD7, 0xCC, 0x98, 0x9D, 0x1F, 0x97,
+ 0x4B, 0x1E, 0xCC, 0xA0, 0x84, 0xD4, 0x40, 0x4C, 0x73, 0xD5, 0xD4, 0x66, 0x1B, 0xB6, 0x8E, 0x63, 0x51, 0xF6, 0xBE, 0x7D,
+ 0x23, 0x7A, 0xB3, 0xA9, 0xBA, 0x57, 0x50, 0xB3, 0x59, 0xBE, 0xAB, 0xB2, 0xA2, 0xCE, 0xA6, 0xBE, 0xFC, 0x9A, 0x7B, 0x95,
+ 0x49, 0xD0, 0x59, 0xA9, 0xD3, 0x5B, 0x4B, 0x70, 0x90, 0x11, 0x02, 0x43, 0xC8, 0x21, 0x6F, 0x3A, 0xDC, 0x94, 0x08, 0x01,
+ 0xB4, 0x97, 0x52, 0x97, 0x24, 0xA1, 0x6F, 0x64, 0x3B, 0xC6, 0x3B, 0x9B, 0x25, 0x27, 0xFA, 0x4C, 0xCB, 0x27, 0xB3, 0x6A,
+ 0x6E, 0x30, 0x82, 0xAC, 0x0F, 0xD1, 0x75, 0xD1, 0xB1, 0xF8, 0x7A, 0x28, 0xAC, 0xAE, 0xAA, 0x69, 0xA6, 0xFE, 0x10, 0x59,
+ 0x44, 0x0F, 0x0A, 0xDF, 0x07, 0x9D, 0x71, 0x9B, 0x5A, 0xAE, 0xA5, 0xEA, 0x16, 0xA5, 0xD1, 0xEF, 0xC5, 0xB5, 0x22, 0x22,
+ 0x6A, 0x1A, 0x6B, 0x63, 0xD9, 0x52, 0x29, 0x32, 0xD1, 0xE5, 0x39, 0x6D, 0x57, 0x34, 0xF6, 0x1C, 0xCA, 0x45, 0x52, 0x88,
+ 0x59, 0xC0, 0x0C, 0x47, 0xA9, 0xC6, 0x91, 0x0A, 0xEC, 0xA5, 0xB8, 0x91, 0xE5, 0x54, 0x18, 0xAC, 0x4F, 0x71, 0x87, 0x1C,
+ 0x72, 0x14, 0xE0, 0xC7, 0x0E, 0xF5, 0x5D, 0x5B, 0xD4, 0xB4, 0x10, 0x74, 0x53, 0x49, 0x4B, 0x72, 0x8A, 0xE8, 0x1E, 0xA2,
+ 0x26, 0xE3, 0x34, 0xD6, 0x46, 0x44, 0xBF, 0x69, 0x24, 0x6A, 0xA7, 0xA9, 0xAA, 0x92, 0xBA, 0xEA, 0xA6, 0x0F, 0x69, 0x2A,
+ 0x56, 0x62, 0x4E, 0xAE, 0xD3, 0x78, 0xC7, 0x33, 0xA6, 0xEC, 0x71, 0xE5, 0xA4, 0x6E, 0x79, 0x48, 0xC8, 0x38, 0x07, 0x1B,
+ 0x6C, 0x37, 0x20, 0x63, 0xAE, 0xFD, 0x32, 0x47, 0x7C, 0xF0, 0x1E, 0xD6, 0x52, 0x40, 0x59, 0xCC, 0xCC, 0x32, 0x13, 0x10,
+ 0xDA, 0x3D, 0x2D, 0xA6, 0xFD, 0x39, 0xCF, 0xC3, 0xD3, 0xC1, 0xFC, 0x69, 0x75, 0x3E, 0x91, 0xDC, 0x10, 0x73, 0xD4, 0x63,
+ 0xE4, 0x72, 0x47, 0x4E, 0x9B, 0x67, 0x86, 0x53, 0x31, 0x09, 0x7E, 0x16, 0xFF, 0x00, 0x4F, 0x13, 0xE9, 0xA0, 0xBF, 0x11,
+ 0xE1, 0xCF, 0x89, 0xD7, 0xCF, 0x38, 0x7A, 0x1F, 0xC4, 0xFF, 0x00, 0xCD, 0xC1, 0xD3, 0xFF, 0x00, 0x55, 0x3F, 0x3D, 0x1A,
+ 0x90, 0x56, 0xF6, 0x47, 0x53, 0xD3, 0xAF, 0x41, 0x9C, 0xF7, 0xC9, 0xCE, 0x3D, 0xDE, 0xA7, 0x8D, 0xB4, 0x68, 0x65, 0xAF,
+ 0x98, 0x11, 0xBE, 0x37, 0xC6, 0xDD, 0x4E, 0xFB, 0xA7, 0x6E, 0x80, 0x75, 0xCF, 0x4F, 0x9F, 0x07, 0xD9, 0xFD, 0xFE, 0xFE,
+ 0x16, 0xBB, 0x62, 0x6D, 0x86, 0xE6, 0x64, 0xF0, 0xCF, 0x3F, 0x70, 0x6B, 0x5A, 0xF2, 0x12, 0xE7, 0x30, 0x50, 0x0A, 0xC6,
+ 0x70, 0x48, 0x19, 0x03, 0xD0, 0x75, 0xC7, 0xC8, 0xF5, 0xC7, 0x13, 0x50, 0x22, 0xF2, 0x1F, 0x4B, 0xE9, 0x6B, 0x52, 0xE4,
+ 0x06, 0x54, 0x4F, 0xD9, 0xEF, 0x9C, 0x8C, 0x1C, 0xF4, 0x20, 0x12, 0x06, 0xDD, 0xB2, 0x3F, 0x80, 0xE3, 0x26, 0x4B, 0x3A,
+ 0x1F, 0xBF, 0xBB, 0x68, 0x45, 0xD3, 0xD0, 0x91, 0xB2, 0x53, 0x8C, 0x75, 0x03, 0x18, 0x07, 0x39, 0xDC, 0x63, 0xAF, 0xAF,
+ 0x63, 0xD7, 0x7E, 0x83, 0x3C, 0xCB, 0x30, 0xE6, 0x73, 0x8F, 0x8F, 0xEB, 0xA5, 0x04, 0xCC, 0x5F, 0xBF, 0xDF, 0xDF, 0x18,
+ 0xD3, 0x02, 0xEA, 0xA2, 0xB1, 0x50, 0x88, 0xFC, 0x69, 0x2D, 0x25, 0xE6, 0x5D, 0x42, 0x90, 0xA4, 0x29, 0x21, 0x69, 0x29,
+ 0x5A, 0x79, 0x54, 0x0A, 0x54, 0x30, 0x46, 0x0E, 0x15, 0x9C, 0x82, 0x3F, 0x01, 0x15, 0xD1, 0xD6, 0xE2, 0x9B, 0x99, 0x6D,
+ 0x8C, 0x62, 0x03, 0x11, 0x7E, 0xFA, 0x12, 0x44, 0x4C, 0xF7, 0x24, 0x49, 0xB5, 0xAC, 0x27, 0xDB, 0x3A, 0xB4, 0x9F, 0x45,
+ 0xDD, 0xD9, 0x77, 0xE9, 0xE5, 0x77, 0xC4, 0x6E, 0x93, 0xBF, 0x50, 0x7E, 0x56, 0x8F, 0x9B, 0x0E, 0x15, 0xEC, 0xCD, 0x26,
+ 0xA6, 0xF4, 0x87, 0xE8, 0x54, 0x2B, 0x9E, 0x6D, 0x52, 0x45, 0x2D, 0xB6, 0x22, 0xB6, 0xEB, 0x8B, 0x87, 0x0D, 0x55, 0xA8,
+ 0xCD, 0xCA, 0x71, 0xC5, 0x29, 0x97, 0x0A, 0x5B, 0x84, 0xB9, 0x2D, 0xA3, 0xCF, 0x6C, 0xC8, 0x1D, 0x7F, 0xF0, 0xBA, 0xEB,
+ 0x2A, 0xDE, 0xDB, 0x56, 0xAD, 0xBA, 0x28, 0x2B, 0xCB, 0x14, 0xD4, 0xB0, 0x07, 0x07, 0x58, 0xBD, 0x46, 0x2D, 0x39, 0xBB,
+ 0xC5, 0xBB, 0x41, 0x4B, 0x07, 0x15, 0xD2, 0xD0, 0x02, 0xB4, 0x95, 0x75, 0x75, 0x53, 0x6B, 0x85, 0xA6, 0x0B, 0x3E, 0xA9,
+ 0xA6, 0xBE, 0xA8, 0xCA, 0x8B, 0x22, 0x7D, 0x56, 0xA3, 0x02, 0x36, 0x61, 0xB9, 0x35, 0xF4, 0x37, 0x30, 0x84, 0xC5, 0x9C,
+ 0x8A, 0x7C, 0x5F, 0xDA, 0xA2, 0x23, 0xED, 0x47, 0x8C, 0xA6, 0xFF, 0x00, 0xCE, 0xA4, 0xA5, 0x3E, 0xC8, 0xC8, 0x9E, 0xE7,
+ 0x90, 0xDA, 0x99, 0x75, 0xD6, 0x9A, 0x4C, 0x45, 0x29, 0x55, 0xBF, 0x57, 0x53, 0x30, 0x14, 0x1E, 0xCD, 0x30, 0x44, 0x52,
+ 0x37, 0x1E, 0x46, 0xAF, 0xD7, 0x9E, 0xC6, 0xFD, 0x55, 0x29, 0x2D, 0xC3, 0xB5, 0xBE, 0x91, 0x9B, 0xF7, 0xE7, 0x50, 0x83,
+ 0xD5, 0xB4, 0xC1, 0x92, 0xEB, 0xCD, 0xA9, 0xD4, 0xB6, 0x84, 0xF3, 0x36, 0xA5, 0x48, 0x4B, 0xCF, 0x3C, 0xDA, 0x96, 0xD2,
+ 0xCA, 0x14, 0xBF, 0x67, 0x05, 0x41, 0x2B, 0x4A, 0xDB, 0xF3, 0x0B, 0xAB, 0x05, 0x21, 0x7C, 0xD2, 0x9C, 0x58, 0x00, 0xE0,
+ 0x39, 0x8C, 0xCD, 0xB9, 0x83, 0x95, 0x56, 0x3E, 0x2F, 0x78, 0x94, 0xC0, 0x4A, 0xDB, 0x3F, 0x2F, 0xA6, 0x34, 0x92, 0x75,
+ 0x19, 0xF6, 0x5E, 0x4B, 0xA9, 0x7C, 0x73, 0x12, 0x14, 0xA3, 0xCD, 0xCD, 0xCA, 0x12, 0xA0, 0xB2, 0x81, 0xCC, 0x79, 0x0A,
+ 0x79, 0xB0, 0xE2, 0x10, 0x11, 0x90, 0x41, 0x2D, 0xE3, 0x9D, 0x45, 0x47, 0x5F, 0x32, 0x59, 0x52, 0x4B, 0xF3, 0x75, 0x9B,
+ 0x37, 0xBD, 0x89, 0x79, 0x89, 0x8A, 0xE9, 0x79, 0x40, 0x3B, 0xF6, 0xEF, 0x04, 0xE7, 0xD7, 0x8D, 0x6E, 0xE1, 0xEA, 0x9C,
+ 0xD5, 0xBA, 0xC9, 0x4D, 0x49, 0xE6, 0x14, 0x89, 0x0B, 0x79, 0x2F, 0xA9, 0xD7, 0x14, 0x86, 0x9F, 0x5E, 0x12, 0x99, 0x09,
+ 0x68, 0x2C, 0x25, 0x2E, 0xE0, 0x12, 0x1C, 0x29, 0x05, 0xA5, 0x80, 0xB0, 0x97, 0x1C, 0x52, 0x8A, 0x99, 0xB8, 0xA5, 0x37,
+ 0x83, 0x33, 0x2A, 0xB5, 0x70, 0xB7, 0x2A, 0x20, 0x20, 0xED, 0x7B, 0xDE, 0x74, 0x91, 0x99, 0xB2, 0xC0, 0x71, 0x31, 0x03,
+ 0x6F, 0x4E, 0xE6, 0xA4, 0x6A, 0x5D, 0xD0, 0xCC, 0xD7, 0xA2, 0x39, 0x1B, 0xDA, 0x23, 0xBC, 0xA7, 0x5B, 0x99, 0xE7, 0x41,
+ 0x88, 0x99, 0x6F, 0x48, 0x5A, 0x33, 0x09, 0xA6, 0xC3, 0xCB, 0x42, 0x9C, 0x85, 0x1B, 0xCD, 0x71, 0x2E, 0xC2, 0x8E, 0xD0,
+ 0x2B, 0x4C, 0xA5, 0x21, 0x28, 0xE5, 0x74, 0xA9, 0xA5, 0xE8, 0x6E, 0x32, 0x02, 0x9F, 0xD4, 0xC1, 0x75, 0x79, 0x3C, 0x36,
+ 0xE9, 0x0B, 0x88, 0xCC, 0xBA, 0x47, 0xD2, 0x39, 0x08, 0xF9, 0xF1, 0xDB, 0x00, 0xF1, 0x2D, 0xEC, 0x6E, 0x9C, 0xD9, 0xB5,
+ 0x6B, 0xD5, 0xEF, 0x66, 0xA4, 0x42, 0x95, 0x0A, 0xAC, 0xDC, 0x46, 0xD3, 0x1E, 0x1D, 0x4E, 0x96, 0x97, 0xCC, 0x38, 0xF1,
+ 0x60, 0x37, 0x11, 0x09, 0x94, 0xCA, 0xE4, 0x5B, 0xEF, 0xD3, 0x17, 0x10, 0xC9, 0x75, 0xE8, 0xCE, 0xCA, 0x6D, 0x71, 0xB9,
+ 0x17, 0xED, 0xB1, 0x63, 0x25, 0x0A, 0x4F, 0xB5, 0xF7, 0xED, 0x6D, 0x75, 0xD2, 0x54, 0xF5, 0x75, 0x24, 0x85, 0x44, 0xC0,
+ 0x90, 0x64, 0x1B, 0x8D, 0xEE, 0x5D, 0xEF, 0xAA, 0xA7, 0x77, 0xF2, 0xE6, 0xA5, 0x51, 0x6E, 0x75, 0x45, 0x52, 0x72, 0x37,
+ 0x82, 0x2C, 0xBF, 0xA9, 0x3A, 0xB7, 0x55, 0xB8, 0x36, 0x4D, 0x9B, 0xA3, 0xCF, 0x5B, 0xDE, 0x32, 0xBC, 0x24, 0xD9, 0xD5,
+ 0xFD, 0x3F, 0x4B, 0xCF, 0xC7, 0xB6, 0x35, 0xCE, 0x89, 0xAF, 0xB6, 0xB7, 0x87, 0x5D, 0x65, 0xB3, 0x66, 0x33, 0x22, 0x42,
+ 0x23, 0x2E, 0xDA, 0xB8, 0x6E, 0xE8, 0x95, 0x6B, 0x76, 0xEB, 0x8A, 0x95, 0x34, 0xB7, 0x93, 0x68, 0xDE, 0x34, 0x3A, 0x84,
+ 0x07, 0x88, 0x77, 0x91, 0x34, 0xD7, 0x94, 0xE3, 0xE9, 0xC3, 0xF1, 0x1B, 0x29, 0x4B, 0xD6, 0xED, 0x81, 0x01, 0x53, 0x5D,
+ 0x1B, 0x6E, 0x64, 0x26, 0xB8, 0xB8, 0x0D, 0xC5, 0xB3, 0x63, 0x53, 0x56, 0xFE, 0xD6, 0xE5, 0x4D, 0x74, 0x6E, 0x55, 0x4C,
+ 0x3E, 0xD6, 0xDF, 0x41, 0x5D, 0x19, 0xCF, 0x54, 0x9D, 0x29, 0x17, 0x4C, 0xA6, 0x1B, 0xEB, 0x9A, 0x4D, 0xDA, 0xFA, 0x15,
+ 0x73, 0x5C, 0xEE, 0xD3, 0xF4, 0xDB, 0x5F, 0xAB, 0xB3, 0xAD, 0xA5, 0xBC, 0xAF, 0x65, 0x6E, 0xAB, 0x6B, 0x69, 0x7E, 0xA0,
+ 0xDE, 0x10, 0x99, 0x27, 0x29, 0x66, 0x4C, 0x4D, 0x2A, 0xD6, 0x77, 0xD8, 0xAE, 0x3E, 0xD2, 0x70, 0x85, 0x4B, 0xA5, 0xD2,
+ 0xA1, 0x22, 0x41, 0x01, 0x69, 0x81, 0x1F, 0x98, 0xB6, 0x9E, 0x12, 0x9A, 0x15, 0xFC, 0xBD, 0xC2, 0xFD, 0xCD, 0xAA, 0xEA,
+ 0x96, 0xD1, 0xEC, 0x56, 0x4D, 0xF0, 0xF4, 0xDF, 0x96, 0x57, 0x54, 0x6E, 0xD3, 0x1E, 0xF5, 0x35, 0x36, 0x94, 0x58, 0xE3,
+ 0xC5, 0x97, 0x8E, 0x32, 0xE9, 0x83, 0xA8, 0x56, 0xDC, 0x9B, 0x0A, 0xA1, 0x23, 0xFF, 0x00, 0x10, 0xAA, 0x54, 0x2D, 0xF5,
+ 0x54, 0x69, 0xF4, 0xFA, 0x1D, 0x66, 0xE4, 0xB4, 0x65, 0x69, 0xE5, 0x4E, 0xE5, 0x72, 0x6B, 0x32, 0x9D, 0x90, 0xBA, 0x5D,
+ 0xAB, 0x55, 0xAA, 0x54, 0xEA, 0xDC, 0xB4, 0x8F, 0x65, 0x0B, 0xAA, 0xAD, 0xCF, 0x32, 0x2B, 0x51, 0xA4, 0x47, 0x90, 0x89,
+ 0x81, 0x4A, 0x11, 0x95, 0x9D, 0x65, 0x5B, 0x77, 0x57, 0xA7, 0xA8, 0x29, 0xEA, 0xA4, 0xA5, 0xA9, 0xCA, 0x53, 0x4C, 0xAC,
+ 0x05, 0xEA, 0x64, 0x19, 0x2E, 0x34, 0xB3, 0x65, 0x45, 0x8E, 0xFD, 0x99, 0xEF, 0xDE, 0x1C, 0x17, 0xB4, 0x4D, 0xA6, 0x67,
+ 0x4C, 0x0F, 0xF1, 0x96, 0x3F, 0xAB, 0x5F, 0x87, 0x07, 0xE6, 0x9F, 0xF5, 0xFF, 0x00, 0xDC, 0x7F, 0x1A, 0xAD, 0x4B, 0xA6,
+ 0x46, 0x08, 0xDF, 0xA7, 0x4F, 0x80, 0xDF, 0xB9, 0xE9, 0xF2, 0xDB, 0x8D, 0x9A, 0xC8, 0xB4, 0xDF, 0xE1, 0x1F, 0x5B, 0xE8,
+ 0x49, 0x13, 0xB9, 0x1A, 0x4C, 0xC8, 0xC6, 0x77, 0xF8, 0x9C, 0xF6, 0xF9, 0x03, 0x81, 0xBF, 0xAF, 0x07, 0x5D, 0xAC, 0x7C,
+ 0xD3, 0xFC, 0xBF, 0xBD, 0xF1, 0xA6, 0xB3, 0xD8, 0xF4, 0xF5, 0xD2, 0x66, 0x40, 0xDF, 0x71, 0xFC, 0x7E, 0x3B, 0x9F, 0x5E,
+ 0xBE, 0xFE, 0xDC, 0x4B, 0x5B, 0xDA, 0x0F, 0x9F, 0xD6, 0xDC, 0xF6, 0xD2, 0xD2, 0x45, 0xD4, 0xFC, 0x7E, 0x27, 0xBF, 0xC0,
+ 0x67, 0x3C, 0x4A, 0xAE, 0x63, 0xD7, 0x97, 0xD7, 0x4D, 0x9E, 0x67, 0xC4, 0xE8, 0x47, 0x5E, 0x4A, 0x41, 0xEF, 0x8E, 0xBB,
+ 0xE3, 0x1F, 0xAE, 0x3B, 0x75, 0xE8, 0x37, 0x38, 0x1C, 0x2B, 0xDB, 0x8E, 0xD6, 0xFF, 0x00, 0x1C, 0xFF, 0x00, 0x1A, 0x20,
+ 0x89, 0x50, 0x78, 0x32, 0xBD, 0xFD, 0x22, 0xF6, 0x72, 0x5F, 0x4C, 0x9A, 0xC4, 0xDC, 0xB7, 0x28, 0xA3, 0xCB, 0xC4, 0x76,
+ 0x83, 0xF2, 0xA4, 0x3A, 0xB2, 0xD4, 0x48, 0x2C, 0x2D, 0x61, 0xA4, 0x3D, 0x35, 0xFE, 0x47, 0x4B, 0x49, 0x75, 0xD3, 0xE4,
+ 0xC7, 0x69, 0xB6, 0xDE, 0x99, 0x31, 0xEF, 0xD8, 0x41, 0x8B, 0x25, 0xF3, 0xE5, 0x85, 0x51, 0x4C, 0x22, 0x2B, 0x66, 0xA1,
+ 0xB5, 0x24, 0x36, 0x5E, 0x7D, 0x69, 0x87, 0xA9, 0xE2, 0x72, 0x94, 0x0F, 0x3C, 0x1F, 0xF4, 0x83, 0x85, 0x82, 0xD6, 0x93,
+ 0x83, 0x1A, 0x94, 0x34, 0x62, 0xCB, 0xD6, 0x5B, 0xBE, 0x2B, 0xF6, 0xC6, 0x9A, 0xDA, 0x57, 0x33, 0x56, 0xC5, 0x66, 0xA3,
+ 0x1E, 0xB3, 0x74, 0x56, 0xD3, 0x45, 0xA8, 0xC5, 0x99, 0x76, 0x4B, 0x8C, 0x81, 0x1D, 0x89, 0x32, 0xC2, 0x19, 0x5B, 0x8C,
+ 0xD0, 0x68, 0x74, 0xFE, 0x78, 0x94, 0x6A, 0x2B, 0x6A, 0x7D, 0x31, 0x98, 0x91, 0x52, 0xA8, 0xCA, 0x7A, 0x4D, 0x56, 0xA3,
+ 0x2D, 0x51, 0xFA, 0x7F, 0x0B, 0xB5, 0xB9, 0xB9, 0xEC, 0x53, 0x4D, 0x54, 0x6D, 0xD7, 0x57, 0xE6, 0x6E, 0x56, 0x8D, 0x2D,
+ 0x49, 0x6B, 0x5F, 0xDD, 0x86, 0x29, 0xA6, 0x67, 0xA9, 0x6A, 0x4B, 0xDB, 0x0A, 0xEB, 0xA0, 0x46, 0xAA, 0xCA, 0x52, 0x49,
+ 0x88, 0xE9, 0xB7, 0x03, 0x79, 0x98, 0xF1, 0xDF, 0xCD, 0x88, 0xD5, 0x5D, 0x1A, 0xAD, 0x59, 0x74, 0x3A, 0x0D, 0x26, 0x7B,
+ 0x14, 0xF8, 0xD3, 0xA3, 0x53, 0x1B, 0xA9, 0x55, 0x63, 0xD3, 0x8C, 0xA9, 0x2E, 0xC6, 0x9B, 0x52, 0x3F, 0x5C, 0x3C, 0xF3,
+ 0xAF, 0x21, 0x58, 0x6E, 0x7C, 0xF8, 0x4F, 0xC4, 0x69, 0xF3, 0x36, 0x71, 0x7E, 0x98, 0x96, 0x55, 0x89, 0x2E, 0x38, 0xA0,
+ 0xE3, 0x9D, 0xDB, 0xBF, 0x86, 0x4A, 0x4E, 0x89, 0x20, 0xAA, 0xA6, 0x97, 0x96, 0x45, 0x66, 0xED, 0x55, 0x46, 0x2F, 0x07,
+ 0x90, 0xD4, 0xD0, 0x9B, 0x9D, 0x4D, 0x2D, 0x49, 0x31, 0x4F, 0x50, 0x52, 0xA1, 0x97, 0xB4, 0xE7, 0xBC, 0x97, 0x89, 0xD7,
+ 0x3D, 0x6F, 0x6A, 0x5C, 0x98, 0x52, 0x5D, 0x61, 0xB5, 0x2F, 0x08, 0x49, 0x0A, 0x09, 0x53, 0x89, 0x0B, 0x64, 0x82, 0xEB,
+ 0x0E, 0x29, 0x6F, 0xA1, 0x05, 0x28, 0x0D, 0xA8, 0x15, 0x25, 0x08, 0x08, 0x0A, 0x50, 0x08, 0x2E, 0x36, 0x09, 0x47, 0x8F,
+ 0xB9, 0x25, 0xAF, 0xE6, 0x0E, 0x12, 0xC5, 0xAD, 0x7B, 0x0D, 0xFE, 0x7A, 0xDA, 0x99, 0xBA, 0x04, 0x67, 0x30, 0x09, 0x98,
+ 0x61, 0xE2, 0x3C, 0x1D, 0xF5, 0x0D, 0x4A, 0xF6, 0xE2, 0xE1, 0x09, 0xF3, 0x76, 0xC9, 0xC6, 0xF8, 0x18, 0x1F, 0xBA, 0xA4,
+ 0xFA, 0x80, 0x01, 0x3B, 0x90, 0x36, 0x1C, 0xA5, 0x3C, 0x61, 0x52, 0xF9, 0x56, 0xC7, 0xF3, 0x7B, 0x58, 0xBF, 0x9D, 0x32,
+ 0x92, 0xCD, 0xB1, 0xC1, 0x9F, 0x87, 0x13, 0xCD, 0xA7, 0x89, 0xEE, 0xB4, 0x17, 0x26, 0xF9, 0x99, 0xFD, 0xA1, 0x00, 0x8C,
+ 0x9C, 0x64, 0x0F, 0xB6, 0x08, 0x04, 0x02, 0x3A, 0xA8, 0xA4, 0x00, 0x33, 0xCE, 0xA5, 0x04, 0x60, 0x1C, 0x80, 0xE9, 0x52,
+ 0x1E, 0x70, 0xFD, 0xC7, 0xED, 0xA2, 0x01, 0x18, 0x0B, 0xBC, 0xDB, 0x1C, 0xDA, 0xDF, 0x43, 0x32, 0xEA, 0xD1, 0x69, 0x64,
+ 0x07, 0xAA, 0x73, 0x19, 0x8A, 0xDB, 0xCC, 0x22, 0x51, 0x54, 0x59, 0x02, 0xA6, 0xF2, 0xA4, 0xE2, 0x0A, 0x0A, 0x10, 0x5D,
+ 0x92, 0x9E, 0x47, 0x59, 0x6A, 0x4B, 0x81, 0x28, 0xF2, 0x18, 0x8E, 0xF1, 0x41, 0x6A, 0x52, 0x82, 0x50, 0xE2, 0x12, 0x54,
+ 0xD9, 0xED, 0xD8, 0x1A, 0xEB, 0x29, 0xA6, 0xF5, 0x35, 0x28, 0xDC, 0x02, 0x61, 0x65, 0x60, 0x00, 0xB8, 0x1D, 0xA2, 0xD1,
+ 0x19, 0xA2, 0xCF, 0x48, 0xCE, 0x22, 0x03, 0xDA, 0xE0, 0x8E, 0x06, 0x18, 0x6F, 0x3D, 0xF9, 0xD7, 0x70, 0xFC, 0x2D, 0xDB,
+ 0xF4, 0xFA, 0x53, 0xB4, 0xA9, 0x93, 0xD8, 0x72, 0x44, 0x86, 0x56, 0x84, 0xCC, 0x44, 0xEA, 0x6D, 0x45, 0x97, 0x5D, 0x4A,
+ 0x14, 0xE2, 0xA5, 0xD5, 0x62, 0xB0, 0xD4, 0xF7, 0x98, 0x6D, 0x6F, 0xC2, 0x90, 0x89, 0x0F, 0x33, 0x25, 0x99, 0x08, 0x90,
+ 0xE4, 0x99, 0x0E, 0x37, 0x1F, 0xCD, 0x25, 0xF7, 0xFD, 0xFA, 0x08, 0x04, 0x9C, 0x86, 0x2A, 0x88, 0xC1, 0x67, 0x93, 0x2D,
+ 0xEC, 0xAE, 0x6D, 0x3C, 0xDB, 0xE9, 0x36, 0x98, 0xB4, 0x34, 0xB3, 0x4F, 0x22, 0x3F, 0x19, 0x33, 0x18, 0x09, 0xD7, 0x24,
+ 0x7E, 0x95, 0xEA, 0x9D, 0xDD, 0xAB, 0x5E, 0x37, 0xAE, 0x4B, 0x6E, 0xEC, 0x97, 0x21, 0xDB, 0x07, 0x4B, 0xEC, 0xDB, 0x1A,
+ 0x1E, 0x9E, 0x5B, 0xA0, 0xA4, 0x51, 0x58, 0x83, 0x70, 0xD1, 0xBE, 0xBA, 0x99, 0x55, 0x62, 0x1B, 0x63, 0xD9, 0x9E, 0x91,
+ 0x2E, 0x5B, 0xAF, 0x47, 0x71, 0xF2, 0x16, 0x53, 0xEC, 0xDE, 0xCA, 0xA2, 0x93, 0x14, 0xB6, 0x3E, 0x7F, 0xFE, 0x24, 0xD7,
+ 0x5F, 0xE2, 0x29, 0xDB, 0xBF, 0x45, 0x1B, 0x74, 0x34, 0x8E, 0x26, 0xB5, 0x54, 0x8C, 0xB6, 0x89, 0x8E, 0x23, 0xC6, 0xAB,
+ 0xF0, 0xFB, 0x54, 0xD7, 0x45, 0x2F, 0x4F, 0x13, 0x51, 0x71, 0xAB, 0x71, 0x5F, 0x69, 0xB7, 0x14, 0x94, 0xD2, 0x46, 0x21,
+ 0xB0, 0xBA, 0xA3, 0x67, 0x4F, 0xE8, 0x52, 0x59, 0x43, 0x4F, 0xD2, 0x62, 0x3C, 0xDA, 0x31, 0xC8, 0x97, 0x63, 0x32, 0xE7,
+ 0x21, 0x03, 0x00, 0xA4, 0x2D, 0xB5, 0x04, 0x9D, 0xF7, 0x23, 0x04, 0x76, 0x23, 0x1C, 0x70, 0x74, 0x01, 0x7B, 0x7D, 0x08,
+ 0xE2, 0xFC, 0x7A, 0xEB, 0xAB, 0xA0, 0x48, 0x4A, 0x78, 0x0B, 0x7D, 0x3E, 0x9F, 0x09, 0xB8, 0xC6, 0xB7, 0xD4, 0x6B, 0x3A,
+ 0x93, 0x45, 0x74, 0x48, 0x85, 0x05, 0x96, 0x9F, 0xE4, 0x0D, 0x07, 0x42, 0x79, 0x9D, 0x0D, 0x8C, 0xA8, 0x34, 0x16, 0x41,
+ 0x52, 0x5A, 0x18, 0x04, 0x36, 0x08, 0x40, 0x56, 0x0F, 0x28, 0xC6, 0x78, 0xA0, 0x2C, 0xC4, 0x29, 0x69, 0xCE, 0x03, 0x9C,
+ 0x62, 0xF1, 0xCF, 0x9D, 0x32, 0x8A, 0x69, 0x94, 0x01, 0xE5, 0xE6, 0x3F, 0x63, 0x94, 0x3E, 0x5A, 0x70, 0xFB, 0x10, 0xFD,
+ 0xD5, 0xFE, 0x23, 0xF9, 0x70, 0x41, 0xD8, 0xF9, 0x1A, 0x26, 0xAF, 0xF4, 0xFF, 0x00, 0xF2, 0x35, 0x3A, 0x2A, 0x46, 0x06,
+ 0x4F, 0xC3, 0xF8, 0x01, 0xDF, 0xE5, 0x8C, 0xF1, 0xD3, 0x9D, 0x56, 0x81, 0x91, 0x50, 0x6D, 0x94, 0xAD, 0x6E, 0x2C, 0x25,
+ 0x09, 0x49, 0x52, 0x94, 0xB5, 0x84, 0x24, 0x04, 0xEE, 0x54, 0x54, 0xAC, 0x00, 0x00, 0xDF, 0x24, 0xA4, 0x6D, 0xE8, 0x37,
+ 0x69, 0x01, 0x73, 0xBE, 0x70, 0x3D, 0xF8, 0x3F, 0xBF, 0x64, 0xD3, 0xE3, 0x82, 0x79, 0x81, 0x4F, 0xDF, 0xE1, 0x69, 0xD0,
+ 0x48, 0xAB, 0x07, 0xDD, 0x43, 0x31, 0xE3, 0xBE, 0xFB, 0x8E, 0x14, 0xA1, 0xB4, 0x36, 0xC3, 0xAB, 0x5B, 0x85, 0x5F, 0x71,
+ 0x2D, 0x24, 0xA1, 0x2A, 0x75, 0x6E, 0x67, 0x0D, 0xA1, 0xA0, 0xE2, 0xDC, 0x27, 0x0D, 0xA5, 0x44, 0xA4, 0x70, 0x0A, 0x90,
+ 0x4C, 0x66, 0x0F, 0xD3, 0xE1, 0x3F, 0xCD, 0xF4, 0x0B, 0x70, 0xAE, 0xAC, 0xF1, 0x34, 0x91, 0x30, 0x93, 0xD4, 0x90, 0xF2,
+ 0x27, 0xAF, 0x2E, 0x96, 0x66, 0x72, 0x5D, 0x4F, 0x3A, 0x56, 0x14, 0x08, 0x18, 0x20, 0x91, 0x9D, 0x89, 0xCE, 0x0E, 0xE9,
+ 0xC7, 0x70, 0x7A, 0x67, 0xA0, 0x24, 0xF0, 0x8B, 0x84, 0x4D, 0xEE, 0x59, 0x08, 0x6D, 0x2A, 0xC4, 0x71, 0xF6, 0x20, 0x9F,
+ 0x8D, 0xFB, 0xF7, 0xE7, 0xED, 0xD2, 0x72, 0x5F, 0x25, 0x0A, 0xC2, 0xBA, 0xFC, 0x77, 0xCF, 0x4F, 0x87, 0xE3, 0x9F, 0x5E,
+ 0xBC, 0x0D, 0xA6, 0x78, 0x17, 0x3E, 0x3C, 0x4F, 0xDF, 0x6D, 0x1A, 0x8B, 0x2B, 0x17, 0x9E, 0xAC, 0xD9, 0xDF, 0x5B, 0x7F,
+ 0x93, 0x6B, 0xAA, 0x25, 0x03, 0xEB, 0x77, 0x60, 0xCA, 0x94, 0x67, 0x5A, 0xF4, 0x0B, 0x85, 0xE6, 0xA6, 0xD3, 0x98, 0x91,
+ 0x1E, 0x2C, 0xEA, 0x5C, 0x8A, 0xCC, 0x39, 0x4F, 0x53, 0x24, 0x26, 0x3C, 0x97, 0x59, 0x5A, 0xE3, 0x92, 0x85, 0x21, 0x7C,
+ 0xC1, 0xB6, 0xDE, 0x2B, 0x71, 0x79, 0xF5, 0xEF, 0xED, 0x4F, 0x45, 0x41, 0xD6, 0x8D, 0x50, 0x53, 0x54, 0x21, 0x02, 0x54,
+ 0x8C, 0x59, 0x4B, 0x5E, 0xD3, 0x9D, 0x67, 0x5D, 0x35, 0x55, 0x3D, 0x28, 0x0E, 0x7A, 0x89, 0xE2, 0x2C, 0x11, 0x7B, 0xF2,
+ 0xB8, 0x3B, 0x6B, 0x7D, 0xA2, 0x5F, 0x48, 0x8F, 0x8D, 0x2F, 0x0D, 0x77, 0xD5, 0x1E, 0xED, 0xB8, 0x2F, 0x97, 0x35, 0x4F,
+ 0x4F, 0xA3, 0xCD, 0x61, 0xBB, 0xCA, 0xC9, 0xB9, 0xA9, 0x94, 0xB7, 0xE0, 0xD5, 0xED, 0x97, 0x1E, 0x6C, 0x55, 0xE1, 0xC6,
+ 0x53, 0x30, 0xA1, 0xCB, 0xA6, 0xBE, 0xEC, 0x20, 0xEA, 0x18, 0x7A, 0x24, 0xC4, 0x21, 0xB5, 0x10, 0x97, 0x1B, 0xF2, 0x56,
+ 0xE7, 0x17, 0xB1, 0xF8, 0xFD, 0xFD, 0xBD, 0xCA, 0x4A, 0xF7, 0x1A, 0xE8, 0x6A, 0x06, 0x9A, 0xA1, 0xCC, 0x13, 0x4A, 0x0A,
+ 0x54, 0x71, 0x1E, 0x91, 0xAE, 0x3A, 0xF6, 0x9C, 0xEE, 0x14, 0xD5, 0x4C, 0x9E, 0xD5, 0x27, 0x4D, 0x74, 0xE3, 0xDA, 0x12,
+ 0x04, 0xA6, 0xD3, 0x4C, 0x55, 0x38, 0xF4, 0xF5, 0xD9, 0xAB, 0xB6, 0x0D, 0x95, 0xAE, 0x5A, 0x67, 0x68, 0xEA, 0x25, 0x9D,
+ 0x6A, 0x51, 0x28, 0xF4, 0xAD, 0x40, 0xB5, 0xE8, 0x57, 0xAD, 0x36, 0x8F, 0x16, 0xD6, 0x7E, 0x5B, 0x10, 0x95, 0x59, 0xA7,
+ 0xC1, 0xA8, 0x47, 0x8B, 0x51, 0xA8, 0xA5, 0x94, 0x2D, 0xD7, 0x52, 0xF3, 0xAD, 0xC6, 0x53, 0x9E, 0x4B, 0xCD, 0x53, 0x12,
+ 0xCB, 0x52, 0xE4, 0xBB, 0x24, 0xB8, 0x5F, 0x8F, 0xF4, 0x65, 0x42, 0x46, 0x66, 0x2A, 0x17, 0xCD, 0xA5, 0xF1, 0x10, 0xF2,
+ 0x5C, 0xCF, 0x1C, 0xF4, 0x57, 0x56, 0xDD, 0x68, 0xB3, 0x55, 0x15, 0x74, 0xFB, 0xD1, 0x3D, 0x28, 0x79, 0x11, 0x2E, 0x4D,
+ 0xD1, 0x33, 0x1A, 0xF3, 0xFB, 0xAF, 0x3E, 0x18, 0xEB, 0x74, 0x7A, 0xAD, 0x46, 0x7B, 0x8C, 0x34, 0xCC, 0x64, 0x4F, 0xA8,
+ 0x45, 0x50, 0x82, 0x2A, 0x13, 0xA4, 0xB6, 0xEC, 0x4E, 0x64, 0xF9, 0x2D, 0xB8, 0xE4, 0x44, 0x38, 0x63, 0xBA, 0xEA, 0xDF,
+ 0x53, 0x02, 0x3B, 0x2E, 0x08, 0xE7, 0xCA, 0x69, 0x2F, 0x37, 0x4F, 0x42, 0x65, 0xBF, 0xE7, 0xFE, 0x27, 0xF0, 0xA5, 0x6B,
+ 0x55, 0x16, 0x99, 0x9A, 0x41, 0x65, 0xE1, 0xA6, 0x3F, 0x73, 0x37, 0xF4, 0xF5, 0x76, 0xEB, 0xA7, 0x70, 0x23, 0xDE, 0xB6,
+ 0x52, 0x1C, 0xAC, 0x19, 0xB3, 0x03, 0x2D, 0xED, 0x05, 0xB5, 0x4C, 0x6A, 0x3A, 0x62, 0xEC, 0x62, 0xB0, 0xEB, 0x4A, 0x8C,
+ 0x3C, 0xE7, 0x1B, 0x1E, 0x73, 0x6E, 0xBA, 0xEA, 0x56, 0x16, 0x86, 0x94, 0xA7, 0x79, 0x46, 0x53, 0xC8, 0xB7, 0x08, 0x50,
+ 0x71, 0xB6, 0xD0, 0xDA, 0x81, 0x40, 0x23, 0x64, 0x27, 0xCC, 0xAF, 0xF0, 0xF1, 0x66, 0x68, 0xCC, 0x95, 0x17, 0x62, 0x2F,
+ 0xDE, 0x4B, 0x4D, 0xA0, 0xEC, 0x91, 0xAB, 0xC6, 0x6D, 0xEB, 0x9C, 0x4F, 0xF3, 0xDF, 0x58, 0xC7, 0xD3, 0x07, 0x70, 0x30,
+ 0x5B, 0x47, 0x92, 0xA5, 0x2D, 0xC3, 0xE6, 0x29, 0xD5, 0xF9, 0x4C, 0xF2, 0xF3, 0xCA, 0x0D, 0xA5, 0xA2, 0x84, 0xB2, 0x85,
+ 0xAD, 0x0D, 0xBB, 0x2B, 0xCE, 0x48, 0x61, 0x4F, 0xB2, 0x14, 0x1A, 0x0A, 0xE6, 0x35, 0x46, 0xC5, 0x49, 0x61, 0xAA, 0xAB,
+ 0x36, 0x16, 0x70, 0x90, 0x18, 0x9C, 0x37, 0xFD, 0xCD, 0x1C, 0x0E, 0x67, 0x11, 0x9F, 0x90, 0x2F, 0xC2, 0xDD, 0xFD, 0x6E,
+ 0xEF, 0x84, 0xAD, 0x16, 0x7E, 0xB5, 0xA8, 0x94, 0x8A, 0x64, 0xA8, 0xD1, 0x1E, 0x8F, 0x53, 0x90, 0xC2, 0x1B, 0x71, 0xE4,
+ 0xBA, 0xDD, 0x3D, 0xD6, 0x56, 0x03, 0xAF, 0xB0, 0xFB, 0x6D, 0xC5, 0x90, 0xA7, 0xE3, 0x36, 0x12, 0xE9, 0x96, 0x5B, 0x41,
+ 0x9D, 0xEC, 0xCD, 0x3E, 0xFC, 0x26, 0xFC, 0xF6, 0xD8, 0x4C, 0xBF, 0x53, 0xF0, 0x9B, 0x1F, 0x97, 0xED, 0x56, 0x5D, 0x22,
+ 0x92, 0x09, 0xA4, 0x62, 0x66, 0x26, 0xFC, 0x46, 0x42, 0x4C, 0xE3, 0x0D, 0xEA, 0xBA, 0x28, 0x6A, 0xF6, 0x86, 0xE5, 0xAD,
+ 0x50, 0x7A, 0x88, 0x8B, 0x08, 0x07, 0x74, 0x60, 0x35, 0xDB, 0xFD, 0x49, 0xA2, 0x78, 0x76, 0xF0, 0xED, 0x65, 0xC6, 0x63,
+ 0x57, 0xB5, 0x4E, 0xC5, 0xD3, 0x76, 0xE4, 0x25, 0xF9, 0x14, 0xF6, 0x2E, 0x1B, 0x8D, 0x98, 0x0E, 0x4A, 0x9C, 0xD7, 0x97,
+ 0x4F, 0x8D, 0xEC, 0x71, 0xBF, 0x65, 0x2E, 0x1C, 0x16, 0x16, 0x95, 0x42, 0x87, 0x10, 0x34, 0xA0, 0x21, 0x25, 0xDA, 0x95,
+ 0x40, 0xA1, 0xE9, 0x5E, 0xC8, 0xC7, 0x65, 0x7B, 0x94, 0x51, 0x2D, 0x4D, 0x34, 0x04, 0xCD, 0x55, 0x21, 0x19, 0xE5, 0xB0,
+ 0x67, 0x04, 0xBE, 0xBA, 0xF3, 0x4F, 0xCD, 0xDC, 0x5A, 0xA9, 0x14, 0xCD, 0x55, 0x16, 0x0E, 0x73, 0x55, 0xBD, 0x26, 0x15,
+ 0x10, 0x1C, 0xEB, 0x81, 0x7E, 0x31, 0x69, 0x0C, 0xDD, 0xD5, 0xBA, 0x3E, 0xA7, 0x5B, 0xD5, 0x6A, 0x2D, 0xEF, 0x46, 0x81,
+ 0x4B, 0x9B, 0x4B, 0xA3, 0xDE, 0xB6, 0xAC, 0xD6, 0x6A, 0xF4, 0x8B, 0xB3, 0x4F, 0xE3, 0x4C, 0x91, 0x54, 0x6A, 0x3F, 0xB5,
+ 0x44, 0x53, 0xA9, 0x15, 0xEB, 0x12, 0x5C, 0x9A, 0x84, 0xD5, 0xC1, 0x77, 0xCB, 0x95, 0x26, 0xD5, 0xAB, 0x54, 0x1C, 0x6D,
+ 0xA1, 0xF5, 0x12, 0x5A, 0x57, 0x93, 0xFF, 0x00, 0x10, 0x0D, 0xD6, 0x8D, 0xFA, 0x3A, 0x6A, 0xA6, 0x91, 0xA5, 0xDC, 0xA1,
+ 0xEA, 0xA6, 0xAA, 0x4B, 0xC0, 0x96, 0xEB, 0xA1, 0x6A, 0x43, 0x2D, 0x2B, 0x7B, 0x4E, 0xBB, 0xF6, 0x52, 0x3A, 0x59, 0xA1,
+ 0x8B, 0xD3, 0x84, 0x62, 0xC8, 0xCC, 0x34, 0xB7, 0xF4, 0x60, 0x9C, 0x85, 0x33, 0x61, 0xA6, 0x9C, 0x42, 0x4A, 0x4A, 0x14,
+ 0x92, 0x32, 0x08, 0xE5, 0x29, 0x52, 0x4E, 0xE1, 0x49, 0xC1, 0xC2, 0xB6, 0x3B, 0x28, 0x64, 0x11, 0x8D, 0xC8, 0x3C, 0x79,
+ 0xEB, 0x4F, 0xB2, 0x9D, 0x99, 0x96, 0xEB, 0xC3, 0x27, 0x7C, 0xFD, 0x6D, 0xAE, 0x99, 0xC6, 0x3E, 0x7F, 0x28, 0xB5, 0xE7,
+ 0x4B, 0x79, 0x48, 0x3B, 0x1C, 0x9E, 0x9B, 0x02, 0x13, 0xD0, 0x77, 0xDB, 0xB7, 0x7F, 0x86, 0x4F, 0x4E, 0x17, 0x53, 0xD8,
+ 0x5F, 0x8A, 0xFE, 0xAC, 0xE8, 0xCE, 0x38, 0x7C, 0x9F, 0xE4, 0xFD, 0x1D, 0x25, 0xE4, 0xA3, 0xF7, 0xFF, 0x00, 0x4E, 0x1F,
+ 0x53, 0xFF, 0x00, 0xEA, 0x7E, 0x46, 0x88, 0x3C, 0xFC, 0xDF, 0xE7, 0x4F, 0xC7, 0x64, 0x10, 0x9D, 0x8E, 0xE0, 0x7F, 0xD0,
+ 0xC1, 0xFE, 0xE1, 0xDB, 0xAF, 0x4D, 0x7F, 0x4F, 0x3A, 0x7F, 0x7F, 0x7F, 0xE1, 0xD3, 0x7C, 0x5C, 0xD1, 0xAD, 0xAA, 0xE5,
+ 0x2E, 0xB3, 0x56, 0xB7, 0x25, 0xDD, 0xB4, 0x78, 0xA9, 0x9C, 0x26, 0x51, 0xE9, 0xF3, 0x62, 0x53, 0xEA, 0x05, 0xE9, 0x10,
+ 0x5E, 0x8F, 0x02, 0xA5, 0x05, 0xFA, 0x8B, 0x6F, 0x40, 0x72, 0x55, 0x26, 0x5B, 0x8D, 0xCA, 0x62, 0x3C, 0xD6, 0xFC, 0x95,
+ 0x2D, 0x29, 0x79, 0x2A, 0x4B, 0xF1, 0xD8, 0x26, 0x3A, 0xA8, 0x2A, 0xA5, 0x68, 0x6A, 0xA4, 0xEA, 0xA5, 0x24, 0xBC, 0x8F,
+ 0x4A, 0x0B, 0x0F, 0x4B, 0xCB, 0x99, 0x7D, 0x35, 0x35, 0x2C, 0x7B, 0x22, 0xDE, 0x19, 0x41, 0xC0, 0xC9, 0x72, 0xCF, 0xA9,
+ 0x68, 0xCE, 0x9B, 0xAF, 0xDE, 0xD1, 0x27, 0x4A, 0x6C, 0xD9, 0x3A, 0x6E, 0xAB, 0x39, 0x48, 0x7C, 0xC9, 0x6E, 0xE5, 0xBD,
+ 0x2E, 0xC9, 0xD7, 0xED, 0xD7, 0x12, 0x41, 0x51, 0x57, 0xB5, 0xD1, 0xE1, 0xA9, 0x31, 0x6D, 0x8A, 0x3D, 0x49, 0x0B, 0xFD,
+ 0xA3, 0x15, 0x69, 0x11, 0xAB, 0xD3, 0xA2, 0x3C, 0x11, 0x22, 0x12, 0xA3, 0x49, 0x43, 0x4F, 0x36, 0xBA, 0xC5, 0xFF, 0x00,
+ 0x97, 0xB5, 0xD2, 0xDB, 0xDA, 0xAD, 0x6B, 0xAE, 0xD7, 0x50, 0xF7, 0x69, 0x78, 0x98, 0x6D, 0xE9, 0xA9, 0x29, 0xA9, 0x01,
+ 0xF6, 0x48, 0x84, 0x61, 0x5F, 0x58, 0x63, 0xC6, 0x5B, 0x5B, 0xD5, 0xC3, 0x4B, 0xC4, 0x78, 0xCD, 0x34, 0x0A, 0xD7, 0xE5,
+ 0xA4, 0x27, 0x2B, 0x52, 0x94, 0xE2, 0xF6, 0xC8, 0x2B, 0x52, 0xCA, 0x94, 0xA5, 0x91, 0x9E, 0x75, 0xAC, 0x95, 0xA9, 0x44,
+ 0xA9, 0x45, 0x4A, 0x24, 0x9A, 0xA7, 0xAB, 0xD9, 0x3D, 0x92, 0x94, 0x73, 0x33, 0x9A, 0x8E, 0xF6, 0xC2, 0xB9, 0x21, 0x6C,
+ 0x26, 0xB4, 0x24, 0xED, 0x80, 0xB7, 0xDE, 0x31, 0xAD, 0x9A, 0xD7, 0xCC, 0x83, 0x9E, 0xE7, 0x3B, 0x8D, 0xF6, 0xEB, 0xB0,
+ 0xEC, 0x00, 0x27, 0xFE, 0xFC, 0x3A, 0x9E, 0x9E, 0x7E, 0x4C, 0xDB, 0x9C, 0x77, 0x2D, 0xF1, 0xBD, 0xB4, 0xD6, 0xC7, 0x19,
+ 0x83, 0x31, 0xF1, 0xF3, 0x13, 0x1F, 0xCE, 0x9A, 0x75, 0x87, 0x21, 0xA5, 0x3F, 0xB6, 0x75, 0x09, 0x51, 0xD9, 0x09, 0x39,
+ 0x52, 0xD4, 0x54, 0x79, 0x40, 0x0D, 0xA4, 0x17, 0x09, 0x52, 0xF2, 0x94, 0xA4, 0x03, 0xCC, 0xAD, 0x80, 0x2A, 0xC6, 0x33,
+ 0x9A, 0x25, 0xF6, 0x5B, 0xF0, 0x22, 0x8D, 0xAC, 0x4D, 0xB1, 0x8C, 0x5E, 0xF1, 0x1A, 0x99, 0x08, 0xBE, 0x66, 0xF1, 0x6F,
+ 0x17, 0xFE, 0x4F, 0x8F, 0x72, 0x2D, 0x4D, 0x37, 0xA5, 0xDC, 0x57, 0x75, 0x2E, 0x99, 0xA9, 0x54, 0xEA, 0x85, 0xBF, 0x62,
+ 0x45, 0x61, 0xAB, 0x9A, 0xF3, 0x5D, 0x69, 0xA7, 0x2D, 0xB4, 0x0B, 0x2E, 0x23, 0xE8, 0x72, 0x64, 0xCA, 0xDD, 0x56, 0xA8,
+ 0x86, 0x5B, 0xB5, 0xAD, 0xAA, 0x82, 0x40, 0x86, 0xE5, 0x62, 0x4A, 0x17, 0x52, 0xAA, 0x21, 0xE5, 0x53, 0x6D, 0x7A, 0x7C,
+ 0xEA, 0x9C, 0x96, 0x9E, 0x8B, 0x5B, 0x5B, 0x45, 0x7B, 0x94, 0x1B, 0x83, 0x4D, 0x07, 0xB7, 0x5C, 0xD9, 0x28, 0xA5, 0x65,
+ 0xA9, 0x6D, 0x45, 0x32, 0x47, 0x53, 0x7A, 0x94, 0x29, 0x1D, 0x67, 0xB8, 0x85, 0x0A, 0x45, 0xC8, 0x2E, 0x5F, 0x96, 0xD3,
+ 0x0C, 0x3C, 0xB6, 0x2E, 0xBE, 0xCC, 0xCF, 0xA3, 0x2F, 0x0C, 0x1F, 0x4E, 0x0F, 0xD1, 0xF7, 0x22, 0xB5, 0x41, 0xD1, 0x8B,
+ 0xD9, 0xEA, 0xF5, 0x0A, 0x8F, 0x02, 0x64, 0x3A, 0x15, 0xB9, 0x7C, 0x55, 0x2D, 0xF9, 0x34, 0xEB, 0x1E, 0x33, 0x0C, 0xB6,
+ 0xDD, 0x22, 0x28, 0x69, 0xA5, 0x4E, 0x8F, 0x26, 0x1C, 0x16, 0x58, 0x75, 0x6D, 0xC7, 0x7A, 0xA6, 0xB8, 0xC9, 0x55, 0x39,
+ 0xA6, 0x61, 0x8F, 0x66, 0x0E, 0x3A, 0xF0, 0xF6, 0x28, 0xFC, 0x7F, 0xE1, 0xEB, 0x7A, 0x29, 0xAC, 0x16, 0xAF, 0x65, 0xAE,
+ 0x96, 0x8A, 0x53, 0x19, 0xE0, 0x70, 0x12, 0x36, 0xC1, 0x83, 0xCB, 0xAF, 0x69, 0xAA, 0xA6, 0xAA, 0x77, 0x69, 0x6B, 0x6E,
+ 0xD3, 0x28, 0xB5, 0x66, 0xCD, 0x41, 0x4B, 0x57, 0x6B, 0xB2, 0x31, 0x4C, 0xEB, 0xA9, 0x1A, 0xC5, 0xE0, 0xCB, 0x4F, 0xF5,
+ 0x86, 0x93, 0x4F, 0xBD, 0x74, 0xC1, 0xB7, 0xAA, 0x90, 0x2A, 0x6B, 0x4D, 0x55, 0xF9, 0xF1, 0x98, 0x75, 0xFB, 0x6A, 0x5D,
+ 0x3A, 0x7C, 0x90, 0xA8, 0xDE, 0xD0, 0xFB, 0x0A, 0x92, 0x86, 0x55, 0x3E, 0x24, 0xBC, 0x46, 0x89, 0x4F, 0x4A, 0x22, 0xC7,
+ 0x53, 0x71, 0x9A, 0x62, 0x3C, 0x96, 0x50, 0x24, 0xAB, 0xAC, 0xA8, 0x6C, 0x84, 0x8F, 0x7E, 0x08, 0x3C, 0x49, 0xC7, 0xCB,
+ 0x12, 0xCC, 0xED, 0xEE, 0xEE, 0x6D, 0xA9, 0x72, 0x31, 0xC5, 0x42, 0x99, 0x93, 0x9E, 0x6F, 0x1F, 0x3D, 0x50, 0x0A, 0xBF,
+ 0xD1, 0x9D, 0x70, 0x55, 0x5A, 0x7A, 0x48, 0xB6, 0xA2, 0xC5, 0x7A, 0x0C, 0xA6, 0xDC, 0x54, 0x97, 0x0A, 0x61, 0x2A, 0x5B,
+ 0xE8, 0x12, 0x42, 0x25, 0x46, 0xA9, 0x9F, 0x6D, 0xA7, 0x54, 0x1F, 0x8A, 0xB4, 0x49, 0x95, 0x36, 0x0B, 0x12, 0x18, 0x66,
+ 0x24, 0x4F, 0x2A, 0x3A, 0x22, 0x49, 0x9A, 0xCF, 0x2B, 0x29, 0xA2, 0x9A, 0xB8, 0x33, 0x9B, 0x0F, 0xAB, 0x9E, 0xF7, 0xF1,
+ 0x3E, 0x75, 0xD6, 0x7E, 0x39, 0xA7, 0x15, 0x29, 0x0F, 0x98, 0x01, 0xB2, 0x18, 0xEC, 0x66, 0x53, 0x9B, 0x1A, 0xD8, 0xD2,
+ 0xBE, 0x8B, 0x54, 0xDB, 0x0A, 0x55, 0x62, 0xEC, 0xFA, 0xB6, 0x0D, 0x11, 0xE9, 0x48, 0xF3, 0x65, 0xCD, 0xA8, 0xBF, 0x43,
+ 0x5C, 0xAF, 0x3D, 0x4A, 0x90, 0x1C, 0xA8, 0xAA, 0xAA, 0x89, 0x09, 0x7E, 0x95, 0x0E, 0xA5, 0x1C, 0x39, 0x29, 0xC7, 0xDD,
+ 0x61, 0x0A, 0x3C, 0xAE, 0xD5, 0xE3, 0x84, 0xA4, 0x40, 0x7C, 0x29, 0xA6, 0xF4, 0xE6, 0xF0, 0x96, 0x7B, 0x41, 0x78, 0xB4,
+ 0x62, 0x7F, 0x98, 0x97, 0xF1, 0xF5, 0xD5, 0x11, 0xC7, 0x00, 0x31, 0x21, 0x10, 0x4C, 0x8E, 0x12, 0x3F, 0x89, 0xB1, 0x36,
+ 0x17, 0x85, 0x8D, 0x39, 0xD1, 0x67, 0x60, 0x6A, 0x15, 0x26, 0xE4, 0xB4, 0x2E, 0x99, 0xF1, 0xE3, 0x35, 0x2A, 0x43, 0xCC,
+ 0xD7, 0x22, 0xCF, 0x08, 0x7E, 0x4C, 0x26, 0x82, 0xC2, 0xC5, 0x36, 0x5B, 0xE1, 0xC7, 0x98, 0x90, 0xCF, 0x94, 0x5C, 0x52,
+ 0xE1, 0xAE, 0x1A, 0x04, 0x61, 0xEC, 0xF5, 0x04, 0xB2, 0xE3, 0x6C, 0xD7, 0x3E, 0xCC, 0xF7, 0x64, 0x8F, 0x89, 0xC4, 0x7A,
+ 0x63, 0xBE, 0xB0, 0xAF, 0x76, 0xBD, 0xC3, 0xA2, 0xA1, 0x88, 0xE6, 0x99, 0x22, 0x66, 0x31, 0x97, 0xCA, 0xB6, 0xBB, 0xC9,
+ 0xE3, 0x67, 0xE9, 0x07, 0x99, 0x7B, 0x6B, 0x9F, 0x8D, 0x5D, 0x77, 0xAB, 0xEA, 0x2B, 0xF3, 0x93, 0x1E, 0xD9, 0xB9, 0xDB,
+ 0xB7, 0x6D, 0x3A, 0x0A, 0x9F, 0x92, 0x29, 0xF4, 0x8B, 0x6D, 0xAA, 0x5C, 0x09, 0x90, 0x57, 0x4E, 0x69, 0xE7, 0x56, 0xA4,
+ 0x31, 0x52, 0x4C, 0x9F, 0xAC, 0x56, 0xEA, 0x54, 0x95, 0x49, 0x75, 0xF5, 0xA9, 0xDC, 0xF2, 0x36, 0x86, 0xFE, 0x77, 0xF1,
+ 0xF5, 0x57, 0xB9, 0xF8, 0x9D, 0xCA, 0x27, 0xD9, 0xDB, 0xE9, 0x29, 0x2E, 0x04, 0xD2, 0x2B, 0x0A, 0xCC, 0xB5, 0x44, 0xC7,
+ 0x6D, 0x75, 0xED, 0xED, 0x15, 0x05, 0x3F, 0xD3, 0x4D, 0x14, 0x14, 0xDD, 0x85, 0x69, 0x9A, 0x95, 0x8B, 0xB2, 0xB0, 0xB1,
+ 0x62, 0xF6, 0x0D, 0x44, 0xDA, 0x2D, 0x74, 0x5E, 0xFA, 0x09, 0x59, 0x75, 0xDB, 0x65, 0x4E, 0x5C, 0x16, 0x35, 0x59, 0xE6,
+ 0x17, 0x75, 0xE9, 0xDD, 0x52, 0x5A, 0xFE, 0xAB, 0xAA, 0x96, 0x15, 0x96, 0x6A, 0x94, 0x87, 0x9C, 0x4B, 0xA9, 0xA2, 0x5C,
+ 0xF4, 0xF1, 0x95, 0xC0, 0xAA, 0xB6, 0xDA, 0xDB, 0x79, 0x21, 0x50, 0x6A, 0x01, 0xDA, 0x7B, 0xEE, 0xB6, 0x9E, 0x7D, 0x9D,
+ 0xDA, 0xF6, 0x2A, 0x90, 0x2A, 0xA5, 0x86, 0xBA, 0x24, 0xB9, 0xC3, 0x0C, 0xA2, 0x70, 0xC4, 0x87, 0x72, 0xDA, 0xD8, 0xD9,
+ 0xE8, 0x84, 0x9A, 0x86, 0xCD, 0x37, 0xF6, 0x67, 0x35, 0x51, 0x50, 0xC9, 0x1D, 0x99, 0x1C, 0x37, 0x84, 0x95, 0xDF, 0xAB,
+ 0x51, 0x2A, 0x15, 0xAA, 0xD4, 0xBB, 0x62, 0x9B, 0x52, 0xA3, 0x5B, 0x32, 0xAA, 0x2E, 0x48, 0xA1, 0xD2, 0xAA, 0xE8, 0x8A,
+ 0xCD, 0x42, 0x9D, 0x0E, 0x4B, 0x6C, 0xBC, 0xEC, 0x15, 0xB7, 0x12, 0x44, 0xB8, 0xED, 0xC6, 0x89, 0x35, 0x72, 0x99, 0x82,
+ 0x86, 0xE4, 0x38, 0x11, 0x4F, 0x44, 0x64, 0x92, 0x12, 0x94, 0x81, 0xA9, 0x15, 0x35, 0xB4, 0x52, 0xD3, 0x42, 0xF5, 0x05,
+ 0x44, 0xF4, 0xDF, 0xDD, 0x21, 0x8C, 0x62, 0x66, 0xC0, 0x78, 0xD6, 0xD9, 0xB3, 0x61, 0x32, 0xDF, 0xD2, 0x47, 0x9F, 0x5B,
+ 0x2D, 0xA7, 0x44, 0x17, 0x93, 0x8C, 0x13, 0x80, 0x7F, 0x7B, 0xAF, 0xBF, 0x7E, 0x87, 0xF9, 0x71, 0x45, 0x08, 0xCA, 0x54,
+ 0xB9, 0x3A, 0x69, 0x21, 0xED, 0x79, 0xB7, 0x17, 0xEF, 0x31, 0x36, 0xD5, 0x02, 0xD8, 0x15, 0xF1, 0x79, 0xEF, 0x62, 0x5F,
+ 0x9F, 0xEB, 0xAC, 0x7C, 0xC4, 0x7E, 0xF0, 0xE2, 0xE1, 0xEC, 0xFC, 0x9D, 0x57, 0x4D, 0x5D, 0xAA, 0xFF, 0x00, 0xB3, 0x73,
+ 0xFF, 0x00, 0x4D, 0x3B, 0x56, 0xBE, 0x6D, 0xB3, 0x8C, 0x93, 0x8C, 0x9C, 0x13, 0xD7, 0x6E, 0xA3, 0xD7, 0x24, 0x03, 0xF3,
+ 0xE2, 0x5A, 0xA0, 0x71, 0xD5, 0x0A, 0x81, 0x21, 0x38, 0x14, 0x23, 0x8C, 0x71, 0x99, 0x9D, 0x4D, 0xA1, 0x1B, 0xDB, 0x1D,
+ 0xBC, 0xC5, 0xE7, 0x1F, 0x1D, 0x6A, 0xE5, 0x46, 0x0E, 0x27, 0x04, 0x02, 0x37, 0x3D, 0x70, 0x73, 0xBF, 0x53, 0x92, 0x46,
+ 0x46, 0xDD, 0x70, 0x47, 0xE1, 0xC6, 0x4D, 0x4C, 0xCD, 0xAE, 0x44, 0x24, 0x89, 0x98, 0x47, 0x3A, 0x06, 0x7E, 0x69, 0xF7,
+ 0xEB, 0x9D, 0x00, 0xD4, 0x26, 0xD2, 0xBC, 0xF2, 0xE7, 0x07, 0x60, 0x72, 0x47, 0x6E, 0xD8, 0x1F, 0x68, 0x76, 0xEB, 0xD3,
+ 0x63, 0xC0, 0xAF, 0x6A, 0x49, 0x1C, 0x44, 0xDE, 0x2D, 0xCC, 0x1D, 0xFE, 0x1A, 0x3E, 0xFE, 0xFE, 0xFB, 0x6B, 0x6E, 0xDA,
+ 0x54, 0xD8, 0x03, 0xB8, 0x3D, 0x48, 0x1E, 0x9D, 0xF6, 0x1D, 0x7A, 0xED, 0x8C, 0xF0, 0x0D, 0x3C, 0xD2, 0xB3, 0xDA, 0xA8,
+ 0x0F, 0xAA, 0xCF, 0xE9, 0xA5, 0x6B, 0xC8, 0xCE, 0x08, 0x62, 0xDD, 0xF0, 0xDE, 0xF6, 0x19, 0xF0, 0x0E, 0x85, 0x99, 0x29,
+ 0x4D, 0xB4, 0xB2, 0x14, 0x09, 0xC7, 0xDD, 0x1B, 0x76, 0xEC, 0x46, 0x08, 0x1E, 0xF0, 0x31, 0x93, 0x92, 0x30, 0x0F, 0x0E,
+ 0x69, 0x6C, 0x51, 0x60, 0x66, 0x6F, 0x62, 0x59, 0x66, 0xC3, 0x29, 0x0E, 0x4B, 0x04, 0xB1, 0xA7, 0x63, 0x12, 0x7C, 0x6D,
+ 0xF2, 0xE6, 0xA5, 0x73, 0xE6, 0xDA, 0xD2, 0xD2, 0xB5, 0xB6, 0xD5, 0xB1, 0x23, 0x52, 0xA4, 0xC7, 0xB2, 0xF5, 0x69, 0xFD,
+ 0x48, 0xA3, 0xA2, 0xA7, 0x15, 0x52, 0xED, 0x5B, 0xA2, 0x89, 0x6B, 0x5B, 0x35, 0x59, 0x12, 0x6A, 0x12, 0x9E, 0x8F, 0x5A,
+ 0x72, 0xE3, 0xF6, 0x39, 0xF7, 0x14, 0x07, 0x97, 0x4F, 0x76, 0x24, 0x15, 0xB7, 0x05, 0x86, 0x27, 0xD3, 0x99, 0x89, 0xE4,
+ 0x53, 0x64, 0x36, 0x87, 0x4B, 0xEE, 0xBA, 0x77, 0x76, 0xA8, 0xA6, 0x91, 0xA3, 0x72, 0xAD, 0xCA, 0x67, 0x15, 0x14, 0x52,
+ 0xB2, 0xBD, 0x56, 0xA5, 0xAA, 0x5E, 0x21, 0x12, 0xF7, 0xE3, 0x59, 0x54, 0xD5, 0x82, 0x8A, 0x95, 0x8F, 0xF4, 0xA6, 0x0C,
+ 0xAD, 0x5F, 0xAB, 0x4A, 0x91, 0x9B, 0xC6, 0xA2, 0x2B, 0xD2, 0xE1, 0xBF, 0x35, 0x70, 0xBA, 0xD5, 0xDA, 0xF4, 0x5A, 0x35,
+ 0xB0, 0xEC, 0xFF, 0x00, 0xAD, 0x93, 0x65, 0x50, 0xDE, 0xAA, 0x3B, 0x4C, 0x97, 0x55, 0x00, 0xA5, 0x15, 0x9B, 0xA6, 0xB1,
+ 0x59, 0x99, 0x3E, 0xE4, 0xBF, 0x2E, 0x34, 0xA1, 0x45, 0xB1, 0x5B, 0xBA, 0xEA, 0x93, 0x9C, 0x8C, 0x95, 0x38, 0x8A, 0x6C,
+ 0x68, 0x0C, 0xAC, 0xB4, 0x72, 0xAE, 0xBA, 0xF7, 0x24, 0x62, 0x8A, 0x66, 0x7A, 0x29, 0xB8, 0xF9, 0x6F, 0x55, 0x55, 0x3E,
+ 0x6A, 0x55, 0x4E, 0xDA, 0x5F, 0x96, 0xD5, 0x7D, 0xC6, 0x7B, 0x50, 0x41, 0x44, 0x18, 0x9B, 0x7B, 0x49, 0xDD, 0xB1, 0xC1,
+ 0xA8, 0xB2, 0xE2, 0xD3, 0x58, 0x32, 0x20, 0x18, 0x34, 0xDA, 0x49, 0x7E, 0xA3, 0x2D, 0x6D, 0xC3, 0xA6, 0x46, 0x85, 0x18,
+ 0x2A, 0x6C, 0xAA, 0x94, 0xA7, 0x13, 0x1E, 0x04, 0x48, 0x8D, 0xB4, 0x8F, 0x35, 0xD9, 0x32, 0x65, 0x2D, 0xA6, 0x1A, 0x65,
+ 0x20, 0xF9, 0xAB, 0x58, 0x47, 0x2F, 0x29, 0x56, 0x32, 0x69, 0xBC, 0x0A, 0xAA, 0x01, 0x08, 0xAB, 0xC7, 0xD2, 0x0D, 0x45,
+ 0x7B, 0x54, 0xF4, 0xA7, 0x4D, 0xED, 0x70, 0x09, 0xB5, 0xA3, 0xCF, 0x1C, 0xF3, 0x3A, 0xBE, 0x9A, 0x27, 0xF4, 0xC1, 0x78,
+ 0xF5, 0xF0, 0x89, 0x67, 0x41, 0xF0, 0xF5, 0xA7, 0x97, 0x04, 0x39, 0xF0, 0x34, 0xFD, 0x08, 0xB7, 0xA6, 0xC4, 0xBA, 0x45,
+ 0x42, 0xBD, 0x0E, 0x2B, 0xB4, 0xF7, 0xDA, 0x78, 0xD3, 0x53, 0x18, 0x4F, 0x89, 0x15, 0x2D, 0x53, 0xA6, 0xB0, 0xDB, 0x49,
+ 0x79, 0xC7, 0x1D, 0x79, 0xE5, 0xC7, 0x29, 0x0A, 0xF2, 0x42, 0x10, 0x3B, 0x28, 0xFC, 0x76, 0xFE, 0xD0, 0x6D, 0xD4, 0x6D,
+ 0xD7, 0xD1, 0x34, 0xFB, 0x54, 0xAD, 0x51, 0x38, 0xEA, 0x11, 0xB7, 0x0F, 0xC7, 0x5C, 0xD5, 0x53, 0x4D, 0x4F, 0x4B, 0xB7,
+ 0x55, 0x55, 0x81, 0xD5, 0x51, 0x52, 0x4A, 0x52, 0x13, 0x87, 0x18, 0x97, 0x2E, 0xBA, 0x63, 0xA5, 0x5F, 0xE1, 0x4D, 0x6B,
+ 0x9D, 0x36, 0xDE, 0x16, 0xC7, 0x88, 0x0D, 0x1A, 0xA3, 0xD7, 0x6B, 0x94, 0xD8, 0x25, 0x30, 0xEE, 0x8B, 0x62, 0xA2, 0xEC,
+ 0x75, 0x48, 0x9C, 0xC4, 0x09, 0xF1, 0x61, 0xBF, 0x26, 0x85, 0x57, 0x62, 0x62, 0x61, 0xB8, 0x91, 0x26, 0x3B, 0x2D, 0xC8,
+ 0xA6, 0x54, 0x92, 0x84, 0x43, 0x61, 0xE6, 0x59, 0x0D, 0x2E, 0x4B, 0xCE, 0x1E, 0x8A, 0x7F, 0xE2, 0x54, 0x7F, 0x5E, 0xC7,
+ 0x2A, 0xF4, 0x57, 0x12, 0xDE, 0x33, 0x4A, 0x99, 0xE1, 0xFE, 0x0C, 0x1D, 0x9D, 0xB9, 0x47, 0xAB, 0x6E, 0xE3, 0xD2, 0x8D,
+ 0x45, 0x91, 0x49, 0x21, 0xB8, 0x5B, 0x8F, 0x3C, 0x6B, 0x8E, 0x1E, 0x2B, 0x3E, 0x91, 0x0F, 0x16, 0xDE, 0x3C, 0x2F, 0x1A,
+ 0xA5, 0x52, 0xE4, 0xD4, 0x2B, 0x9A, 0xCB, 0xD3, 0x34, 0xD4, 0xA5, 0x3D, 0x6F, 0x69, 0xD5, 0xB9, 0x70, 0x56, 0x62, 0xD0,
+ 0xE1, 0x34, 0xF3, 0xE5, 0xD5, 0x7B, 0x5A, 0xDA, 0x96, 0xC4, 0x8A, 0xCC, 0xB5, 0x3A, 0x4B, 0xCE, 0x3B, 0x31, 0xC3, 0x0E,
+ 0x2B, 0xAA, 0x2D, 0x43, 0x8A, 0x95, 0x05, 0xB8, 0xE7, 0x2E, 0xF7, 0xE3, 0x77, 0xF7, 0xB1, 0x53, 0xB7, 0x41, 0xC5, 0x0A,
+ 0x4C, 0x63, 0xAE, 0xA2, 0x1A, 0x93, 0x89, 0xC4, 0xEB, 0x6D, 0xBD, 0xB9, 0x22, 0x81, 0xA2, 0x8A, 0x5F, 0x7A, 0x26, 0xBA,
+ 0x9B, 0x73, 0x3E, 0x1B, 0x16, 0x3C, 0xA0, 0xEA, 0xBC, 0xE9, 0xCE, 0xAB, 0x6B, 0xC7, 0x87, 0xAB, 0x92, 0x9F, 0x79, 0x59,
+ 0x57, 0xFD, 0xD3, 0x2A, 0x14, 0x09, 0x51, 0xDF, 0xAC, 0xD0, 0x5D, 0xAC, 0xD4, 0x9D, 0xA7, 0x55, 0xE9, 0xCD, 0x14, 0xA6,
+ 0x54, 0x49, 0x50, 0x9E, 0x94, 0xFC, 0x77, 0x02, 0xE2, 0x05, 0xB2, 0x97, 0x9B, 0x43, 0x52, 0x19, 0x49, 0x1C, 0x85, 0x6D,
+ 0xA5, 0x4D, 0xAB, 0x2D, 0xBF, 0xC4, 0xFE, 0x23, 0x66, 0xA2, 0xA3, 0x72, 0xBB, 0x27, 0x50, 0xD6, 0xB4, 0xAF, 0x66, 0x6C,
+ 0xCC, 0xC7, 0xCC, 0x7B, 0x6B, 0x4A, 0xB6, 0xEB, 0xA2, 0x55, 0x6B, 0xA4, 0xBB, 0x4D, 0x43, 0x30, 0x8D, 0xC9, 0xC2, 0x66,
+ 0x4B, 0xE7, 0x5D, 0x0B, 0xF1, 0x59, 0x32, 0x85, 0x7E, 0xDD, 0xF6, 0x3E, 0xB6, 0xDB, 0xEB, 0x6D, 0xD8, 0x3A, 0x9D, 0x60,
+ 0xDA, 0x8B, 0xAC, 0xF2, 0x29, 0x2A, 0x52, 0x65, 0x9A, 0x73, 0xD2, 0xED, 0x8A, 0x93, 0xBC, 0xA7, 0x74, 0xCF, 0xA4, 0xAA,
+ 0xA1, 0x42, 0x75, 0xD3, 0xB7, 0xD6, 0x36, 0xCA, 0x98, 0x59, 0x0E, 0x3C, 0xD2, 0x0F, 0x67, 0xE3, 0x22, 0xBA, 0xE8, 0xDF,
+ 0xA4, 0x1A, 0x77, 0x68, 0x3A, 0xE6, 0xCA, 0xD3, 0x2D, 0x1D, 0xC9, 0xA8, 0x9A, 0x67, 0x1D, 0x54, 0x46, 0x43, 0x5B, 0xEC,
+ 0x09, 0xD4, 0x5A, 0xC9, 0x10, 0xD9, 0x18, 0xB8, 0xC6, 0x01, 0x8B, 0x48, 0xBA, 0xAE, 0x88, 0xA7, 0xB4, 0x12, 0x95, 0x72,
+ 0x8E, 0xBD, 0x48, 0x00, 0x1F, 0xC3, 0x3D, 0x73, 0x93, 0x8D, 0xFB, 0x63, 0xAE, 0x39, 0x03, 0x80, 0xB1, 0x6B, 0x4B, 0x07,
+ 0x1C, 0x1F, 0x43, 0xD3, 0x5D, 0x11, 0x38, 0x2E, 0xDA, 0xD9, 0x5E, 0x23, 0xCF, 0x6D, 0x1E, 0xD3, 0x61, 0x18, 0xE5, 0x04,
+ 0x01, 0x9E, 0xA3, 0x1F, 0x01, 0x83, 0xD8, 0x0D, 0x86, 0xDD, 0xBA, 0x71, 0xB5, 0x34, 0xB4, 0xF5, 0x5C, 0x1B, 0x49, 0x9B,
+ 0x0E, 0x1E, 0x99, 0x89, 0xB8, 0x4C, 0x43, 0x7D, 0x0E, 0x13, 0x86, 0xC9, 0xF7, 0x7F, 0xBB, 0xE8, 0x8E, 0x62, 0x91, 0xD7,
+ 0x03, 0xDF, 0xBF, 0xBF, 0x6C, 0xFE, 0x83, 0x8B, 0x59, 0x67, 0xEF, 0xC6, 0x9E, 0x59, 0x82, 0xEF, 0x07, 0xCB, 0xE3, 0x6F,
+ 0x8E, 0xBE, 0x79, 0xBF, 0xED, 0x7E, 0x5F, 0xDD, 0xC2, 0xD5, 0x74, 0xBF, 0xE9, 0x3E, 0x6F, 0xFE, 0xDA, 0x77, 0x29, 0xC1,
+ 0xBE, 0xE4, 0x9E, 0xDB, 0x0C, 0x7C, 0xF0, 0x47, 0xC7, 0xBF, 0x5E, 0xBC, 0x60, 0xB6, 0x80, 0x03, 0xC7, 0x3E, 0xAF, 0x3A,
+ 0x83, 0x49, 0x95, 0xAB, 0x27, 0x7E, 0xBB, 0x74, 0x1D, 0x31, 0x8E, 0xF9, 0xED, 0xDB, 0x85, 0xA3, 0x5F, 0x3C, 0xD0, 0x37,
+ 0xD8, 0x9D, 0xBA, 0x0D, 0xCF, 0x6E, 0xA3, 0x6D, 0xBD, 0xFB, 0xF7, 0xDF, 0x87, 0x0C, 0x4F, 0x13, 0x1F, 0x1F, 0xBF, 0xBB,
+ 0x9A, 0x35, 0xF0, 0xBA, 0x0F, 0xAA, 0x71, 0x9C, 0x01, 0xDF, 0xE7, 0x9E, 0xDF, 0x9E, 0x76, 0xF7, 0xAE, 0xFF, 0x00, 0x3F,
+ 0xDB, 0xF7, 0xD2, 0xBF, 0x3F, 0xC1, 0x8E, 0xD2, 0xCF, 0xC7, 0xBD, 0xB5, 0xAF, 0x95, 0xFB, 0x40, 0x40, 0x19, 0xEB, 0x90,
+ 0x4E, 0xDD, 0x37, 0x19, 0xEF, 0xD3, 0x1E, 0xBF, 0x3C, 0xF1, 0x45, 0x4D, 0x89, 0xE9, 0x18, 0x14, 0x3C, 0xE5, 0xEF, 0xE6,
+ 0xF1, 0xA7, 0xA6, 0xCC, 0x8A, 0x63, 0x4F, 0x2C, 0xA8, 0xB4, 0x0A, 0x89, 0x56, 0xE4, 0x02, 0x46, 0x4E, 0xC3, 0x9B, 0xAE,
+ 0x3A, 0x63, 0x20, 0x10, 0x76, 0x27, 0x6C, 0xF0, 0x55, 0x44, 0x66, 0x11, 0x27, 0xCB, 0xE0, 0x09, 0x64, 0x6D, 0xA5, 0x11,
+ 0xCE, 0x3E, 0x1F, 0x3E, 0xEE, 0x6F, 0xCE, 0x62, 0x74, 0x8A, 0xE3, 0x47, 0x8A, 0xDA, 0x96, 0xE8, 0x4A, 0x12, 0xD9, 0xCF,
+ 0xBF, 0x9B, 0x20, 0x72, 0x80, 0x01, 0x52, 0x8A, 0x94, 0x79, 0x52, 0x94, 0x82, 0xA5, 0x28, 0x80, 0x9C, 0xA8, 0x80, 0x53,
+ 0x49, 0x4C, 0x76, 0x73, 0x07, 0x1E, 0x1E, 0x7F, 0x5D, 0x38, 0xB3, 0x9B, 0xCC, 0x2F, 0xCA, 0xC1, 0x04, 0x63, 0x96, 0xF9,
+ 0x8E, 0x5F, 0xD4, 0xBB, 0x6E, 0xB9, 0xA6, 0xD3, 0x28, 0x5A, 0x97, 0x73, 0x41, 0x34, 0x96, 0x29, 0x76, 0xE4, 0x8D, 0x47,
+ 0x8B, 0x4F, 0x7D, 0x3C, 0xB5, 0x83, 0x6C, 0xA1, 0xE4, 0xD2, 0xAD, 0x62, 0xC3, 0x2E, 0x24, 0x9A, 0x74, 0xBD, 0x49, 0xBA,
+ 0x24, 0xC3, 0xB6, 0xA8, 0x35, 0x07, 0x31, 0x2A, 0x4D, 0x21, 0xCA, 0xCC, 0xEA, 0x3A, 0x44, 0x06, 0x9F, 0xAA, 0x3F, 0xAD,
+ 0x03, 0xB6, 0x9B, 0xAF, 0xF4, 0x53, 0xF9, 0x95, 0x52, 0xF1, 0x48, 0xC5, 0x00, 0x47, 0xBD, 0xB9, 0x5C, 0x03, 0x76, 0x26,
+ 0x31, 0xA9, 0xAD, 0x69, 0x07, 0x33, 0x70, 0x3C, 0x49, 0x33, 0xD9, 0xAA, 0x0F, 0x84, 0x43, 0xCD, 0x62, 0x8B, 0x6D, 0x48,
+ 0x96, 0xEC, 0xFA, 0xD5, 0x54, 0xA2, 0x55, 0x6E, 0xBB, 0x51, 0x9B, 0x5B, 0xAC, 0x49, 0x09, 0xFF, 0x00, 0x49, 0xAA, 0xD5,
+ 0xA4, 0xBB, 0x36, 0xA0, 0xE0, 0xD8, 0xE1, 0xB5, 0x48, 0x7D, 0xC4, 0xB0, 0x93, 0xF7, 0x18, 0x4B, 0x4D, 0xA7, 0x01, 0x03,
+ 0x8E, 0x56, 0x95, 0x5A, 0xAD, 0x28, 0xB8, 0xE6, 0xA6, 0x62, 0xF8, 0xEC, 0x39, 0x02, 0xF7, 0x6F, 0x06, 0xD8, 0x43, 0x79,
+ 0x57, 0xA9, 0x9C, 0xAF, 0x3F, 0x3F, 0x91, 0x63, 0x4C, 0xBB, 0xA3, 0x4B, 0x9B, 0xAE, 0x3C, 0xC3, 0xC1, 0x4E, 0x46, 0x71,
+ 0xA5, 0x14, 0xF9, 0x8D, 0x25, 0x25, 0x4A, 0x69, 0x5B, 0xA9, 0xB3, 0x90, 0x46, 0xC4, 0x65, 0x0A, 0xDC, 0xA0, 0xE7, 0x1C,
+ 0xC0, 0xA8, 0x11, 0xDB, 0xBD, 0x9B, 0x5F, 0x8C, 0x76, 0xE6, 0xFA, 0x8D, 0xCD, 0x8A, 0x6B, 0x7D, 0xE8, 0x8F, 0x3F, 0xA7,
+ 0x3E, 0x2E, 0xCD, 0xDE, 0xCD, 0x9F, 0xF6, 0xE5, 0xA1, 0x1E, 0x95, 0x11, 0x98, 0xAD, 0x34, 0x10, 0x86, 0x5B, 0x4A, 0x00,
+ 0xC0, 0x24, 0x01, 0xD7, 0x72, 0x0F, 0x53, 0xF7, 0x8E, 0x09, 0x51, 0x24, 0xF1, 0x54, 0xD2, 0x07, 0x37, 0x59, 0xF3, 0xC4,
+ 0x7A, 0x72, 0x7C, 0xF5, 0xAD, 0x14, 0x53, 0x48, 0x74, 0xF6, 0x2F, 0x8E, 0xDF, 0x73, 0x9F, 0xA6, 0x9C, 0x52, 0xE8, 0x4D,
+ 0x2D, 0x95, 0x21, 0x48, 0x0A, 0x0A, 0x04, 0x6C, 0x31, 0x81, 0xD0, 0x8C, 0x7D, 0xDC, 0x8D, 0xBA, 0xFA, 0x1E, 0xC3, 0x81,
+ 0x2C, 0x04, 0x45, 0xED, 0xC5, 0xCB, 0x3F, 0x30, 0xC5, 0xFE, 0x5A, 0x7D, 0x23, 0x32, 0x67, 0xCC, 0xC7, 0xA3, 0x02, 0x6A,
+ 0x79, 0xD0, 0x7B, 0x7E, 0x81, 0xA8, 0x54, 0x7A, 0x0E, 0x9C, 0x5E, 0x77, 0x42, 0x6D, 0x0A, 0x5E, 0x9F, 0xDC, 0x28, 0xB6,
+ 0x26, 0xDD, 0x72, 0x50, 0xEC, 0x88, 0x36, 0xC6, 0x97, 0x6A, 0xAD, 0x61, 0xBF, 0xF1, 0x72, 0xE9, 0xAC, 0xC5, 0x63, 0x9A,
+ 0x4C, 0x9B, 0x63, 0x4D, 0x35, 0x58, 0x32, 0xCD, 0x7D, 0xC8, 0xA1, 0x53, 0x28, 0xF6, 0xF5, 0xCD, 0x0A, 0xA1, 0x08, 0xF9,
+ 0xB4, 0xF6, 0x9B, 0x7B, 0x6D, 0xA0, 0xAE, 0x82, 0x8A, 0xAA, 0x87, 0x65, 0x85, 0x9C, 0x6D, 0xEE, 0x27, 0x4B, 0x39, 0xE9,
+ 0xA3, 0x70, 0x07, 0x92, 0x44, 0x85, 0x9D, 0x67, 0x40, 0x53, 0x55, 0x54, 0x44, 0x80, 0xB4, 0x78, 0x9B, 0x84, 0xB3, 0x6A,
+ 0x59, 0xB4, 0xCD, 0xCC, 0x11, 0xA7, 0x46, 0xB2, 0xE8, 0x96, 0xA4, 0x78, 0x75, 0xD5, 0x0B, 0xBB, 0x45, 0xF5, 0x82, 0x84,
+ 0x6D, 0xFB, 0xF6, 0xCC, 0x96, 0xDB, 0x32, 0x9B, 0x43, 0x8D, 0xCD, 0xA4, 0xD7, 0x69, 0x33, 0x18, 0x6E, 0x65, 0x0E, 0xEB,
+ 0xB5, 0xEA, 0xCC, 0x7F, 0x9A, 0x57, 0x6D, 0x6B, 0x9A, 0x95, 0x22, 0x25, 0x66, 0x83, 0x5A, 0x80, 0xA5, 0xC5, 0xA8, 0x53,
+ 0xA5, 0xB0, 0xF3, 0x65, 0x0A, 0x52, 0x9A, 0x6A, 0x6A, 0xA6, 0xBD, 0xAA, 0x9A, 0x6A, 0x3A, 0x5A, 0x61, 0x2A, 0x96, 0x1E,
+ 0x54, 0x7B, 0x4E, 0x73, 0xE7, 0x99, 0xD4, 0x1C, 0xCD, 0x8E, 0x4C, 0x4A, 0xB1, 0x1F, 0x0E, 0x39, 0xF2, 0x9A, 0x88, 0xD6,
+ 0x42, 0x41, 0x1D, 0x14, 0x37, 0x19, 0x39, 0xDB, 0x24, 0x7C, 0xF7, 0x1D, 0x7A, 0x1E, 0xA3, 0x6E, 0xAD, 0x89, 0x56, 0xC3,
+ 0x16, 0x12, 0xEC, 0x0F, 0xC9, 0x97, 0x05, 0xB8, 0xE1, 0x5D, 0xB2, 0xCB, 0x72, 0x41, 0xBB, 0x79, 0xFD, 0x79, 0x7E, 0x76,
+ 0xB8, 0x81, 0x50, 0xC9, 0xC9, 0xC9, 0xC7, 0xA1, 0xEF, 0xFC, 0xBF, 0x4D, 0xC0, 0xE9, 0xC2, 0xEB, 0x62, 0x00, 0x31, 0x73,
+ 0x2C, 0x62, 0xED, 0xCE, 0xD6, 0xE3, 0xE3, 0xAA, 0x6B, 0xA8, 0x22, 0x9A, 0x4A, 0x0E, 0x2A, 0x63, 0xDA, 0xBB, 0xC4, 0x32,
+ 0xCB, 0x13, 0x33, 0xFA, 0xE9, 0x3F, 0x33, 0xDD, 0xF9, 0xFF, 0x00, 0x77, 0x0A, 0x5E, 0xEF, 0xCD, 0xD3, 0xEA, 0x7F, 0xD4,
+ 0x7C, 0x9F, 0xFD, 0x74, 0xEC, 0x2E, 0xFF, 0x00, 0xB4, 0x3E, 0x5B, 0xFE, 0x99, 0xFC, 0xF8, 0x21, 0xC6, 0x3D, 0x6D, 0xF5,
+ 0xD4, 0x6B, 0x12, 0xE0, 0xF7, 0x9F, 0xC7, 0x19, 0xF9, 0x9F, 0xD0, 0x70, 0x3D, 0xE4, 0x78, 0xB7, 0x62, 0xC4, 0xD8, 0xE3,
+ 0x46, 0xB1, 0x2E, 0x74, 0xC6, 0x07, 0xA9, 0x27, 0x61, 0xFF, 0x00, 0x5E, 0xBF, 0x97, 0x0A, 0x0B, 0xB0, 0xA8, 0x4E, 0x24,
+ 0xCF, 0x6B, 0xF0, 0x1C, 0x66, 0x2F, 0xA3, 0x49, 0x29, 0xCF, 0x53, 0x9D, 0xCE, 0xC3, 0xF9, 0x8C, 0x8C, 0x63, 0xB9, 0xCF,
+ 0xCF, 0xA7, 0x15, 0xD2, 0xC4, 0xB0, 0x66, 0xED, 0xAF, 0xDA, 0x33, 0xF0, 0xD1, 0xA4, 0x94, 0xE0, 0xC6, 0x09, 0x19, 0xEF,
+ 0xF1, 0xCF, 0x40, 0x37, 0x39, 0xEF, 0xEE, 0x00, 0xEF, 0x9E, 0x28, 0xA7, 0x98, 0x93, 0x8A, 0x5C, 0xB8, 0xBB, 0x68, 0x0B,
+ 0xE5, 0xE6, 0x02, 0x73, 0xA1, 0xB1, 0x92, 0xF3, 0x12, 0xC7, 0xCD, 0xE0, 0xF2, 0xFF, 0x00, 0x12, 0x13, 0x8E, 0x73, 0x02,
+ 0x33, 0x90, 0x49, 0x24, 0xE7, 0xA7, 0x62, 0x01, 0xF4, 0xF5, 0xF7, 0xFB, 0xC6, 0xD7, 0x05, 0x25, 0xDE, 0x98, 0x11, 0xE2,
+ 0x56, 0xE4, 0x9F, 0xEA, 0x6C, 0x5D, 0xC6, 0x0E, 0xE1, 0x03, 0x72, 0xDE, 0xD2, 0x86, 0x54, 0x3F, 0x5E, 0x5B, 0x66, 0x2D,
+ 0x9D, 0x11, 0x48, 0x69, 0x6D, 0x4B, 0xA1, 0xD6, 0x5D, 0xA1, 0x3F, 0x71, 0x26, 0x7D, 0x72, 0x45, 0x3A, 0x83, 0x42, 0x69,
+ 0x0E, 0x2B, 0xEB, 0x99, 0x14, 0x9F, 0x20, 0xD5, 0x9F, 0x78, 0xA0, 0x73, 0x08, 0x62, 0x6C, 0x98, 0x96, 0xFB, 0x0B, 0x49,
+ 0x49, 0x2E, 0x39, 0x5D, 0x79, 0x0A, 0x4C, 0x8A, 0x74, 0x75, 0xA6, 0x6F, 0x53, 0x4D, 0x45, 0x35, 0x56, 0x55, 0x5F, 0x4D,
+ 0x14, 0x91, 0x90, 0xBD, 0x56, 0x58, 0xA5, 0x64, 0x2F, 0x13, 0x53, 0x10, 0x94, 0xA2, 0x5B, 0xDE, 0x20, 0x65, 0x25, 0xB8,
+ 0xDA, 0x3C, 0xE1, 0x9E, 0xF6, 0x3C, 0xEB, 0x7B, 0xE2, 0x12, 0xE0, 0xAE, 0x4C, 0xBB, 0x63, 0x69, 0xFD, 0x7E, 0xA8, 0x2B,
+ 0x17, 0x73, 0x4F, 0x52, 0xEF, 0xFD, 0x67, 0xAA, 0x34, 0x53, 0xEC, 0xEE, 0xDE, 0xD2, 0xA9, 0x42, 0x35, 0x91, 0x60, 0xC2,
+ 0x43, 0x67, 0xCA, 0x8D, 0x6F, 0xE9, 0x75, 0x9C, 0xEA, 0x19, 0xA7, 0xD2, 0x58, 0x08, 0x8B, 0x0E, 0xA1, 0x59, 0x05, 0xB6,
+ 0x92, 0xE4, 0x26, 0xCA, 0x5F, 0xE2, 0x2A, 0x4A, 0x8D, 0xA1, 0x3A, 0x87, 0xF3, 0x37, 0x13, 0x9D, 0xC6, 0x90, 0xA6, 0x88,
+ 0xC7, 0x4E, 0xD8, 0xC8, 0x44, 0x8D, 0xFC, 0x6B, 0x31, 0x2B, 0xA9, 0x59, 0x8A, 0x6F, 0x49, 0xC8, 0x37, 0xA6, 0xD9, 0x6D,
+ 0x73, 0x37, 0xCD, 0xF5, 0x1C, 0x45, 0x8E, 0x0A, 0x53, 0xB0, 0xC7, 0xA7, 0x5C, 0x7C, 0x07, 0x73, 0xD3, 0x72, 0x06, 0xE7,
+ 0x8C, 0x02, 0x00, 0x75, 0xAE, 0x8B, 0x30, 0xDB, 0x27, 0x74, 0x8F, 0x7E, 0xD8, 0xC7, 0x7C, 0x63, 0xE5, 0xBE, 0x7D, 0x3B,
+ 0xF0, 0xF4, 0xA3, 0x16, 0x96, 0xDE, 0xBF, 0x05, 0xD6, 0x69, 0x8E, 0xDA, 0x3A, 0x0C, 0x7A, 0x63, 0x18, 0xFE, 0x3D, 0x7A,
+ 0xFC, 0x7A, 0x75, 0xE0, 0xD3, 0x44, 0x71, 0xEB, 0xF2, 0xFF, 0x00, 0x06, 0x85, 0x92, 0x94, 0x80, 0x52, 0x06, 0x33, 0xD8,
+ 0xE3, 0x62, 0x76, 0x00, 0xEF, 0xEB, 0x92, 0x08, 0xDB, 0x18, 0xC6, 0xFC, 0x1D, 0xDF, 0xF1, 0xF2, 0xC1, 0xA3, 0xE9, 0x07,
+ 0x8C, 0xE4, 0x8F, 0x1A, 0xD6, 0x5B, 0xD7, 0xCB, 0x7A, 0x5B, 0x7C, 0x51, 0x2F, 0xA9, 0x94, 0xD3, 0x5A, 0xB6, 0xDB, 0x6A,
+ 0xA3, 0x6D, 0xEA, 0x0D, 0xBA, 0x51, 0xCC, 0xDD, 0xC9, 0xA7, 0x37, 0x33, 0x02, 0x9D, 0x77, 0x52, 0x94, 0xD9, 0xCF, 0x99,
+ 0x21, 0xA8, 0x65, 0xAA, 0xCD, 0x38, 0x9C, 0x96, 0xAA, 0x94, 0x98, 0x2E, 0x36, 0x42, 0xB0, 0x41, 0x46, 0xE7, 0xE5, 0x6E,
+ 0x53, 0x52, 0x7B, 0x37, 0xA2, 0xAA, 0x5F, 0xEA, 0xA2, 0xA2, 0xE5, 0xF2, 0x24, 0xA1, 0x8B, 0x5A, 0x35, 0x8E, 0xE8, 0x81,
+ 0x58, 0xC7, 0x4A, 0x2A, 0x67, 0xA5, 0xB2, 0x72, 0x41, 0xEF, 0x36, 0x64, 0x22, 0xDC, 0xF4, 0xE3, 0x5E, 0xF5, 0x56, 0x97,
+ 0xA8, 0x7A, 0x0F, 0xA7, 0xBA, 0x69, 0xAA, 0xF5, 0x17, 0x2E, 0x7A, 0xD6, 0x94, 0x51, 0x5A, 0x57, 0x84, 0xCF, 0x12, 0xAD,
+ 0xE6, 0x74, 0x8B, 0xCF, 0x43, 0x65, 0xAD, 0xC9, 0xAD, 0xE8, 0xB5, 0xFF, 0x00, 0x3F, 0xED, 0x39, 0x32, 0x75, 0x9B, 0xED,
+ 0x2B, 0x97, 0x67, 0x48, 0x98, 0xF2, 0x9E, 0x8C, 0xA1, 0x3E, 0x88, 0x54, 0xDC, 0x5A, 0xB2, 0xD4, 0xDF, 0x66, 0xF7, 0x4B,
+ 0xB7, 0x41, 0x54, 0xA1, 0x4C, 0xEC, 0x6F, 0x12, 0x8D, 0x08, 0x7B, 0x1B, 0x93, 0x07, 0x5D, 0x17, 0xB5, 0xD7, 0x0A, 0xE4,
+ 0xBA, 0x6A, 0xEA, 0x51, 0x71, 0x68, 0xB2, 0x46, 0x4A, 0xA6, 0x2F, 0xD4, 0x5E, 0x62, 0x29, 0xC0, 0xCE, 0x39, 0xC4, 0xEB,
+ 0xEE, 0x21, 0xE7, 0x58, 0x7C, 0x25, 0xB9, 0x2C, 0x29, 0x01, 0xE4, 0xB6, 0xAF, 0x31, 0xB5, 0xA1, 0xD6, 0x5B, 0x7D, 0x89,
+ 0x11, 0xDD, 0xCE, 0x1F, 0x89, 0x36, 0x2B, 0xAC, 0x4B, 0x84, 0xF8, 0xD9, 0xE8, 0xAF, 0xB4, 0xE0, 0x09, 0x51, 0x52, 0x53,
+ 0xC6, 0xC8, 0xA6, 0x52, 0x32, 0x91, 0x7C, 0x43, 0xDB, 0xA6, 0x11, 0x89, 0x86, 0x32, 0x6A, 0x86, 0x6F, 0xCD, 0xC8, 0xE4,
+ 0xBF, 0xF8, 0x9D, 0x21, 0xE7, 0x0E, 0xCA, 0xFC, 0x32, 0x7E, 0x43, 0x39, 0x03, 0x7F, 0x4C, 0x6F, 0xC1, 0xA7, 0xAF, 0x9C,
+ 0xE7, 0xD1, 0x7F, 0x9F, 0xF3, 0xE0, 0xD1, 0xA7, 0x49, 0x78, 0x76, 0x3F, 0x0C, 0x0D, 0x8F, 0x4E, 0xE7, 0xA6, 0x7F, 0x3C,
+ 0x71, 0xA9, 0x45, 0xA7, 0xA6, 0x93, 0xBF, 0x55, 0x5C, 0x79, 0x84, 0x8F, 0xD2, 0x22, 0xFA, 0x70, 0xC3, 0x8B, 0x74, 0xFF,
+ 0x00, 0x55, 0x3C, 0xCC, 0xDA, 0x7C, 0x66, 0x7E, 0x0E, 0xB1, 0x2E, 0x93, 0xD3, 0x98, 0x9E, 0x9E, 0x9D, 0xFF, 0x00, 0xEF,
+ 0xEB, 0x9E, 0xDC, 0x28, 0x8B, 0x4D, 0x07, 0x92, 0xFE, 0x73, 0x29, 0xE0, 0xE3, 0xD1, 0xD2, 0xF5, 0x63, 0x33, 0x71, 0x23,
+ 0xBB, 0x6F, 0x89, 0x11, 0xE4, 0xC6, 0xB0, 0x53, 0xBE, 0xA4, 0x0F, 0xEB, 0x1C, 0xFC, 0x7D, 0x3F, 0xBB, 0xDF, 0xC3, 0xF5,
+ 0xAE, 0xAB, 0xD8, 0x29, 0x33, 0xE0, 0xB8, 0x3E, 0x9E, 0x9A, 0x0B, 0xC4, 0x3D, 0x44, 0x33, 0x02, 0x19, 0xF3, 0x2D, 0xBB,
+ 0xE3, 0x58, 0x17, 0x7A, 0xFD, 0xAC, 0x82, 0x31, 0xCA, 0x9D, 0x81, 0x1B, 0x77, 0xC1, 0xCF, 0xC7, 0x27, 0xBE, 0xDE, 0xA2,
+ 0x65, 0x69, 0x4A, 0x96, 0xF5, 0xD4, 0x92, 0x4C, 0x3E, 0xEA, 0x47, 0x07, 0x7E, 0xD2, 0x5A, 0x1F, 0x4B, 0xE9, 0x6B, 0x35,
+ 0x39, 0xF5, 0x7B, 0xF3, 0x82, 0x7E, 0x6E, 0x87, 0x53, 0xBD, 0x40, 0x38, 0xEF, 0x84, 0x83, 0xF8, 0x67, 0x1D, 0xF7, 0x2A,
+ 0x3B, 0xE0, 0xEC, 0x06, 0x0F, 0x14, 0x54, 0x52, 0x37, 0x73, 0x3E, 0xD3, 0xD3, 0x26, 0x15, 0x0B, 0x84, 0xCF, 0x48, 0x65,
+ 0x6F, 0xE0, 0x2D, 0x4B, 0x13, 0xDF, 0x80, 0x38, 0x26, 0xD3, 0xE8, 0x41, 0xFE, 0xAB, 0xF3, 0xA5, 0xA8, 0x4D, 0x31, 0xDA,
+ 0x52, 0xB3, 0x92, 0x90, 0x4F, 0x5E, 0xB8, 0x23, 0x60, 0x01, 0xC0, 0x1B, 0x9C, 0x67, 0xA0, 0x07, 0xD7, 0x3C, 0x65, 0x55,
+ 0x52, 0xA9, 0x61, 0x6D, 0xF0, 0xC5, 0xF3, 0x3E, 0x74, 0x99, 0x6D, 0x24, 0x2F, 0x24, 0xB1, 0x11, 0x13, 0xFC, 0xDB, 0xC5,
+ 0xB5, 0x2B, 0xE9, 0xF7, 0x8C, 0xDD, 0x2A, 0xD3, 0x6D, 0x29, 0xB5, 0xA3, 0xB9, 0x6B, 0x35, 0x50, 0xD4, 0xAB, 0x52, 0x8B,
+ 0x51, 0xA4, 0x32, 0xA9, 0x0D, 0xA5, 0xD5, 0x8A, 0xBF, 0xD6, 0xF5, 0x59, 0x8A, 0x53, 0x6D, 0xA8, 0x73, 0x07, 0x66, 0x4E,
+ 0x98, 0x5E, 0x52, 0xC2, 0x47, 0x32, 0x9D, 0xE6, 0x2A, 0x38, 0x2A, 0xE3, 0xA3, 0x6F, 0xF1, 0x9B, 0x7B, 0x7B, 0x54, 0x05,
+ 0x0B, 0xB9, 0x45, 0x31, 0x3C, 0x2F, 0x53, 0x55, 0x8C, 0x11, 0x33, 0xE7, 0xE1, 0x1A, 0xE5, 0x6B, 0xA5, 0x16, 0xAA, 0x98,
+ 0x73, 0x41, 0x6A, 0xBA, 0x85, 0xF6, 0x56, 0x66, 0x38, 0x00, 0x9F, 0x31, 0x1A, 0xAD, 0x76, 0xEC, 0xBA, 0xC5, 0x6E, 0x45,
+ 0x4E, 0xE7, 0xB8, 0xE4, 0x19, 0x97, 0x15, 0xD1, 0x55, 0xA8, 0x5C, 0x15, 0xE9, 0x4E, 0x12, 0xA5, 0xBF, 0x54, 0xAB, 0x48,
+ 0x5C, 0xB9, 0x23, 0x27, 0x7E, 0x46, 0x4A, 0x91, 0x15, 0x84, 0x92, 0x42, 0x23, 0xC7, 0x6D, 0x09, 0xC0, 0x48, 0x1C, 0x71,
+ 0x13, 0x52, 0xD6, 0xD4, 0xAD, 0x55, 0x35, 0x2C, 0xF2, 0xD9, 0xF8, 0x29, 0x7E, 0xC9, 0x6D, 0x6B, 0x45, 0x27, 0x4D, 0xFD,
+ 0xEA, 0x9E, 0xA5, 0xC5, 0xF8, 0x88, 0xEC, 0x20, 0x7A, 0x46, 0xA4, 0x58, 0xC4, 0x25, 0x03, 0x20, 0x60, 0xF5, 0xDF, 0x04,
+ 0x01, 0xD0, 0x1C, 0x7B, 0xC0, 0x3E, 0xFD, 0xB7, 0x39, 0xE2, 0xF5, 0xAF, 0x6F, 0x53, 0xCA, 0xDF, 0x1D, 0xEE, 0x73, 0xC6,
+ 0x74, 0xB7, 0x9A, 0x9E, 0xC7, 0xE3, 0x91, 0xB0, 0xEB, 0xD7, 0x23, 0x23, 0xE1, 0x8E, 0xB8, 0x1B, 0xEC, 0x78, 0x35, 0x51,
+ 0x50, 0xC9, 0xEC, 0xD2, 0xDD, 0x1A, 0x81, 0x0B, 0xC1, 0x76, 0x99, 0xC3, 0xC3, 0x3E, 0x2D, 0xAF, 0xDC, 0xE4, 0xFB, 0xC9,
+ 0xF8, 0xFE, 0x5B, 0xE4, 0xFF, 0x00, 0x0F, 0xD0, 0xD4, 0x11, 0x92, 0x61, 0xBF, 0x1D, 0xFD, 0x54, 0xC4, 0xC7, 0x97, 0x9D,
+ 0x08, 0xF9, 0xC8, 0x29, 0x39, 0xE9, 0x93, 0xF1, 0x38, 0xEF, 0x8E, 0xBD, 0x3B, 0xFE, 0x1B, 0xF0, 0x69, 0xF3, 0xFB, 0x7D,
+ 0xFD, 0xDB, 0x4C, 0xCA, 0xDB, 0x1E, 0xD2, 0xC3, 0xAD, 0xA9, 0x29, 0x21, 0x68, 0x29, 0x39, 0xDD, 0x3D, 0x30, 0x08, 0xFC,
+ 0x40, 0xEA, 0x7B, 0xE7, 0x19, 0xC7, 0x13, 0x54, 0xC4, 0x03, 0x7B, 0x4F, 0x07, 0x79, 0xD0, 0xE1, 0xF4, 0xF1, 0xFB, 0xDB,
+ 0xE7, 0x6D, 0x63, 0xA4, 0xBE, 0x26, 0xAA, 0x3A, 0x23, 0x4F, 0x9D, 0xA5, 0x5A, 0x87, 0x6C, 0x35, 0xA8, 0x5A, 0x3B, 0x50,
+ 0x96, 0xFC, 0xAA, 0x65, 0x2A, 0x7A, 0x03, 0xD2, 0xAD, 0xE7, 0x9F, 0x59, 0x5B, 0xE8, 0xA5, 0x3C, 0xBC, 0xA9, 0x84, 0xA1,
+ 0x6A, 0x52, 0xDB, 0x65, 0xA2, 0x95, 0x25, 0x2A, 0xFB, 0x00, 0xA3, 0x21, 0x1A, 0xEC, 0xFE, 0x25, 0xDA, 0x1D, 0xBA, 0xE9,
+ 0x37, 0x36, 0x97, 0xDD, 0xAB, 0xFA, 0x72, 0x4D, 0x3D, 0xBC, 0x84, 0x6B, 0x8D, 0xAC, 0xDB, 0xA8, 0x2B, 0x9E, 0x91, 0x4A,
+ 0x2B, 0xA5, 0xC1, 0x96, 0x96, 0xF7, 0x0F, 0xE9, 0x9C, 0x5A, 0x3B, 0x69, 0xC7, 0x76, 0xEA, 0x86, 0x9C, 0xDF, 0x97, 0x2D,
+ 0x1D, 0xCD, 0x2A, 0xA4, 0xD4, 0xE9, 0x56, 0xED, 0x22, 0xD3, 0x8D, 0x4A, 0x9A, 0x2A, 0x7C, 0xEA, 0x71, 0x53, 0xC5, 0x56,
+ 0xA5, 0x3A, 0x2C, 0x36, 0xDD, 0x50, 0x0A, 0x75, 0xBA, 0x5C, 0x19, 0x9E, 0xCC, 0x95, 0x9C, 0x94, 0x34, 0xA6, 0x23, 0xE7,
+ 0x91, 0x96, 0xD0, 0x95, 0xBB, 0xBB, 0x45, 0x6D, 0x3F, 0x95, 0x47, 0x48, 0x53, 0x0C, 0xCA, 0xC0, 0xA9, 0x3E, 0x93, 0x05,
+ 0xAC, 0x45, 0x38, 0x0D, 0x6F, 0x45, 0x65, 0x72, 0x53, 0x54, 0xC1, 0xEF, 0x04, 0x02, 0xB2, 0x17, 0x99, 0x7C, 0xE1, 0xBC,
+ 0xCF, 0x09, 0x37, 0x20, 0xAB, 0x24, 0x13, 0xEF, 0x38, 0xF8, 0x60, 0x0D, 0xC7, 0x4F, 0x5E, 0xBC, 0x67, 0x3C, 0xB3, 0xE9,
+ 0x09, 0x16, 0xBB, 0xCA, 0x92, 0xC4, 0xD8, 0xB7, 0x9D, 0x6A, 0x11, 0xF7, 0xF7, 0xFA, 0x69, 0x4F, 0x37, 0xDE, 0xAF, 0xC7,
+ 0xFB, 0xF8, 0xAD, 0x1A, 0x79, 0x70, 0x68, 0x71, 0x4F, 0xFB, 0xAA, 0xFF, 0x00, 0xC7, 0x58, 0xAF, 0xEE, 0x9F, 0x97, 0xEA,
+ 0x38, 0xBA, 0x32, 0xFA, 0x7E, 0xE6, 0xA7, 0x6F, 0xDD, 0xAB, 0xEF, 0x9A, 0x74, 0x81, 0xE9, 0xF3, 0x4F, 0xEA, 0x38, 0xD5,
+ 0xF7, 0x6B, 0xFF, 0x00, 0x6B, 0xF5, 0x35, 0xB5, 0x3E, 0xE5, 0x5F, 0x1F, 0xA1, 0xAC, 0x87, 0x5F, 0x92, 0xBF, 0x43, 0xC7,
+ 0x3E, 0xEF, 0xBA, 0x7F, 0xB6, 0x9F, 0xAE, 0xA7, 0x73, 0xDF, 0x3F, 0xDA, 0xFD, 0x4D, 0x0A, 0xAE, 0x87, 0xE0, 0x7F, 0x4E,
+ 0x1D, 0x7F, 0xFD, 0xDD, 0xCF, 0x53, 0xE9, 0xA2, 0xAC, 0xD7, 0xFE, 0xEA, 0x7F, 0xF0, 0xD3, 0x6A, 0xB5, 0xFE, 0x8C, 0xEF,
+ 0xF5, 0x57, 0xFA, 0x2B, 0x85, 0xA9, 0xD5, 0x23, 0xA8, 0x7F, 0xEA, 0x03, 0xDF, 0xFE, 0xF3, 0x7F, 0xDA, 0x47, 0x1C, 0xFA,
+ 0xF2, 0xEB, 0xFF, 0x00, 0xF2, 0x7F, 0xFE, 0x94, 0xFD, 0x6A, 0xD5, 0xBE, 0xB7, 0xFF, 0x00, 0xD1, 0xA3, 0x7C, 0xBF, 0x44,
+ 0xF1, 0xAD, 0x18, 0x7D, 0x7F, 0x63, 0x5E, 0x91, 0x8A, 0x3E, 0x1F, 0xF8, 0xBA, 0x7A, 0x23, 0xFF, 0x00, 0x28, 0x7F, 0x58,
+ 0xFF, 0x00, 0x1E, 0x2F, 0x5A, 0xD1, 0x97, 0xD3, 0xF7, 0x34, 0x07, 0xFE, 0xE8, 0xBF, 0xFE, 0xB0, 0xFF, 0x00, 0x88, 0x78,
+ 0x0F, 0x78, 0xFF, 0x00, 0x6D, 0x7F, 0x43, 0x58, 0xF3, 0x57, 0xAD, 0x1F, 0x53, 0x5B, 0x14, 0x7D, 0xE1, 0xF3, 0xFD, 0x0F,
+ 0x06, 0xAF, 0x49, 0xBB, 0xD1, 0x5F, 0xD6, 0x1F, 0xDB, 0x1C, 0x1A, 0x34, 0xDB, 0xA8, 0x7D, 0xC5, 0x7C, 0xBF, 0xE2, 0x0E,
+ 0x0D, 0x1A, 0xAF, 0x7A, 0x9B, 0xFE, 0xAF, 0x7F, 0xFF, 0x00, 0x99, 0xBF, 0xED, 0xAB, 0x8E, 0x63, 0x1F, 0x1A, 0xBE, 0xAE,
+ 0xB8, 0x37, 0x7D, 0xCF, 0x8D, 0x5F, 0xF9, 0x1A, 0xDB, 0x69, 0x47, 0xFA, 0xA9, 0x8F, 0xEB, 0x3B, 0xFD, 0xA5, 0x71, 0xAD,
+ 0x3E, 0xE5, 0x5F, 0x1F, 0xA1, 0xAD, 0xF6, 0x3D, 0xDA, 0x7F, 0xDB, 0xFB, 0x9A, 0x9C, 0xD9, 0xE8, 0x9F, 0x8A, 0xFF, 0x00,
+ 0x55, 0x70, 0x51, 0x93, 0xFD, 0xAF, 0xFE, 0x4E, 0xBA, 0x34, 0x4F, 0x1D, 0x9A, 0x35, 0xFF, 0xD9
+};
+
+NPT_UInt8 Platinum_120x120_png[26577] =
+{
+ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x81,
+ 0x00, 0x00, 0x00, 0x81, 0x08, 0x02, 0x00, 0x00, 0x00, 0x68, 0xC2, 0x4E, 0x07, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47,
+ 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC,
+ 0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00,
+ 0xFA, 0x00, 0x00, 0x00, 0x80, 0xE8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xEA, 0x60, 0x00, 0x00, 0x3A, 0x98, 0x00, 0x00,
+ 0x17, 0x70, 0x9C, 0xBA, 0x51, 0x3C, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x12, 0x00, 0x00,
+ 0x0B, 0x12, 0x01, 0xD2, 0xDD, 0x7E, 0xFC, 0x00, 0x00, 0x67, 0x3A, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5E, 0x9D, 0xBD, 0x05,
+ 0x98, 0x9D, 0xD5, 0xD5, 0xF7, 0x3D, 0x68, 0x21, 0x68, 0x84, 0x84, 0xE8, 0x44, 0x67, 0x26, 0xE3, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0x92, 0xF1, 0x89, 0x4D, 0xDC, 0x85, 0xB8, 0x13, 0x08, 0x10, 0xDC, 0xDD, 0x9D, 0x42, 0xA1, 0x58, 0xA1, 0x2D, 0xA5, 0x50,
+ 0xA1, 0x85, 0xB6, 0xB4, 0x94, 0xEA, 0x5B, 0x6F, 0xE9, 0x53, 0x8A, 0xE5, 0xFD, 0xAD, 0xBD, 0xEE, 0x7B, 0xCF, 0x3D, 0x93,
+ 0xC0, 0xF3, 0xBD, 0xDF, 0x5C, 0xFB, 0x3A, 0xD7, 0x7D, 0xCE, 0x9C, 0x39, 0x73, 0xCE, 0x92, 0xFF, 0xB2, 0xFF, 0xDE, 0xE7,
+ 0xB4, 0xC1, 0xAE, 0x61, 0x9F, 0x91, 0x9F, 0x2F, 0xB8, 0x3C, 0x71, 0xE2, 0x34, 0xCF, 0x23, 0xCE, 0xE5, 0x89, 0x13, 0x9F,
+ 0xFB, 0xF8, 0x9C, 0x3E, 0xFA, 0x99, 0x72, 0xF7, 0x8B, 0xCF, 0x4F, 0x9C, 0xE6, 0x79, 0x98, 0x3F, 0x3D, 0xED, 0x84, 0x3C,
+ 0xAC, 0xCF, 0x3C, 0x71, 0x42, 0xEE, 0x98, 0x9F, 0xD3, 0x3D, 0xD7, 0xA3, 0x7E, 0x7B, 0xDA, 0x69, 0x67, 0x98, 0x5F, 0xF1,
+ 0xA0, 0xBC, 0x10, 0xFF, 0xE8, 0xB4, 0xD3, 0x9C, 0x37, 0xA0, 0x7F, 0xA2, 0x77, 0xB9, 0xD5, 0x9F, 0xD3, 0x4F, 0x3F, 0xFD,
+ 0x8C, 0x33, 0xCE, 0xE0, 0xF6, 0xCC, 0x33, 0xCF, 0x3C, 0xFD, 0x74, 0x1F, 0xAE, 0x4F, 0x3B, 0xFD, 0xC4, 0xE9, 0xA7, 0x9D,
+ 0xC9, 0xDB, 0xFE, 0xFC, 0xF3, 0xCF, 0x4F, 0xF8, 0x7C, 0xFA, 0xF9, 0x67, 0x27, 0xBE, 0xF8, 0xE2, 0x8B, 0x13, 0x9F, 0x9D,
+ 0xF8, 0xE4, 0xF3, 0xCF, 0x7C, 0x3E, 0xFB, 0xFC, 0xD3, 0x13, 0x5F, 0xF0, 0x3A, 0x3C, 0x72, 0xFA, 0x17, 0x27, 0x3E, 0xF9,
+ 0xE2, 0x73, 0x1F, 0x9E, 0xFA, 0x85, 0xBC, 0x31, 0x1E, 0xD5, 0x77, 0x28, 0xAF, 0xEF, 0xBE, 0xB9, 0xD3, 0xCF, 0xE0, 0x21,
+ 0x7D, 0x1B, 0xCE, 0xBF, 0xE6, 0xC2, 0xF9, 0x25, 0x8F, 0x9C, 0x76, 0x1A, 0xAF, 0x63, 0x3F, 0xD8, 0xE7, 0x3C, 0xF5, 0xC4,
+ 0xC8, 0x33, 0xF5, 0x4A, 0x5F, 0xD0, 0xFE, 0xD5, 0x17, 0xA7, 0x7D, 0x71, 0x26, 0x22, 0x39, 0xF1, 0xF9, 0x17, 0x3E, 0xE6,
+ 0x53, 0xF0, 0x17, 0xA7, 0x8D, 0xFA, 0xF8, 0xF2, 0x47, 0x03, 0x9D, 0xCB, 0xCD, 0x5A, 0xCA, 0x6D, 0x7F, 0xC7, 0x32, 0xBD,
+ 0x30, 0xB7, 0x4B, 0xB9, 0xEB, 0x59, 0x4B, 0xFA, 0x3B, 0x96, 0xF4, 0xB5, 0x2F, 0x75, 0xD7, 0x62, 0xEF, 0x75, 0x6F, 0xDB,
+ 0x50, 0x6F, 0xDB, 0x12, 0x59, 0xAD, 0x4B, 0x9D, 0x8B, 0xB6, 0x25, 0x3D, 0xAD, 0x8B, 0xCD, 0x1A, 0x74, 0x2F, 0xFA, 0xB9,
+ 0xEE, 0x6E, 0x19, 0xEA, 0x6E, 0x19, 0xD0, 0xD5, 0xD5, 0xD4, 0xB7, 0xA8, 0xB9, 0x9F, 0x8B, 0x45, 0xCD, 0x83, 0x5C, 0xF4,
+ 0x34, 0xF5, 0x73, 0xAB, 0x0F, 0xEA, 0xD2, 0x6B, 0x6E, 0x79, 0x8E, 0x79, 0x9D, 0xC1, 0xBE, 0xF6, 0xC5, 0x43, 0x1D, 0x4B,
+ 0x97, 0xF4, 0xAC, 0x58, 0xDE, 0xBF, 0x7A, 0xD5, 0xE2, 0xF5, 0xEB, 0x96, 0x6F, 0xDC, 0xB0, 0x62, 0xF3, 0xDA, 0xE5, 0xEB,
+ 0xD6, 0xAF, 0xD8, 0xB0, 0x71, 0xE5, 0x96, 0xCD, 0x6B, 0xB6, 0x70, 0xBB, 0x76, 0xD9, 0x86, 0x15, 0x83, 0xAB, 0x97, 0xF5,
+ 0xAD, 0x5A, 0xBA, 0x68, 0x78, 0xA8, 0x9D, 0xB7, 0x31, 0xD8, 0xD5, 0xD2, 0xDF, 0xDD, 0xD0, 0xDB, 0x55, 0xDF, 0xD3, 0x51,
+ 0xBB, 0xA8, 0xB5, 0xB6, 0xAB, 0xB3, 0xBA, 0xAB, 0xBD, 0xBA, 0xB3, 0xAD, 0xAA, 0xA3, 0x95, 0x55, 0xD9, 0xCE, 0xAD, 0x73,
+ 0xCD, 0x05, 0x8F, 0x57, 0x77, 0xCA, 0x23, 0x35, 0xED, 0xED, 0xB5, 0x1D, 0x9D, 0xB5, 0x9D, 0xDC, 0xB6, 0xD7, 0xB6, 0xB5,
+ 0x56, 0xB7, 0xF1, 0x78, 0x4B, 0x65, 0x7B, 0x73, 0x45, 0x47, 0x73, 0x79, 0xAB, 0xAC, 0x8A, 0xB6, 0xA6, 0xF2, 0xD6, 0x86,
+ 0x92, 0xA6, 0x86, 0xD2, 0xE6, 0xC6, 0xE2, 0xA6, 0xFA, 0xA2, 0xE6, 0xFA, 0x92, 0x16, 0x59, 0xC5, 0x8D, 0x75, 0x25, 0xF5,
+ 0x75, 0xDC, 0x16, 0x37, 0xF3, 0xA0, 0x5C, 0x14, 0xD5, 0xD5, 0x16, 0x35, 0xC8, 0x2A, 0xAE, 0xAB, 0x2D, 0xAE, 0xA9, 0x29,
+ 0xAA, 0x95, 0x8B, 0xC2, 0x5A, 0x2E, 0xAA, 0x0B, 0x6B, 0x58, 0x3E, 0x56, 0xCA, 0x7C, 0x3C, 0x73, 0x2D, 0x82, 0xE6, 0xA2,
+ 0xAF, 0x6D, 0x99, 0x47, 0xCA, 0x2A, 0x7A, 0x91, 0x3B, 0x02, 0x45, 0xCA, 0x5C, 0x1B, 0xB9, 0x0F, 0x99, 0x8B, 0x25, 0x3D,
+ 0x2D, 0xA2, 0x00, 0x2B, 0x74, 0x34, 0xE1, 0x5E, 0x2F, 0xF6, 0x0A, 0x5D, 0x45, 0x6F, 0xE4, 0xDB, 0xEB, 0x15, 0xB4, 0x48,
+ 0xB9, 0xD1, 0x59, 0x9D, 0x8D, 0xBD, 0x2C, 0x1E, 0xB1, 0xCB, 0x3E, 0xB3, 0xBB, 0xCD, 0xE8, 0x60, 0xD1, 0xD2, 0xA5, 0xBD,
+ 0xC3, 0x2B, 0x87, 0xD6, 0xAC, 0x59, 0xBC, 0x76, 0x79, 0xFF, 0xCA, 0xE5, 0x03, 0xC3, 0xDB, 0x37, 0xED, 0xD8, 0xBB, 0x63,
+ 0xFF, 0xC6, 0x35, 0x9B, 0x56, 0x2E, 0x5D, 0xBD, 0x69, 0xF5, 0x66, 0xD6, 0xDA, 0x65, 0x9B, 0x56, 0x0C, 0xAD, 0x1C, 0xEE,
+ 0x5B, 0xBE, 0xA4, 0x6B, 0x79, 0x6F, 0xF3, 0x50, 0x67, 0x63, 0x7F, 0x77, 0x7D, 0x3F, 0x02, 0xED, 0xAC, 0x5D, 0xD4, 0x51,
+ 0xD3, 0xD5, 0x52, 0xD3, 0xD9, 0x54, 0xD5, 0x8E, 0xF4, 0x8D, 0x4C, 0xDB, 0x74, 0x71, 0xCD, 0x72, 0x54, 0x62, 0x14, 0xC0,
+ 0xEA, 0xA8, 0xEB, 0x64, 0x71, 0x81, 0x4A, 0x58, 0xAD, 0x95, 0x22, 0xFD, 0xA6, 0xB2, 0x16, 0x56, 0x23, 0xA2, 0x2F, 0x6D,
+ 0x46, 0x07, 0x35, 0x25, 0x8D, 0xC8, 0xBD, 0xBE, 0xB8, 0x5E, 0x44, 0xAF, 0xD2, 0x97, 0x8B, 0x5A, 0x11, 0x7A, 0x61, 0xBD,
+ 0x91, 0x7B, 0x9D, 0xC8, 0xDD, 0x08, 0xBD, 0xA6, 0xA8, 0x1A, 0xA1, 0x9B, 0x0B, 0xD1, 0x04, 0xD7, 0x55, 0x05, 0xD5, 0xA2,
+ 0x83, 0xD1, 0xD6, 0x8D, 0xA0, 0x47, 0xD9, 0xB8, 0x2B, 0x6E, 0xA4, 0x3C, 0x60, 0x6C, 0x5C, 0x44, 0xCF, 0xF2, 0x18, 0xF8,
+ 0x20, 0x3A, 0xB0, 0xA6, 0x6A, 0x04, 0x3D, 0x62, 0xEC, 0x6A, 0xE3, 0x1E, 0x89, 0x0F, 0xA8, 0xB8, 0x8D, 0x88, 0x7B, 0x54,
+ 0xD0, 0x56, 0xEE, 0x8B, 0x1A, 0x44, 0x01, 0xCE, 0xDD, 0xFA, 0x1E, 0xBD, 0xCB, 0xDF, 0x1A, 0xAD, 0xF4, 0x74, 0xB6, 0x0D,
+ 0x0C, 0xB6, 0x0D, 0x2E, 0x59, 0xB4, 0x74, 0x59, 0xDF, 0x8A, 0x95, 0x03, 0x2B, 0x10, 0xF1, 0x65, 0x5B, 0x77, 0xBF, 0xFD,
+ 0xFD, 0x1F, 0xFC, 0xF5, 0xAF, 0x7F, 0xFD, 0xC7, 0x3F, 0xFE, 0xF5, 0xBB, 0xDF, 0xFC, 0xFE, 0x89, 0x47, 0x9F, 0xD9, 0xB8,
+ 0x6A, 0xD3, 0x86, 0xE5, 0xEB, 0x37, 0xAC, 0xDE, 0x24, 0xDE, 0x80, 0x86, 0xBA, 0x97, 0x0F, 0x76, 0x0C, 0xC9, 0x7F, 0x6F,
+ 0xEC, 0xEE, 0xAC, 0xEB, 0x6E, 0xAF, 0xE9, 0x62, 0x61, 0xE6, 0x22, 0x71, 0x0C, 0xB9, 0xCA, 0x51, 0x03, 0x16, 0x6D, 0xD5,
+ 0xA0, 0x1E, 0xA0, 0xD2, 0x6F, 0xAB, 0xEB, 0xEC, 0xAA, 0xEB, 0x52, 0x7D, 0xB4, 0x57, 0xB7, 0xB7, 0x55, 0xA1, 0xAD, 0x8E,
+ 0xA6, 0xB2, 0x26, 0x91, 0x7E, 0x29, 0x86, 0xDF, 0xC4, 0x32, 0x26, 0x2F, 0x6A, 0x40, 0xE8, 0xAA, 0x00, 0x84, 0x6B, 0x6F,
+ 0xAB, 0x8A, 0xB8, 0x5B, 0x53, 0x57, 0xE4, 0xC8, 0x5D, 0x0D, 0x5F, 0x17, 0xD2, 0x67, 0x95, 0xE7, 0x57, 0xF9, 0x9C, 0x6C,
+ 0xEC, 0x16, 0x4C, 0xDC, 0x8B, 0x21, 0x35, 0x73, 0x5D, 0x2E, 0xBC, 0x38, 0x08, 0x83, 0x88, 0x79, 0x44, 0x85, 0xBE, 0xA8,
+ 0x55, 0x16, 0xD7, 0x8A, 0x30, 0xAE, 0xC9, 0xA3, 0x83, 0x41, 0x8B, 0x30, 0x5E, 0xA1, 0x5B, 0x89, 0x77, 0x34, 0xF4, 0xE8,
+ 0x42, 0xD6, 0xDC, 0xB6, 0xD7, 0x77, 0xEB, 0x6D, 0x5B, 0xDD, 0x22, 0x7D, 0x1C, 0x18, 0xE1, 0x57, 0x3D, 0xCD, 0xBD, 0x03,
+ 0xED, 0xFD, 0xE8, 0x60, 0x71, 0xD7, 0x92, 0x65, 0x3D, 0x4B, 0xB6, 0xAE, 0xDB, 0xF6, 0xA7, 0x3F, 0xFE, 0x19, 0x3C, 0xFD,
+ 0xF8, 0xE3, 0xFF, 0xF9, 0xF8, 0xE3, 0x8F, 0x3F, 0xFB, 0xE4, 0x53, 0xAE, 0x7F, 0xFA, 0xD3, 0xF7, 0xB6, 0xAC, 0xDF, 0xB6,
+ 0x6E, 0x78, 0x3D, 0xE8, 0xB4, 0x7A, 0x68, 0xE5, 0xD2, 0xEE, 0x25, 0xFC, 0x49, 0x37, 0xCA, 0x6E, 0x10, 0x90, 0xE9, 0xA8,
+ 0x12, 0x08, 0x72, 0xCC, 0xBF, 0xBC, 0xB5, 0xB1, 0xB2, 0x4D, 0x8C, 0x1A, 0xD3, 0x36, 0xF0, 0x82, 0x56, 0x5A, 0xAA, 0x5A,
+ 0x81, 0x9D, 0x96, 0xDA, 0xD6, 0x8E, 0x1A, 0x11, 0x7A, 0x43, 0x59, 0x63, 0x59, 0x4E, 0x79, 0x43, 0x49, 0x43, 0x73, 0x65,
+ 0x8B, 0xFE, 0x8A, 0x67, 0x36, 0x96, 0x37, 0x18, 0xD8, 0x71, 0xA4, 0x8F, 0x2B, 0xA8, 0xB1, 0x8B, 0xBD, 0x1B, 0x05, 0x28,
+ 0xE6, 0x00, 0x41, 0x18, 0x7B, 0x15, 0xAB, 0xA0, 0x5A, 0x0C, 0xBF, 0x60, 0x44, 0xF4, 0x95, 0xF9, 0x55, 0x15, 0x46, 0x01,
+ 0x5C, 0x8C, 0xE8, 0xC0, 0x35, 0x70, 0x31, 0xF3, 0x93, 0x70, 0x5C, 0x80, 0xB8, 0xA7, 0x55, 0xD0, 0xDC, 0x8A, 0x5B, 0x44,
+ 0xDC, 0xAC, 0xA2, 0x47, 0xE2, 0x6A, 0xE9, 0x22, 0x68, 0x90, 0x57, 0xEF, 0x8E, 0x11, 0x7A, 0x57, 0x93, 0xA0, 0x7F, 0x27,
+ 0xC6, 0xE8, 0x9A, 0xB9, 0x88, 0xBB, 0xA9, 0xDF, 0x4A, 0x7F, 0x94, 0xE8, 0x1B, 0xBA, 0xDB, 0x1A, 0xBA, 0x55, 0x07, 0xBA,
+ 0xC0, 0xF1, 0x45, 0xA2, 0x86, 0xEE, 0xFE, 0xB6, 0x3E, 0x64, 0x3A, 0xD0, 0x3E, 0xB8, 0xAC, 0x67, 0xE9, 0x83, 0xF7, 0x3C,
+ 0x84, 0xD0, 0x3F, 0xFA, 0xE8, 0xA3, 0xFF, 0x9A, 0x1F, 0x34, 0xF1, 0xEF, 0x7F, 0xFF, 0x9B, 0x47, 0x5E, 0x7F, 0xFD, 0x3B,
+ 0xAB, 0x96, 0xAD, 0x5E, 0xBB, 0x62, 0xDD, 0xAA, 0x25, 0xAB, 0x89, 0x1C, 0x3C, 0x19, 0x1D, 0x88, 0x21, 0xE3, 0x01, 0x2E,
+ 0xFE, 0x08, 0x94, 0x03, 0x26, 0x8A, 0x2A, 0xEE, 0x6A, 0xA9, 0x40, 0xD0, 0xCD, 0x66, 0xB5, 0x36, 0x54, 0x36, 0x56, 0xE6,
+ 0x56, 0x82, 0x30, 0x9B, 0x56, 0x6D, 0x6D, 0xAA, 0x68, 0xAE, 0xC8, 0x29, 0xAB, 0x2F, 0xAD, 0xE3, 0xA2, 0xB9, 0x5C, 0xF0,
+ 0xA7, 0xA1, 0x44, 0x2C, 0xDD, 0x2E, 0x47, 0xE8, 0xE0, 0x4F, 0x71, 0x8D, 0x62, 0xBD, 0xEA, 0x80, 0x0B, 0x07, 0x79, 0x8C,
+ 0x02, 0x44, 0xE2, 0x85, 0xD5, 0x48, 0x9F, 0x8B, 0xAA, 0xDC, 0x72, 0x75, 0x02, 0xAE, 0x7D, 0x8C, 0x69, 0xAB, 0x94, 0x91,
+ 0x29, 0xA1, 0x4F, 0x03, 0xA9, 0x77, 0x11, 0x48, 0x35, 0x8A, 0x8A, 0xC4, 0xDD, 0xA5, 0x81, 0x54, 0x6D, 0x7C, 0x00, 0xC0,
+ 0x15, 0x87, 0x68, 0x32, 0x16, 0x27, 0xF0, 0x22, 0x12, 0x77, 0x4D, 0x1E, 0xB9, 0xA3, 0x12, 0x9E, 0x03, 0xB0, 0x88, 0x0E,
+ 0x3C, 0x72, 0xEF, 0x43, 0xD0, 0xBA, 0xC4, 0x09, 0xEA, 0x44, 0xE8, 0xC4, 0x4C, 0x15, 0x3A, 0xC0, 0xDD, 0x55, 0x23, 0xB7,
+ 0xD8, 0x2F, 0xE2, 0x13, 0x28, 0x6F, 0xEC, 0xC4, 0x15, 0x3A, 0xEB, 0xDB, 0xB1, 0xEE, 0x25, 0x3D, 0xCB, 0x1F, 0x7D, 0xE8,
+ 0x49, 0x72, 0x9B, 0x4F, 0x3E, 0xF9, 0xF8, 0x33, 0x7E, 0xBE, 0xF8, 0x94, 0x9B, 0x4F, 0x3F, 0xFD, 0x54, 0x7D, 0xE2, 0xD8,
+ 0xA1, 0x63, 0xC3, 0x83, 0x2B, 0x56, 0x2E, 0x5E, 0x45, 0xE4, 0x40, 0x07, 0xBD, 0x4D, 0xFC, 0x95, 0x04, 0xDE, 0x96, 0xF2,
+ 0x0E, 0x81, 0x20, 0x83, 0xE9, 0x88, 0x1E, 0x35, 0xA8, 0x26, 0x04, 0x58, 0x4A, 0x1B, 0x1A, 0x4A, 0xB1, 0xF1, 0xA6, 0xA6,
+ 0x8A, 0x46, 0x2C, 0xBD, 0x32, 0xBF, 0xA2, 0x2A, 0xAF, 0xEA, 0x95, 0x97, 0x5F, 0xFF, 0xE4, 0xD3, 0xCF, 0xBF, 0xF3, 0xFA,
+ 0xF7, 0xEA, 0x0B, 0xEB, 0xCA, 0x73, 0x51, 0x43, 0x43, 0x63, 0xA9, 0x22, 0x4F, 0xAD, 0xA2, 0x8D, 0x22, 0xBB, 0x77, 0x21,
+ 0x6B, 0xD1, 0x41, 0x51, 0x03, 0x1E, 0x50, 0x59, 0x58, 0x83, 0xD0, 0xB9, 0x15, 0xA1, 0x1B, 0xD1, 0xEB, 0x05, 0xA2, 0xAF,
+ 0xC8, 0x2B, 0xE7, 0xB6, 0x34, 0x97, 0x8B, 0x4A, 0x1F, 0xD7, 0xC0, 0x55, 0x0D, 0x62, 0xEF, 0xAE, 0x75, 0x0B, 0x88, 0x8F,
+ 0x81, 0x14, 0x2B, 0x77, 0x0B, 0x2F, 0x08, 0x57, 0xD5, 0xC0, 0x12, 0xA0, 0x57, 0x40, 0x6F, 0x50, 0x89, 0xCB, 0x52, 0x84,
+ 0x41, 0x0D, 0x1D, 0x0D, 0x7D, 0xAC, 0xF6, 0xFA, 0xDE, 0xF6, 0xC6, 0x1E, 0x59, 0x22, 0xFA, 0x5E, 0xAF, 0xB1, 0xB7, 0xD5,
+ 0xF5, 0x38, 0x78, 0x5D, 0x2B, 0xA8, 0x8D, 0xC8, 0x24, 0x7B, 0x71, 0x17, 0x20, 0xDE, 0x51, 0xD7, 0xBE, 0xA8, 0xBE, 0x13,
+ 0x1B, 0x5C, 0xBD, 0x74, 0xCD, 0x40, 0xD7, 0xE0, 0xD5, 0x57, 0x5E, 0xF7, 0xD1, 0x47, 0xFF, 0x83, 0xE1, 0x93, 0x91, 0x92,
+ 0x32, 0x92, 0x98, 0xF2, 0xF3, 0xDF, 0x4F, 0x3F, 0xE6, 0x91, 0x27, 0x1F, 0x7F, 0x6A, 0xD5, 0xE0, 0xCA, 0x15, 0xFD, 0xC3,
+ 0xC3, 0x3D, 0xCB, 0xAC, 0x1F, 0x34, 0x55, 0x99, 0x64, 0x46, 0xAD, 0xDE, 0x44, 0x54, 0xF0, 0x44, 0x61, 0xBD, 0xAE, 0x08,
+ 0x78, 0x01, 0xDC, 0x5B, 0x54, 0xCA, 0x35, 0x05, 0x55, 0x39, 0x89, 0x99, 0x5B, 0xD6, 0x6F, 0xFD, 0xF8, 0xE3, 0x4F, 0x7E,
+ 0xFD, 0xC1, 0x2F, 0xFF, 0xF5, 0xAF, 0x7F, 0xAD, 0xE8, 0x5D, 0x9E, 0x97, 0x92, 0x5B, 0x99, 0x5B, 0x2E, 0xD6, 0xED, 0xE2,
+ 0x8C, 0x57, 0xF4, 0x6A, 0xF2, 0xDE, 0x05, 0xF8, 0x38, 0x26, 0x5F, 0x50, 0x5D, 0x9D, 0x2F, 0xE6, 0x2F, 0x2B, 0xAF, 0x52,
+ 0x6D, 0xBF, 0x22, 0x47, 0xA4, 0x5F, 0x9A, 0x5B, 0x51, 0x96, 0x5F, 0xEE, 0xA3, 0x06, 0x6E, 0x70, 0x7C, 0xA0, 0xB7, 0x59,
+ 0x96, 0x1B, 0x3F, 0xC5, 0xC6, 0x7B, 0x9A, 0x9C, 0x88, 0xDA, 0xD5, 0x32, 0xD8, 0xD5, 0x28, 0xB2, 0x36, 0x38, 0x23, 0x86,
+ 0xEF, 0x45, 0x76, 0xEE, 0x9A, 0xD5, 0xAB, 0x10, 0x6F, 0x2D, 0x5D, 0xD2, 0x41, 0x01, 0xF4, 0xBE, 0xF6, 0x46, 0x16, 0x96,
+ 0x8E, 0xD0, 0xE5, 0xB7, 0x22, 0x6E, 0x03, 0x35, 0x6A, 0xF5, 0x8E, 0xED, 0x9B, 0x80, 0xA9, 0x56, 0x6F, 0x45, 0xAF, 0xD8,
+ 0x8D, 0xF1, 0x72, 0xDB, 0x56, 0x25, 0x58, 0x51, 0x95, 0x57, 0xB1, 0x61, 0xD5, 0xB6, 0xDE, 0xF6, 0xBE, 0x0D, 0x2B, 0x37,
+ 0x7E, 0xF7, 0x3B, 0xDF, 0xD7, 0x4C, 0x1C, 0x1D, 0x98, 0x1F, 0x71, 0x09, 0x94, 0xF2, 0xE6, 0xF7, 0x7E, 0xB0, 0x7E, 0xD9,
+ 0x3A, 0xF0, 0x6A, 0x69, 0xE7, 0x50, 0x7F, 0x4B, 0x2F, 0xC1, 0xA0, 0xB5, 0xBA, 0x45, 0xA0, 0xA6, 0xCC, 0x11, 0xBD, 0xEB,
+ 0x04, 0x24, 0x97, 0x0D, 0x62, 0xD1, 0xE8, 0xA0, 0xD8, 0x81, 0x72, 0xA4, 0x5C, 0x9A, 0x59, 0x9C, 0x1D, 0x9F, 0x79, 0x60,
+ 0xF7, 0x21, 0x20, 0xEE, 0x9F, 0x7F, 0xFF, 0xC7, 0xCF, 0xDE, 0xFB, 0x65, 0x73, 0x4D, 0x4B, 0x61, 0x7A, 0x41, 0x49, 0x7A,
+ 0x21, 0xD2, 0x44, 0x43, 0x55, 0x05, 0x95, 0x1A, 0x51, 0x59, 0x56, 0xEE, 0xD8, 0x3B, 0x77, 0x55, 0xD6, 0xF6, 0xB7, 0x62,
+ 0xF5, 0x05, 0x15, 0x88, 0xBB, 0x4C, 0xA4, 0x5F, 0x63, 0x56, 0x15, 0x72, 0xE7, 0xAE, 0xAC, 0xFC, 0xF2, 0xD2, 0xBC, 0x32,
+ 0x1F, 0x91, 0x69, 0x8B, 0x23, 0xE8, 0xCE, 0x66, 0x81, 0x91, 0xEE, 0x16, 0xCD, 0xCA, 0x07, 0x10, 0x7A, 0x67, 0xB3, 0xA0,
+ 0x8A, 0x49, 0x63, 0xC4, 0xD2, 0x55, 0xD0, 0x8E, 0x81, 0x37, 0x01, 0xE8, 0xB2, 0xAC, 0xBD, 0x7B, 0xC1, 0xDD, 0xB9, 0xAE,
+ 0x5D, 0xA4, 0xF6, 0x0E, 0xBE, 0x1B, 0x84, 0x21, 0x43, 0x97, 0x24, 0x1D, 0x84, 0xC1, 0xC6, 0x2D, 0xCE, 0xA8, 0xC4, 0x35,
+ 0x63, 0x91, 0xA4, 0xA5, 0x46, 0x32, 0x74, 0xC1, 0x6E, 0xC5, 0x0D, 0x85, 0x8E, 0xF2, 0x06, 0x56, 0x43, 0x59, 0x7D, 0x51,
+ 0x7A, 0xFE, 0xA6, 0x35, 0x97, 0x2D, 0xEE, 0x5E, 0xD6, 0xDF, 0xD6, 0x7B, 0xFD, 0xD5, 0x37, 0x7E, 0xF8, 0xE1, 0x6F, 0xAD,
+ 0x0E, 0xB8, 0x30, 0x3A, 0x38, 0xF1, 0xEE, 0xBB, 0x3F, 0xDB, 0xB4, 0x62, 0x23, 0x90, 0xD5, 0xD3, 0xB8, 0xA8, 0xB7, 0xA5,
+ 0x07, 0x07, 0x22, 0xA8, 0x36, 0x95, 0xB6, 0x39, 0xC9, 0x4C, 0xA9, 0xC8, 0x1D, 0x93, 0x37, 0x90, 0x22, 0x08, 0x6E, 0x53,
+ 0x75, 0x8C, 0x97, 0x30, 0x90, 0x9B, 0x98, 0x5B, 0x94, 0x56, 0x84, 0xF2, 0xBE, 0xFB, 0x9D, 0xB7, 0xBE, 0xF3, 0xDA, 0x9B,
+ 0x3B, 0xB7, 0xEE, 0xCE, 0x49, 0xCA, 0xE6, 0xF1, 0x9C, 0xB8, 0xEC, 0x8A, 0x9C, 0x8A, 0xCA, 0xFC, 0x72, 0xC4, 0x6A, 0x64,
+ 0x2A, 0x11, 0x55, 0xE3, 0xAA, 0x48, 0x56, 0x1F, 0x01, 0x7C, 0x3C, 0xC8, 0xC3, 0x23, 0xAA, 0x18, 0x15, 0xBA, 0xFC, 0x21,
+ 0x0A, 0x30, 0xA2, 0x2F, 0xC9, 0x2D, 0x2D, 0xC9, 0x2D, 0xC1, 0x15, 0xC4, 0x0F, 0x14, 0x73, 0x3C, 0x08, 0x3E, 0x92, 0x20,
+ 0x1A, 0xAD, 0x38, 0xB9, 0xA3, 0xCA, 0x1A, 0x4B, 0x17, 0xD1, 0x9B, 0x74, 0xA5, 0xB5, 0xC9, 0xC9, 0x67, 0xD4, 0xDE, 0x15,
+ 0xD9, 0x91, 0xB5, 0x45, 0xF9, 0x96, 0xC6, 0x91, 0xE8, 0x8A, 0xE8, 0x91, 0xB2, 0x73, 0x6B, 0x92, 0x74, 0x91, 0xBB, 0x5B,
+ 0x13, 0x8D, 0x14, 0x4D, 0x9A, 0x38, 0x1A, 0xF3, 0x37, 0xE9, 0x4A, 0x33, 0xB9, 0x20, 0xF9, 0x09, 0x21, 0x11, 0xC1, 0x55,
+ 0x17, 0x56, 0x65, 0xC6, 0xA5, 0xE1, 0x07, 0x9B, 0xD6, 0x6C, 0x5B, 0xD4, 0xD2, 0xBD, 0x71, 0xD5, 0xC6, 0x47, 0x1F, 0x78,
+ 0xEC, 0xFF, 0xFC, 0xF1, 0xAF, 0x56, 0x0D, 0x9F, 0x7D, 0xF6, 0x09, 0xD7, 0xEF, 0xFC, 0xE8, 0xDD, 0x75, 0x2B, 0x37, 0x90,
+ 0xBC, 0x52, 0x5E, 0x2D, 0x6A, 0x44, 0xDF, 0x02, 0xF4, 0x0A, 0xFA, 0x9A, 0xBC, 0x4B, 0xFE, 0x6E, 0x93, 0x99, 0x42, 0x5E,
+ 0x56, 0xCC, 0x53, 0x05, 0x84, 0x13, 0xA4, 0x45, 0xA4, 0x22, 0xC7, 0xCC, 0x98, 0xB4, 0xE1, 0xBE, 0x15, 0x4B, 0xBB, 0x97,
+ 0x25, 0x87, 0x25, 0x94, 0x67, 0x96, 0x15, 0xA7, 0x17, 0x67, 0xC4, 0xA4, 0x89, 0xEC, 0xF2, 0x4B, 0x49, 0x96, 0x14, 0x46,
+ 0x54, 0xFA, 0xE5, 0x5C, 0x17, 0x38, 0x9A, 0x50, 0xD0, 0xAF, 0xC8, 0x15, 0xA1, 0x03, 0xF7, 0xDC, 0x12, 0x5A, 0x04, 0x76,
+ 0xF2, 0xCA, 0xCC, 0x23, 0x15, 0xBA, 0xE4, 0x3A, 0xAF, 0x4C, 0x97, 0x8F, 0x06, 0x4C, 0x37, 0x8A, 0x5A, 0x1C, 0x17, 0x7B,
+ 0x17, 0x28, 0x6F, 0x76, 0x14, 0xE0, 0xDA, 0xB8, 0x44, 0x51, 0x27, 0x5F, 0x6C, 0x02, 0xDF, 0x47, 0x44, 0xAF, 0xD2, 0x27,
+ 0x72, 0x4A, 0xF0, 0xAC, 0x75, 0xF2, 0x19, 0x1B, 0x5D, 0x15, 0xE8, 0xB5, 0x4C, 0xB5, 0xD7, 0xAA, 0x06, 0xC1, 0xFD, 0x4A,
+ 0x53, 0xB2, 0xAA, 0x13, 0xB8, 0x15, 0x93, 0x93, 0xBA, 0x20, 0xBB, 0x32, 0x6C, 0xD6, 0xC9, 0x31, 0x30, 0xC6, 0x84, 0xD0,
+ 0xD8, 0xA1, 0x9E, 0x65, 0xFB, 0x76, 0x5D, 0x49, 0x48, 0x18, 0x68, 0xEF, 0xDB, 0xB6, 0x65, 0xC7, 0x73, 0xCF, 0x7C, 0xF3,
+ 0xAF, 0x7F, 0xFD, 0xFB, 0x17, 0x9F, 0x7D, 0x2E, 0x2D, 0x8A, 0x13, 0x9F, 0x7F, 0xF2, 0xC9, 0x27, 0x18, 0xEF, 0xEA, 0xA1,
+ 0x55, 0x4B, 0xFB, 0x96, 0xF1, 0x87, 0x24, 0xF5, 0x2D, 0x15, 0x64, 0xF4, 0x1A, 0x48, 0x9D, 0x58, 0x2A, 0x17, 0x45, 0x75,
+ 0x26, 0x7D, 0x74, 0x92, 0x74, 0x63, 0x9B, 0xA5, 0xC5, 0x39, 0x25, 0x05, 0x69, 0xF9, 0xF1, 0x21, 0x31, 0xD5, 0x25, 0x35,
+ 0xF1, 0x81, 0x71, 0xC9, 0x11, 0x71, 0x71, 0xC1, 0xD1, 0xE1, 0x73, 0xC3, 0xF8, 0xA4, 0x49, 0x61, 0x09, 0x19, 0x71, 0x69,
+ 0x85, 0x59, 0x45, 0xC5, 0x3C, 0x2D, 0xAF, 0x54, 0xC4, 0x87, 0x34, 0x91, 0x2C, 0x7F, 0x68, 0x64, 0x6A, 0x57, 0x69, 0x81,
+ 0xA3, 0x1B, 0x07, 0x6D, 0x0A, 0x0C, 0xF2, 0xE4, 0x97, 0x97, 0xE4, 0xC8, 0x73, 0xB0, 0xFD, 0xB2, 0x7C, 0x44, 0x2F, 0xAF,
+ 0xA0, 0xAE, 0x80, 0x0E, 0x24, 0x60, 0x7A, 0x03, 0x29, 0xF0, 0xED, 0x86, 0x50, 0x8F, 0x99, 0x1B, 0x54, 0x31, 0xC6, 0x2E,
+ 0x98, 0x2E, 0x12, 0x17, 0x78, 0x11, 0x64, 0x57, 0x34, 0xB7, 0x0A, 0x50, 0x1D, 0x88, 0xB8, 0xEB, 0x47, 0x24, 0x2E, 0x0A,
+ 0x30, 0xF8, 0x63, 0xB1, 0x9E, 0x6B, 0x2B, 0x77, 0xA7, 0x68, 0x32, 0xE0, 0x63, 0x93, 0x77, 0x0D, 0x9E, 0x6A, 0xB9, 0x54,
+ 0x3A, 0x82, 0xB0, 0x79, 0x15, 0x65, 0x59, 0x65, 0xB1, 0x81, 0xD1, 0xA4, 0x28, 0x57, 0x5C, 0x71, 0xD3, 0x9A, 0xE5, 0x9B,
+ 0x86, 0xBA, 0x17, 0x53, 0x27, 0x5F, 0xB1, 0xF7, 0xE8, 0x37, 0xBE, 0xFE, 0xE2, 0x07, 0xBF, 0xFA, 0x2D, 0xB9, 0xE9, 0xFF,
+ 0xFC, 0xCF, 0xC7, 0xBF, 0xFF, 0xDD, 0x9F, 0x9E, 0x79, 0xF2, 0x1B, 0x43, 0x9D, 0x03, 0xCB, 0x7B, 0x97, 0x01, 0xDF, 0x88,
+ 0x9E, 0xD5, 0x50, 0x54, 0xAF, 0x21, 0x14, 0x4F, 0x92, 0x34, 0xB1, 0xD8, 0xA4, 0x8F, 0x05, 0x92, 0xB6, 0x0B, 0x50, 0x28,
+ 0x38, 0xE4, 0x94, 0x23, 0xE2, 0xFC, 0xD4, 0xDC, 0xA8, 0x85, 0x11, 0x35, 0xA5, 0xB5, 0xC9, 0x91, 0x49, 0x41, 0x73, 0x16,
+ 0x06, 0xCD, 0xF5, 0xCF, 0x4E, 0xCB, 0x69, 0xAE, 0x6D, 0x0F, 0x99, 0x17, 0x94, 0x9E, 0x94, 0x99, 0x9F, 0x51, 0x50, 0x94,
+ 0x5D, 0x8C, 0xAA, 0x10, 0x9F, 0x5A, 0xB1, 0x60, 0x3D, 0x0E, 0xA1, 0xA6, 0xAD, 0xCA, 0x70, 0xD0, 0xA6, 0xD4, 0x5C, 0x94,
+ 0xF1, 0x64, 0xF1, 0x1B, 0xD7, 0xEA, 0xF5, 0x42, 0x5F, 0x41, 0x97, 0x8F, 0xD8, 0x72, 0x7D, 0xBF, 0x09, 0x95, 0x5E, 0xBB,
+ 0x16, 0x29, 0x8B, 0xD0, 0x6B, 0x25, 0x90, 0xB2, 0xD4, 0xB4, 0x79, 0x04, 0xC9, 0x5A, 0x4B, 0x57, 0x59, 0x93, 0x53, 0xEA,
+ 0x85, 0x00, 0x7A, 0xAD, 0x80, 0x8C, 0x37, 0xBD, 0x91, 0xDE, 0x8B, 0x27, 0xB7, 0xD1, 0xCE, 0x8C, 0x74, 0x05, 0xAC, 0xE1,
+ 0x1B, 0xE4, 0xB1, 0x6D, 0x03, 0x9B, 0xAD, 0x6B, 0xE2, 0x48, 0x22, 0x08, 0x68, 0x20, 0x26, 0x80, 0xA2, 0x24, 0xBF, 0xAC,
+ 0x28, 0xA3, 0x30, 0x29, 0x34, 0x3E, 0xDA, 0x3F, 0x62, 0xFF, 0x9E, 0xCB, 0xF7, 0xEE, 0xBA, 0x7C, 0xE5, 0xD0, 0xBA, 0x81,
+ 0xCE, 0xC5, 0xAB, 0x97, 0xAC, 0x3B, 0x76, 0xE4, 0xEA, 0x67, 0x9E, 0x7E, 0xFE, 0xC7, 0x3F, 0x7A, 0xF7, 0x67, 0x3F, 0xFD,
+ 0xE5, 0x9B, 0xDF, 0xFB, 0xE1, 0x6D, 0xB7, 0xDF, 0xD3, 0xD5, 0xD0, 0x31, 0xD8, 0xB5, 0xA4, 0x32, 0xBB, 0xA2, 0x3C, 0xBB,
+ 0xB4, 0x26, 0xBF, 0xB2, 0xA2, 0xB0, 0xD2, 0x80, 0x72, 0x75, 0x65, 0x5E, 0x0D, 0xC1, 0x53, 0x32, 0x16, 0x7A, 0x06, 0x46,
+ 0x01, 0x0E, 0x04, 0x19, 0xB9, 0xA0, 0x83, 0x9C, 0xD4, 0xDC, 0x08, 0xFF, 0x30, 0x55, 0x49, 0xD8, 0x82, 0x90, 0xE8, 0x90,
+ 0x68, 0x3A, 0x2B, 0xD9, 0x29, 0xD9, 0x21, 0xFE, 0x41, 0x59, 0xC9, 0xD9, 0x79, 0xE9, 0xF9, 0x04, 0x67, 0xD4, 0x60, 0x25,
+ 0x68, 0xF5, 0x67, 0x3D, 0xC3, 0xB9, 0x50, 0xD8, 0xF1, 0x88, 0xDE, 0xF9, 0x93, 0x9C, 0x72, 0xFB, 0xB7, 0x38, 0x01, 0xFF,
+ 0x14, 0x1D, 0x48, 0xCA, 0x28, 0x9A, 0x68, 0x12, 0x4D, 0x18, 0x03, 0xEF, 0x6D, 0xAB, 0xD5, 0x28, 0xDA, 0xD9, 0x59, 0xDF,
+ 0x85, 0x88, 0xAD, 0x94, 0x55, 0xD0, 0xDA, 0x75, 0x41, 0xDC, 0x0A, 0x2C, 0xA3, 0xA4, 0x6F, 0x2C, 0x5D, 0xEC, 0x7D, 0x74,
+ 0x5A, 0x89, 0xC4, 0x9B, 0xAB, 0x65, 0x61, 0xE9, 0x9A, 0x74, 0x6A, 0xB9, 0xC4, 0xF5, 0x48, 0xC7, 0xA6, 0xA2, 0xCD, 0x2A,
+ 0xA0, 0xAE, 0xAC, 0xD9, 0xC4, 0x00, 0xE9, 0x73, 0x49, 0x96, 0x6D, 0x90, 0x9A, 0x77, 0x8C, 0x08, 0xD2, 0x62, 0x52, 0xE7,
+ 0x4C, 0x9A, 0x35, 0xB0, 0x68, 0xC9, 0xD1, 0x23, 0xD7, 0x11, 0x9C, 0x07, 0x16, 0x2D, 0xA3, 0x8D, 0xB1, 0x6E, 0x78, 0x1D,
+ 0xA9, 0xEA, 0xE3, 0x8F, 0x3D, 0x83, 0x43, 0xD0, 0xB1, 0x38, 0x72, 0xF0, 0xAA, 0xFA, 0xA2, 0x1A, 0x92, 0x8B, 0xD2, 0xAC,
+ 0xA2, 0xBC, 0x84, 0x5C, 0x92, 0x71, 0x1B, 0x09, 0x79, 0xA9, 0xF2, 0xA2, 0x0A, 0xCD, 0xD6, 0x35, 0x69, 0x51, 0x21, 0x96,
+ 0xE5, 0x94, 0x22, 0x59, 0xCC, 0x3C, 0x27, 0x35, 0x27, 0x32, 0x38, 0x3C, 0x2D, 0x3E, 0x9D, 0x4F, 0x17, 0x1F, 0x11, 0x5F,
+ 0x94, 0x5B, 0xD2, 0xD3, 0x3E, 0xB4, 0x70, 0xDE, 0x82, 0xF8, 0xA8, 0x84, 0x9C, 0xA4, 0x2C, 0x90, 0xAA, 0x20, 0xB3, 0x50,
+ 0x10, 0x29, 0x47, 0xC4, 0xE7, 0x75, 0x08, 0xC5, 0x25, 0x7D, 0x35, 0x6B, 0xEC, 0xB8, 0x2C, 0xB0, 0xA3, 0x42, 0x77, 0xC1,
+ 0x47, 0xAE, 0xED, 0xDF, 0x8A, 0x1F, 0xA8, 0xBD, 0xAB, 0x94, 0x25, 0x4D, 0xAC, 0x1F, 0x29, 0x4D, 0x91, 0xB5, 0x15, 0xB1,
+ 0x35, 0x6D, 0x95, 0xBB, 0x1A, 0xBB, 0xB4, 0x18, 0x01, 0x22, 0x1A, 0x8A, 0x20, 0x3B, 0x6D, 0x16, 0x23, 0x7A, 0x6F, 0x74,
+ 0xF5, 0xA2, 0x8D, 0x9A, 0x3F, 0x12, 0xD7, 0x84, 0x67, 0x4C, 0xCB, 0x4C, 0xF3, 0x1F, 0x4D, 0x19, 0xE5, 0xB6, 0x44, 0x10,
+ 0x1C, 0xB8, 0xA0, 0xD2, 0x51, 0xAC, 0x40, 0x58, 0xC8, 0x28, 0x37, 0x2D, 0x2F, 0x3D, 0x31, 0x75, 0xEE, 0x14, 0xDF, 0x94,
+ 0xA8, 0xD4, 0x03, 0xFB, 0xAE, 0xDE, 0xB3, 0xE3, 0xE8, 0xB2, 0xA1, 0xF5, 0xE4, 0x14, 0xF4, 0xB2, 0xD6, 0x0F, 0x6F, 0x3A,
+ 0xB2, 0xE7, 0x8A, 0x9B, 0xAE, 0xBF, 0xED, 0xDA, 0xAB, 0x6F, 0xDE, 0x34, 0xBC, 0x35, 0x3F, 0x29, 0xA7, 0xB5, 0xB6, 0xA3,
+ 0x34, 0xB3, 0x34, 0x2D, 0x32, 0xB9, 0x24, 0x0B, 0xF4, 0x10, 0xCB, 0x55, 0xA4, 0xE6, 0xD5, 0x24, 0x4F, 0x77, 0x53, 0x14,
+ 0xC4, 0xA4, 0x42, 0x29, 0xC8, 0x2E, 0x2A, 0xC8, 0x2C, 0xC0, 0xD8, 0x13, 0x22, 0x13, 0xB0, 0xFA, 0xDE, 0x8E, 0xC1, 0x92,
+ 0xBC, 0x8A, 0x9E, 0xF6, 0x01, 0x14, 0xEF, 0x3F, 0x67, 0x41, 0x6A, 0x5C, 0x2A, 0xBF, 0xCA, 0x49, 0x71, 0x74, 0xC0, 0x9B,
+ 0x61, 0x95, 0x66, 0x97, 0x10, 0xA2, 0x2D, 0x2E, 0x59, 0x29, 0x7B, 0xC5, 0x3D, 0x46, 0x01, 0x56, 0x79, 0xF6, 0xC2, 0xC7,
+ 0x81, 0x72, 0x8C, 0xDD, 0xC5, 0x13, 0x07, 0xBB, 0x4D, 0x14, 0xB5, 0x6B, 0x4C, 0xDA, 0xAE, 0xC6, 0x6E, 0x41, 0x46, 0xB2,
+ 0x4C, 0xB7, 0x15, 0xAC, 0x17, 0x72, 0xAB, 0x6D, 0xC8, 0x0A, 0x07, 0xF7, 0x15, 0x70, 0x58, 0xDA, 0x20, 0xB3, 0xDD, 0x4A,
+ 0xCD, 0x7F, 0xB4, 0x6D, 0xA0, 0x71, 0xD8, 0x55, 0x83, 0x38, 0x81, 0x93, 0xD8, 0xE5, 0x97, 0x4B, 0x18, 0xCC, 0x2E, 0x41,
+ 0x07, 0x29, 0xB1, 0x29, 0xC1, 0x0B, 0x82, 0x27, 0x5F, 0x34, 0x79, 0xD5, 0xD2, 0x0D, 0x07, 0xF7, 0x1F, 0xDF, 0xBE, 0x65,
+ 0x1F, 0xAE, 0x40, 0xEA, 0x89, 0xD5, 0xAF, 0x5E, 0xB6, 0xFE, 0xF0, 0xDE, 0x63, 0x7B, 0xB6, 0x1E, 0xA4, 0x9C, 0x4E, 0x09,
+ 0x4F, 0x20, 0xE4, 0x16, 0x67, 0x97, 0xC5, 0x85, 0xC4, 0x08, 0x80, 0x64, 0x15, 0xCA, 0x67, 0xD6, 0x58, 0x6A, 0xC2, 0xA9,
+ 0x86, 0x50, 0x2E, 0x54, 0x46, 0x0A, 0x44, 0xB9, 0xD9, 0x05, 0xD9, 0x29, 0x39, 0x88, 0x3B, 0x70, 0x7E, 0x40, 0x5A, 0x62,
+ 0xFA, 0x60, 0xF7, 0x72, 0x82, 0xB3, 0xDF, 0xEC, 0xF9, 0x71, 0xE1, 0x71, 0x29, 0xB1, 0xA9, 0x04, 0x06, 0x5E, 0x0A, 0x5F,
+ 0xE1, 0x99, 0x2C, 0x1B, 0x18, 0xAC, 0x0E, 0x3C, 0x20, 0xE3, 0xD8, 0xBE, 0x7D, 0xE4, 0x64, 0xD1, 0xAB, 0x16, 0x59, 0xA2,
+ 0x03, 0xB5, 0x77, 0x07, 0xCD, 0xEB, 0x1C, 0x1B, 0xD7, 0x07, 0x9D, 0x66, 0xBA, 0x2B, 0x6E, 0xC0, 0x44, 0x13, 0x4A, 0x6B,
+ 0xE0, 0xC8, 0x5A, 0xBB, 0x60, 0x4E, 0x56, 0xA3, 0x08, 0xE3, 0xB4, 0xDA, 0x4D, 0x4F, 0xD8, 0xD3, 0x19, 0x76, 0xD2, 0x4D,
+ 0x83, 0x39, 0x4E, 0xE2, 0xAF, 0xE9, 0xBF, 0xEB, 0x01, 0xAA, 0x00, 0x4A, 0xD6, 0xDA, 0xD2, 0x26, 0x6D, 0x06, 0xA0, 0x03,
+ 0x45, 0x55, 0x47, 0x46, 0x69, 0x79, 0xA9, 0x71, 0x69, 0xB1, 0xE1, 0x91, 0x17, 0x8E, 0x3B, 0x17, 0xE0, 0xBE, 0xFC, 0xF0,
+ 0xF5, 0x3B, 0x77, 0x5E, 0xBE, 0xB8, 0x7F, 0x4D, 0x43, 0x45, 0x2B, 0x4D, 0x1E, 0x1A, 0x18, 0x6B, 0x87, 0x37, 0xD2, 0x55,
+ 0x25, 0xA3, 0x8D, 0xF2, 0x0B, 0x27, 0x92, 0xF3, 0x09, 0xC3, 0x02, 0xC2, 0x78, 0x26, 0x82, 0xE3, 0x15, 0x00, 0x16, 0xD5,
+ 0x81, 0x82, 0x86, 0xBA, 0x97, 0x8A, 0xA9, 0x28, 0xB7, 0x18, 0xB1, 0x22, 0x62, 0x9E, 0x0C, 0x10, 0x25, 0x45, 0x24, 0x04,
+ 0xCC, 0x09, 0x08, 0x5C, 0xB0, 0xD0, 0x7F, 0xCE, 0xBC, 0xA8, 0x90, 0xB0, 0xE4, 0x98, 0x94, 0x8C, 0xA4, 0x9C, 0x9C, 0xF4,
+ 0x3C, 0x9E, 0xA0, 0x58, 0x34, 0x46, 0x07, 0x56, 0x91, 0x27, 0xCB, 0xFA, 0x2B, 0xA4, 0xEF, 0xE8, 0xC0, 0x49, 0x57, 0x4C,
+ 0xC5, 0x04, 0xA4, 0x08, 0xC8, 0x28, 0xA4, 0xB8, 0x0A, 0x50, 0x99, 0xAA, 0xAC, 0xED, 0xAC, 0x63, 0x24, 0xAE, 0x1A, 0xBB,
+ 0xB6, 0x41, 0xD5, 0x1A, 0xBB, 0xB5, 0xF4, 0x31, 0x17, 0xA7, 0x14, 0xBD, 0x86, 0x01, 0xAB, 0x00, 0xDB, 0x82, 0xE7, 0x02,
+ 0xD4, 0xB6, 0xD8, 0x5A, 0x9C, 0x59, 0x84, 0x1F, 0xA4, 0xC5, 0x65, 0x26, 0x44, 0xC5, 0xCD, 0x98, 0x36, 0xFD, 0xD2, 0x89,
+ 0x53, 0xD6, 0x0E, 0x6F, 0xC5, 0x15, 0xD6, 0xAD, 0xBA, 0xAC, 0xA1, 0xAA, 0xA3, 0x2C, 0xBB, 0x12, 0xE4, 0xA1, 0x88, 0x6D,
+ 0x2C, 0x6E, 0xC8, 0x4B, 0xCC, 0x0E, 0xF4, 0xF5, 0xAF, 0x29, 0x6B, 0xC8, 0xCF, 0x2A, 0x00, 0x55, 0xB2, 0x13, 0xB3, 0xF8,
+ 0xC3, 0xFC, 0x4C, 0x31, 0x3A, 0x8B, 0x0C, 0x64, 0x2C, 0x2C, 0xAB, 0x03, 0x1E, 0x47, 0xB8, 0xAA, 0x03, 0x30, 0x07, 0x4D,
+ 0x27, 0x44, 0x26, 0xC6, 0x84, 0xC6, 0x80, 0x4B, 0x78, 0x40, 0x46, 0x62, 0x86, 0x04, 0xE4, 0x94, 0x5C, 0x79, 0x9D, 0xAC,
+ 0x42, 0x55, 0x83, 0xFA, 0x81, 0x17, 0xD9, 0xFF, 0x7F, 0x28, 0x80, 0xD7, 0xF1, 0x31, 0x68, 0xBE, 0xA8, 0xB9, 0xBA, 0x8B,
+ 0xA5, 0x56, 0x6F, 0x96, 0x8B, 0x2D, 0x6E, 0xC5, 0xE4, 0xCD, 0x64, 0x2C, 0xB2, 0x7B, 0xA7, 0x1F, 0x5E, 0x59, 0x8F, 0x54,
+ 0x58, 0x2E, 0xE6, 0x58, 0x63, 0xB7, 0x51, 0x57, 0x5D, 0xC1, 0x8A, 0x5E, 0x15, 0xE0, 0x74, 0x6F, 0xDC, 0x2E, 0x3C, 0xA9,
+ 0x24, 0x3A, 0x10, 0x83, 0xCD, 0x71, 0xB0, 0x22, 0x3F, 0x23, 0x3F, 0x33, 0x29, 0x53, 0xF0, 0x3A, 0x20, 0xF8, 0x6B, 0x67,
+ 0x9D, 0x8D, 0x8B, 0xEC, 0xDB, 0x73, 0xD5, 0xE6, 0xF5, 0x7B, 0x69, 0xE2, 0x66, 0xC6, 0xE5, 0x25, 0x85, 0x25, 0xE5, 0xA6,
+ 0x16, 0x90, 0xB7, 0xC4, 0x87, 0xC6, 0xFA, 0xCD, 0xF7, 0xAF, 0x2B, 0x6B, 0xCC, 0xCD, 0xC8, 0x0B, 0x5A, 0xB0, 0x30, 0x3D,
+ 0x21, 0x03, 0x84, 0x11, 0x44, 0xCA, 0x2C, 0x19, 0x93, 0x59, 0x2A, 0x70, 0x3B, 0x7E, 0x96, 0x53, 0x8C, 0x7C, 0x0B, 0x53,
+ 0xF3, 0x79, 0x32, 0x12, 0x4F, 0x4F, 0x48, 0xC7, 0x21, 0xD2, 0xE2, 0xD3, 0x32, 0x12, 0x33, 0xB9, 0xCB, 0x83, 0xF9, 0xA9,
+ 0x79, 0xF8, 0x13, 0x0A, 0x50, 0x38, 0xF2, 0xEA, 0xE0, 0x94, 0xD2, 0xB7, 0x68, 0x73, 0xF2, 0x85, 0x7A, 0x92, 0x2E, 0x1F,
+ 0xB1, 0xEE, 0xEA, 0x45, 0x2D, 0x95, 0x48, 0xDF, 0x69, 0x15, 0xC8, 0x23, 0x06, 0xC4, 0xAD, 0x51, 0x9F, 0x7C, 0xA1, 0x71,
+ 0x55, 0x71, 0xC6, 0xBB, 0xAC, 0xAC, 0xAD, 0xBD, 0x5B, 0xB8, 0xF7, 0x4A, 0x5F, 0x11, 0x7F, 0x8C, 0x02, 0xA4, 0x6B, 0x46,
+ 0xFF, 0x80, 0xF9, 0x9F, 0xA0, 0x90, 0xB4, 0x10, 0x00, 0x74, 0x89, 0x07, 0xB4, 0x18, 0x35, 0x66, 0x66, 0x16, 0x60, 0x86,
+ 0x99, 0x49, 0x59, 0x49, 0xD1, 0x49, 0x58, 0xE8, 0xF8, 0x8B, 0x2E, 0xF6, 0x9B, 0xB3, 0x60, 0xC3, 0x9A, 0x9D, 0xDB, 0xB6,
+ 0x1D, 0xEC, 0xEF, 0x5E, 0x91, 0x9F, 0x5E, 0x94, 0x14, 0x91, 0x9C, 0x14, 0x9B, 0x92, 0x18, 0x93, 0x44, 0x42, 0xE9, 0x37,
+ 0xC7, 0xBF, 0xBE, 0xB2, 0x99, 0xE7, 0x2F, 0x9C, 0xE7, 0x8F, 0x28, 0x11, 0x22, 0xD7, 0xDE, 0x94, 0x66, 0x0C, 0x76, 0x0B,
+ 0x16, 0xE5, 0x18, 0x84, 0x49, 0x2B, 0x20, 0xF9, 0xC1, 0xE4, 0xB3, 0x92, 0x72, 0xB3, 0x52, 0x73, 0xE4, 0x16, 0x05, 0xA4,
+ 0x01, 0x44, 0xB9, 0x68, 0xD1, 0xC5, 0xA2, 0xB1, 0x7E, 0x20, 0x40, 0xE7, 0xE2, 0xFB, 0xFF, 0x47, 0xD1, 0x8F, 0xE8, 0xC0,
+ 0x89, 0x9C, 0x0A, 0xEB, 0xA6, 0x44, 0xE2, 0x11, 0x1D, 0x2A, 0xE9, 0xAF, 0x4E, 0x16, 0xB4, 0x83, 0xF2, 0x66, 0xE8, 0xE1,
+ 0x0C, 0x40, 0x6C, 0x63, 0xC7, 0x98, 0xB6, 0x85, 0x7B, 0x6F, 0x7F, 0x78, 0x8C, 0xD0, 0x75, 0x14, 0xE5, 0xF4, 0x8D, 0xDD,
+ 0xFE, 0xA5, 0x54, 0x64, 0x66, 0x2C, 0x65, 0xDB, 0xC2, 0x9A, 0x14, 0x09, 0x5E, 0x67, 0x17, 0x23, 0xC1, 0x82, 0xB4, 0x3C,
+ 0x24, 0x42, 0x58, 0x46, 0x07, 0xF3, 0x7D, 0xE7, 0x8D, 0x3B, 0xE7, 0x5C, 0x42, 0xF1, 0xDE, 0x5D, 0x57, 0x0F, 0x2F, 0xDB,
+ 0x44, 0xD9, 0x15, 0x1B, 0x11, 0x07, 0xFA, 0x93, 0x50, 0x86, 0x2F, 0x0C, 0x27, 0x90, 0xD6, 0x96, 0x37, 0x62, 0xBC, 0x01,
+ 0x73, 0xE7, 0x63, 0xCB, 0x59, 0xC9, 0x59, 0x1A, 0x15, 0xBE, 0x02, 0xC7, 0x89, 0x16, 0xFC, 0x56, 0xCD, 0x1C, 0x59, 0xA3,
+ 0x33, 0xFE, 0x44, 0x57, 0x6E, 0x5A, 0xAE, 0x64, 0xA5, 0x6E, 0x62, 0xCA, 0x73, 0xBC, 0x82, 0x56, 0x27, 0xF8, 0x6A, 0x1D,
+ 0x78, 0x0D, 0x5F, 0xAF, 0xE5, 0xE3, 0x98, 0xE5, 0xE3, 0x88, 0xDB, 0x9B, 0xA7, 0x8F, 0x1E, 0xB4, 0x5A, 0x33, 0x1F, 0x03,
+ 0xE5, 0x84, 0x41, 0xFB, 0x48, 0x7D, 0xB9, 0x93, 0x53, 0xDA, 0x47, 0x46, 0x4B, 0x9C, 0x6C, 0xA7, 0x55, 0x67, 0x4F, 0x32,
+ 0x08, 0x94, 0xD6, 0x8D, 0x3C, 0x62, 0xD3, 0x50, 0x9D, 0x8C, 0xEB, 0x68, 0x50, 0xEA, 0x32, 0x1A, 0x6A, 0x8C, 0x67, 0xCD,
+ 0xFC, 0x8F, 0xE2, 0xC0, 0xAB, 0x83, 0xBC, 0xF4, 0x3C, 0xC4, 0x4A, 0xCF, 0x20, 0x21, 0x2C, 0x2E, 0x6C, 0x61, 0xC8, 0xB9,
+ 0xE7, 0x9C, 0x9D, 0x14, 0x9D, 0xBC, 0x75, 0xE3, 0xBE, 0x55, 0x2B, 0xB6, 0xD5, 0x55, 0xB4, 0x88, 0x0E, 0xFC, 0x82, 0xC8,
+ 0xEE, 0xC3, 0x16, 0x06, 0xF9, 0xCF, 0x9A, 0x07, 0x16, 0x65, 0xA5, 0x66, 0x13, 0x54, 0x0D, 0xA0, 0x67, 0x22, 0x4A, 0x93,
+ 0x20, 0x09, 0x86, 0x78, 0x8B, 0x2C, 0x27, 0x9C, 0xE6, 0x95, 0x14, 0xE4, 0x22, 0x47, 0xA4, 0x23, 0x72, 0x31, 0xB5, 0x98,
+ 0xA8, 0x21, 0x37, 0x03, 0xDB, 0x97, 0x50, 0xEC, 0x66, 0x44, 0xFC, 0xD6, 0x51, 0xA4, 0x57, 0xE8, 0x56, 0xC4, 0xA7, 0x7C,
+ 0x50, 0x25, 0x6E, 0x9F, 0xA3, 0x6A, 0x1E, 0xD1, 0x81, 0x62, 0x0E, 0x53, 0x3D, 0x64, 0xAD, 0xB7, 0x63, 0x64, 0xED, 0xB5,
+ 0x74, 0x06, 0x7E, 0xDE, 0x3A, 0x76, 0xCC, 0x18, 0xC4, 0x62, 0xBA, 0x17, 0xDC, 0xC9, 0x70, 0x90, 0xBE, 0xF6, 0xCB, 0xB8,
+ 0x90, 0xAE, 0x7D, 0x69, 0x9D, 0x36, 0xEB, 0x1B, 0x8A, 0x45, 0x2B, 0x2C, 0x6D, 0xE5, 0xEB, 0x54, 0xD6, 0x19, 0xC9, 0x32,
+ 0x0D, 0x2F, 0x94, 0x4E, 0x8E, 0x69, 0xC1, 0x4B, 0xD5, 0xA3, 0x79, 0x11, 0x82, 0x50, 0xA4, 0x4E, 0x8E, 0x4C, 0x8C, 0x0C,
+ 0x8A, 0x9A, 0x3C, 0xE9, 0x92, 0x4B, 0x26, 0x4E, 0xA6, 0x44, 0x58, 0xBF, 0x7A, 0x27, 0xAD, 0xAD, 0xE4, 0x84, 0x74, 0x14,
+ 0x10, 0x1B, 0x1C, 0x83, 0x7A, 0xFC, 0x66, 0xCF, 0xAD, 0x28, 0xAD, 0xCB, 0x4C, 0xCF, 0xC1, 0x21, 0xC0, 0x2E, 0xFE, 0x04,
+ 0xE5, 0x29, 0x1C, 0xA9, 0x98, 0xBC, 0xB1, 0x54, 0x5E, 0x3F, 0x8F, 0xD4, 0xA8, 0xA4, 0x24, 0xAB, 0x54, 0x75, 0xA0, 0x0B,
+ 0x49, 0x89, 0xEB, 0xA4, 0xCB, 0xAD, 0x2B, 0x44, 0x44, 0x59, 0x48, 0x76, 0x30, 0xC6, 0x15, 0xAC, 0xE8, 0x4F, 0xB6, 0x77,
+ 0xAF, 0xE8, 0xED, 0x2B, 0xDB, 0xD7, 0xE7, 0x13, 0xF9, 0x78, 0x2D, 0xF7, 0xE4, 0xA4, 0x65, 0xAC, 0xED, 0x33, 0x69, 0x72,
+ 0x27, 0x7F, 0x1E, 0x89, 0x3B, 0x49, 0xBD, 0xDA, 0xB5, 0xDA, 0xB2, 0x6B, 0xD7, 0x46, 0xCA, 0x46, 0xB2, 0xD2, 0x7A, 0xB3,
+ 0x13, 0x70, 0xD7, 0xE4, 0xF1, 0x00, 0x79, 0x7E, 0xB1, 0x51, 0x92, 0x7A, 0x83, 0x27, 0x20, 0x4B, 0x63, 0x27, 0xAF, 0x46,
+ 0x5B, 0x8C, 0x58, 0xAB, 0x48, 0x27, 0x2D, 0x3F, 0x37, 0x39, 0x27, 0x3D, 0x29, 0x23, 0x39, 0x26, 0x39, 0x26, 0x08, 0xD0,
+ 0x5F, 0x70, 0xD6, 0x59, 0x67, 0x81, 0x39, 0xBB, 0xB6, 0x5C, 0xDE, 0xB7, 0x68, 0x38, 0x23, 0x39, 0x2B, 0xC4, 0x2F, 0x24,
+ 0xD4, 0x3F, 0x34, 0xD8, 0x2F, 0xD0, 0x6F, 0xC6, 0xFC, 0xC2, 0xBC, 0x4A, 0x70, 0x7C, 0x81, 0xEF, 0x1C, 0x74, 0x80, 0xEB,
+ 0x00, 0x47, 0x36, 0xBB, 0x1F, 0xD1, 0xC1, 0xA8, 0xCE, 0x41, 0x69, 0x91, 0xAB, 0x03, 0xFE, 0x97, 0x2A, 0x43, 0x2F, 0xDC,
+ 0x35, 0x12, 0x48, 0x6D, 0x7A, 0xAA, 0xD2, 0xF7, 0xFA, 0x81, 0xD7, 0xE4, 0xF5, 0x71, 0xAF, 0xD5, 0x7B, 0xB5, 0xAB, 0x8F,
+ 0xFB, 0xD8, 0xFC, 0xC4, 0xD6, 0xA8, 0x63, 0x2C, 0x5D, 0xEE, 0x96, 0x37, 0xE9, 0xD3, 0x90, 0x11, 0x95, 0x94, 0xC8, 0x5A,
+ 0x99, 0x1D, 0xBA, 0x30, 0xE4, 0x62, 0x43, 0xB3, 0x51, 0x3C, 0x31, 0xA4, 0x1A, 0x2E, 0x18, 0x70, 0x2B, 0xBB, 0xC6, 0x3B,
+ 0x7A, 0x55, 0xF6, 0x87, 0xCC, 0x63, 0xE5, 0xB6, 0x41, 0x56, 0x71, 0x4B, 0x23, 0x3A, 0x28, 0x6B, 0x94, 0x97, 0xE2, 0x5A,
+ 0x5F, 0xC4, 0x74, 0xAA, 0x69, 0x6A, 0x6A, 0xA3, 0xC2, 0xD6, 0x50, 0x0C, 0x0F, 0x88, 0x96, 0x84, 0xE5, 0x94, 0xF8, 0x54,
+ 0xEA, 0xA6, 0xD0, 0x80, 0xE0, 0xF3, 0xCE, 0x1D, 0x17, 0x11, 0x16, 0xB9, 0x69, 0xDD, 0x9E, 0x25, 0x03, 0x6B, 0x29, 0x74,
+ 0x83, 0xFD, 0x43, 0x28, 0xAF, 0x42, 0x03, 0x02, 0xE7, 0xCE, 0x98, 0x2D, 0x30, 0x92, 0x99, 0xBF, 0xC0, 0x77, 0x1E, 0x78,
+ 0x45, 0x58, 0xE6, 0xAF, 0xB2, 0xD3, 0x0C, 0x1C, 0x65, 0x8A, 0x4B, 0x8D, 0x24, 0x48, 0xD9, 0x4E, 0x7E, 0x69, 0x73, 0x1B,
+ 0x57, 0xBE, 0x82, 0x4B, 0xBA, 0x8A, 0x1D, 0x65, 0x88, 0x40, 0x71, 0x02, 0xAF, 0xB1, 0xAB, 0x0E, 0xAC, 0xDC, 0xBD, 0x96,
+ 0x7E, 0xB2, 0xE8, 0xAD, 0x6F, 0xA9, 0x87, 0xE9, 0x12, 0x1D, 0x78, 0xB1, 0xDB, 0x5E, 0x8F, 0x0D, 0xA1, 0x65, 0x0C, 0x40,
+ 0x64, 0x06, 0x22, 0x9D, 0x1C, 0xCF, 0x14, 0x50, 0x3B, 0xFB, 0xCE, 0x20, 0x10, 0x33, 0x77, 0xE9, 0x4D, 0x1A, 0x5A, 0x2D,
+ 0xC5, 0x43, 0xE9, 0x37, 0xF2, 0x4C, 0x77, 0x12, 0x5B, 0x5B, 0x04, 0xF8, 0x38, 0x42, 0x17, 0x05, 0x57, 0x34, 0x33, 0xE7,
+ 0x6A, 0x2E, 0x55, 0xEA, 0x4E, 0x23, 0x4B, 0x27, 0x5C, 0x84, 0x04, 0x74, 0xA0, 0x7E, 0x80, 0x91, 0x6A, 0x6A, 0xC4, 0x44,
+ 0x05, 0x88, 0x4F, 0x8C, 0x8E, 0x07, 0x79, 0xA6, 0x5D, 0x32, 0x75, 0xD2, 0x84, 0x4B, 0x96, 0xF6, 0xAF, 0x5A, 0xB1, 0x74,
+ 0x33, 0x4D, 0xBD, 0xB0, 0xC0, 0xF0, 0xC0, 0xD9, 0x01, 0xE4, 0x42, 0x73, 0x67, 0xF9, 0xA6, 0x27, 0xA5, 0x91, 0x6B, 0xCE,
+ 0x9F, 0x8D, 0x1F, 0x88, 0x0E, 0xB4, 0xD3, 0x20, 0x89, 0x8D, 0x80, 0xBE, 0x13, 0x15, 0x24, 0x96, 0xE6, 0x38, 0xBD, 0x0A,
+ 0x47, 0x07, 0xD9, 0x65, 0xA3, 0x81, 0x65, 0x04, 0xC7, 0xFF, 0x9F, 0x70, 0xE6, 0x14, 0xB0, 0x93, 0xE9, 0x08, 0xDD, 0xC9,
+ 0x6E, 0xD3, 0x9D, 0xC8, 0xEF, 0x33, 0x06, 0xC4, 0x2D, 0x92, 0xB8, 0x78, 0x22, 0xB1, 0xD4, 0x44, 0x54, 0x49, 0x1C, 0x47,
+ 0x40, 0xC6, 0x60, 0xB7, 0xA2, 0xB9, 0xFC, 0x09, 0xE6, 0x5C, 0x64, 0x84, 0x5E, 0x2C, 0x11, 0xB5, 0x86, 0xA9, 0x08, 0x13,
+ 0x92, 0xA2, 0x06, 0x87, 0x53, 0xE6, 0x0E, 0xAA, 0x34, 0xDB, 0x71, 0xA6, 0x86, 0x85, 0x32, 0xC9, 0x72, 0x66, 0xE8, 0x55,
+ 0x4D, 0xCD, 0x95, 0x4D, 0x4A, 0x68, 0x68, 0xAB, 0x90, 0xB9, 0x0D, 0x2F, 0x68, 0xFA, 0x45, 0x75, 0xD5, 0xC5, 0x0D, 0x36,
+ 0x35, 0xD2, 0x96, 0x4E, 0x1E, 0x3D, 0xFC, 0xE4, 0x6C, 0x52, 0x1D, 0x10, 0x26, 0x2A, 0x54, 0xE0, 0xE8, 0xEC, 0xB3, 0xCF,
+ 0xAC, 0x2E, 0xAD, 0x5F, 0xBF, 0x72, 0x7B, 0x6D, 0x79, 0x73, 0x64, 0x48, 0x14, 0xF9, 0x52, 0xC0, 0x3C, 0xFF, 0x39, 0x33,
+ 0x66, 0x27, 0xC5, 0x26, 0x17, 0xE6, 0x14, 0xA3, 0x8C, 0xC4, 0xA8, 0x44, 0xF5, 0x03, 0x70, 0x4C, 0xB2, 0xA3, 0xAC, 0x82,
+ 0x11, 0x35, 0x10, 0x87, 0x4D, 0xF3, 0xF2, 0xA4, 0xC4, 0xC6, 0xD1, 0xD3, 0x29, 0xE5, 0x6E, 0x5D, 0xE1, 0x94, 0xE6, 0x3F,
+ 0xC6, 0x15, 0xAC, 0xBD, 0xE7, 0x19, 0x1D, 0xA8, 0x02, 0xA4, 0xD6, 0x4B, 0x95, 0xBC, 0x8B, 0x0B, 0x47, 0x07, 0xA3, 0x41,
+ 0x7C, 0x24, 0x4B, 0x71, 0x72, 0x76, 0x9D, 0x77, 0xAB, 0x1A, 0x4A, 0x64, 0xF4, 0x6A, 0x96, 0x63, 0xAA, 0x9A, 0x4A, 0xBA,
+ 0x1E, 0x20, 0xD7, 0xD2, 0x9A, 0x97, 0x21, 0x09, 0x0D, 0x1F, 0x67, 0x52, 0xE8, 0x10, 0xCD, 0x0A, 0xC5, 0xAE, 0xAB, 0x0B,
+ 0x1C, 0xDE, 0x99, 0x0E, 0x63, 0xC9, 0x7F, 0x18, 0x52, 0x32, 0xEF, 0x85, 0xCF, 0x03, 0xAB, 0x07, 0x36, 0x5C, 0x6B, 0x35,
+ 0x3E, 0x21, 0xFC, 0x06, 0x69, 0x5A, 0x98, 0xBE, 0xA9, 0x36, 0x23, 0x25, 0x2C, 0xE7, 0xD8, 0xB0, 0x4C, 0x48, 0x48, 0x89,
+ 0x0D, 0x8F, 0x0E, 0x0F, 0x0C, 0x05, 0x8E, 0x50, 0xC6, 0xFA, 0x95, 0x5B, 0x69, 0x38, 0xC6, 0x84, 0xC7, 0xA2, 0x15, 0xE0,
+ 0x68, 0xDE, 0xCC, 0x39, 0x09, 0xD1, 0x89, 0x78, 0xC6, 0xBC, 0x59, 0x73, 0xD1, 0x01, 0x75, 0x2F, 0xA9, 0x11, 0x61, 0x99,
+ 0x7E, 0x83, 0x11, 0x8A, 0x24, 0x48, 0x92, 0xAE, 0xA0, 0x80, 0x3C, 0x51, 0x83, 0xF5, 0x0C, 0xD7, 0x09, 0xBE, 0x4A, 0x07,
+ 0x5E, 0xC5, 0x8C, 0xB1, 0x77, 0x3C, 0x75, 0x0C, 0xE2, 0xF3, 0xBF, 0xCC, 0x12, 0xAB, 0xD7, 0x94, 0xD7, 0x2E, 0xBD, 0xEB,
+ 0xE3, 0xA5, 0x8C, 0x69, 0xB7, 0x52, 0xA4, 0xEC, 0x30, 0xC8, 0x4C, 0x9A, 0xE8, 0xE6, 0xEC, 0x16, 0x5E, 0xEC, 0x85, 0x2A,
+ 0x43, 0x53, 0x49, 0xB1, 0x6E, 0x43, 0x34, 0x53, 0xDB, 0xB7, 0x9C, 0x03, 0x1D, 0x79, 0x33, 0x2D, 0xB1, 0xCC, 0x32, 0xEC,
+ 0x9A, 0x6B, 0xA6, 0x31, 0xC4, 0x5B, 0x78, 0x3B, 0xF9, 0xA9, 0x05, 0xCC, 0x6F, 0xCB, 0x33, 0x2B, 0x84, 0xD3, 0xE9, 0x70,
+ 0xDC, 0x20, 0x16, 0xB6, 0x42, 0x2C, 0x04, 0xA0, 0x4C, 0xFB, 0x9A, 0x59, 0x39, 0xE3, 0x40, 0x99, 0x73, 0x01, 0xE5, 0xF2,
+ 0xBE, 0x13, 0xB3, 0xB3, 0x13, 0x33, 0x4D, 0x48, 0x88, 0x8F, 0x0C, 0x8A, 0xBC, 0x74, 0xD2, 0x25, 0x53, 0xA7, 0x5C, 0x3A,
+ 0xBC, 0x64, 0xE3, 0xA2, 0xF6, 0x25, 0x74, 0x98, 0x49, 0x84, 0xA8, 0x8D, 0xE7, 0xCD, 0xF4, 0x8D, 0x8B, 0x8C, 0x2F, 0x2B,
+ 0xAC, 0xE0, 0x82, 0xBA, 0x3A, 0xC9, 0x94, 0xBB, 0xF8, 0x81, 0x18, 0x20, 0x73, 0x18, 0xB7, 0x50, 0x10, 0x89, 0x3B, 0x0A,
+ 0x00, 0x9D, 0x1C, 0x80, 0x32, 0x6A, 0x18, 0x05, 0xFA, 0xE2, 0x7F, 0x63, 0x1E, 0x71, 0x73, 0xA7, 0x93, 0x30, 0x47, 0xC4,
+ 0x3D, 0x66, 0x9D, 0x2C, 0x7D, 0xAB, 0x06, 0x5C, 0xC1, 0x07, 0x03, 0x57, 0x5C, 0xB6, 0x8C, 0x49, 0x2E, 0x14, 0x8B, 0x35,
+ 0xB4, 0x8E, 0x30, 0x58, 0x9D, 0xAC, 0xC6, 0xF0, 0x58, 0xDD, 0x52, 0xD6, 0x78, 0x80, 0x4C, 0xA9, 0x0C, 0x9F, 0xB2, 0x1A,
+ 0x14, 0xB2, 0xDC, 0x4A, 0x2F, 0xA9, 0x4F, 0x19, 0x4E, 0x3A, 0xDA, 0x26, 0xD7, 0xA4, 0xF7, 0x40, 0xC2, 0x87, 0x0E, 0xBA,
+ 0x1A, 0x16, 0x7D, 0xFB, 0x5B, 0xDF, 0x7B, 0xEC, 0x91, 0x27, 0xE1, 0x22, 0xD2, 0xE8, 0x6F, 0xAD, 0x6C, 0x66, 0xFE, 0x0E,
+ 0x17, 0x48, 0x18, 0x86, 0x35, 0xC2, 0xA2, 0x50, 0x35, 0xC8, 0xD0, 0xB1, 0x00, 0x6F, 0x10, 0x57, 0x40, 0x1C, 0x54, 0x4C,
+ 0x00, 0x0B, 0xDD, 0x4D, 0x46, 0x5D, 0x94, 0xC4, 0x20, 0xFE, 0xF9, 0xE3, 0xCE, 0xEB, 0x6E, 0xEB, 0x5F, 0xD2, 0xB7, 0x32,
+ 0x39, 0x2E, 0x15, 0x1D, 0x90, 0x17, 0x05, 0xCC, 0xF5, 0x23, 0x3E, 0x57, 0x95, 0xD4, 0x2D, 0x98, 0x33, 0x9B, 0xAA, 0x0D,
+ 0x3F, 0x40, 0x6D, 0x1A, 0x93, 0x09, 0xD4, 0xC0, 0xD1, 0x29, 0x33, 0x7A, 0x42, 0x8E, 0xC7, 0x0F, 0x46, 0x45, 0x02, 0xF0,
+ 0xA7, 0x38, 0xDD, 0x24, 0xAC, 0x9E, 0xE4, 0xD5, 0x9A, 0xBC, 0x26, 0x3F, 0xBA, 0x4C, 0xF6, 0x25, 0x8B, 0xC2, 0x82, 0xB7,
+ 0xEA, 0x35, 0x7C, 0xAF, 0xE8, 0x6D, 0x0D, 0xE8, 0xA3, 0x48, 0x62, 0x15, 0x00, 0x83, 0xD5, 0x31, 0x73, 0x37, 0xA2, 0x0A,
+ 0xB6, 0x18, 0x03, 0x77, 0xC8, 0xC3, 0x5C, 0x1B, 0x16, 0x31, 0xE2, 0x36, 0x78, 0x2D, 0x90, 0xCD, 0x35, 0x62, 0x12, 0x4B,
+ 0x2F, 0x32, 0x0E, 0x61, 0xC8, 0x36, 0x60, 0x08, 0xB0, 0x03, 0xCF, 0x00, 0xB9, 0x1B, 0x72, 0x47, 0xB5, 0xE9, 0xBE, 0x49,
+ 0x73, 0x86, 0x14, 0x13, 0x1D, 0x30, 0x68, 0x64, 0xBD, 0xF7, 0x93, 0x5F, 0x31, 0x05, 0xFE, 0xDB, 0xDF, 0xFE, 0xB6, 0x67,
+ 0xFB, 0x81, 0xDC, 0xA4, 0xAC, 0xD6, 0xAA, 0xA6, 0xEE, 0xA6, 0x45, 0xB0, 0x51, 0xA0, 0x12, 0x09, 0xE3, 0xB3, 0xA6, 0xB5,
+ 0xB9, 0x52, 0xF2, 0x5A, 0x5E, 0x93, 0xE0, 0xCC, 0x18, 0x00, 0x88, 0x47, 0x88, 0x84, 0x04, 0xEC, 0x9A, 0x0C, 0x95, 0x6A,
+ 0x20, 0x30, 0x60, 0xE1, 0xB8, 0x73, 0xBF, 0x56, 0x98, 0x57, 0xBA, 0x6E, 0xC5, 0x96, 0x8C, 0xE4, 0x4C, 0x12, 0x21, 0x32,
+ 0x54, 0x4A, 0x65, 0xFF, 0xB9, 0x7E, 0x55, 0xA5, 0x35, 0x81, 0xF3, 0xFD, 0xC8, 0xA0, 0x88, 0x1F, 0x34, 0x9A, 0x32, 0x52,
+ 0xF3, 0x0A, 0x92, 0x51, 0x03, 0xAE, 0x90, 0xCF, 0x48, 0x6E, 0x94, 0x1A, 0x46, 0xA4, 0xEF, 0xE4, 0x9A, 0xA0, 0x8A, 0x9B,
+ 0x74, 0x4A, 0x5E, 0x04, 0xB1, 0x45, 0x25, 0xCE, 0x1F, 0x8E, 0x29, 0x20, 0x2C, 0xCA, 0x8B, 0x0E, 0xD2, 0x51, 0x86, 0x2A,
+ 0x20, 0x9F, 0xE6, 0x15, 0x82, 0xB6, 0xF8, 0x63, 0xAB, 0x6E, 0x4F, 0xF9, 0x2D, 0x21, 0x41, 0x74, 0x50, 0x53, 0xC8, 0x32,
+ 0x48, 0x22, 0x04, 0xA6, 0x3A, 0x8C, 0x5A, 0xB9, 0x92, 0xC8, 0xDA, 0x06, 0x55, 0xD5, 0xC4, 0x08, 0x8B, 0xD8, 0x25, 0x25,
+ 0x8C, 0xE1, 0x9A, 0x19, 0x82, 0x5F, 0xBD, 0x0E, 0x0B, 0x45, 0x25, 0xF9, 0xD2, 0x74, 0x33, 0xC4, 0x02, 0xE8, 0x08, 0xDA,
+ 0x1D, 0x73, 0xE6, 0xE6, 0x89, 0x21, 0x71, 0x8C, 0x21, 0x53, 0x22, 0x92, 0x0A, 0x52, 0x0A, 0x5E, 0xFE, 0xE6, 0x6B, 0x42,
+ 0xD5, 0x3A, 0xF1, 0xC5, 0xDD, 0xB7, 0xDE, 0xCF, 0x27, 0xA4, 0xF1, 0xD9, 0xD7, 0xDC, 0xD3, 0xDB, 0xD4, 0xAD, 0x3C, 0x51,
+ 0x82, 0x04, 0xD1, 0x82, 0x98, 0x41, 0xE4, 0xC0, 0x87, 0x98, 0xA6, 0x91, 0x2C, 0x62, 0x5F, 0xE8, 0x20, 0x35, 0x3A, 0x05,
+ 0x1B, 0x8F, 0x08, 0x0E, 0xA7, 0x77, 0x84, 0x43, 0x6C, 0x5E, 0xBB, 0x3D, 0x27, 0x2B, 0x9F, 0x00, 0x10, 0x15, 0x12, 0x91,
+ 0x1C, 0x9B, 0xE8, 0x3F, 0x67, 0x4E, 0x79, 0x51, 0x65, 0x68, 0x70, 0x08, 0x61, 0x83, 0xB6, 0x1D, 0xF5, 0x81, 0xC6, 0x64,
+ 0x45, 0x86, 0x12, 0x4F, 0xE1, 0xAA, 0xCA, 0xB0, 0x91, 0x76, 0x54, 0xF6, 0x99, 0x63, 0x1E, 0x4F, 0x1F, 0x29, 0x6B, 0x6D,
+ 0x9B, 0x61, 0x34, 0xE0, 0x38, 0x85, 0xB4, 0xED, 0x73, 0x8C, 0xC1, 0xFD, 0x31, 0x0A, 0x90, 0xC8, 0x94, 0x9A, 0xAB, 0xB7,
+ 0x3E, 0x0A, 0x26, 0x2A, 0x6B, 0x3E, 0xA4, 0xC3, 0x98, 0x14, 0x9A, 0xBC, 0x61, 0xAA, 0x16, 0x55, 0x6B, 0xEF, 0xCC, 0xD5,
+ 0x8A, 0x4B, 0x9F, 0x77, 0x29, 0xDD, 0x3C, 0x0E, 0x0F, 0x50, 0x7F, 0xAB, 0x14, 0x57, 0x99, 0xD0, 0xE6, 0x57, 0x01, 0x1D,
+ 0xA6, 0xDD, 0x26, 0x94, 0x1B, 0xA1, 0x11, 0x14, 0x94, 0x79, 0xC7, 0x55, 0xBC, 0x3F, 0x46, 0xF3, 0x99, 0xF1, 0x19, 0x5B,
+ 0xD6, 0xED, 0xE6, 0x96, 0x11, 0xF1, 0x03, 0x77, 0x3F, 0x84, 0x0E, 0xD0, 0xC4, 0xAB, 0x2F, 0xBF, 0xD2, 0x5C, 0xDD, 0xC6,
+ 0x10, 0xB8, 0xA7, 0x79, 0x11, 0xEC, 0xD2, 0xEE, 0x56, 0x51, 0x06, 0x3E, 0x81, 0x43, 0x34, 0x95, 0x89, 0x1A, 0x08, 0x21,
+ 0x4C, 0x28, 0x69, 0x24, 0x64, 0xA6, 0x64, 0xF3, 0xB7, 0xC9, 0x51, 0xF1, 0xD1, 0xA1, 0x91, 0xB3, 0xA6, 0x4D, 0x9F, 0x3B,
+ 0x73, 0xCE, 0xFA, 0xB5, 0x3B, 0x4B, 0xF3, 0x2B, 0xE7, 0xCF, 0x9C, 0x9F, 0x16, 0x93, 0x52, 0x5D, 0x58, 0x19, 0xEE, 0x1F,
+ 0x5C, 0x90, 0x55, 0x92, 0x48, 0xFB, 0x39, 0x24, 0x82, 0x71, 0x3C, 0x33, 0x61, 0x6D, 0x19, 0x49, 0x40, 0x46, 0xA6, 0x19,
+ 0x23, 0x85, 0x95, 0x88, 0x55, 0xE1, 0x5E, 0x4A, 0x87, 0xB1, 0x10, 0x54, 0x92, 0xE1, 0xB4, 0x77, 0x9C, 0x82, 0xCB, 0x60,
+ 0xD1, 0x28, 0xDB, 0x37, 0x79, 0x8E, 0x9A, 0xFC, 0xC9, 0xD0, 0xFF, 0x65, 0xD2, 0x47, 0x01, 0xBA, 0x7C, 0x14, 0xBE, 0xD5,
+ 0x9C, 0xAD, 0x28, 0x9D, 0x88, 0x6A, 0xC0, 0xDD, 0x5D, 0xD5, 0x34, 0x0F, 0xBC, 0x91, 0xD6, 0xA5, 0x29, 0x38, 0x34, 0x6E,
+ 0x05, 0x1F, 0x9D, 0x95, 0x6B, 0x24, 0x50, 0x0F, 0x90, 0x94, 0xA6, 0x40, 0x9A, 0x6E, 0x26, 0xFF, 0x2B, 0x36, 0x55, 0x7E,
+ 0x01, 0xB8, 0x4C, 0xB2, 0x38, 0xEF, 0xD2, 0x59, 0xB9, 0xC9, 0x79, 0xFB, 0x77, 0x1E, 0x26, 0x14, 0xC7, 0x2C, 0x8C, 0x3A,
+ 0xB8, 0xF3, 0x88, 0x92, 0x76, 0x7F, 0xF7, 0x9B, 0xDF, 0x5E, 0xB6, 0x79, 0x07, 0x41, 0x18, 0xA1, 0xF7, 0xB5, 0x2D, 0x82,
+ 0xC0, 0xD2, 0xD7, 0xDA, 0x0B, 0x40, 0x75, 0xD6, 0xD2, 0x40, 0x14, 0xBE, 0x2D, 0x04, 0x0B, 0x58, 0x40, 0x78, 0x3A, 0xAE,
+ 0x40, 0xFF, 0x2E, 0x3E, 0x32, 0x36, 0x60, 0xFE, 0x82, 0xC9, 0x17, 0x4F, 0x58, 0xB7, 0x62, 0x1B, 0xC9, 0x6E, 0xB0, 0x6F,
+ 0x40, 0x59, 0x4E, 0x09, 0xD4, 0x20, 0xC6, 0x99, 0x39, 0x09, 0x59, 0x3C, 0x2D, 0x22, 0x20, 0x44, 0xFA, 0xCF, 0x19, 0xA6,
+ 0xFB, 0x6F, 0x52, 0x14, 0xB9, 0x95, 0x0C, 0xD5, 0x88, 0xDB, 0xB4, 0x4B, 0x35, 0x2F, 0x52, 0x1B, 0x37, 0x15, 0x19, 0x8F,
+ 0x8F, 0x52, 0x92, 0x94, 0xCD, 0xD9, 0x8A, 0x42, 0x23, 0x3E, 0xE1, 0x8D, 0x01, 0xDE, 0x9C, 0xE7, 0x2B, 0xF0, 0xC7, 0x8A,
+ 0x5E, 0x3B, 0xE4, 0x2C, 0x1F, 0x61, 0xE8, 0xE5, 0x3B, 0xDB, 0x13, 0x54, 0x0D, 0x22, 0xEB, 0x82, 0x2A, 0x51, 0x8C, 0x59,
+ 0x4A, 0xDA, 0xC6, 0xC0, 0x55, 0xB2, 0x4A, 0x49, 0xB3, 0x1C, 0x3F, 0x21, 0xB4, 0x16, 0x4B, 0x67, 0xCD, 0x28, 0x80, 0x0B,
+ 0x89, 0x0A, 0xA0, 0xBC, 0xA1, 0xB5, 0x3A, 0x33, 0x5B, 0xAD, 0xB0, 0x4C, 0x02, 0x2E, 0x7E, 0x0D, 0xDA, 0xD0, 0x42, 0x48,
+ 0x4D, 0x48, 0x63, 0x14, 0x33, 0x7D, 0xC2, 0x14, 0x5A, 0x0E, 0x3B, 0xB7, 0xEC, 0x67, 0x3A, 0x9F, 0x1C, 0x9E, 0xD8, 0xD7,
+ 0xD1, 0x6F, 0x78, 0x73, 0x9F, 0x7F, 0xFE, 0xC5, 0x7F, 0x5F, 0x7D, 0xF9, 0x5B, 0xC3, 0x4B, 0x57, 0xF3, 0x6A, 0x50, 0x1C,
+ 0xE1, 0x5A, 0x0F, 0xB5, 0x0F, 0xA0, 0x09, 0x1C, 0xA2, 0xB5, 0xAE, 0xAD, 0xB1, 0xB4, 0x1E, 0xAA, 0x44, 0x59, 0x66, 0x31,
+ 0x29, 0x36, 0xF3, 0x19, 0xAC, 0x3E, 0x26, 0x28, 0x6A, 0xD6, 0xC4, 0xE9, 0x2B, 0x97, 0x6D, 0x66, 0x36, 0x0E, 0x3B, 0x68,
+ 0x71, 0xD7, 0xD0, 0x55, 0x97, 0x5F, 0x03, 0xBF, 0x88, 0x0C, 0x8A, 0x72, 0x3D, 0x2E, 0x30, 0xBA, 0x30, 0x51, 0xC7, 0x90,
+ 0x4C, 0xC1, 0xC4, 0x03, 0x78, 0x0F, 0xA4, 0x46, 0xC4, 0x58, 0x2E, 0x78, 0x4B, 0x25, 0x02, 0x44, 0x25, 0xD8, 0x3B, 0xD2,
+ 0x57, 0x20, 0x92, 0xC8, 0x4C, 0x84, 0xC8, 0x35, 0xDD, 0x3D, 0xC6, 0xD1, 0x04, 0x64, 0xD3, 0x23, 0x52, 0xA8, 0xD1, 0xB6,
+ 0x9D, 0xA7, 0xE8, 0xD5, 0xD4, 0xD3, 0x71, 0x85, 0x93, 0x71, 0x5F, 0x61, 0xE7, 0x64, 0xE9, 0x3B, 0x3A, 0x18, 0xC5, 0x54,
+ 0x2D, 0x10, 0x09, 0x8A, 0x56, 0x8C, 0xA0, 0x2B, 0xC0, 0x5F, 0xB5, 0x68, 0xE7, 0x11, 0x61, 0x90, 0x29, 0xAB, 0x52, 0x39,
+ 0xF5, 0x68, 0x48, 0x08, 0x0A, 0xE6, 0x39, 0xC4, 0x5E, 0x21, 0xFE, 0x19, 0x4D, 0x08, 0xE7, 0xB2, 0x50, 0xF8, 0x65, 0x78,
+ 0x80, 0x77, 0x48, 0x22, 0x35, 0x7D, 0xB6, 0x33, 0xAB, 0x02, 0xA0, 0x29, 0xB2, 0x00, 0xF1, 0x69, 0xE3, 0x27, 0x4F, 0xBF,
+ 0x68, 0x6A, 0x7F, 0xC7, 0xD0, 0x91, 0x03, 0xD7, 0x4A, 0x7B, 0x2E, 0xA3, 0xE8, 0x95, 0x17, 0x5E, 0x35, 0x6C, 0x2D, 0x36,
+ 0x16, 0x7C, 0xFC, 0xF2, 0xF3, 0x2F, 0xC1, 0x2B, 0x6D, 0xAE, 0x68, 0xE8, 0xA8, 0x6B, 0x5B, 0xDC, 0x35, 0x08, 0x6B, 0x08,
+ 0xEE, 0x22, 0x35, 0x04, 0x0E, 0x41, 0xC9, 0x5D, 0x0D, 0xE3, 0x28, 0xB3, 0xB8, 0x30, 0x25, 0x0F, 0x59, 0x87, 0x2F, 0x08,
+ 0x59, 0xBF, 0x72, 0x73, 0x5F, 0x6B, 0x3F, 0xFD, 0x8C, 0x2B, 0x0E, 0x5C, 0xF9, 0x8D, 0xAF, 0xBF, 0x7C, 0xFC, 0xAA, 0x1B,
+ 0xAA, 0xF3, 0x2B, 0xDB, 0xEB, 0xBB, 0x32, 0x63, 0x52, 0x79, 0x4E, 0x31, 0x83, 0x01, 0x14, 0x20, 0x83, 0xFB, 0x42, 0xA4,
+ 0xCF, 0x42, 0xB8, 0x44, 0x5A, 0x02, 0x03, 0xD2, 0x97, 0xEB, 0x0C, 0xA7, 0x13, 0xA7, 0xFD, 0x41, 0x5C, 0x8D, 0x37, 0xCC,
+ 0xAD, 0x66, 0x44, 0x2C, 0xC6, 0x3B, 0x6E, 0x30, 0x30, 0xA5, 0x96, 0x1B, 0x7E, 0xA5, 0x52, 0x4B, 0x77, 0xE0, 0xC8, 0xAB,
+ 0x00, 0xCD, 0x7C, 0x2C, 0xF4, 0xAB, 0xE1, 0x5B, 0xF3, 0x57, 0x05, 0x88, 0x1F, 0xA8, 0x0E, 0xB4, 0x43, 0x29, 0x66, 0x6E,
+ 0x28, 0x37, 0x27, 0x2F, 0x11, 0xBA, 0x81, 0x78, 0x31, 0x70, 0x23, 0x77, 0x25, 0x76, 0x3B, 0x7B, 0x19, 0xCC, 0x5D, 0xC5,
+ 0x22, 0x79, 0x02, 0x64, 0x9E, 0x42, 0x71, 0x02, 0x6D, 0x33, 0x78, 0xFC, 0x80, 0xBE, 0x8A, 0x64, 0x6F, 0x60, 0x91, 0x49,
+ 0x2E, 0xD3, 0x48, 0xF0, 0x63, 0x43, 0x22, 0x7D, 0x2F, 0xF5, 0x1D, 0x77, 0xE6, 0x39, 0xBC, 0xDD, 0x23, 0x07, 0xAF, 0x59,
+ 0xDC, 0xBB, 0x22, 0x3D, 0x2A, 0xE5, 0xFA, 0x63, 0xD7, 0x7F, 0xFA, 0x5F, 0x61, 0x2D, 0xF2, 0x03, 0x6F, 0xEE, 0xB5, 0x57,
+ 0xBF, 0xB3, 0x71, 0xCD, 0x66, 0x32, 0x57, 0x5C, 0x61, 0xA8, 0x13, 0x7A, 0x1D, 0x24, 0xFB, 0x45, 0x86, 0xCE, 0x4E, 0x6F,
+ 0x83, 0xB2, 0x51, 0x7C, 0x37, 0x2B, 0x2E, 0x63, 0xE7, 0x96, 0xBD, 0xB0, 0xAC, 0x07, 0x5B, 0x7B, 0x9F, 0xFB, 0xFA, 0x0B,
+ 0xEF, 0xFF, 0xE2, 0xC3, 0x57, 0x5F, 0xFA, 0xEE, 0xB2, 0x9E, 0xE5, 0xE8, 0x4C, 0xDE, 0x40, 0x66, 0x21, 0x31, 0xA6, 0x24,
+ 0x83, 0x41, 0x50, 0x61, 0x41, 0x56, 0x0E, 0x12, 0xB7, 0x49, 0x91, 0x20, 0x8C, 0xAD, 0x0C, 0x28, 0xD9, 0x72, 0x49, 0x9D,
+ 0xA5, 0x6C, 0x86, 0x42, 0x20, 0xB4, 0x09, 0x74, 0x23, 0x4F, 0x16, 0x80, 0x62, 0xBC, 0x63, 0x13, 0x53, 0x1C, 0xC8, 0x9B,
+ 0x02, 0x49, 0x95, 0x43, 0x48, 0xD0, 0x5B, 0x57, 0xF4, 0x63, 0x6C, 0xDF, 0x2B, 0x7D, 0xFD, 0x15, 0x0A, 0x40, 0x0E, 0xA2,
+ 0x03, 0x2B, 0x71, 0x35, 0x70, 0x21, 0xDE, 0xE4, 0x19, 0xD2, 0x64, 0x1E, 0xEC, 0x62, 0xCC, 0x59, 0x99, 0x94, 0x66, 0x0B,
+ 0x83, 0xAB, 0x00, 0xBD, 0x50, 0xB6, 0xA5, 0xEA, 0xCF, 0x3A, 0x84, 0xF3, 0x6A, 0x85, 0x96, 0x6E, 0xE6, 0xE8, 0xC0, 0xA0,
+ 0x2D, 0xF6, 0x22, 0x51, 0x4B, 0x67, 0xB6, 0x0C, 0x69, 0x25, 0xB9, 0x0C, 0x8F, 0xA6, 0xED, 0x43, 0x52, 0x7F, 0xEE, 0xE9,
+ 0xE7, 0x06, 0xCC, 0xF2, 0xDB, 0xB6, 0x61, 0x27, 0xA2, 0x24, 0x97, 0x67, 0x03, 0xC1, 0xEF, 0x7E, 0xF7, 0x07, 0xDC, 0x81,
+ 0x5D, 0x05, 0x42, 0xE6, 0xFD, 0xE4, 0xD3, 0x6F, 0x3C, 0xF7, 0x22, 0xAC, 0x3A, 0x44, 0xBF, 0xBC, 0x7B, 0x29, 0x9C, 0xEA,
+ 0x25, 0x9D, 0x43, 0x83, 0x6D, 0xFD, 0x03, 0x2D, 0xBD, 0x7D, 0xAD, 0xA4, 0x4F, 0x74, 0xE0, 0x1B, 0x2F, 0xDF, 0x7F, 0x0C,
+ 0x34, 0x3B, 0x7E, 0xF4, 0xDA, 0xDF, 0x7C, 0xF8, 0x87, 0xFF, 0xFC, 0xE7, 0x3F, 0xBF, 0xFD, 0xCD, 0x1F, 0xAF, 0x3A, 0x74,
+ 0x9C, 0xED, 0x53, 0xDD, 0x4D, 0x5D, 0x15, 0xB9, 0xA5, 0xE8, 0xA9, 0x92, 0x69, 0x7E, 0x96, 0x0C, 0x5B, 0x0A, 0x73, 0x0A,
+ 0x24, 0x0C, 0xB8, 0x88, 0xAF, 0xF6, 0xCE, 0xAF, 0xCA, 0xB2, 0x8B, 0x79, 0x26, 0x61, 0x9F, 0x0C, 0x82, 0xE1, 0x1D, 0x75,
+ 0x0C, 0x6A, 0xD0, 0x36, 0x06, 0xCF, 0x27, 0xC2, 0x6B, 0xE8, 0x76, 0xCB, 0x02, 0xA7, 0x00, 0xB6, 0x01, 0x59, 0x4D, 0x9E,
+ 0xBB, 0xD6, 0xE4, 0xF5, 0x93, 0x9E, 0x72, 0x21, 0x7D, 0x5D, 0x3E, 0xCA, 0x1C, 0xB6, 0xF2, 0x35, 0x35, 0xD4, 0xC8, 0x23,
+ 0x50, 0x59, 0x0D, 0x47, 0x55, 0x76, 0x2B, 0x28, 0x6F, 0xBB, 0xBC, 0xA0, 0xBC, 0xA2, 0xB0, 0x82, 0xA5, 0x66, 0x2E, 0xD2,
+ 0x37, 0xB9, 0x10, 0x86, 0x5F, 0x55, 0x5C, 0xCD, 0xAA, 0x2C, 0xAA, 0xAA, 0x28, 0x16, 0x57, 0x30, 0x04, 0x1E, 0x61, 0x30,
+ 0xB8, 0xC1, 0x40, 0x8A, 0x4F, 0x49, 0x27, 0x52, 0xCC, 0x1C, 0x26, 0x31, 0x13, 0x38, 0xC2, 0x15, 0x68, 0xBD, 0xC5, 0x87,
+ 0x45, 0x86, 0x07, 0x06, 0xC3, 0xA3, 0x3A, 0xFF, 0xEC, 0x71, 0xE3, 0xC7, 0x8D, 0x5F, 0xD2, 0x37, 0x7C, 0xEC, 0xF0, 0x75,
+ 0x55, 0xC5, 0x55, 0xB5, 0x65, 0x75, 0xAF, 0xBF, 0xF6, 0x06, 0x0A, 0x40, 0x0D, 0x9F, 0x7E, 0xFA, 0x5F, 0x2E, 0xFE, 0xF2,
+ 0xD7, 0xBF, 0x1F, 0x3F, 0x7A, 0x1C, 0xD3, 0x5E, 0xDE, 0xBB, 0x74, 0xED, 0x92, 0xD5, 0x2B, 0x97, 0xAE, 0x5A, 0xB1, 0x64,
+ 0xD5, 0xAA, 0x25, 0xAB, 0x96, 0xF4, 0x2E, 0x81, 0xE6, 0x75, 0x68, 0xF7, 0xE1, 0xAD, 0xEB, 0xB6, 0xBE, 0xF3, 0xC3, 0xF7,
+ 0x3E, 0x63, 0xCB, 0xEE, 0x89, 0xCF, 0xFF, 0xFD, 0x3F, 0x1F, 0x3F, 0xFF, 0xEC, 0x4B, 0x6B, 0xD8, 0x1C, 0x38, 0xB8, 0x82,
+ 0x84, 0xAA, 0xA9, 0x82, 0x4D, 0x7A, 0xD5, 0xC8, 0xD7, 0xDB, 0x1D, 0xC2, 0xC6, 0xCB, 0x32, 0x05, 0x76, 0x10, 0x3D, 0x12,
+ 0x47, 0xEE, 0x6C, 0x32, 0x90, 0x2A, 0xD2, 0xE4, 0x72, 0x0E, 0x87, 0x2E, 0x5F, 0x83, 0x99, 0x43, 0x45, 0x31, 0x3A, 0x10,
+ 0x58, 0x73, 0x9A, 0x10, 0x99, 0xB9, 0xAE, 0xF9, 0x3B, 0x43, 0x37, 0x85, 0x23, 0x6B, 0xE9, 0x27, 0x2B, 0x00, 0xB9, 0xF3,
+ 0xF1, 0x47, 0xE9, 0x00, 0xAB, 0xD7, 0x1A, 0xCA, 0x0C, 0x4C, 0x1C, 0x03, 0x1F, 0x21, 0xB1, 0x1A, 0x39, 0x96, 0xE6, 0xBA,
+ 0xCC, 0x64, 0x23, 0x7D, 0x15, 0x31, 0xB2, 0xD6, 0x60, 0x80, 0x1A, 0x24, 0x56, 0x9B, 0x92, 0x4D, 0x62, 0x89, 0x70, 0x52,
+ 0x84, 0x5B, 0xE8, 0xC0, 0x91, 0xC9, 0x8B, 0x9C, 0xC9, 0x09, 0x91, 0x2D, 0xAD, 0x90, 0xF7, 0x47, 0x66, 0xC9, 0xFB, 0xA0,
+ 0x74, 0xC2, 0x15, 0x08, 0x0C, 0xB1, 0x61, 0xB1, 0x34, 0x9C, 0xA9, 0xA7, 0x2E, 0xBA, 0xE0, 0xC2, 0x0B, 0xCF, 0x38, 0x17,
+ 0xBE, 0xF4, 0x35, 0x57, 0xDD, 0x02, 0x99, 0x0E, 0x04, 0xB8, 0xFB, 0xB6, 0x7B, 0xD8, 0xDC, 0x41, 0x84, 0x00, 0x94, 0x34,
+ 0x4E, 0xBC, 0xFA, 0xEA, 0x6B, 0x6B, 0x86, 0xD7, 0xE2, 0x13, 0x5B, 0x56, 0x6D, 0xDA, 0xBE, 0x61, 0x3B, 0xFB, 0x32, 0x37,
+ 0xAE, 0x5E, 0xBF, 0x77, 0xC7, 0xBE, 0x43, 0x7B, 0x0F, 0xBF, 0xFD, 0xC6, 0x0F, 0x3F, 0xFF, 0x82, 0x98, 0x2E, 0xCF, 0x47,
+ 0x13, 0xBF, 0xF9, 0xF5, 0xEF, 0x0F, 0xEE, 0x3A, 0xC8, 0x46, 0xC1, 0x45, 0x8D, 0xD4, 0x19, 0x6D, 0x2D, 0xE5, 0x8D, 0xA8,
+ 0xC1, 0x64, 0xC9, 0x2A, 0x53, 0xE9, 0x4F, 0x94, 0x66, 0x17, 0x03, 0x3E, 0x48, 0x1F, 0xF5, 0x90, 0x8C, 0x11, 0x42, 0x6A,
+ 0xCD, 0x0E, 0x03, 0xFD, 0x8C, 0x92, 0xD4, 0x51, 0xD9, 0x18, 0x22, 0x97, 0xD5, 0x84, 0x19, 0x2D, 0x48, 0xC3, 0x43, 0x8B,
+ 0x61, 0x37, 0x0B, 0xB2, 0x3A, 0x70, 0xC2, 0xAF, 0x4A, 0xDF, 0x62, 0x8E, 0x15, 0xBA, 0xF7, 0x02, 0x21, 0xF8, 0xE8, 0x0E,
+ 0x05, 0x87, 0x9C, 0xAD, 0xCC, 0x7A, 0x97, 0x7B, 0xA3, 0x8C, 0x62, 0x97, 0x5D, 0x8C, 0x5D, 0x94, 0x94, 0x15, 0x1A, 0x9E,
+ 0x9A, 0xC9, 0xFA, 0x25, 0xEA, 0x16, 0x09, 0x7F, 0x56, 0x2A, 0x64, 0x53, 0x64, 0x08, 0xB5, 0xB6, 0x44, 0xEA, 0x38, 0x65,
+ 0x96, 0x0B, 0xCA, 0xE9, 0xC7, 0x70, 0x43, 0x82, 0xFA, 0x3E, 0xEF, 0x3B, 0x37, 0x5D, 0xDE, 0x99, 0xEB, 0x0A, 0xA9, 0xE8,
+ 0x20, 0x3E, 0x22, 0x21, 0x26, 0x2C, 0x8A, 0xF9, 0xD7, 0xC2, 0xF9, 0x01, 0x93, 0x2E, 0x1E, 0x7F, 0xB6, 0xCF, 0x99, 0xD0,
+ 0xB3, 0xAE, 0xBE, 0xF2, 0xA6, 0xCD, 0xAB, 0x2F, 0x43, 0x0D, 0x87, 0xF7, 0x1C, 0xFE, 0xF7, 0xBF, 0xFF, 0xA3, 0x0E, 0x21,
+ 0x1B, 0xC1, 0x4F, 0x9C, 0xF8, 0xE3, 0x1F, 0xFF, 0x74, 0xCB, 0xF5, 0xB7, 0xB2, 0xFF, 0x72, 0xCB, 0xCA, 0x8D, 0xF0, 0xE0,
+ 0x77, 0x6F, 0xDD, 0x83, 0xAA, 0x3E, 0xFC, 0xF0, 0x43, 0xB3, 0x2D, 0xE7, 0x53, 0x91, 0xBF, 0xE1, 0x60, 0xB3, 0x91, 0xE6,
+ 0x89, 0xC7, 0x9E, 0xDE, 0xBE, 0x76, 0x1B, 0xDB, 0x72, 0x16, 0x35, 0xD0, 0x02, 0x61, 0x57, 0x65, 0x03, 0x59, 0x1F, 0xB1,
+ 0x81, 0xA5, 0x74, 0x0D, 0x14, 0x40, 0xE5, 0x88, 0xF9, 0x23, 0x77, 0xEA, 0x21, 0xF9, 0x20, 0xA5, 0x75, 0xC4, 0x98, 0x86,
+ 0x62, 0xD3, 0x7D, 0x29, 0x00, 0x15, 0xA4, 0x55, 0x85, 0x1A, 0x24, 0xB7, 0x36, 0xD9, 0x9D, 0x3B, 0xE1, 0x71, 0x5C, 0xC1,
+ 0x19, 0x3E, 0xA7, 0x08, 0xC6, 0x9E, 0x12, 0x88, 0xC6, 0x48, 0x9F, 0x0F, 0xAE, 0x9F, 0x9D, 0x65, 0x74, 0x90, 0x6B, 0x09,
+ 0x4F, 0x42, 0x90, 0x1F, 0x21, 0x70, 0x8F, 0xE6, 0xAB, 0x1A, 0x5E, 0x94, 0x87, 0x1A, 0x55, 0x54, 0x49, 0x09, 0x8A, 0x0E,
+ 0x4C, 0x11, 0x57, 0xC3, 0x3B, 0x96, 0xD9, 0x40, 0x69, 0x6D, 0x63, 0x79, 0xBD, 0xEC, 0xD4, 0x90, 0xC1, 0x0E, 0x1F, 0x83,
+ 0x32, 0x9B, 0x38, 0x2F, 0xDA, 0x72, 0xAC, 0x29, 0x4B, 0x66, 0x1D, 0xD2, 0xC2, 0x4D, 0x96, 0x71, 0x98, 0x4C, 0x25, 0xE3,
+ 0x4D, 0xDB, 0x27, 0x26, 0x45, 0xD4, 0x10, 0x19, 0xEB, 0xA8, 0x61, 0xDE, 0xBC, 0x4B, 0xC6, 0x4F, 0x38, 0xDD, 0xE7, 0x34,
+ 0xF8, 0xFE, 0x57, 0x1E, 0xBA, 0x66, 0xDF, 0xEE, 0xA3, 0xBC, 0x08, 0xE2, 0x46, 0xEE, 0x46, 0xC4, 0x9F, 0xEB, 0x66, 0x1B,
+ 0x4A, 0xBA, 0x5F, 0xFD, 0xEA, 0xD7, 0x2F, 0xBF, 0xFC, 0xEA, 0xCB, 0x2F, 0xBD, 0xF6, 0xF3, 0x9F, 0xBF, 0xAF, 0xBB, 0x3F,
+ 0x8C, 0x86, 0x44, 0x49, 0xB2, 0x3B, 0xCA, 0x6C, 0xCF, 0xF9, 0xE0, 0x57, 0xBF, 0xBB, 0x7C, 0xDF, 0xE5, 0xB8, 0x0B, 0x7B,
+ 0x46, 0x06, 0x5A, 0x07, 0x28, 0x32, 0x9A, 0x8D, 0x37, 0x60, 0xEF, 0x86, 0xB1, 0x51, 0x46, 0xFE, 0x86, 0xA0, 0x01, 0x2B,
+ 0x3A, 0x22, 0xE0, 0x95, 0xD9, 0x7F, 0xD9, 0x42, 0xEF, 0xB6, 0xB5, 0xA2, 0x89, 0x67, 0xD6, 0x95, 0xCB, 0x64, 0x9B, 0x8A,
+ 0x44, 0xBC, 0x47, 0xBC, 0x41, 0x74, 0xA0, 0xB1, 0x4D, 0xFD, 0x80, 0x3A, 0x63, 0x0C, 0x01, 0xC0, 0x86, 0x62, 0x44, 0xAF,
+ 0x3D, 0x95, 0x31, 0x86, 0xAF, 0x3A, 0xB0, 0x4B, 0xE2, 0x81, 0x97, 0xA6, 0x6A, 0xF9, 0xAA, 0x5E, 0x8E, 0xAA, 0x7D, 0x02,
+ 0x5E, 0xE9, 0x78, 0x09, 0x21, 0x01, 0xE0, 0x12, 0x1D, 0x08, 0xA9, 0x1F, 0xB9, 0xEB, 0x00, 0x00, 0x7F, 0xE7, 0x03, 0x38,
+ 0x94, 0x7F, 0x94, 0x41, 0xEF, 0x4F, 0xF8, 0x29, 0x86, 0x7D, 0x8F, 0x47, 0x4B, 0x02, 0xEE, 0x84, 0x04, 0xEC, 0x45, 0xDF,
+ 0x1F, 0x21, 0x81, 0x3A, 0x0B, 0x44, 0x4A, 0x8C, 0x4A, 0x8A, 0x8B, 0x88, 0xA1, 0xCD, 0xC0, 0x44, 0x3E, 0x60, 0xEE, 0xDC,
+ 0x4B, 0x2E, 0x9E, 0xC4, 0xE1, 0x02, 0x89, 0xA1, 0xF1, 0x44, 0xDA, 0xA3, 0x87, 0xAF, 0x69, 0xAC, 0x6A, 0x5A, 0xBD, 0x74,
+ 0xB5, 0xEE, 0xBA, 0x31, 0xE1, 0x41, 0x02, 0xB5, 0xF7, 0x47, 0x6C, 0xFF, 0x33, 0x91, 0xBE, 0xFD, 0x31, 0xAE, 0x20, 0x7B,
+ 0x05, 0x9F, 0x7F, 0xEE, 0xC5, 0x9D, 0x5B, 0x77, 0xAD, 0x5B, 0xBA, 0x86, 0x30, 0x3E, 0xD0, 0xDA, 0x87, 0x37, 0x68, 0xAD,
+ 0x87, 0x70, 0x59, 0xB8, 0x2F, 0xCE, 0x41, 0xD2, 0x45, 0x29, 0x4E, 0x6B, 0x84, 0xDF, 0x22, 0x7A, 0x1A, 0x85, 0x7C, 0x96,
+ 0x8E, 0xFA, 0x16, 0x50, 0x11, 0xC5, 0xF0, 0x64, 0xEC, 0x80, 0x58, 0x88, 0x43, 0x88, 0xDF, 0x18, 0x1D, 0x90, 0x50, 0x15,
+ 0xCB, 0xB4, 0xD9, 0xE9, 0x48, 0xD3, 0x04, 0x93, 0x30, 0x90, 0x46, 0x24, 0x10, 0x2F, 0x17, 0xBC, 0x75, 0x71, 0x7F, 0x8C,
+ 0xD0, 0xBD, 0x77, 0x71, 0x05, 0x9F, 0x11, 0x72, 0xB6, 0xCB, 0xBC, 0xFC, 0x32, 0xD2, 0xA4, 0xFC, 0x7B, 0x41, 0x46, 0x29,
+ 0xB8, 0x94, 0x25, 0x28, 0xA5, 0x1C, 0x4E, 0x50, 0x56, 0xDF, 0x52, 0xD5, 0xC4, 0x7B, 0x95, 0x0F, 0xD0, 0xC0, 0x26, 0x56,
+ 0xF9, 0x18, 0xB4, 0x3F, 0xB5, 0xFF, 0xCC, 0x40, 0x46, 0x1A, 0xD7, 0x6C, 0x8A, 0xCB, 0x33, 0xC1, 0xD9, 0xD4, 0x68, 0x3A,
+ 0xC4, 0x60, 0xAA, 0xA5, 0xEF, 0x92, 0xA8, 0x80, 0x1A, 0x98, 0x76, 0x11, 0x9F, 0x69, 0x38, 0xA3, 0x86, 0x10, 0xFF, 0x85,
+ 0x0C, 0xE5, 0x27, 0x5C, 0x3C, 0x1E, 0x35, 0x24, 0x84, 0xC4, 0xE1, 0x0D, 0xA8, 0xA1, 0xB5, 0xAE, 0x95, 0x20, 0xFC, 0xDE,
+ 0x4F, 0x7F, 0x31, 0xB2, 0xEB, 0xE6, 0x0B, 0x7C, 0xE2, 0x13, 0xA4, 0xAC, 0x1B, 0x02, 0x35, 0x5A, 0xA8, 0xA3, 0xC8, 0x5E,
+ 0x4D, 0xF3, 0xC3, 0x23, 0xE0, 0xD8, 0xCD, 0xD7, 0xDD, 0xB2, 0x6D, 0xFD, 0xF6, 0xE1, 0xC1, 0xE1, 0x15, 0xFD, 0xCB, 0x69,
+ 0x81, 0xB0, 0x47, 0x0A, 0x11, 0x93, 0xDA, 0x8A, 0xE8, 0xAB, 0x5A, 0x78, 0xC3, 0xBD, 0xCD, 0x8B, 0x06, 0x5B, 0xFB, 0x06,
+ 0xDB, 0xFB, 0xDA, 0xEB, 0x9A, 0x77, 0x6F, 0xDD, 0xCD, 0xF3, 0x7B, 0x5B, 0xBA, 0xD9, 0xC3, 0x43, 0xFC, 0xE7, 0x56, 0x3B,
+ 0x25, 0x92, 0x59, 0x49, 0xE6, 0x5A, 0x4A, 0x06, 0x25, 0x6A, 0xA0, 0xAC, 0x23, 0x6D, 0x95, 0x89, 0xBF, 0x43, 0x84, 0x11,
+ 0xD1, 0xA7, 0x3A, 0x56, 0x4F, 0x7B, 0x8A, 0x2E, 0xA1, 0x7E, 0x40, 0x32, 0x40, 0xF7, 0xC2, 0x31, 0x7F, 0x05, 0x22, 0x5D,
+ 0x3E, 0x8E, 0xC4, 0x19, 0x6D, 0x8F, 0x9E, 0x6E, 0xEB, 0x5D, 0x2F, 0xF9, 0x00, 0xFD, 0xF3, 0xEF, 0x65, 0x0B, 0x15, 0xF8,
+ 0xCE, 0xDE, 0x92, 0x7C, 0x09, 0x5F, 0x8A, 0x45, 0x14, 0xAE, 0x92, 0x78, 0x94, 0xD7, 0x77, 0xD6, 0xB5, 0xE1, 0xF2, 0x7C,
+ 0x48, 0x3E, 0x00, 0x29, 0x3C, 0x85, 0x15, 0x1F, 0x92, 0xFE, 0x81, 0xC4, 0x0C, 0xE3, 0xCE, 0xDA, 0x0F, 0x00, 0x8E, 0x58,
+ 0x9A, 0xB7, 0xF1, 0xE6, 0x78, 0x1F, 0x66, 0x2E, 0x86, 0x2B, 0x24, 0x32, 0x00, 0x88, 0x0D, 0x8B, 0x63, 0x2A, 0x10, 0xB4,
+ 0xC0, 0x7F, 0xFE, 0xAC, 0xD9, 0x17, 0x5E, 0x78, 0x21, 0x6A, 0xC8, 0x8C, 0x4F, 0x27, 0x44, 0x1F, 0xDA, 0x7F, 0x65, 0x67,
+ 0x53, 0xD7, 0x9A, 0x65, 0x6B, 0xBF, 0xF7, 0xFA, 0x9B, 0x8A, 0x3C, 0xBA, 0x0F, 0x90, 0x65, 0xF0, 0x47, 0x9C, 0x80, 0xB8,
+ 0xFD, 0xD1, 0xBF, 0xFF, 0xF3, 0xCF, 0x7F, 0x7E, 0xF4, 0xCF, 0x7F, 0xFE, 0x93, 0x12, 0x8F, 0x5F, 0x69, 0xFC, 0x20, 0xCD,
+ 0x3D, 0xB8, 0xE7, 0xF0, 0xFA, 0x55, 0x1B, 0x70, 0x26, 0x34, 0xB1, 0xB4, 0x6B, 0xF1, 0x50, 0x5B, 0x7F, 0x5F, 0x4B, 0x37,
+ 0x05, 0xC7, 0x40, 0x5B, 0xEF, 0xE0, 0xA2, 0x21, 0x36, 0x8C, 0xAC, 0xEE, 0x5F, 0x31, 0xD8, 0xD1, 0xBF, 0x77, 0xFB, 0x5E,
+ 0x12, 0x2A, 0xFE, 0xE4, 0xBE, 0x3B, 0xEF, 0xE7, 0x23, 0x2C, 0xED, 0x5E, 0xBC, 0x64, 0xD1, 0x62, 0x9E, 0x46, 0x4E, 0x6C,
+ 0xF6, 0xF3, 0xD0, 0xC1, 0xAD, 0xE7, 0xB3, 0x88, 0x32, 0xB2, 0x44, 0x07, 0x04, 0x67, 0xFA, 0xB8, 0x2C, 0x87, 0x89, 0x44,
+ 0x10, 0x4E, 0xCC, 0xC9, 0x4C, 0x84, 0x8B, 0xE6, 0x28, 0xC3, 0x8B, 0xFE, 0x5E, 0xD1, 0x8F, 0xE8, 0x40, 0x73, 0x47, 0x2B,
+ 0x6E, 0x2F, 0x81, 0x92, 0x6B, 0xFB, 0xB8, 0x4E, 0xC0, 0x35, 0x97, 0x90, 0xC7, 0xF3, 0x49, 0xE3, 0xCA, 0xA4, 0x7D, 0x96,
+ 0x59, 0xCC, 0x76, 0x67, 0x2E, 0xD8, 0x28, 0xC9, 0x07, 0x83, 0x6E, 0x4E, 0xDB, 0x15, 0xD1, 0x0F, 0x75, 0xF4, 0xF3, 0x08,
+ 0xED, 0x36, 0x4C, 0x0C, 0x74, 0xC2, 0x57, 0x04, 0x94, 0x72, 0xD8, 0x09, 0x24, 0x09, 0x12, 0xDE, 0x20, 0x9D, 0x83, 0xD4,
+ 0x3C, 0xA2, 0x82, 0x62, 0x25, 0xED, 0x23, 0x02, 0x03, 0x3A, 0x80, 0xE5, 0x99, 0x18, 0x9E, 0x10, 0x43, 0xD1, 0x10, 0x14,
+ 0x19, 0x38, 0x7F, 0xFE, 0x3C, 0xDF, 0xD9, 0xE7, 0x9E, 0x37, 0x8E, 0xE3, 0x59, 0x40, 0xBC, 0xEB, 0x8F, 0xDF, 0x4E, 0xE9,
+ 0xD0, 0xD5, 0xDC, 0x45, 0x3E, 0xCA, 0x26, 0x83, 0xDF, 0xFF, 0xFE, 0x8F, 0x9F, 0x7C, 0x22, 0x22, 0x26, 0xFF, 0x31, 0x3B,
+ 0x93, 0x3F, 0x61, 0x47, 0x14, 0x60, 0xF5, 0xE1, 0x6F, 0xFE, 0xC0, 0xFA, 0xC3, 0x6F, 0xFF, 0xFC, 0xB7, 0xBF, 0xFD, 0x43,
+ 0x53, 0x29, 0x75, 0x07, 0xB6, 0xF0, 0xEF, 0xDA, 0xB6, 0x7B, 0xE3, 0xF0, 0xFA, 0x4D, 0x2B, 0x36, 0xAC, 0x59, 0xB6, 0x66,
+ 0xF5, 0x00, 0x9B, 0x67, 0x97, 0x73, 0xE6, 0xC2, 0xAA, 0xC1, 0x15, 0xE8, 0x95, 0x7D, 0xFD, 0x64, 0xB7, 0x6C, 0xF0, 0xFF,
+ 0xE0, 0x03, 0x02, 0xFB, 0xA7, 0xFF, 0xFD, 0xEF, 0x7F, 0xFE, 0xFC, 0xE7, 0x3F, 0x6F, 0x5E, 0xB3, 0x99, 0xDF, 0xAE, 0x5C,
+ 0xBC, 0x92, 0xB6, 0x07, 0xB5, 0x61, 0x4F, 0x73, 0x37, 0xFE, 0x2D, 0x25, 0xBA, 0xEE, 0xCD, 0x22, 0x9D, 0x11, 0x09, 0x94,
+ 0x12, 0x18, 0xF2, 0x52, 0x72, 0xA0, 0xCF, 0xD0, 0xC7, 0x4D, 0x8B, 0x4D, 0x72, 0xA5, 0x3F, 0x82, 0xF8, 0xA7, 0x14, 0xBD,
+ 0xB1, 0x3C, 0xE1, 0x52, 0xFA, 0xA8, 0x64, 0xBD, 0x74, 0x49, 0x91, 0x7B, 0xB6, 0x24, 0xD1, 0x36, 0x23, 0xD6, 0x0B, 0x5B,
+ 0x34, 0xA2, 0x7C, 0xD3, 0xF9, 0x29, 0x64, 0xEA, 0x42, 0x37, 0xA6, 0xBE, 0xBC, 0xE9, 0xA5, 0x6F, 0xBC, 0xCC, 0x89, 0x11,
+ 0x7F, 0xFB, 0xDB, 0x5F, 0x7E, 0xF5, 0xC1, 0x87, 0x8F, 0x3D, 0xF8, 0x38, 0xF9, 0x38, 0xEF, 0xB2, 0xAF, 0x49, 0xDA, 0x6D,
+ 0xD2, 0xF5, 0x04, 0x7F, 0xAB, 0xD8, 0xD3, 0x51, 0x0F, 0x76, 0x91, 0x86, 0x4B, 0xF5, 0x9F, 0x6E, 0x48, 0x54, 0xB0, 0x7D,
+ 0x4C, 0x1E, 0xAD, 0x6A, 0xE0, 0x33, 0x98, 0xC0, 0x90, 0xC2, 0xD8, 0x8B, 0x8E, 0x34, 0x4C, 0xBA, 0x88, 0xA0, 0xB0, 0x85,
+ 0x0B, 0xFC, 0xE6, 0xCC, 0x9C, 0x71, 0xD6, 0x99, 0xA7, 0x53, 0x37, 0xAC, 0x59, 0xBA, 0x1E, 0x6F, 0x60, 0xEF, 0x0D, 0x71,
+ 0x95, 0x2D, 0xCA, 0xB7, 0xDC, 0x78, 0xC7, 0x0B, 0xCF, 0xBD, 0xFC, 0x83, 0xB7, 0xDF, 0x79, 0xEF, 0xDD, 0xF7, 0x7F, 0xFA,
+ 0x93, 0x5F, 0xBC, 0xFD, 0xE6, 0x8F, 0x19, 0x07, 0xBD, 0xF1, 0xDD, 0xB7, 0xDF, 0xFA, 0xFE, 0x8F, 0x7F, 0xF8, 0x83, 0x9F,
+ 0xFC, 0xF4, 0x27, 0x3F, 0xFF, 0xD5, 0x2F, 0x7F, 0x83, 0x1A, 0x34, 0x47, 0xB2, 0xFB, 0x35, 0x77, 0x6D, 0xDB, 0xB3, 0x61,
+ 0xE5, 0x86, 0x6D, 0xEB, 0xB7, 0x6D, 0x59, 0xBB, 0x45, 0x0E, 0x18, 0x59, 0xBB, 0x85, 0x92, 0x62, 0xC7, 0xA6, 0x1D, 0xBB,
+ 0xB7, 0xED, 0xDC, 0xBC, 0x72, 0xE3, 0x8B, 0xCF, 0xBD, 0xA4, 0xCE, 0xF4, 0xDF, 0x4F, 0xA5, 0x4A, 0x7F, 0xEA, 0xD1, 0xA7,
+ 0x51, 0xCF, 0xF6, 0xB5, 0x5B, 0xD7, 0xAF, 0x58, 0x2F, 0x9A, 0xE0, 0xE4, 0x85, 0x36, 0x8E, 0x6C, 0x58, 0xD4, 0x56, 0x6F,
+ 0x34, 0x41, 0xA3, 0x8C, 0x62, 0x28, 0xAB, 0x3C, 0x2B, 0x36, 0x3D, 0x3E, 0x28, 0x26, 0x35, 0x3A, 0xB9, 0xA2, 0xB8, 0x12,
+ 0x7A, 0x36, 0x33, 0x54, 0xC0, 0x67, 0xB4, 0xDC, 0x45, 0xD6, 0x5F, 0xB6, 0xC6, 0xEA, 0xC0, 0xCA, 0x7D, 0x24, 0x17, 0x76,
+ 0x8B, 0x49, 0xE5, 0x77, 0x48, 0x20, 0x32, 0xBD, 0xCF, 0xD4, 0xA8, 0x24, 0xBA, 0x17, 0x78, 0x03, 0x01, 0xE0, 0xEF, 0x7F,
+ 0xFF, 0x27, 0x9F, 0xF3, 0x5F, 0xFF, 0xFC, 0x3B, 0xE6, 0xC3, 0x5B, 0x07, 0x07, 0x1E, 0xBA, 0xF7, 0x61, 0x52, 0x72, 0x69,
+ 0x7C, 0x0A, 0x28, 0x71, 0x54, 0x01, 0x9B, 0xB3, 0x19, 0x04, 0x49, 0x54, 0x00, 0x49, 0xA5, 0x5F, 0x46, 0xDD, 0x6F, 0x86,
+ 0xDA, 0x9E, 0xF4, 0x39, 0x33, 0x2D, 0x21, 0x25, 0x25, 0x2E, 0x09, 0x50, 0xC2, 0x1B, 0x48, 0x93, 0xA2, 0xC9, 0x56, 0x03,
+ 0x43, 0x19, 0xD0, 0x4F, 0x9F, 0x72, 0x29, 0x87, 0x02, 0xB1, 0x03, 0xE7, 0xD8, 0x15, 0x37, 0x6F, 0x5C, 0xB7, 0x03, 0x63,
+ 0x6C, 0x6F, 0xE0, 0x8C, 0x99, 0xE5, 0x6C, 0x21, 0xBE, 0xF6, 0xE8, 0x0D, 0xF7, 0xDD, 0xF3, 0xE0, 0x83, 0xF7, 0x3D, 0x7A,
+ 0xFF, 0x3D, 0x0F, 0xB3, 0x73, 0xFF, 0xEB, 0x4F, 0x3D, 0xFF, 0xEC, 0xD3, 0x2F, 0xB0, 0x5E, 0x7D, 0xE9, 0xDB, 0xE8, 0x03,
+ 0x35, 0xE0, 0x1F, 0x72, 0x7C, 0x90, 0xD9, 0x44, 0x4E, 0x2A, 0xF5, 0xE1, 0x6F, 0x7E, 0x77, 0xF4, 0xE0, 0x95, 0x1C, 0xB1,
+ 0xB3, 0x6B, 0xCB, 0xAE, 0xFD, 0x3B, 0x77, 0x1F, 0xD8, 0xB5, 0xE7, 0xE0, 0xAE, 0x43, 0x07, 0x76, 0x1E, 0xD8, 0xB1, 0x79,
+ 0xFB, 0xA3, 0x0F, 0x3F, 0x61, 0xE3, 0x8A, 0x22, 0xD8, 0xBF, 0xFE, 0xFD, 0xD1, 0xB5, 0x57, 0x5C, 0x7B, 0xD9, 0x3A, 0x72,
+ 0xDF, 0xDD, 0xA8, 0x6D, 0xC3, 0xF2, 0x75, 0xB8, 0xC5, 0x50, 0xEF, 0xE2, 0xDE, 0xF6, 0x5E, 0x82, 0x04, 0x6A, 0x28, 0x4A,
+ 0xCD, 0x67, 0x10, 0x42, 0x55, 0x3F, 0xD4, 0xB9, 0x18, 0xD1, 0xB1, 0x65, 0x81, 0xE9, 0x69, 0x54, 0x70, 0x14, 0xF6, 0xA4,
+ 0x3A, 0x30, 0x96, 0x2E, 0x0A, 0xC0, 0xCB, 0xF5, 0x62, 0xCC, 0xE2, 0x71, 0x47, 0x07, 0x63, 0x4C, 0x5E, 0xEF, 0x8E, 0x74,
+ 0xD2, 0x73, 0xA4, 0xD7, 0x46, 0x12, 0xC6, 0x16, 0x09, 0xAD, 0x4A, 0x90, 0x1D, 0x83, 0x2A, 0x76, 0x12, 0xEA, 0x46, 0x49,
+ 0xAC, 0xF2, 0x5D, 0x13, 0x2A, 0x39, 0xB9, 0x80, 0x5D, 0xED, 0x06, 0x88, 0xBF, 0xF8, 0xE0, 0x83, 0x0F, 0x76, 0x6C, 0xD9,
+ 0x45, 0xD1, 0xC7, 0x68, 0x8C, 0xDC, 0x9C, 0xC4, 0x49, 0xE8, 0x8B, 0xF9, 0x95, 0xF8, 0x93, 0xB4, 0x68, 0xB2, 0x84, 0x46,
+ 0x68, 0x5B, 0x2B, 0x9A, 0x23, 0x69, 0xE5, 0x9C, 0x12, 0x93, 0x9E, 0x14, 0x93, 0x00, 0x2E, 0x25, 0x86, 0xC7, 0x47, 0x87,
+ 0xC4, 0x30, 0xB5, 0x0F, 0x9A, 0xED, 0xC7, 0xE0, 0x7E, 0xEA, 0x84, 0xA9, 0xBB, 0xB6, 0x1E, 0xDA, 0x75, 0xD9, 0x21, 0xC6,
+ 0x96, 0xE4, 0x2A, 0xCC, 0xD7, 0x68, 0x5A, 0x70, 0x3E, 0x0B, 0x00, 0xB2, 0x6D, 0xE3, 0xF6, 0xBD, 0xDB, 0xF7, 0x5D, 0xBE,
+ 0xF7, 0xCA, 0x5B, 0x6F, 0xBA, 0x93, 0x4D, 0xCB, 0x40, 0xF9, 0x3D, 0x77, 0x3F, 0x4C, 0x6F, 0xE3, 0xED, 0x1F, 0xBC, 0xF3,
+ 0xBB, 0xDF, 0xFE, 0x1F, 0x4D, 0xA2, 0x4C, 0xEC, 0x10, 0xC9, 0xFE, 0xE3, 0x5F, 0xFF, 0x7C, 0xFC, 0xD1, 0xA7, 0xA8, 0xDD,
+ 0x76, 0x6E, 0xDE, 0x09, 0x3A, 0xED, 0xBB, 0x6C, 0x1F, 0x67, 0x2B, 0xBC, 0xF2, 0xD2, 0xAB, 0x94, 0xE2, 0x60, 0x96, 0x86,
+ 0x71, 0x7D, 0x3E, 0xB7, 0x20, 0xDE, 0xF1, 0x2B, 0xAF, 0xDD, 0xB9, 0xE5, 0x32, 0x74, 0x46, 0x54, 0xA7, 0xDC, 0x23, 0x9C,
+ 0xE0, 0x0D, 0xF5, 0x25, 0x35, 0xE0, 0x01, 0x9A, 0xB8, 0xF1, 0xF8, 0xCD, 0xBF, 0xFB, 0xFD, 0x1F, 0x69, 0x11, 0x62, 0x22,
+ 0xE4, 0xEB, 0xA4, 0x76, 0x8C, 0xED, 0x8C, 0xC4, 0x47, 0xC4, 0xCD, 0x87, 0x62, 0x9D, 0x2C, 0x7D, 0x9E, 0x76, 0x0A, 0x1D,
+ 0xD8, 0x4E, 0x16, 0xBD, 0x5C, 0x77, 0x9C, 0x24, 0x35, 0xA1, 0x36, 0xCA, 0x45, 0x64, 0xCA, 0xF8, 0x4C, 0xC8, 0x5E, 0x30,
+ 0x7B, 0x7E, 0x4B, 0x23, 0x87, 0x4E, 0xAD, 0xA4, 0xEE, 0x4D, 0x0A, 0x8F, 0x27, 0x32, 0xDF, 0x71, 0xD3, 0x3D, 0x7F, 0xFE,
+ 0xB3, 0x6E, 0x15, 0xFE, 0xEC, 0x3F, 0xFF, 0xF9, 0xB7, 0xB1, 0xA9, 0x13, 0x94, 0x48, 0x75, 0x95, 0x0D, 0x18, 0x3E, 0x11,
+ 0x9B, 0x52, 0x4E, 0x0A, 0x72, 0xE9, 0xBA, 0xB8, 0x69, 0x75, 0xAA, 0x44, 0x66, 0xEB, 0x0D, 0x44, 0x33, 0x36, 0xC8, 0xAB,
+ 0xF9, 0x08, 0x83, 0x28, 0x2A, 0x51, 0xD2, 0xA4, 0xB0, 0xF0, 0x30, 0xBF, 0x85, 0xD3, 0x26, 0x4F, 0xB9, 0x68, 0xDC, 0xC5,
+ 0x1B, 0xD7, 0xEF, 0xDC, 0xB1, 0xF5, 0x10, 0x84, 0x4C, 0x3E, 0x3F, 0x69, 0x31, 0x31, 0xB3, 0xA9, 0xB2, 0x8E, 0x70, 0xBA,
+ 0x69, 0xC5, 0x66, 0x4E, 0x08, 0xE1, 0x7C, 0x8F, 0xCD, 0xAB, 0xB7, 0xED, 0xDB, 0x79, 0xE0, 0x9A, 0x2B, 0xAE, 0x45, 0x19,
+ 0x0F, 0xDD, 0xFF, 0x04, 0xEB, 0x7B, 0x6F, 0xFC, 0xE0, 0x8F, 0x7F, 0xF8, 0x8B, 0xD9, 0x39, 0xEB, 0x64, 0x4A, 0x2A, 0xDC,
+ 0x3F, 0xFD, 0xE9, 0x4F, 0xDF, 0x7B, 0xE3, 0x6D, 0x4A, 0xEE, 0x37, 0xDF, 0x7C, 0xEB, 0x2F, 0x7F, 0xF9, 0x8B, 0xCD, 0xB5,
+ 0xAC, 0x0E, 0x34, 0xC5, 0x12, 0x9D, 0xFD, 0xE3, 0x1F, 0x4F, 0x3F, 0xF9, 0xEC, 0xD1, 0xFD, 0x47, 0xB7, 0xAC, 0xDD, 0x2A,
+ 0x67, 0x60, 0x0C, 0x2C, 0xE7, 0x7F, 0x1D, 0xDE, 0x77, 0x84, 0xFE, 0x2E, 0x1E, 0xCF, 0x13, 0x5E, 0xFF, 0xD6, 0x77, 0xD9,
+ 0x39, 0xAB, 0xF4, 0x56, 0xC0, 0x33, 0x29, 0x36, 0x11, 0xFA, 0x37, 0xC2, 0x85, 0x75, 0xC0, 0x6D, 0x7A, 0x2C, 0xB7, 0xE2,
+ 0x07, 0x5F, 0xB6, 0x1C, 0x3F, 0x38, 0x25, 0x8B, 0xC6, 0xA1, 0x22, 0x19, 0x96, 0xA7, 0x2D, 0x43, 0x14, 0xBE, 0xE9, 0xFE,
+ 0xCF, 0x9E, 0x36, 0x0D, 0xCE, 0xE1, 0xB6, 0xCD, 0x7B, 0xD7, 0xAE, 0xDA, 0xDA, 0xDB, 0xB1, 0x98, 0x94, 0x89, 0xEC, 0x05,
+ 0x88, 0xB8, 0xFD, 0xD6, 0xBB, 0x68, 0x99, 0xA9, 0x29, 0x99, 0x1D, 0xDB, 0x9F, 0x53, 0xBE, 0xAE, 0x5B, 0xB9, 0x3E, 0x2D,
+ 0x2A, 0x85, 0x6C, 0x5A, 0x72, 0x09, 0x13, 0x0C, 0x64, 0xB0, 0x6E, 0x62, 0xB2, 0x6D, 0xF6, 0x42, 0x34, 0xE7, 0x11, 0x61,
+ 0x62, 0x39, 0x51, 0x3A, 0x0D, 0x68, 0x02, 0x64, 0x13, 0xC2, 0xE2, 0x19, 0x0F, 0xCC, 0x9F, 0x36, 0x77, 0xE6, 0xE4, 0x99,
+ 0x97, 0x6D, 0x39, 0xB8, 0x74, 0x70, 0x1D, 0xE9, 0x60, 0x46, 0x5C, 0x3A, 0x1E, 0x46, 0x29, 0x8E, 0x7B, 0x41, 0xBD, 0x5E,
+ 0xD2, 0xB9, 0x84, 0xB0, 0xC9, 0x81, 0x5E, 0x1B, 0x97, 0x6D, 0xDC, 0xB6, 0x61, 0x37, 0xA3, 0xE9, 0x23, 0xFB, 0x8F, 0xDE,
+ 0x76, 0xE3, 0x1D, 0x0F, 0x3F, 0xF0, 0xE4, 0xE3, 0x8F, 0x3C, 0xFD, 0x9D, 0x6F, 0x7F, 0xFF, 0x2F, 0x7F, 0xFE, 0x87, 0x1A,
+ 0x87, 0x00, 0x92, 0x04, 0xF2, 0x4F, 0x1D, 0x6B, 0x77, 0xAB, 0x09, 0x9B, 0xDA, 0x7A, 0xFD, 0xC0, 0x20, 0x18, 0x55, 0xB7,
+ 0x3C, 0xF7, 0xA3, 0x8F, 0xFE, 0xF9, 0xFE, 0xFB, 0xBF, 0xFA, 0xF1, 0x0F, 0xDF, 0xF9, 0xD9, 0xCF, 0x7E, 0xF1, 0xF7, 0x8F,
+ 0x64, 0xD6, 0xA4, 0x8F, 0x43, 0x48, 0x88, 0x0F, 0x8E, 0xE5, 0x5C, 0x09, 0xDA, 0x79, 0x73, 0x2E, 0x9D, 0x9E, 0x18, 0x11,
+ 0x8B, 0xE9, 0x10, 0xD5, 0x44, 0x07, 0xB1, 0x29, 0x2C, 0x8F, 0xE8, 0x4F, 0xAD, 0x09, 0x9F, 0x31, 0xD2, 0xD7, 0x8E, 0xA0,
+ 0x6D, 0x0D, 0x2A, 0x70, 0x1B, 0xC4, 0x10, 0x56, 0x88, 0x66, 0x93, 0x88, 0x1E, 0xFA, 0x54, 0xC0, 0xFC, 0x79, 0x34, 0x15,
+ 0xB0, 0x71, 0xBA, 0xF6, 0x3B, 0xB6, 0x1F, 0xDE, 0xB7, 0xE3, 0xC8, 0x9A, 0xE5, 0x1B, 0xEA, 0x2B, 0x1A, 0xA8, 0x59, 0x68,
+ 0x54, 0x90, 0xE1, 0x11, 0x21, 0x0D, 0x16, 0x1B, 0x65, 0x7C, 0xF1, 0x39, 0xBD, 0x04, 0x68, 0x10, 0x29, 0xE1, 0x89, 0x05,
+ 0x09, 0xD9, 0xB4, 0xFB, 0x65, 0xAE, 0x9B, 0xA2, 0x8D, 0x2D, 0xB9, 0x16, 0xC6, 0x03, 0x19, 0x1E, 0xD3, 0xF6, 0xD4, 0x3C,
+ 0xDA, 0xF4, 0xE0, 0x2C, 0x8B, 0xF9, 0x3B, 0x0D, 0x3E, 0x22, 0x1E, 0xFA, 0x9B, 0x37, 0xD9, 0x97, 0x82, 0x76, 0xE7, 0x96,
+ 0x83, 0xE5, 0x39, 0x55, 0xE9, 0xD1, 0xA9, 0xD4, 0x6E, 0x3C, 0xC8, 0x89, 0x06, 0x38, 0x04, 0xE7, 0x17, 0x70, 0x18, 0x06,
+ 0x8C, 0x3F, 0xB6, 0x6A, 0xA1, 0x95, 0x8E, 0x86, 0x45, 0xC3, 0x03, 0xAB, 0xD6, 0x2C, 0xDD, 0xB8, 0x79, 0xC3, 0x8E, 0xAB,
+ 0x0F, 0x5F, 0xFF, 0xF0, 0x43, 0x4F, 0x3D, 0xF6, 0xE8, 0xD3, 0xAF, 0xBF, 0xFA, 0x06, 0xDB, 0xF9, 0x8D, 0xD4, 0x14, 0xF3,
+ 0xE9, 0x79, 0x48, 0xF9, 0x86, 0x95, 0xA8, 0xF4, 0x4F, 0xF9, 0xE3, 0x82, 0x92, 0xA6, 0xBF, 0xF6, 0xC7, 0x34, 0xA3, 0x3E,
+ 0x97, 0xFC, 0xF5, 0x81, 0xBB, 0x1F, 0x4C, 0x89, 0x4C, 0x04, 0x0F, 0x79, 0x0F, 0x53, 0x2F, 0x9A, 0x12, 0x11, 0x16, 0x4D,
+ 0x36, 0x41, 0xCD, 0x4F, 0x48, 0xA3, 0xEA, 0x64, 0xE1, 0xCD, 0xAA, 0x09, 0xB3, 0x4E, 0xE1, 0x0A, 0x3C, 0xEE, 0xE8, 0xC0,
+ 0x72, 0x34, 0xC6, 0xB0, 0x65, 0x64, 0x6A, 0x91, 0x3A, 0xC2, 0xC4, 0x37, 0x4D, 0x1E, 0xC9, 0xE5, 0x49, 0x5D, 0xD8, 0xA5,
+ 0x25, 0xFD, 0xB5, 0x71, 0xE7, 0xD2, 0x79, 0xA6, 0x5D, 0xBA, 0x7C, 0x70, 0xD5, 0xEE, 0x1D, 0x07, 0xAF, 0x38, 0x72, 0xDD,
+ 0xDE, 0xDD, 0x47, 0x07, 0xFB, 0x96, 0x92, 0x5C, 0x31, 0xE1, 0x22, 0x5C, 0xDF, 0x7C, 0xFC, 0x66, 0xAA, 0x2A, 0x45, 0xE4,
+ 0x37, 0xBE, 0xF7, 0x7D, 0x86, 0x97, 0x30, 0x21, 0x78, 0x73, 0x24, 0x70, 0x23, 0x0D, 0x45, 0x14, 0x9C, 0x21, 0x53, 0x46,
+ 0xE6, 0x59, 0x54, 0x21, 0xA4, 0xDE, 0x24, 0xE0, 0x14, 0x1F, 0xD2, 0x42, 0xCF, 0x2D, 0x2F, 0xCF, 0x29, 0xC9, 0x8C, 0x15,
+ 0x68, 0x62, 0x53, 0x78, 0x61, 0x7A, 0x11, 0x46, 0x97, 0x1A, 0x9E, 0x42, 0x1E, 0x92, 0x18, 0x9A, 0x58, 0x9C, 0x5E, 0x9A,
+ 0x12, 0x91, 0x92, 0x15, 0x9F, 0x0B, 0x11, 0x9F, 0x13, 0x8A, 0x84, 0x99, 0x50, 0x58, 0x0F, 0x4D, 0x86, 0xD3, 0x67, 0xD8,
+ 0x9C, 0xBC, 0x6A, 0xE9, 0xBA, 0x6D, 0x6B, 0xB6, 0x6F, 0x5D, 0xBF, 0xE3, 0xE8, 0xE1, 0xAB, 0xEE, 0xBD, 0xEB, 0x41, 0x92,
+ 0xA8, 0x5F, 0xBC, 0xFF, 0xE1, 0x7F, 0xFF, 0xEB, 0x14, 0xD8, 0x5A, 0x3A, 0x78, 0x45, 0xAF, 0xC8, 0xA3, 0x75, 0x86, 0x5E,
+ 0xD8, 0xDF, 0xDA, 0xA8, 0xCE, 0x23, 0x9F, 0x7C, 0x26, 0x9E, 0x81, 0x32, 0xEF, 0xBF, 0xE3, 0x7E, 0x62, 0xD8, 0xCE, 0x0D,
+ 0x3B, 0x1A, 0x6B, 0x9A, 0x2F, 0x19, 0x37, 0x21, 0x22, 0x28, 0x88, 0x94, 0x9A, 0xE1, 0x20, 0x7E, 0x60, 0xD4, 0x90, 0xA4,
+ 0xED, 0x48, 0x57, 0x19, 0x56, 0x13, 0x63, 0x2F, 0x7C, 0x4E, 0xA6, 0x45, 0x7A, 0xE9, 0x02, 0xC2, 0x73, 0x76, 0xB7, 0x42,
+ 0x68, 0x02, 0x63, 0xBA, 0x0B, 0xA9, 0xE4, 0x2D, 0x44, 0x7F, 0xFF, 0x79, 0xF3, 0xCF, 0x39, 0xE7, 0x1C, 0x0E, 0x66, 0x64,
+ 0x2F, 0xC6, 0xAC, 0x4B, 0xA7, 0x31, 0x5B, 0xA7, 0x64, 0x43, 0x19, 0x74, 0x78, 0x98, 0xC6, 0x6C, 0xD9, 0xB8, 0xBB, 0xA9,
+ 0xA6, 0x03, 0xE6, 0x04, 0x43, 0xCA, 0xAE, 0x96, 0x8E, 0xDB, 0xAF, 0xBD, 0xF5, 0x77, 0xBF, 0xFD, 0xD3, 0x6D, 0x37, 0xDF,
+ 0x87, 0xA5, 0x10, 0xB8, 0x28, 0x89, 0x51, 0x27, 0x7A, 0x82, 0x3C, 0x0A, 0x5F, 0x9A, 0xFF, 0xC2, 0x84, 0x84, 0x74, 0x9B,
+ 0xFC, 0x95, 0x17, 0xA1, 0x37, 0x40, 0x1E, 0x45, 0x0B, 0xA4, 0xB6, 0xA8, 0x8A, 0xF1, 0x4B, 0x56, 0x7C, 0x3A, 0x6A, 0xC6,
+ 0x7B, 0x32, 0xD8, 0x1C, 0x09, 0x43, 0x22, 0x26, 0x93, 0x44, 0x80, 0x6D, 0x7B, 0x40, 0x22, 0x64, 0x16, 0xCA, 0xC9, 0x9A,
+ 0xB2, 0xA6, 0xFA, 0xF2, 0xB6, 0xAA, 0xA2, 0xC6, 0xA2, 0x4C, 0xFA, 0xBE, 0xB5, 0x15, 0xB9, 0xB5, 0x1C, 0x35, 0x30, 0xD8,
+ 0xCD, 0x01, 0x87, 0x43, 0xAB, 0x87, 0xD6, 0xB0, 0x6D, 0xF6, 0xD0, 0x9E, 0xA3, 0xD7, 0x5E, 0x7D, 0xE3, 0x03, 0xF7, 0x3E,
+ 0x06, 0x87, 0x83, 0x2E, 0x13, 0x27, 0x4F, 0x69, 0xB6, 0xEA, 0x5A, 0xBA, 0x24, 0xAF, 0x9C, 0xD2, 0x42, 0x18, 0xFB, 0x1F,
+ 0xB6, 0xFA, 0xFF, 0xE7, 0x33, 0xD2, 0x53, 0x3D, 0x92, 0x67, 0x0C, 0x64, 0xA9, 0x86, 0x78, 0xE6, 0xDD, 0xB7, 0xDD, 0x45,
+ 0xEB, 0x65, 0xCB, 0xBA, 0xCB, 0xD6, 0x2F, 0x59, 0x3F, 0xF9, 0xBC, 0xF1, 0xA1, 0xF3, 0x64, 0xDF, 0x03, 0xB3, 0x90, 0x84,
+ 0xE8, 0x78, 0x3E, 0x9A, 0x24, 0x14, 0x31, 0x8E, 0x1A, 0x54, 0x07, 0xA0, 0x93, 0xC7, 0x21, 0x46, 0x5D, 0x3B, 0x3A, 0xF0,
+ 0xCA, 0x5D, 0xD1, 0xDF, 0xE1, 0x2A, 0x01, 0xD9, 0xEE, 0x54, 0xC8, 0x56, 0xDB, 0xBC, 0x16, 0xFF, 0x83, 0x6E, 0x33, 0x6D,
+ 0x4E, 0xC8, 0x9D, 0x17, 0x5C, 0x70, 0xC1, 0xE9, 0x67, 0x72, 0x26, 0xA5, 0xFC, 0x70, 0xCE, 0xE5, 0x05, 0xE7, 0x8E, 0x9B,
+ 0x37, 0x75, 0x0E, 0x41, 0x95, 0x3D, 0xC3, 0x3B, 0x36, 0xEF, 0xDB, 0xBD, 0xE3, 0xF0, 0x60, 0xFF, 0xEA, 0xCC, 0xC4, 0x1C,
+ 0xBF, 0x69, 0xF3, 0xC3, 0x16, 0x84, 0xD2, 0x22, 0xA6, 0x15, 0x01, 0x33, 0x85, 0x77, 0x9C, 0x1C, 0x97, 0xA2, 0x8D, 0x43,
+ 0xD4, 0xC0, 0x14, 0x2C, 0x27, 0x3E, 0x53, 0x02, 0x72, 0x74, 0x2A, 0x65, 0x07, 0x05, 0x84, 0x54, 0x7F, 0x79, 0x15, 0xA8,
+ 0x01, 0x6A, 0xC5, 0x65, 0x1B, 0x77, 0xDC, 0x72, 0xED, 0xAD, 0xE0, 0x3B, 0xD9, 0x7D, 0x4F, 0x63, 0x0F, 0xC7, 0x77, 0x70,
+ 0xAC, 0x47, 0x6A, 0x74, 0x5A, 0x42, 0x74, 0x12, 0xEF, 0x84, 0xBD, 0x37, 0x4C, 0x57, 0x8A, 0x0B, 0xCA, 0xD3, 0xE2, 0xB2,
+ 0xB3, 0xE2, 0xF3, 0x7B, 0x3B, 0x96, 0xB2, 0x45, 0xB0, 0xA6, 0x84, 0x53, 0x80, 0x96, 0x41, 0x88, 0xE7, 0x0C, 0x42, 0x8E,
+ 0x18, 0xDC, 0xB2, 0x6A, 0x2B, 0x99, 0xFE, 0xEE, 0x9D, 0xFB, 0x8E, 0x5D, 0x71, 0xD5, 0x9D, 0xB7, 0xDD, 0x4B, 0xF2, 0x4A,
+ 0xAC, 0x7E, 0xE7, 0xC7, 0x3F, 0x23, 0x9D, 0xA3, 0xBC, 0xE0, 0x74, 0x9C, 0x77, 0xDF, 0xF9, 0x05, 0xEB, 0x27, 0xEF, 0xFC,
+ 0xEC, 0xED, 0xB7, 0xDE, 0x31, 0x8F, 0xBF, 0x4F, 0xB3, 0x8F, 0xEA, 0xFA, 0x5F, 0xFF, 0xFA, 0xB7, 0x56, 0x82, 0xC6, 0x41,
+ 0xBE, 0xA0, 0x6F, 0xFB, 0xDB, 0x0F, 0xFF, 0x70, 0xDB, 0x8D, 0xB7, 0x93, 0x62, 0x0C, 0x75, 0x0F, 0x5D, 0x71, 0xF8, 0x86,
+ 0xD0, 0xB9, 0xC1, 0xF3, 0x2E, 0x9D, 0x1D, 0x11, 0x14, 0x12, 0x1D, 0x1A, 0x8E, 0x6D, 0xE1, 0x07, 0x9C, 0x72, 0xC1, 0xF6,
+ 0x08, 0x29, 0x36, 0x8D, 0x43, 0xB8, 0x3A, 0x38, 0xB5, 0x1A, 0xF8, 0xAD, 0xE8, 0xE0, 0xCB, 0xB8, 0x79, 0xAA, 0x0C, 0x8D,
+ 0x99, 0xDA, 0x54, 0x30, 0x6A, 0x20, 0x7D, 0x94, 0x6E, 0x33, 0x19, 0x58, 0x74, 0x50, 0x38, 0xFC, 0x11, 0x08, 0xFE, 0x53,
+ 0x2F, 0x99, 0x74, 0xE1, 0xF9, 0x17, 0x7C, 0xED, 0x6B, 0x5F, 0x63, 0x37, 0x80, 0x3D, 0x9D, 0xF4, 0x8C, 0xD3, 0xCE, 0xBE,
+ 0x74, 0xC2, 0x64, 0x32, 0x84, 0xBE, 0xF6, 0xC1, 0xED, 0x1B, 0xF7, 0xAC, 0x5E, 0xB9, 0x8D, 0x8D, 0x92, 0x64, 0xB4, 0x91,
+ 0x61, 0xB1, 0x6D, 0x0D, 0x5D, 0x6C, 0xEA, 0x8B, 0x0F, 0xE7, 0xFD, 0xA5, 0xA0, 0x2D, 0x3C, 0x23, 0x2D, 0x3A, 0x19, 0xC0,
+ 0xC1, 0xF6, 0x8F, 0xEC, 0xBB, 0xF2, 0x91, 0xFB, 0x1F, 0xFD, 0xE6, 0xB3, 0x2F, 0x40, 0x72, 0x79, 0xEB, 0xAD, 0x1F, 0xFC,
+ 0xFA, 0xD7, 0xBF, 0xA6, 0xF7, 0xA0, 0xE6, 0x48, 0xDB, 0x87, 0x0A, 0x80, 0xE3, 0x1C, 0x81, 0xA9, 0xA2, 0xB4, 0x12, 0x8C,
+ 0x80, 0xB0, 0xC4, 0xDB, 0x60, 0x14, 0x91, 0x12, 0x97, 0x91, 0x1A, 0x9F, 0x99, 0x40, 0x00, 0x8C, 0xCD, 0xC8, 0x4F, 0x29,
+ 0xAD, 0x2B, 0x6B, 0xED, 0x6C, 0x1D, 0x6A, 0xAD, 0xEF, 0xC1, 0x11, 0xE5, 0x78, 0xB7, 0xD6, 0x01, 0x0E, 0x55, 0xE3, 0x70,
+ 0x0B, 0x80, 0x9B, 0xBA, 0x6C, 0xFF, 0xAE, 0x83, 0x87, 0xF6, 0x1E, 0x39, 0x76, 0xE8, 0x2A, 0xB2, 0x58, 0x0A, 0x3D, 0x60,
+ 0xEA, 0x81, 0x7B, 0x1F, 0xB9, 0xEF, 0xEE, 0x87, 0xEE, 0xB9, 0xFD, 0xBE, 0x07, 0xEF, 0x79, 0x98, 0xBB, 0x4F, 0x3D, 0xF9,
+ 0xFC, 0x37, 0x5F, 0x78, 0x95, 0xF9, 0xCF, 0x8B, 0xDF, 0x7C, 0x95, 0x21, 0xD2, 0x0F, 0x7E, 0xF8, 0xD3, 0xF7, 0xDE, 0xFD,
+ 0xE5, 0x7B, 0x3F, 0xFB, 0xE5, 0x4F, 0x7F, 0xFC, 0xF3, 0x17, 0xBF, 0xF9, 0xAD, 0x6B, 0xAF, 0xBC, 0x91, 0x7E, 0x0C, 0x2D,
+ 0xB2, 0x03, 0x7B, 0x8F, 0xA2, 0x60, 0x50, 0x28, 0x74, 0x41, 0x20, 0x26, 0x15, 0x1F, 0x16, 0x1D, 0x13, 0x1A, 0xCB, 0x74,
+ 0x96, 0x3A, 0x1F, 0x1D, 0x8C, 0xB8, 0x42, 0x2C, 0x21, 0xDA, 0x09, 0x0F, 0x63, 0x2E, 0x54, 0x43, 0x3E, 0x1E, 0x05, 0xC8,
+ 0x64, 0x6E, 0x0C, 0x19, 0xCF, 0x4E, 0x47, 0x6D, 0x0F, 0x56, 0x2A, 0x72, 0x74, 0x10, 0x9B, 0x4C, 0x35, 0x88, 0x14, 0x28,
+ 0x65, 0x83, 0xFD, 0x69, 0x73, 0xCE, 0xA7, 0xB7, 0x33, 0xE3, 0xD2, 0xA9, 0x53, 0x26, 0x4F, 0x9A, 0x38, 0xE1, 0x62, 0x9A,
+ 0x3C, 0xE3, 0xC6, 0x8D, 0x83, 0x0E, 0x2D, 0xA7, 0xC3, 0x9E, 0x26, 0xCE, 0x31, 0x6B, 0xEA, 0x4C, 0x68, 0x9D, 0x4B, 0xFB,
+ 0x57, 0xB0, 0xB1, 0x7B, 0x71, 0xFF, 0x5A, 0x30, 0x84, 0xE7, 0xAB, 0x99, 0xE0, 0xBF, 0xB8, 0x2D, 0xCA, 0xA6, 0x3B, 0x86,
+ 0xD1, 0xD9, 0x7C, 0xC3, 0x8B, 0xCB, 0x92, 0x5F, 0x7D, 0xF1, 0xD9, 0xDF, 0xFF, 0xF6, 0x11, 0x49, 0x0E, 0x10, 0x4F, 0xDB,
+ 0xA3, 0x3C, 0xBB, 0x9C, 0xCA, 0x08, 0xF4, 0xE3, 0x45, 0x80, 0x32, 0x34, 0x4D, 0x0B, 0xAB, 0x30, 0xB3, 0xAC, 0xA4, 0xB0,
+ 0xA2, 0x20, 0xB7, 0xA2, 0xBA, 0xA4, 0x6D, 0xF3, 0xFA, 0x3D, 0x9C, 0xFE, 0x00, 0x8D, 0xB3, 0xA3, 0x65, 0x90, 0x19, 0x35,
+ 0x34, 0xC8, 0xA1, 0x9E, 0xE1, 0xB5, 0xC3, 0x9B, 0x09, 0x2A, 0xCC, 0x1B, 0x08, 0x12, 0x7B, 0xB7, 0x1D, 0x38, 0xB4, 0xE7,
+ 0x4A, 0x5A, 0x81, 0xD7, 0x1C, 0xBB, 0xF1, 0xFA, 0xE3, 0x37, 0xDF, 0x70, 0xFD, 0xED, 0x80, 0xD5, 0xF5, 0xC7, 0x6E, 0xB8,
+ 0xE1, 0xDA, 0xDB, 0x6E, 0xBE, 0xF9, 0xEE, 0xDB, 0x6F, 0xB9, 0xFB, 0x96, 0xEB, 0x6F, 0xBB, 0xEB, 0xD6, 0x7B, 0x50, 0xCC,
+ 0xC3, 0x0F, 0x3C, 0x7E, 0xDB, 0xCD, 0x77, 0xDD, 0x7B, 0xD7, 0xC3, 0xDC, 0xEE, 0xDF, 0x75, 0x60, 0xD5, 0xC0, 0x30, 0x50,
+ 0xC9, 0x21, 0x16, 0x57, 0x5E, 0x7E, 0x3D, 0x19, 0xDA, 0x94, 0xF3, 0x2F, 0x0E, 0x5D, 0x18, 0x12, 0x15, 0x1A, 0x89, 0x34,
+ 0xE8, 0x74, 0xA1, 0x03, 0xF2, 0x69, 0xAC, 0x8A, 0x37, 0x96, 0x12, 0x65, 0xE3, 0x81, 0x34, 0x86, 0x4F, 0xB9, 0x90, 0x80,
+ 0xE8, 0xC0, 0xDA, 0xFB, 0xC9, 0xCC, 0x48, 0xEF, 0x58, 0x4E, 0xB1, 0x08, 0x1D, 0xB0, 0xA7, 0x25, 0x39, 0x31, 0x2D, 0x2E,
+ 0x46, 0x4A, 0x59, 0xA2, 0x50, 0x44, 0x48, 0x28, 0xA0, 0x44, 0x8B, 0x8D, 0x82, 0x16, 0xCE, 0xF3, 0xFC, 0x59, 0x73, 0xFD,
+ 0x66, 0xCE, 0x9E, 0x33, 0xDD, 0x77, 0xE6, 0xD4, 0x69, 0x6C, 0x0E, 0x98, 0x3C, 0x61, 0xE2, 0x79, 0x17, 0x9C, 0xCF, 0x69,
+ 0xBC, 0x20, 0xD5, 0xB8, 0x73, 0xCE, 0x9B, 0x76, 0xE9, 0xF4, 0x4B, 0x27, 0x4F, 0x99, 0x36, 0x69, 0x12, 0xC3, 0x4B, 0xDE,
+ 0x34, 0x6F, 0x74, 0xE1, 0xDC, 0x85, 0xA0, 0x39, 0x21, 0x97, 0x4D, 0xC5, 0x77, 0xDC, 0x7A, 0xCF, 0x2F, 0x7F, 0xF9, 0xC1,
+ 0xC9, 0x7D, 0x69, 0x14, 0x03, 0x4C, 0x93, 0xCE, 0xDF, 0x70, 0xF5, 0x2D, 0xEB, 0x96, 0x6C, 0x84, 0x79, 0x97, 0x93, 0x90,
+ 0x03, 0x93, 0x2E, 0x3E, 0x26, 0xB9, 0xA4, 0xB0, 0x86, 0x29, 0x7C, 0x5C, 0x64, 0x2C, 0x4E, 0x56, 0x9C, 0x2D, 0xE7, 0x08,
+ 0xF5, 0x2E, 0x5A, 0xCA, 0xB9, 0x49, 0x83, 0xBD, 0xAB, 0x16, 0x19, 0x57, 0xE0, 0x08, 0x31, 0x0E, 0xE4, 0xE0, 0x9C, 0x2C,
+ 0x36, 0x89, 0x2C, 0x5F, 0xBC, 0x61, 0xE5, 0x92, 0xF5, 0x6B, 0x57, 0x6F, 0xE3, 0x04, 0xDA, 0x65, 0x03, 0xAB, 0x57, 0x2C,
+ 0x5E, 0x43, 0xFF, 0x83, 0x53, 0x6A, 0x77, 0x6C, 0xDC, 0xBD, 0x73, 0xD3, 0xBE, 0xDD, 0xDB, 0xF7, 0x72, 0xEA, 0xD1, 0xC1,
+ 0xDD, 0x97, 0xD3, 0x95, 0xDA, 0xBA, 0x61, 0xFB, 0xDE, 0xCB, 0x0E, 0x62, 0xE9, 0xFB, 0xB6, 0x1F, 0x3C, 0x7C, 0xE0, 0xD8,
+ 0x15, 0x87, 0x8E, 0x5D, 0x71, 0xE4, 0xF8, 0x65, 0x9B, 0x76, 0xAF, 0x59, 0xBC, 0x8A, 0xD3, 0x90, 0x00, 0x49, 0x36, 0x72,
+ 0x1F, 0xD8, 0x77, 0x0D, 0x86, 0x38, 0x65, 0xFC, 0xC4, 0x88, 0xC0, 0x08, 0x00, 0x96, 0xE6, 0x0A, 0x4E, 0x89, 0x4C, 0x50,
+ 0x00, 0x23, 0x29, 0x5C, 0x41, 0x23, 0xB3, 0x0D, 0x0C, 0xA3, 0x71, 0x69, 0x44, 0x25, 0x3E, 0x9A, 0x74, 0x4A, 0xAA, 0x6E,
+ 0x08, 0x01, 0xF9, 0xD0, 0x31, 0xD9, 0x16, 0x9A, 0x31, 0x76, 0x34, 0xAA, 0x39, 0x8C, 0x36, 0xD7, 0xB4, 0xF2, 0x16, 0x57,
+ 0x88, 0x4C, 0xE0, 0xBF, 0xF2, 0xBF, 0xE9, 0xAF, 0x71, 0xDE, 0x0C, 0xBB, 0xB1, 0xD9, 0x18, 0x03, 0xE7, 0x19, 0xEA, 0x39,
+ 0x3B, 0xDC, 0x45, 0x25, 0xB3, 0xE7, 0x53, 0xCA, 0xC1, 0xC9, 0xA5, 0xF5, 0xE6, 0x3B, 0x7D, 0xC6, 0xB4, 0xA9, 0x53, 0xD0,
+ 0x0A, 0x44, 0x68, 0xC6, 0x96, 0xBC, 0x6F, 0x9C, 0x37, 0x21, 0x2A, 0x6A, 0xF6, 0x74, 0x5F, 0x32, 0xEB, 0x25, 0x7D, 0xAB,
+ 0xA3, 0x16, 0x46, 0x86, 0xCD, 0x0D, 0xA6, 0xCE, 0x80, 0xE0, 0xF5, 0xE4, 0x63, 0x5F, 0x7F, 0xEF, 0xBD, 0x9F, 0xFF, 0xE5,
+ 0x2F, 0x7F, 0xA3, 0x3E, 0xA2, 0x13, 0xF7, 0xFE, 0xCF, 0x3F, 0x00, 0xC1, 0x8F, 0x1D, 0x3E, 0xCE, 0x11, 0x2D, 0x14, 0x04,
+ 0x32, 0x13, 0x4E, 0x2F, 0x4E, 0x4D, 0x48, 0x47, 0x85, 0xC5, 0xB9, 0x95, 0x7C, 0xE0, 0xF4, 0x14, 0x32, 0x66, 0x46, 0x13,
+ 0x15, 0x04, 0x06, 0xF8, 0x4E, 0x54, 0xE0, 0xCC, 0xEC, 0x2A, 0x8A, 0xEA, 0x0A, 0x32, 0x4A, 0xEB, 0x4B, 0x5A, 0x09, 0xD7,
+ 0xAC, 0xC6, 0xDA, 0x45, 0x95, 0xC5, 0x74, 0x18, 0x06, 0x87, 0x7A, 0x56, 0xEA, 0xB1, 0xA9, 0x9C, 0xDF, 0xC7, 0x2D, 0x30,
+ 0x85, 0x7F, 0x0C, 0x0F, 0xAD, 0x25, 0x9B, 0x58, 0xDC, 0x3D, 0xBC, 0x7A, 0xC9, 0xA6, 0x95, 0x03, 0xAB, 0x88, 0x1F, 0x1B,
+ 0x56, 0x6C, 0xA5, 0x2A, 0xA6, 0x08, 0xDD, 0xB8, 0x72, 0xDB, 0x96, 0x35, 0xDB, 0xB7, 0xAD, 0xDB, 0x45, 0xCA, 0x8B, 0xB3,
+ 0xD2, 0x71, 0x41, 0x4A, 0x1C, 0x87, 0xB3, 0x6D, 0xD3, 0x01, 0xA8, 0xF3, 0x93, 0x2E, 0xBE, 0x88, 0x8F, 0x0F, 0x95, 0x4F,
+ 0xFC, 0x20, 0x3C, 0x9C, 0x78, 0xA0, 0xFD, 0x2E, 0xD3, 0x7F, 0x4C, 0xB0, 0x6A, 0xA0, 0x9D, 0x47, 0xC2, 0xAA, 0x77, 0xC7,
+ 0x2C, 0x1F, 0x41, 0x7C, 0x43, 0x4E, 0x92, 0xA1, 0x8A, 0x69, 0x42, 0x90, 0xAA, 0x8F, 0x61, 0xC5, 0xD8, 0x96, 0x8E, 0xFA,
+ 0x81, 0x56, 0x1F, 0x40, 0xB9, 0xFE, 0x1B, 0x3A, 0x0A, 0xFC, 0x7B, 0x9A, 0x0A, 0x64, 0x4A, 0x51, 0x81, 0x61, 0x20, 0x3E,
+ 0xDD, 0x05, 0x3C, 0x03, 0x7D, 0xA0, 0x15, 0x56, 0xB0, 0x5F, 0x00, 0x8A, 0x91, 0xE5, 0x17, 0x18, 0xE2, 0x17, 0x4A, 0x0B,
+ 0x88, 0xA7, 0xC1, 0x2C, 0x32, 0x6F, 0x3A, 0x3A, 0xC0, 0xCF, 0x7F, 0xCA, 0x84, 0xC9, 0x1C, 0x73, 0xB0, 0x7D, 0xF3, 0x01,
+ 0x4E, 0x19, 0x66, 0xA6, 0x04, 0x39, 0x0E, 0x96, 0x51, 0x67, 0x4B, 0x17, 0x0D, 0x35, 0x3A, 0x42, 0x57, 0x1F, 0xBE, 0x96,
+ 0xC3, 0x40, 0xE8, 0xF0, 0x0C, 0x0F, 0xAC, 0xA1, 0x37, 0xC0, 0x1E, 0x50, 0x80, 0x88, 0x6E, 0x55, 0x44, 0x70, 0x14, 0x15,
+ 0x5C, 0x5A, 0x62, 0x06, 0xBE, 0x08, 0xDD, 0x3A, 0x3B, 0x35, 0x1F, 0x10, 0xE0, 0x42, 0x76, 0x18, 0x64, 0x15, 0x56, 0x31,
+ 0xC5, 0xAB, 0x6A, 0xCD, 0x48, 0x85, 0xAE, 0xDD, 0x52, 0x96, 0x57, 0x5B, 0x98, 0x59, 0xC1, 0x49, 0x87, 0x9C, 0xB6, 0xC4,
+ 0x86, 0xF8, 0xEA, 0xD2, 0x66, 0x9C, 0xA3, 0xBF, 0x6B, 0x79, 0x57, 0xDB, 0xE2, 0xBE, 0xCE, 0x65, 0xEC, 0xE1, 0x31, 0xC7,
+ 0xD6, 0xF4, 0x0E, 0x2D, 0x5A, 0x41, 0x85, 0xB1, 0xA4, 0x67, 0xD5, 0xFA, 0xD5, 0x3B, 0xE4, 0xA8, 0xE9, 0x9E, 0xE5, 0xAB,
+ 0x86, 0x37, 0xE0, 0x2E, 0x12, 0xDB, 0x3B, 0xFA, 0xF1, 0x3F, 0x52, 0x5E, 0x08, 0xE7, 0xE4, 0x0B, 0x99, 0xD1, 0x19, 0xA9,
+ 0x11, 0x49, 0xEC, 0x42, 0xA4, 0x6B, 0x82, 0xA3, 0xF3, 0x89, 0x60, 0xE8, 0xC4, 0x85, 0x46, 0xB1, 0x5B, 0x54, 0x04, 0x12,
+ 0x25, 0x99, 0x82, 0x66, 0x47, 0x9A, 0x0E, 0x59, 0x14, 0x1A, 0x23, 0x7D, 0x45, 0x63, 0x1F, 0x27, 0xF5, 0x34, 0xD2, 0x77,
+ 0x90, 0x27, 0xCD, 0xEC, 0x8A, 0x76, 0x49, 0xA9, 0x96, 0x15, 0xE3, 0x74, 0x37, 0xE3, 0x9D, 0x3E, 0xB3, 0x99, 0xBA, 0x18,
+ 0x5F, 0xA3, 0xE9, 0x1F, 0x81, 0x1A, 0xC4, 0x21, 0x00, 0x68, 0x6E, 0x51, 0x06, 0x66, 0x3E, 0x76, 0x05, 0x84, 0x10, 0x3C,
+ 0x88, 0x5D, 0x2C, 0x14, 0xC0, 0xD8, 0x52, 0xFF, 0x84, 0x07, 0x2F, 0x99, 0x48, 0x48, 0xBF, 0xA8, 0xB1, 0xAA, 0x71, 0xD7,
+ 0xD6, 0x03, 0x38, 0xF8, 0xA6, 0x0D, 0x7B, 0xA0, 0x7C, 0xD5, 0x57, 0xC9, 0xB9, 0x2D, 0xB4, 0x48, 0xDB, 0x9B, 0xE4, 0x08,
+ 0x1F, 0x33, 0x5F, 0x6C, 0x29, 0x97, 0xE1, 0x49, 0x59, 0x76, 0x42, 0x1E, 0x2A, 0xAF, 0xAE, 0x68, 0x84, 0x31, 0x47, 0xC1,
+ 0x98, 0x97, 0x51, 0x44, 0x8D, 0x2D, 0x5B, 0x04, 0x32, 0x0B, 0x68, 0x5B, 0xB2, 0xB7, 0x09, 0x1D, 0x70, 0x91, 0x97, 0x5D,
+ 0x52, 0x55, 0xDE, 0x20, 0x47, 0x24, 0xD0, 0x61, 0xCE, 0xAF, 0xCC, 0xCF, 0x2C, 0x2F, 0xCE, 0xAD, 0x46, 0x01, 0x00, 0x54,
+ 0x7F, 0xD7, 0x52, 0x92, 0x57, 0x9C, 0x6F, 0xB0, 0x7B, 0x05, 0x4A, 0xC5, 0x2D, 0x9A, 0x6B, 0x17, 0xA1, 0x12, 0x74, 0x83,
+ 0x67, 0xC8, 0x59, 0x30, 0x4C, 0x3D, 0x9B, 0x07, 0x28, 0x3B, 0xE4, 0x80, 0xAD, 0xE6, 0x3E, 0x39, 0x42, 0xA2, 0xBE, 0x5B,
+ 0xCF, 0x37, 0x85, 0xA4, 0x94, 0x1C, 0x9A, 0x04, 0xA5, 0x8C, 0x37, 0x4F, 0xA4, 0x81, 0x87, 0xC0, 0xF6, 0xDB, 0xE8, 0x70,
+ 0xF1, 0x03, 0x8C, 0xC0, 0xD6, 0x07, 0x28, 0xC3, 0xA4, 0x6D, 0x52, 0xAF, 0x25, 0x46, 0xCA, 0xCE, 0x75, 0x90, 0x23, 0x39,
+ 0x5A, 0xC7, 0x24, 0x49, 0x26, 0x6B, 0x92, 0xDF, 0xB2, 0xC0, 0x22, 0x53, 0xAF, 0x1A, 0xDB, 0x77, 0x0B, 0x57, 0x99, 0xC3,
+ 0x79, 0xE9, 0x79, 0x36, 0x29, 0x32, 0x6A, 0x90, 0xA9, 0x90, 0x99, 0x7C, 0xA5, 0x82, 0xC8, 0xEA, 0x5F, 0xAA, 0x06, 0x70,
+ 0x89, 0xE4, 0x8C, 0x77, 0x26, 0xCA, 0x08, 0x89, 0x46, 0x1F, 0xA0, 0x24, 0xB7, 0x5C, 0x8B, 0x56, 0xC2, 0xA2, 0x55, 0xF4,
+ 0x24, 0x0F, 0x26, 0x7C, 0x49, 0x04, 0xE3, 0xAE, 0xB4, 0xE4, 0x16, 0xF8, 0x5F, 0x70, 0xDE, 0xF9, 0x9C, 0xC8, 0x4E, 0x82,
+ 0x41, 0x12, 0x05, 0xE1, 0xEE, 0x8A, 0xCB, 0x6F, 0xDC, 0xB9, 0xF3, 0x30, 0x87, 0x81, 0x00, 0x17, 0x8D, 0xD5, 0xAD, 0x28,
+ 0x83, 0x23, 0x19, 0x39, 0xDA, 0x90, 0xBD, 0xAB, 0xC5, 0x19, 0x32, 0xF7, 0x26, 0xA9, 0xAD, 0xAB, 0x68, 0x22, 0x23, 0x42,
+ 0xDC, 0x20, 0x0F, 0x9F, 0x16, 0x2C, 0x22, 0x30, 0x70, 0x17, 0x5C, 0x2A, 0xCC, 0x2E, 0xCD, 0x4A, 0x11, 0x6F, 0x90, 0x3D,
+ 0x23, 0x6C, 0x61, 0x4B, 0x2D, 0xA0, 0x1B, 0x5F, 0x56, 0x50, 0x83, 0x3E, 0xC0, 0x2E, 0xC2, 0x4F, 0x6D, 0x79, 0x2B, 0xB1,
+ 0x1A, 0x65, 0x40, 0xD8, 0x21, 0x8B, 0x05, 0xAF, 0xAA, 0x0B, 0x1A, 0xB8, 0xDB, 0x5C, 0xD3, 0x5D, 0x9E, 0x5F, 0xD7, 0x5A,
+ 0xD3, 0xC3, 0x36, 0xE1, 0xC2, 0xB4, 0x32, 0xF2, 0x2B, 0x8A, 0x4A, 0x98, 0xE1, 0xED, 0x35, 0xDD, 0x55, 0x79, 0x35, 0x8C,
+ 0x0A, 0x38, 0x61, 0x88, 0x52, 0x3C, 0x2D, 0x2A, 0x8D, 0x33, 0x01, 0x38, 0x50, 0x87, 0x46, 0x69, 0x4D, 0x79, 0x9D, 0xEF,
+ 0xE4, 0xE9, 0x7C, 0x4C, 0xD5, 0x41, 0x52, 0xA4, 0xD4, 0x68, 0x22, 0x5C, 0x53, 0x1F, 0x18, 0x1D, 0xC8, 0x35, 0x91, 0x83,
+ 0x65, 0xE5, 0xAE, 0x17, 0xC9, 0xE8, 0x46, 0x75, 0x60, 0x03, 0x2F, 0xDD, 0x1B, 0x3B, 0x8F, 0xD6, 0x44, 0x68, 0x0C, 0x37,
+ 0xC6, 0x3B, 0x20, 0xD5, 0x01, 0xA4, 0x82, 0x12, 0xFF, 0x46, 0x41, 0x50, 0xB2, 0x82, 0xB0, 0x44, 0x94, 0xA1, 0x38, 0xE3,
+ 0xCA, 0xDA, 0x0A, 0x5D, 0x2E, 0xE4, 0x39, 0x68, 0xCB, 0x3C, 0x27, 0x26, 0x2C, 0x02, 0xB7, 0x60, 0xCB, 0xC6, 0x82, 0x39,
+ 0x73, 0x2F, 0x38, 0x7F, 0x1C, 0x71, 0xFB, 0x82, 0x73, 0xCE, 0xE7, 0x3D, 0x6C, 0x5D, 0xB7, 0xF7, 0xF8, 0xD5, 0xB7, 0xA3,
+ 0x09, 0x32, 0xDA, 0xC5, 0xBD, 0xAB, 0xC4, 0x5A, 0x4B, 0x5A, 0xCA, 0x0B, 0x6B, 0x31, 0x4C, 0x4E, 0x85, 0xE3, 0x09, 0xD8,
+ 0x14, 0xE9, 0x10, 0xA1, 0x18, 0x56, 0x40, 0xA2, 0xB4, 0x04, 0x52, 0xD0, 0x81, 0xF0, 0x65, 0xD8, 0x8F, 0x9F, 0x9E, 0x87,
+ 0xE1, 0xA3, 0x03, 0xDA, 0xC8, 0x28, 0x83, 0xD2, 0x44, 0x4E, 0xA0, 0xCB, 0x2E, 0x93, 0x1A, 0x22, 0xB7, 0x9C, 0x23, 0x89,
+ 0xA0, 0x07, 0xB2, 0x4F, 0xA2, 0x30, 0xB7, 0xBA, 0xB4, 0xB0, 0xBE, 0x9C, 0xAD, 0x2E, 0x35, 0xED, 0x75, 0x55, 0x1D, 0x64,
+ 0xB1, 0xC0, 0x97, 0x90, 0xF5, 0x8B, 0xEB, 0x0B, 0xB3, 0xCB, 0x2B, 0x0B, 0x1B, 0xC8, 0xB2, 0xD0, 0x47, 0x7E, 0x4A, 0x49,
+ 0x79, 0x56, 0x4D, 0x5D, 0x69, 0x1B, 0xFD, 0x44, 0x94, 0x51, 0x90, 0x51, 0x2E, 0x03, 0xE4, 0x94, 0x1C, 0xFA, 0xCA, 0xBC,
+ 0x0D, 0x9C, 0x80, 0xFF, 0x98, 0x12, 0x9F, 0xCC, 0x96, 0x13, 0x0E, 0xC9, 0xA0, 0xB5, 0x45, 0x70, 0x02, 0x85, 0xE8, 0xFB,
+ 0x3A, 0x2B, 0x4A, 0x3A, 0x8F, 0x02, 0x4A, 0x52, 0x31, 0x48, 0x33, 0x58, 0x94, 0x81, 0x8B, 0x44, 0xC5, 0xC9, 0x33, 0xC3,
+ 0xE5, 0x91, 0x51, 0x3A, 0xF0, 0x2A, 0x60, 0x8C, 0xF4, 0x4F, 0x9E, 0x4A, 0x2B, 0x35, 0xC8, 0x8B, 0x74, 0xEA, 0x0D, 0xD2,
+ 0xFA, 0x97, 0x5B, 0x51, 0x89, 0x68, 0x25, 0x8C, 0x14, 0x36, 0x0E, 0x03, 0x89, 0x8B, 0x4C, 0x88, 0xE5, 0xAE, 0xF1, 0x56,
+ 0xE7, 0x57, 0xE1, 0xF1, 0xE2, 0x16, 0x61, 0x0C, 0xF1, 0xD9, 0xD0, 0xEA, 0xC7, 0xE6, 0x3D, 0xCA, 0x3D, 0xAD, 0xF5, 0x62,
+ 0x42, 0xE2, 0xB7, 0x6D, 0xD8, 0x7B, 0xE3, 0x8D, 0xF7, 0x72, 0x6E, 0x1D, 0xFB, 0x5E, 0x49, 0xF6, 0x85, 0x3D, 0x56, 0x58,
+ 0x93, 0x9B, 0x54, 0xC4, 0xAF, 0x48, 0x04, 0x81, 0xD0, 0x78, 0xF3, 0xD9, 0x52, 0xE2, 0xD3, 0x18, 0x7F, 0xF2, 0xB2, 0x31,
+ 0x64, 0x07, 0x9C, 0x32, 0x14, 0x2F, 0x6D, 0x7A, 0xBC, 0x24, 0x33, 0x39, 0x97, 0x12, 0x9A, 0x4F, 0x84, 0xBF, 0xA2, 0x9E,
+ 0x9C, 0x74, 0x51, 0x0F, 0x7E, 0x80, 0x0E, 0xE0, 0x25, 0x02, 0x5C, 0x65, 0xC5, 0x35, 0xC5, 0x05, 0xD5, 0x00, 0x00, 0xEE,
+ 0x82, 0xD5, 0x67, 0xA6, 0xD1, 0xCA, 0x95, 0xDD, 0x86, 0xF1, 0x31, 0xE9, 0x39, 0x69, 0x05, 0x59, 0x29, 0x05, 0xDC, 0xE2,
+ 0x07, 0x29, 0x91, 0xE9, 0xEC, 0x8B, 0x29, 0xCD, 0xAF, 0xA6, 0xF2, 0x80, 0x4B, 0x48, 0xF8, 0x2C, 0xCF, 0xAE, 0xD4, 0x0D,
+ 0x2F, 0x1C, 0x86, 0x49, 0x7D, 0xC0, 0xF1, 0x0D, 0x7C, 0x40, 0xA2, 0x20, 0x15, 0x8F, 0xE4, 0x45, 0x44, 0x63, 0x53, 0x2A,
+ 0x1B, 0x90, 0x30, 0x81, 0x41, 0xC3, 0x03, 0xD2, 0x57, 0xB9, 0x0B, 0x10, 0x25, 0xE8, 0xD2, 0xB9, 0xA1, 0x8F, 0x95, 0xFB,
+ 0xC9, 0xBC, 0x30, 0xCC, 0x6A, 0x0C, 0x45, 0x69, 0xF4, 0x68, 0x94, 0x8F, 0xEA, 0x0C, 0x25, 0x54, 0x13, 0xDE, 0x80, 0xA3,
+ 0xFA, 0xD0, 0xA0, 0x6D, 0x7C, 0xD0, 0xE8, 0x5F, 0x4D, 0x20, 0x5A, 0x1C, 0x85, 0x77, 0x63, 0xD4, 0x13, 0x8B, 0x40, 0x71,
+ 0x05, 0x02, 0x38, 0xFC, 0xF5, 0x39, 0xD3, 0x67, 0x5E, 0x74, 0xDE, 0xF9, 0x5A, 0xE5, 0x61, 0xDD, 0x5B, 0xD6, 0xEE, 0xD9,
+ 0xBF, 0xFF, 0xD8, 0xA1, 0x43, 0xD7, 0x2A, 0xA1, 0xBA, 0x22, 0xB7, 0x0E, 0xAA, 0x19, 0x66, 0x8E, 0x8D, 0xF3, 0x5B, 0x29,
+ 0x12, 0x43, 0xA2, 0x89, 0x3A, 0x5C, 0x80, 0x45, 0x1C, 0x94, 0xC0, 0x86, 0x40, 0x0A, 0x05, 0xAE, 0x93, 0x63, 0xD3, 0x91,
+ 0xBB, 0x9C, 0x1F, 0x12, 0x95, 0x44, 0xFA, 0x94, 0x10, 0x95, 0x42, 0xE8, 0x96, 0x2D, 0x08, 0x12, 0xEA, 0x04, 0x4E, 0xF9,
+ 0x15, 0x52, 0x46, 0x7F, 0x74, 0x95, 0xA9, 0x8A, 0x38, 0x0F, 0x04, 0x8F, 0x41, 0x49, 0x54, 0x79, 0x70, 0xDD, 0x48, 0x70,
+ 0xF9, 0xEC, 0x3C, 0x82, 0xCE, 0x50, 0x0C, 0xDC, 0xE7, 0xEC, 0x8C, 0x7C, 0x22, 0x0A, 0x2E, 0x48, 0x4B, 0x9F, 0x03, 0x6E,
+ 0x68, 0x87, 0xB0, 0xDD, 0xA8, 0xBF, 0x75, 0xE8, 0xC0, 0xAE, 0x2B, 0x1F, 0xBC, 0xEF, 0x49, 0xB2, 0x58, 0xBC, 0x64, 0xDE,
+ 0x8C, 0x79, 0x24, 0x84, 0x26, 0x43, 0x8D, 0xC7, 0x2C, 0x10, 0xAE, 0x11, 0xB4, 0x48, 0x59, 0x96, 0xFB, 0xD9, 0x8D, 0x75,
+ 0x3A, 0x06, 0xAA, 0x6A, 0x18, 0xA5, 0x03, 0xAF, 0xED, 0xD3, 0x3F, 0xA0, 0x99, 0xA3, 0x71, 0xD8, 0x5E, 0x68, 0x6B, 0xC1,
+ 0x3B, 0xA5, 0xB3, 0xA9, 0xAA, 0x8B, 0x4B, 0x02, 0x0B, 0x56, 0x1F, 0x63, 0x14, 0x63, 0x95, 0xA4, 0xBA, 0xC1, 0x78, 0x05,
+ 0xAC, 0x82, 0x4D, 0xB4, 0x08, 0x8C, 0x24, 0x83, 0x02, 0x61, 0x51, 0x03, 0x9B, 0xCB, 0xD0, 0x01, 0xB7, 0x04, 0xC6, 0x2B,
+ 0x2E, 0xBF, 0x69, 0xDB, 0x96, 0x03, 0x6B, 0x56, 0x6C, 0x27, 0x66, 0x12, 0x51, 0x49, 0x7E, 0x08, 0xBF, 0xA8, 0x21, 0x31,
+ 0x2E, 0x15, 0x89, 0xE3, 0x0A, 0x48, 0x33, 0x9C, 0xCC, 0x38, 0x34, 0x3A, 0x2E, 0x22, 0x89, 0x0B, 0x5C, 0x21, 0x32, 0x44,
+ 0x8A, 0x3E, 0x3E, 0x33, 0xBF, 0x65, 0xC5, 0x1A, 0x5F, 0x91, 0xBA, 0xC9, 0x3C, 0x19, 0xE5, 0xA1, 0x24, 0x8A, 0x6A, 0xF4,
+ 0x44, 0xB3, 0x44, 0xD4, 0x60, 0x94, 0x24, 0xE7, 0x43, 0xB1, 0x31, 0x22, 0x39, 0x0F, 0xD1, 0x13, 0x60, 0xC2, 0x83, 0x22,
+ 0x50, 0x9B, 0x6C, 0x33, 0x49, 0xE6, 0x14, 0xBD, 0x0A, 0x39, 0xC0, 0x25, 0xBD, 0x40, 0xF6, 0xB6, 0x14, 0xD5, 0x72, 0x7C,
+ 0x1C, 0xBD, 0x5B, 0x68, 0x3B, 0x90, 0x48, 0xB6, 0xAE, 0xDD, 0xF9, 0xC0, 0xFD, 0x8F, 0x7F, 0xF8, 0x9B, 0x3F, 0xFE, 0xFC,
+ 0x67, 0x1F, 0xEE, 0xDA, 0xB6, 0x13, 0x05, 0xCC, 0x98, 0x32, 0x9D, 0xC6, 0x01, 0x9E, 0x4D, 0xC2, 0xCA, 0x5D, 0x00, 0xCA,
+ 0x40, 0x6E, 0x94, 0x64, 0x2B, 0xA4, 0x21, 0x21, 0xDC, 0xB2, 0x73, 0x48, 0x3A, 0x66, 0x60, 0x35, 0xDA, 0x42, 0x0E, 0x3E,
+ 0xCA, 0x43, 0xB2, 0xC9, 0x8F, 0x4D, 0x43, 0x69, 0x90, 0xC9, 0xAF, 0x52, 0x9D, 0x16, 0x05, 0xA8, 0x6A, 0xFB, 0x45, 0xEA,
+ 0xEC, 0x76, 0xD9, 0xF1, 0x90, 0x6D, 0x94, 0x7B, 0x9B, 0x53, 0x16, 0xAC, 0x4C, 0xA2, 0xE6, 0x04, 0x70, 0x1B, 0xC6, 0x4D,
+ 0x42, 0x15, 0xCB, 0xFB, 0x93, 0x83, 0x3E, 0x08, 0xCE, 0x7E, 0x81, 0xFE, 0xB3, 0xE6, 0x50, 0xDC, 0xD1, 0xF6, 0x40, 0x0D,
+ 0xBC, 0xE0, 0x86, 0x75, 0xBB, 0xB7, 0x6D, 0x39, 0xB8, 0x7C, 0xE9, 0xA6, 0xD6, 0xC6, 0x3E, 0xAA, 0x30, 0xE4, 0xC5, 0x56,
+ 0x56, 0xCC, 0x13, 0x01, 0x21, 0x77, 0x19, 0x95, 0x90, 0x2B, 0x27, 0xA4, 0x0B, 0x1B, 0x43, 0xFC, 0x20, 0x4E, 0x84, 0x1E,
+ 0xC1, 0x2D, 0xAC, 0x3D, 0x1E, 0x89, 0x89, 0x0E, 0x8B, 0x21, 0x73, 0xC7, 0xD5, 0x78, 0x32, 0xBF, 0xE5, 0x57, 0x2C, 0x50,
+ 0x11, 0x85, 0x19, 0x25, 0x89, 0x1D, 0x44, 0x61, 0xB9, 0xC4, 0xD2, 0xD8, 0x64, 0xF2, 0x2B, 0x56, 0x66, 0x8A, 0xCC, 0xF2,
+ 0x04, 0xCD, 0x52, 0xB2, 0xC9, 0xBB, 0x08, 0x12, 0xF8, 0x41, 0x51, 0x56, 0x39, 0x3D, 0xA8, 0x82, 0x9C, 0xAA, 0x9C, 0x94,
+ 0xE2, 0xCC, 0xD8, 0x6C, 0x2A, 0xC4, 0x8A, 0xAC, 0x4A, 0x4A, 0x19, 0xE6, 0xE4, 0x94, 0x14, 0x14, 0x71, 0x6F, 0x7C, 0xF7,
+ 0x87, 0xFF, 0xFD, 0xF8, 0x8B, 0xDF, 0xBC, 0xFF, 0x87, 0xA3, 0x87, 0xAF, 0xE5, 0xF9, 0x86, 0x90, 0x10, 0x10, 0xE0, 0x2B,
+ 0xED, 0x03, 0x36, 0x08, 0x2D, 0x98, 0xE1, 0x4B, 0xA9, 0x84, 0x85, 0x41, 0x9D, 0xE2, 0x98, 0x0D, 0x98, 0x3B, 0x78, 0xB0,
+ 0x4C, 0xDC, 0xD0, 0x44, 0x58, 0x9C, 0x8F, 0x97, 0x13, 0xE9, 0x45, 0x1E, 0xEB, 0x07, 0xA0, 0xAA, 0xC3, 0x14, 0x4B, 0x94,
+ 0xC6, 0xB5, 0x5B, 0x2D, 0x3B, 0xC3, 0x52, 0x4B, 0x0E, 0xD0, 0xC2, 0x6D, 0xCC, 0x3A, 0xA5, 0x32, 0x54, 0x2B, 0x02, 0x8B,
+ 0x06, 0x94, 0x30, 0x07, 0x0C, 0x84, 0x0C, 0x8A, 0x2A, 0xCF, 0x04, 0x06, 0xB6, 0x16, 0xFB, 0x72, 0x18, 0x08, 0x3A, 0xA0,
+ 0xA4, 0xE0, 0x4C, 0x96, 0x1D, 0xDB, 0x8F, 0x74, 0xB5, 0x0F, 0x72, 0x42, 0x11, 0x1B, 0xC1, 0x81, 0x7B, 0xAC, 0x98, 0x15,
+ 0xBA, 0x30, 0x9C, 0x3F, 0x47, 0xAC, 0xD8, 0x35, 0x0E, 0x11, 0xE4, 0x17, 0x1C, 0x46, 0x36, 0x8C, 0x3F, 0x51, 0xA3, 0x84,
+ 0x46, 0x87, 0x87, 0x44, 0x87, 0x07, 0x70, 0x4D, 0xE9, 0x14, 0x15, 0x41, 0x47, 0x39, 0x28, 0x92, 0xC5, 0x16, 0x7E, 0xC9,
+ 0xD0, 0x42, 0xA3, 0xC9, 0x86, 0xB9, 0x95, 0x43, 0x5E, 0x78, 0x24, 0x2C, 0x96, 0x57, 0x13, 0x8F, 0xE1, 0x5D, 0xF1, 0xFE,
+ 0x63, 0x33, 0xB8, 0xD5, 0x12, 0x4F, 0x55, 0x82, 0x82, 0x09, 0x1E, 0xD9, 0xA9, 0xC5, 0xE5, 0x85, 0xF5, 0x72, 0xF2, 0x74,
+ 0xCB, 0x60, 0x4F, 0x9B, 0xF4, 0x04, 0x81, 0xAC, 0xDC, 0xD4, 0xA2, 0xBC, 0x94, 0x7C, 0xC6, 0x18, 0x30, 0xA0, 0x68, 0xA4,
+ 0xD3, 0xAE, 0x87, 0x2D, 0x70, 0xCB, 0x75, 0x77, 0xDC, 0x7A, 0xFD, 0xBD, 0xA0, 0x13, 0xDF, 0x54, 0x42, 0xB4, 0x18, 0x1E,
+ 0xE2, 0x5B, 0x49, 0xB6, 0x1F, 0xD8, 0x75, 0x84, 0xBE, 0xC8, 0x8A, 0x65, 0xEB, 0x30, 0xF1, 0xB8, 0x88, 0x28, 0xA4, 0xC4,
+ 0x49, 0x02, 0x7C, 0x64, 0x30, 0x80, 0xB7, 0xE4, 0xE8, 0xC0, 0xD3, 0x92, 0xB3, 0x14, 0xA5, 0xEC, 0xAC, 0x84, 0x4C, 0x5D,
+ 0xE2, 0x92, 0x0E, 0x57, 0x69, 0x84, 0x28, 0xF9, 0xD5, 0xAE, 0xA0, 0x03, 0x55, 0xAB, 0x12, 0x4F, 0x12, 0x35, 0x02, 0x56,
+ 0x82, 0x18, 0xA6, 0xD2, 0x36, 0x25, 0x1E, 0xC8, 0x1E, 0x49, 0x64, 0x93, 0xC0, 0x30, 0x27, 0x00, 0x44, 0xA2, 0xCB, 0x04,
+ 0xF7, 0x74, 0xCB, 0x86, 0x7D, 0x9B, 0x37, 0xEE, 0x93, 0xB3, 0xFD, 0x4A, 0x1B, 0x01, 0x74, 0x72, 0x1B, 0xFA, 0x42, 0xB4,
+ 0x9B, 0x10, 0x22, 0xF0, 0x1D, 0x16, 0x10, 0xCE, 0x05, 0xE6, 0x8C, 0xAC, 0x41, 0x8F, 0xF0, 0xC0, 0x68, 0x2C, 0x9A, 0x0B,
+ 0x76, 0xC5, 0x86, 0x2E, 0x0C, 0x43, 0xC4, 0xB2, 0x02, 0xC2, 0x28, 0x0C, 0xD9, 0xA9, 0xC9, 0x2D, 0x07, 0x97, 0xF2, 0x48,
+ 0xA8, 0x7F, 0x58, 0x48, 0x40, 0x28, 0x4F, 0xE0, 0xDF, 0xA1, 0x27, 0xFC, 0x00, 0x45, 0xE2, 0x52, 0xBC, 0x14, 0x3A, 0x4E,
+ 0x8A, 0xA1, 0x1D, 0x9B, 0x88, 0xE8, 0x15, 0x8B, 0x78, 0x9C, 0x3A, 0x23, 0x27, 0xAD, 0x84, 0x1C, 0x89, 0xD5, 0x56, 0xDF,
+ 0x07, 0x2A, 0xB6, 0x37, 0x0F, 0x74, 0x77, 0x2C, 0x2D, 0xC9, 0xAB, 0xA9, 0x2A, 0x69, 0x22, 0x78, 0x14, 0xA5, 0x97, 0x02,
+ 0x92, 0x29, 0x49, 0xE9, 0xD8, 0x04, 0xF1, 0x89, 0x4A, 0x4D, 0x3C, 0x29, 0x31, 0x15, 0x14, 0x61, 0x1A, 0xC6, 0x79, 0xF3,
+ 0x03, 0xDD, 0x43, 0x74, 0x0C, 0x5B, 0x6A, 0x5B, 0xE8, 0xB7, 0x4F, 0xB9, 0x64, 0x32, 0xA0, 0x87, 0xA6, 0x49, 0xA5, 0x68,
+ 0xB5, 0x02, 0x00, 0x82, 0x45, 0xA7, 0x5C, 0x7C, 0x60, 0xC9, 0x4D, 0x13, 0x0C, 0x49, 0x26, 0x59, 0xC9, 0x62, 0xA7, 0xE0,
+ 0x88, 0xB9, 0xEC, 0x01, 0x06, 0xD6, 0x02, 0x50, 0x8A, 0x4B, 0x98, 0xFF, 0x28, 0x05, 0xC4, 0x39, 0x84, 0x46, 0x3B, 0xDE,
+ 0xB3, 0x31, 0x43, 0x92, 0x28, 0x00, 0xC1, 0x69, 0x78, 0x44, 0x45, 0x2C, 0x14, 0x23, 0xC5, 0xFC, 0x81, 0xD4, 0xB3, 0xCF,
+ 0x3A, 0x03, 0xD1, 0x6C, 0xDA, 0xB8, 0x8F, 0xF3, 0xA1, 0xBA, 0xBB, 0x96, 0x61, 0x98, 0x44, 0xD4, 0xDC, 0xF4, 0x42, 0xF6,
+ 0xB7, 0x12, 0x39, 0x29, 0xCD, 0x30, 0x7F, 0xC4, 0x0D, 0xB0, 0x00, 0x38, 0x48, 0x96, 0x30, 0x80, 0x40, 0xB9, 0x10, 0x89,
+ 0x2F, 0x08, 0x97, 0xFA, 0x7C, 0x41, 0x30, 0xA2, 0x0F, 0x9A, 0x1F, 0x4C, 0x4B, 0x4A, 0xAF, 0x17, 0xCE, 0x87, 0xDA, 0x1D,
+ 0x10, 0x34, 0x3F, 0x28, 0xC8, 0x2F, 0x24, 0x78, 0x01, 0x27, 0xBC, 0x84, 0xF1, 0x38, 0x4A, 0xE2, 0x6F, 0x79, 0x29, 0xD2,
+ 0x36, 0xCC, 0x42, 0x70, 0x2C, 0x28, 0x4A, 0x52, 0xAC, 0x58, 0x69, 0x0F, 0x03, 0x65, 0x31, 0x61, 0x49, 0x24, 0xAC, 0xB5,
+ 0x00, 0x4F, 0x51, 0x23, 0x55, 0xC5, 0xD2, 0xC1, 0xF5, 0x1B, 0xD6, 0xEC, 0xE2, 0x78, 0x8C, 0x55, 0x2B, 0xB6, 0xEE, 0xDE,
+ 0x79, 0x74, 0xDF, 0x9E, 0x63, 0x87, 0xF6, 0x5F, 0x7F, 0x60, 0xCF, 0xD5, 0xE4, 0x6F, 0x14, 0x34, 0x8B, 0x5A, 0xFB, 0x5A,
+ 0xEA, 0xDB, 0xA8, 0x5D, 0x38, 0x45, 0xAC, 0xA6, 0xB2, 0x89, 0x3C, 0x38, 0x23, 0x35, 0x87, 0x57, 0x13, 0x9B, 0x08, 0xA0,
+ 0xC7, 0x19, 0xC3, 0x28, 0x9E, 0xEF, 0x81, 0x88, 0x8A, 0x88, 0x06, 0xA6, 0xCC, 0x51, 0x4B, 0x21, 0xA7, 0xD0, 0x81, 0x57,
+ 0xDC, 0x96, 0xB5, 0xAA, 0x70, 0xE4, 0xC9, 0x8B, 0x54, 0xE2, 0x96, 0xC1, 0x21, 0x3A, 0x30, 0x3C, 0xAD, 0x53, 0xB2, 0x07,
+ 0xE4, 0x41, 0xE3, 0x13, 0x72, 0xAB, 0x25, 0x85, 0xCC, 0xF9, 0xA4, 0x48, 0x19, 0xE5, 0x0A, 0xC0, 0x28, 0x25, 0x1B, 0xAE,
+ 0x30, 0x7F, 0xB6, 0x2F, 0x31, 0x99, 0xFE, 0xC1, 0x86, 0xB5, 0x7B, 0x07, 0x7A, 0x56, 0x02, 0xCA, 0x84, 0x4A, 0xD9, 0xBD,
+ 0x43, 0x3B, 0xCB, 0x40, 0x84, 0x86, 0x59, 0x84, 0x8E, 0xEC, 0x70, 0x02, 0xF4, 0x81, 0x69, 0xB3, 0xC2, 0x17, 0x46, 0x20,
+ 0x59, 0xA4, 0x2C, 0xA7, 0x32, 0xCE, 0x0B, 0xE4, 0x36, 0x60, 0xDE, 0x42, 0x6E, 0xFD, 0x67, 0xFB, 0xFB, 0xCF, 0x0D, 0x60,
+ 0xC7, 0xB2, 0x2C, 0x73, 0xCD, 0xE3, 0x81, 0x0B, 0x82, 0x64, 0xCD, 0x0B, 0x14, 0x0D, 0x05, 0x84, 0x82, 0x63, 0x68, 0x1D,
+ 0xE9, 0xF0, 0xCA, 0xE4, 0xBE, 0x60, 0x14, 0xF5, 0x44, 0x43, 0x55, 0x4B, 0x43, 0x65, 0x67, 0x6E, 0x7A, 0x69, 0x05, 0xE7,
+ 0xF3, 0x57, 0x77, 0x2E, 0x5F, 0xBC, 0x11, 0xD7, 0x5C, 0xB7, 0x66, 0xE7, 0x91, 0x43, 0xD7, 0xEF, 0xDD, 0x7F, 0xCD, 0x2D,
+ 0xB7, 0x3C, 0x70, 0xFC, 0xF8, 0x1D, 0x00, 0x26, 0xC5, 0x1A, 0x47, 0x97, 0xF0, 0x75, 0x61, 0xFA, 0x35, 0x62, 0xF4, 0xF0,
+ 0x69, 0x1E, 0xD3, 0x2D, 0xA6, 0x32, 0x2D, 0xC8, 0xE3, 0x6B, 0xA3, 0x3A, 0x38, 0x2D, 0xB5, 0xBF, 0x8B, 0x2F, 0x1A, 0x1A,
+ 0xE4, 0xA0, 0x76, 0x5E, 0x7F, 0xCA, 0xC4, 0x09, 0x98, 0x1A, 0x0A, 0xA0, 0x36, 0xF2, 0x51, 0xE1, 0x6A, 0x45, 0x66, 0x57,
+ 0x9A, 0xC7, 0xF0, 0x35, 0x17, 0x3A, 0x49, 0x07, 0x63, 0x39, 0x4C, 0x99, 0xF1, 0x59, 0xCC, 0xD9, 0x69, 0xA9, 0xB2, 0xD4,
+ 0x1B, 0xBC, 0x40, 0xA4, 0xD7, 0x78, 0xBA, 0x2C, 0x33, 0x59, 0x95, 0x9C, 0x24, 0x5A, 0x13, 0x64, 0x49, 0xD4, 0xB4, 0x5E,
+ 0x63, 0x3E, 0x6A, 0xDA, 0x4D, 0xC1, 0x33, 0x26, 0x5F, 0x8A, 0x5C, 0xD6, 0xAF, 0xDD, 0x45, 0x24, 0x20, 0xC4, 0x09, 0xA7,
+ 0x3C, 0xB5, 0x00, 0x59, 0xE3, 0xDD, 0x54, 0xB9, 0xE4, 0xA6, 0x20, 0x06, 0xF2, 0x02, 0x2E, 0x78, 0xD0, 0x04, 0xDE, 0x28,
+ 0xE9, 0x44, 0x05, 0x84, 0x61, 0x6E, 0x18, 0x7E, 0xE0, 0x1C, 0x3F, 0xCE, 0xB3, 0x43, 0xD0, 0x0B, 0x66, 0x8B, 0xD0, 0xA5,
+ 0x6F, 0xE8, 0x3B, 0x8F, 0x86, 0x2E, 0xB7, 0x7A, 0x4D, 0x7F, 0x97, 0x0B, 0x6E, 0xD1, 0x04, 0x5E, 0x82, 0x1A, 0xD4, 0x93,
+ 0xD0, 0x44, 0x64, 0xB0, 0x94, 0xBB, 0x44, 0x0B, 0x66, 0x12, 0x14, 0xD5, 0x60, 0x60, 0x5E, 0x46, 0x59, 0x6B, 0x5D, 0x6F,
+ 0x4B, 0x43, 0x6F, 0x7F, 0xF7, 0xCA, 0x81, 0x1E, 0xCE, 0x9C, 0x3F, 0xB0, 0x63, 0xDB, 0xD1, 0x43, 0x07, 0x8E, 0xDF, 0x7A,
+ 0xEB, 0x83, 0xB7, 0xDC, 0xF1, 0xC8, 0x50, 0xDF, 0xEA, 0xD9, 0xD3, 0xE7, 0x68, 0x59, 0x73, 0xD6, 0x19, 0x67, 0x5E, 0x78,
+ 0xC1, 0x79, 0x90, 0xC6, 0xA7, 0x4C, 0x9C, 0xC4, 0x62, 0xD6, 0xCB, 0xC1, 0x87, 0x3C, 0xC8, 0x2D, 0xDC, 0x9C, 0x89, 0xE3,
+ 0x27, 0x4D, 0x1C, 0x3F, 0x81, 0xAE, 0xFE, 0xC5, 0x17, 0x5D, 0x80, 0xA3, 0xA3, 0x03, 0xAC, 0x8D, 0x66, 0x9A, 0xE8, 0xC0,
+ 0x0B, 0x32, 0x7A, 0x9D, 0x96, 0x02, 0x0A, 0x65, 0xB0, 0xFB, 0x97, 0x45, 0x21, 0xFA, 0x25, 0x28, 0x94, 0xEE, 0xCD, 0x53,
+ 0x5D, 0x32, 0x93, 0x7A, 0x83, 0x48, 0x7C, 0xB4, 0x26, 0x1C, 0x0F, 0xB0, 0x70, 0x64, 0x72, 0x24, 0x21, 0xF9, 0x6A, 0xE5,
+ 0x62, 0x72, 0xB5, 0x48, 0x6D, 0x34, 0x71, 0x1E, 0xDA, 0x94, 0xF1, 0xE3, 0x99, 0xBD, 0xD0, 0x3C, 0xC8, 0x4C, 0xA1, 0x0C,
+ 0x26, 0xC7, 0x4F, 0x03, 0x97, 0xC9, 0xEB, 0x1B, 0xAB, 0xDB, 0xAB, 0xCA, 0x9B, 0x10, 0xBD, 0xA9, 0x4E, 0xD3, 0x90, 0x1A,
+ 0x81, 0x84, 0x68, 0x8C, 0x04, 0x5D, 0xE4, 0x91, 0x04, 0x97, 0x24, 0x44, 0x5A, 0xB6, 0xB3, 0x16, 0xB0, 0x67, 0x9F, 0xD2,
+ 0x8F, 0x33, 0x5C, 0x38, 0x42, 0x84, 0x25, 0x6A, 0x98, 0x35, 0x57, 0xAE, 0xCD, 0xAD, 0x51, 0x86, 0x3F, 0x4F, 0x43, 0x07,
+ 0x68, 0x8E, 0x96, 0x09, 0x93, 0x00, 0xB0, 0x08, 0x87, 0x10, 0x1D, 0xB0, 0xB5, 0x1F, 0x52, 0x41, 0x56, 0x59, 0x4D, 0x45,
+ 0x1B, 0x2D, 0x58, 0xEC, 0xB7, 0xB7, 0x6B, 0xF9, 0xD0, 0xD0, 0xDA, 0xCB, 0xB6, 0x1D, 0x3E, 0x7A, 0xE4, 0xC6, 0x5B, 0x6E,
+ 0xBA, 0xFF, 0xF6, 0xDB, 0x1F, 0xE6, 0x54, 0x49, 0xFE, 0x10, 0xE9, 0x9F, 0x79, 0xFA, 0x19, 0x48, 0x9C, 0xB6, 0x3C, 0x43,
+ 0x94, 0xD9, 0xD3, 0x66, 0x10, 0xCF, 0x58, 0x73, 0x67, 0xCC, 0xE2, 0x76, 0xF6, 0x8C, 0x99, 0x33, 0x2F, 0x9D, 0x31, 0x6D,
+ 0xD2, 0x64, 0x0E, 0x03, 0xBD, 0x74, 0xCA, 0x25, 0xF4, 0x89, 0x79, 0x6F, 0xC4, 0x64, 0xB0, 0x71, 0xC4, 0x0F, 0x4E, 0x81,
+ 0xF5, 0x49, 0x8E, 0x02, 0x44, 0x07, 0x9E, 0x34, 0x54, 0xAF, 0x47, 0x97, 0x08, 0x23, 0x95, 0x9A, 0x11, 0xBA, 0x43, 0x2B,
+ 0x3B, 0x39, 0x61, 0x3D, 0x39, 0x73, 0xD5, 0x0C, 0x55, 0x9A, 0x5C, 0xD2, 0xBD, 0x80, 0xCE, 0x25, 0x1C, 0x53, 0x74, 0x30,
+ 0x6D, 0xD2, 0xA5, 0x30, 0x9A, 0xEA, 0x2B, 0x5B, 0x11, 0x2E, 0xB2, 0xE0, 0x91, 0xC4, 0x84, 0x34, 0x0E, 0xE5, 0xA2, 0xAC,
+ 0x6D, 0x6F, 0xE9, 0xCB, 0x61, 0xEF, 0x6A, 0xBE, 0xEC, 0x08, 0x8B, 0x0D, 0x4F, 0x4C, 0x4D, 0xCA, 0x24, 0x07, 0x37, 0x85,
+ 0x1E, 0x9A, 0x08, 0x07, 0x73, 0x34, 0x05, 0x44, 0xF4, 0x6A, 0xF8, 0x9C, 0x24, 0xC5, 0x62, 0x98, 0xE1, 0x3B, 0x6D, 0x16,
+ 0x0B, 0x3E, 0x8E, 0x91, 0x8E, 0x2F, 0x4B, 0x7E, 0x65, 0xD4, 0xC0, 0x93, 0x09, 0x8F, 0x00, 0x14, 0x4E, 0x40, 0x30, 0x27,
+ 0x6D, 0xD5, 0x12, 0x04, 0x30, 0xC0, 0x15, 0xB2, 0x93, 0x8B, 0x5A, 0xAA, 0xBB, 0x7B, 0xDA, 0x97, 0x74, 0xB4, 0x0C, 0xAD,
+ 0x59, 0xB1, 0x8D, 0x03, 0x9E, 0x39, 0x51, 0x95, 0xAA, 0xE5, 0xA6, 0x9B, 0xEE, 0xA3, 0x9B, 0xC2, 0x29, 0x07, 0x67, 0x9C,
+ 0xC6, 0xD7, 0x15, 0x9E, 0x0E, 0xC5, 0x44, 0xA5, 0x8F, 0x6A, 0x61, 0x8C, 0xEB, 0x32, 0xD6, 0x30, 0x17, 0x93, 0xA7, 0x7B,
+ 0xCF, 0xF2, 0xF3, 0xF5, 0xE3, 0x1F, 0x21, 0x7D, 0x3C, 0x00, 0x08, 0xC2, 0x09, 0xD0, 0x01, 0x71, 0xCB, 0xC7, 0x93, 0xE6,
+ 0x7B, 0xB2, 0xFE, 0xA4, 0x4C, 0x8E, 0x72, 0xFD, 0x12, 0x89, 0x3B, 0x4C, 0xD5, 0xAF, 0x20, 0x50, 0x9E, 0x42, 0x01, 0xF1,
+ 0xC9, 0x0E, 0x16, 0xC5, 0x25, 0x09, 0xE5, 0x26, 0x5E, 0x82, 0x81, 0x5B, 0x31, 0x4A, 0xF7, 0x5B, 0x92, 0xF7, 0xE0, 0x18,
+ 0xC4, 0x8D, 0x99, 0x24, 0xC7, 0x25, 0x51, 0x16, 0x21, 0x41, 0xCC, 0x13, 0xB9, 0x20, 0xDF, 0xE4, 0xD8, 0xCC, 0x84, 0x88,
+ 0x54, 0x92, 0x10, 0x42, 0x62, 0x3E, 0x1C, 0xDB, 0x9C, 0xB2, 0xF4, 0xC4, 0x6C, 0x62, 0x80, 0x6C, 0x67, 0x8B, 0x91, 0x73,
+ 0x36, 0xD1, 0x5F, 0xD0, 0xC2, 0x50, 0x50, 0x85, 0x4F, 0x28, 0x6B, 0xF6, 0x82, 0xB9, 0xB3, 0xE7, 0xA9, 0xED, 0x8B, 0x0E,
+ 0x66, 0xCC, 0x9E, 0x3D, 0x0D, 0x93, 0xF4, 0x55, 0x0B, 0x9D, 0x3B, 0x55, 0xAE, 0x55, 0x3D, 0xEA, 0x1C, 0xFE, 0x33, 0x17,
+ 0x00, 0x5C, 0xA4, 0xED, 0x20, 0x21, 0x80, 0x46, 0x5E, 0x84, 0x1A, 0x48, 0x5B, 0x49, 0x58, 0x61, 0x50, 0xD3, 0x5C, 0x22,
+ 0x0B, 0xEA, 0xEF, 0x1C, 0x1E, 0xE8, 0x5A, 0xC1, 0xE9, 0x30, 0xDB, 0xB7, 0x1E, 0xBC, 0xE6, 0xAA, 0xDB, 0x6F, 0xBC, 0xE1,
+ 0x3E, 0x94, 0x11, 0x1D, 0x18, 0x83, 0x13, 0x4C, 0xB8, 0xF0, 0x22, 0xDF, 0xA9, 0xD3, 0xB1, 0x7A, 0xB1, 0x80, 0x79, 0xF3,
+ 0x29, 0xF8, 0xE5, 0x3D, 0xCC, 0x97, 0xA3, 0xAC, 0x74, 0x94, 0x22, 0x89, 0x80, 0xE9, 0xDE, 0x23, 0x7A, 0x96, 0x0E, 0x5A,
+ 0x54, 0x07, 0x12, 0x93, 0x4F, 0x32, 0x73, 0xB1, 0x6B, 0x77, 0x59, 0x71, 0x7F, 0x15, 0x65, 0x75, 0x94, 0x32, 0x60, 0x65,
+ 0x19, 0x71, 0x8F, 0x58, 0xBD, 0x34, 0x70, 0xD2, 0x34, 0x0C, 0xA4, 0xC3, 0x7C, 0x32, 0xC4, 0x1B, 0xC7, 0x03, 0xA8, 0x92,
+ 0x4C, 0xDF, 0x2A, 0x3E, 0x14, 0xA2, 0xB5, 0x30, 0x04, 0x30, 0x49, 0x9E, 0xCC, 0x5B, 0x9A, 0x3B, 0x1D, 0x3B, 0x92, 0x23,
+ 0x70, 0x82, 0x03, 0x39, 0xC0, 0x31, 0x31, 0x3B, 0xA9, 0xB8, 0x34, 0xA3, 0xB2, 0x3C, 0xA7, 0x06, 0x63, 0xAC, 0xAF, 0xE8,
+ 0x20, 0x31, 0x27, 0xBB, 0x90, 0xF6, 0x4E, 0x6A, 0x0E, 0x88, 0x81, 0x07, 0x00, 0x62, 0x84, 0x04, 0xF9, 0xB4, 0x7E, 0xFE,
+ 0xF3, 0xE7, 0xFA, 0x2B, 0xD4, 0x70, 0xAB, 0x4E, 0x80, 0x02, 0x58, 0xF3, 0xA6, 0xCD, 0xF4, 0x9D, 0x2A, 0x10, 0x01, 0x38,
+ 0xA0, 0x69, 0x79, 0xC4, 0xF8, 0x81, 0x0C, 0xFE, 0x08, 0x0C, 0x73, 0x04, 0x9D, 0xD1, 0x01, 0xD6, 0x20, 0x9D, 0x8F, 0xB0,
+ 0x38, 0xAA, 0xB6, 0xCA, 0xB2, 0xFA, 0x76, 0xB8, 0xCB, 0x35, 0x1D, 0x64, 0x41, 0x4B, 0x06, 0xD6, 0x11, 0x8D, 0x37, 0xAE,
+ 0xDD, 0x45, 0x3C, 0xB8, 0xEA, 0xCA, 0x5B, 0xAF, 0xBF, 0xFE, 0xEE, 0x5D, 0xDB, 0x2F, 0x5F, 0x30, 0x33, 0x80, 0x08, 0x4C,
+ 0x51, 0x49, 0x4D, 0xC3, 0x40, 0x17, 0x92, 0x1D, 0x4B, 0xE5, 0xEE, 0x8C, 0x4C, 0x5C, 0xB9, 0xAB, 0xF4, 0x4D, 0x00, 0x30,
+ 0x1E, 0x40, 0xE8, 0x32, 0x3A, 0x00, 0xFD, 0xD0, 0x81, 0x93, 0xE1, 0x7C, 0x19, 0x23, 0xF5, 0x94, 0xF6, 0x7E, 0x12, 0xDC,
+ 0x7F, 0x29, 0x91, 0xCF, 0x06, 0x00, 0x76, 0xD3, 0x33, 0xB8, 0x67, 0x8D, 0xE8, 0xC0, 0x69, 0xB5, 0xC6, 0xC5, 0x87, 0x44,
+ 0xE9, 0x84, 0x07, 0x94, 0xA7, 0x5E, 0xD3, 0xCF, 0x03, 0x38, 0x90, 0x54, 0x10, 0x06, 0x40, 0x83, 0xC6, 0x8A, 0xCE, 0xDA,
+ 0xAA, 0x56, 0x92, 0xD4, 0xC5, 0x83, 0xEB, 0xA0, 0x4D, 0x70, 0x56, 0x64, 0x75, 0x71, 0x53, 0x7E, 0x4E, 0x39, 0x0A, 0x20,
+ 0x4A, 0x83, 0x8D, 0x64, 0xB7, 0x68, 0x82, 0x1C, 0x09, 0xF7, 0x27, 0x20, 0xD3, 0xD0, 0x47, 0x9D, 0x12, 0x0C, 0x8C, 0xA5,
+ 0x8B, 0xD5, 0x4F, 0xC5, 0x03, 0xA6, 0x1B, 0x3F, 0x10, 0xE9, 0xAB, 0x6E, 0xF4, 0x96, 0xA7, 0x89, 0xBE, 0xFD, 0x82, 0xD1,
+ 0x22, 0x21, 0x9D, 0x08, 0xCF, 0x3F, 0x25, 0x65, 0xA0, 0x10, 0xA9, 0xE4, 0xEC, 0xB8, 0x8A, 0x36, 0x3A, 0xDB, 0x1D, 0x8D,
+ 0x03, 0xD4, 0xEA, 0xE8, 0x60, 0xEB, 0xE6, 0x03, 0x5B, 0x36, 0xED, 0x23, 0x1E, 0x5C, 0x75, 0xD5, 0xAD, 0xBB, 0x76, 0x5C,
+ 0x3E, 0xDF, 0xD7, 0xEF, 0xBC, 0xB3, 0xCF, 0x30, 0x6F, 0xD8, 0x4F, 0x3E, 0xC2, 0xFC, 0x20, 0x14, 0x10, 0x32, 0xDF, 0x4C,
+ 0xAB, 0xFC, 0x83, 0x08, 0x6C, 0x3A, 0xC5, 0x32, 0x86, 0xEF, 0x80, 0x8F, 0xB4, 0x31, 0x16, 0x4A, 0xEE, 0x17, 0x1E, 0x14,
+ 0xC6, 0x21, 0x0E, 0xA2, 0x03, 0xF8, 0x84, 0x5F, 0x81, 0x2A, 0x46, 0xD6, 0x92, 0x71, 0xBA, 0xEB, 0xAB, 0x64, 0x7D, 0xEA,
+ 0x22, 0xD9, 0x80, 0x8F, 0xF5, 0x00, 0x53, 0x21, 0x4B, 0x43, 0xD1, 0xED, 0x75, 0xC7, 0x41, 0xAE, 0x26, 0x75, 0x01, 0xD3,
+ 0xA9, 0x21, 0xF9, 0x24, 0xA0, 0x2A, 0xB6, 0x49, 0x22, 0x0F, 0x20, 0x90, 0x8C, 0x56, 0x73, 0x22, 0x79, 0x5D, 0x4F, 0x67,
+ 0xEB, 0xE2, 0xA5, 0x8B, 0x37, 0x1C, 0x39, 0x72, 0xFD, 0x8A, 0xE5, 0x9B, 0x69, 0x5A, 0x70, 0x66, 0x5A, 0x71, 0x56, 0x75,
+ 0x71, 0x46, 0x05, 0xE7, 0xAA, 0xE1, 0x34, 0xD4, 0x3B, 0x88, 0x4F, 0x1B, 0x7F, 0x66, 0x6C, 0x17, 0x28, 0x15, 0xC6, 0xEC,
+ 0xF9, 0x48, 0x9F, 0x53, 0x4E, 0x0D, 0x1C, 0x61, 0xF2, 0xBE, 0xD8, 0x3B, 0xA0, 0x64, 0xB4, 0x22, 0xF1, 0xC0, 0x6F, 0xA6,
+ 0x0D, 0xCB, 0x0B, 0x78, 0x1A, 0x38, 0x16, 0x1E, 0x4E, 0xEF, 0x53, 0x26, 0x80, 0xE4, 0x69, 0x58, 0x03, 0x09, 0x71, 0x75,
+ 0x51, 0x33, 0x27, 0x03, 0xA1, 0x06, 0x2A, 0x64, 0x38, 0x96, 0x4B, 0x86, 0xD6, 0xAF, 0x5D, 0xBB, 0x03, 0x2C, 0x42, 0x13,
+ 0x87, 0x2F, 0xBF, 0xE1, 0xEA, 0x63, 0xB7, 0x05, 0x05, 0x84, 0x5D, 0x74, 0xDE, 0x38, 0xB4, 0x8E, 0xE8, 0xD5, 0xD2, 0x65,
+ 0x39, 0x42, 0x17, 0xB4, 0xD1, 0xB7, 0x64, 0x30, 0x67, 0x21, 0x69, 0xB7, 0x2E, 0x6A, 0x20, 0xA4, 0x8F, 0x2B, 0xE8, 0x5D,
+ 0x9F, 0xD1, 0xF4, 0x60, 0x27, 0x9F, 0x39, 0xB9, 0xEB, 0xA0, 0xB9, 0xA6, 0xB2, 0x27, 0xDD, 0xDB, 0x91, 0xBB, 0x52, 0x94,
+ 0x61, 0xE6, 0xEE, 0x3A, 0x99, 0xCC, 0x64, 0xB9, 0x7F, 0x38, 0xB8, 0xA3, 0x80, 0x70, 0xC3, 0x8E, 0x09, 0x89, 0x46, 0xEE,
+ 0x20, 0x95, 0x1C, 0xFE, 0x67, 0x72, 0x47, 0x1E, 0x01, 0x61, 0xAA, 0x2B, 0x0C, 0x1F, 0x62, 0x70, 0xF5, 0xA6, 0x0D, 0x7B,
+ 0x0F, 0x1F, 0xBE, 0x6E, 0xEF, 0x9E, 0xAB, 0xF8, 0xD8, 0x7B, 0x77, 0x1F, 0xEB, 0x6A, 0x5B, 0xB2, 0xA8, 0x65, 0x31, 0xDF,
+ 0x92, 0x51, 0x5F, 0xD9, 0x5E, 0x5B, 0xD2, 0x9A, 0x97, 0x56, 0x2C, 0xFC, 0xB0, 0x0C, 0x99, 0x62, 0x46, 0x9B, 0x32, 0x3B,
+ 0x32, 0x20, 0x9C, 0x8F, 0x67, 0xD2, 0x7F, 0x7F, 0x0D, 0xD1, 0xEA, 0x10, 0x26, 0x48, 0x4A, 0xB2, 0xA4, 0x79, 0x11, 0xB7,
+ 0x6A, 0xFE, 0x80, 0x06, 0x17, 0x8A, 0xDD, 0x08, 0x8B, 0x82, 0x23, 0x34, 0x38, 0x82, 0x5E, 0x3F, 0x2D, 0x29, 0x46, 0x05,
+ 0xA0, 0x5F, 0x5B, 0x53, 0x3F, 0xFC, 0xA8, 0xBE, 0x8E, 0xE5, 0x2B, 0x96, 0x6E, 0x05, 0x91, 0x28, 0xC4, 0xF6, 0xEC, 0x3E,
+ 0xB6, 0x6B, 0xC7, 0xD1, 0xBD, 0xBB, 0xAF, 0x24, 0x32, 0x97, 0xE4, 0x55, 0xD1, 0xE8, 0x55, 0x05, 0x40, 0xF3, 0x09, 0xF7,
+ 0x0B, 0xE5, 0x64, 0x4F, 0x05, 0x19, 0x67, 0xA6, 0x2B, 0x52, 0x0E, 0x8E, 0x5C, 0xC8, 0x51, 0x87, 0x22, 0x7A, 0xA9, 0xCC,
+ 0x51, 0x40, 0x50, 0x88, 0x73, 0x57, 0xAE, 0xC3, 0xA4, 0x2F, 0xA6, 0x23, 0xE2, 0x31, 0xCB, 0xCD, 0x2C, 0x8D, 0xE8, 0x0D,
+ 0x7F, 0xD8, 0xDB, 0x19, 0x85, 0xE7, 0xCD, 0x90, 0x1A, 0x96, 0x15, 0xDD, 0x92, 0xF4, 0xA8, 0x64, 0x99, 0xEB, 0xBA, 0x3C,
+ 0x32, 0xC4, 0x3D, 0x46, 0x07, 0x27, 0x8F, 0x19, 0xAC, 0x13, 0x00, 0xDF, 0x5C, 0xD3, 0x97, 0xA6, 0x2B, 0x40, 0x49, 0xD9,
+ 0xC6, 0x37, 0x62, 0xF6, 0x0E, 0xAF, 0x5A, 0xBA, 0x89, 0x53, 0x70, 0xB6, 0x6F, 0x3D, 0xB4, 0x6F, 0xEF, 0xD5, 0xD7, 0x5E,
+ 0x7B, 0xE7, 0x9D, 0x77, 0x3E, 0xBA, 0x7F, 0xEF, 0xD5, 0x7B, 0x76, 0x5D, 0x09, 0x14, 0xE0, 0x07, 0xD4, 0x47, 0xCB, 0x86,
+ 0x36, 0x30, 0x07, 0xA6, 0x8D, 0x4A, 0xE1, 0x4A, 0x3F, 0x99, 0x7E, 0x00, 0xEF, 0x56, 0x46, 0xA7, 0x48, 0xD0, 0x5F, 0xE6,
+ 0xD5, 0x7C, 0x42, 0x84, 0x82, 0x68, 0xD8, 0x77, 0xAE, 0x81, 0x11, 0x4D, 0x83, 0x6F, 0x66, 0x49, 0x72, 0xC2, 0x52, 0xC1,
+ 0xE9, 0x35, 0x7F, 0x25, 0x88, 0xE1, 0x17, 0x22, 0x0C, 0x09, 0xD3, 0xB1, 0x20, 0x29, 0xE0, 0x58, 0x27, 0x26, 0x39, 0x75,
+ 0xE5, 0xED, 0x8C, 0x36, 0x01, 0xA2, 0xCD, 0x1B, 0xF7, 0xEE, 0xBC, 0xEC, 0x08, 0x5D, 0xF4, 0xD5, 0x2B, 0xB7, 0xD3, 0xC7,
+ 0x5D, 0xB1, 0x7C, 0xCB, 0x8E, 0xAD, 0x87, 0x21, 0x6A, 0x90, 0x11, 0xF1, 0x0A, 0xC4, 0x73, 0x31, 0xF6, 0x00, 0x29, 0x86,
+ 0x45, 0x01, 0x6A, 0xEC, 0x08, 0xDD, 0xBC, 0x19, 0x1E, 0xE4, 0x95, 0x35, 0xEB, 0xD3, 0x69, 0x2E, 0x4B, 0x9E, 0xC0, 0x7B,
+ 0x56, 0x1D, 0x7C, 0xD9, 0x62, 0x3B, 0x86, 0x1A, 0x38, 0x48, 0xC2, 0xAD, 0x15, 0xA5, 0x14, 0xBA, 0x71, 0x52, 0xEB, 0x6A,
+ 0xA9, 0x65, 0xAE, 0x9D, 0x61, 0xCE, 0x58, 0xFA, 0x86, 0x4B, 0x6F, 0x1A, 0x19, 0x2D, 0xC4, 0xC8, 0xEC, 0x02, 0x02, 0x88,
+ 0x14, 0x65, 0xA1, 0x31, 0xA0, 0x04, 0xF9, 0x38, 0xDF, 0xA3, 0x0D, 0x73, 0x5B, 0x76, 0x33, 0x94, 0xD5, 0xE2, 0x10, 0xD4,
+ 0x04, 0xA4, 0x86, 0x74, 0xE8, 0x60, 0xA9, 0x1C, 0x3E, 0x74, 0xFD, 0xCD, 0xB7, 0x3E, 0x74, 0xC7, 0x1D, 0x8F, 0xDC, 0x7B,
+ 0xFF, 0xD3, 0x77, 0xDF, 0xF9, 0xD8, 0x0D, 0xD7, 0xDD, 0x7D, 0xFC, 0x9A, 0x3B, 0xF7, 0xEC, 0xBC, 0x6A, 0xE5, 0xF0, 0x16,
+ 0x8A, 0xA3, 0xC1, 0xCE, 0x15, 0x32, 0x66, 0x89, 0x93, 0xEE, 0xBA, 0x76, 0x00, 0x69, 0x84, 0xF1, 0xC1, 0x40, 0x64, 0x64,
+ 0x6A, 0x44, 0x23, 0x19, 0x88, 0xEA, 0xC3, 0x50, 0x0B, 0x4C, 0xD6, 0x24, 0xD9, 0xA1, 0x7F, 0xF0, 0xBC, 0x00, 0xC1, 0x6E,
+ 0xCE, 0xA4, 0x0D, 0x90, 0x3A, 0x59, 0x08, 0x09, 0xF4, 0x56, 0x99, 0x85, 0x45, 0x26, 0x02, 0x6E, 0xC5, 0xD9, 0x55, 0xAD,
+ 0x7C, 0xE3, 0x6F, 0xF7, 0x72, 0x3A, 0x13, 0x28, 0x60, 0xA0, 0x6F, 0x15, 0x86, 0x4F, 0x35, 0x40, 0x1F, 0x77, 0xE5, 0xF0,
+ 0x56, 0xBA, 0x14, 0x14, 0xCC, 0x83, 0xBD, 0xAB, 0x77, 0x6C, 0x3A, 0x08, 0xA0, 0x73, 0x7A, 0x12, 0x8A, 0xE7, 0x02, 0x88,
+ 0x57, 0xE9, 0x4B, 0xA1, 0x63, 0x74, 0x60, 0x25, 0xCE, 0x05, 0xEF, 0x4D, 0x44, 0x8F, 0x9A, 0x83, 0x4D, 0x77, 0x2B, 0x48,
+ 0xDE, 0x2A, 0xB7, 0x63, 0x75, 0x60, 0xD1, 0xC6, 0xDA, 0xB2, 0xF6, 0x15, 0xA4, 0xB5, 0xC0, 0x10, 0x3F, 0x16, 0x93, 0xB7,
+ 0x42, 0x97, 0x24, 0x47, 0x1F, 0xF4, 0x92, 0x5B, 0xB5, 0x47, 0xCD, 0x14, 0xE9, 0x64, 0x32, 0x81, 0x33, 0xD2, 0x71, 0x0B,
+ 0x63, 0xDE, 0x13, 0x20, 0x70, 0xF1, 0x85, 0x17, 0x49, 0xD8, 0x9C, 0x31, 0xFB, 0xE2, 0x71, 0xE7, 0x53, 0xE9, 0x68, 0xC1,
+ 0xC9, 0x0F, 0xFB, 0x93, 0x2F, 0x3E, 0xFF, 0x82, 0xA8, 0xE0, 0x68, 0x80, 0xF8, 0xE1, 0x87, 0x9F, 0xFB, 0xCE, 0x77, 0xDE,
+ 0x79, 0xF4, 0xD1, 0xE7, 0xEF, 0xBA, 0xEB, 0xB1, 0x6B, 0xAE, 0xBC, 0x0D, 0x28, 0xD8, 0xBA, 0x71, 0xFF, 0xB2, 0x25, 0x1B,
+ 0x97, 0xF6, 0xAF, 0x81, 0x2D, 0xC1, 0x40, 0x98, 0x2D, 0x9E, 0xA6, 0xA9, 0x95, 0x41, 0x17, 0x4F, 0x1B, 0x1E, 0x2C, 0xF9,
+ 0xA8, 0xA0, 0x53, 0xB0, 0x14, 0xDE, 0x9A, 0x05, 0x22, 0x7A, 0x96, 0xDA, 0xA9, 0x93, 0x9C, 0x98, 0x43, 0x81, 0x69, 0x17,
+ 0x92, 0x98, 0x89, 0x98, 0xE8, 0x87, 0x47, 0x27, 0xD3, 0x17, 0xA9, 0x2C, 0x68, 0x04, 0xEE, 0x40, 0x1E, 0xB2, 0x20, 0xF4,
+ 0xBD, 0x7B, 0xE7, 0x15, 0xC7, 0x8E, 0xDE, 0x76, 0xD9, 0xF6, 0x23, 0x07, 0x0F, 0x1E, 0xDF, 0xBB, 0xF7, 0xD8, 0xD6, 0xAD,
+ 0x07, 0x48, 0x93, 0x80, 0x44, 0xCA, 0x66, 0x6E, 0xA1, 0x18, 0xA1, 0x00, 0x5E, 0x96, 0x13, 0xC5, 0x14, 0x70, 0x84, 0xED,
+ 0xC2, 0x32, 0xF6, 0xCE, 0x47, 0x70, 0xEE, 0xEA, 0x83, 0xA3, 0x17, 0x6A, 0xF0, 0xF9, 0x32, 0x22, 0xAA, 0x45, 0x1E, 0xAB,
+ 0x00, 0x11, 0x34, 0x68, 0xEE, 0x2E, 0x77, 0x66, 0x6D, 0x06, 0x8A, 0x26, 0xD9, 0xE7, 0x48, 0x2D, 0xEF, 0x28, 0xED, 0xE4,
+ 0x01, 0x8E, 0xDB, 0x99, 0x30, 0x4D, 0x3A, 0xA6, 0x98, 0xC1, 0x42, 0x49, 0x22, 0x42, 0x52, 0xDF, 0x9B, 0x2F, 0x66, 0xF7,
+ 0x7E, 0x57, 0x3C, 0x4A, 0x38, 0x4D, 0x96, 0x8F, 0xCF, 0xAC, 0x29, 0xBE, 0x6B, 0x96, 0x6F, 0x79, 0xF0, 0xE1, 0xE7, 0x9E,
+ 0x79, 0xEA, 0xD5, 0xEB, 0x6F, 0xBC, 0x0F, 0x7B, 0x3C, 0x7C, 0xF0, 0x3A, 0xBE, 0xF3, 0x60, 0x68, 0x60, 0x0D, 0x4C, 0xA1,
+ 0x2E, 0xBE, 0xA2, 0xBA, 0x79, 0xA0, 0x20, 0xB5, 0x8C, 0x7D, 0xE7, 0xD4, 0x19, 0xEA, 0x88, 0xF2, 0x66, 0x62, 0x52, 0xEC,
+ 0xA0, 0xCD, 0xD8, 0xA3, 0x98, 0x27, 0x98, 0xC3, 0x85, 0xF4, 0xC9, 0x83, 0xE9, 0xB5, 0x26, 0x0A, 0xF1, 0x20, 0x30, 0x92,
+ 0xC7, 0x85, 0x6C, 0x60, 0xE8, 0x20, 0xE8, 0x80, 0xB6, 0x4D, 0x41, 0x56, 0x45, 0x4B, 0x6D, 0x0F, 0xF2, 0x05, 0x73, 0xB6,
+ 0x6D, 0x3D, 0x74, 0x60, 0xFF, 0xF1, 0xDB, 0x6E, 0x7D, 0x98, 0x8C, 0xE0, 0x8A, 0xCB, 0xAF, 0xBF, 0xFA, 0xEA, 0xDB, 0xAE,
+ 0x3C, 0x7A, 0x33, 0xEF, 0x01, 0xC5, 0x34, 0x56, 0x75, 0x51, 0x45, 0xD3, 0xCE, 0x0A, 0x0B, 0x09, 0x9F, 0x3B, 0x63, 0xC6,
+ 0x08, 0xBC, 0x04, 0x22, 0xE8, 0x28, 0x49, 0x97, 0x83, 0xF9, 0x77, 0xA2, 0x0F, 0x79, 0x65, 0xFE, 0xA9, 0xBB, 0x84, 0xE7,
+ 0xE0, 0x2E, 0x7E, 0x7B, 0x0A, 0x1D, 0x78, 0xE1, 0xDB, 0x4B, 0x60, 0xD1, 0xC1, 0xB4, 0xCE, 0xA6, 0xE9, 0xC1, 0xDA, 0x45,
+ 0xF3, 0x5D, 0x67, 0x72, 0xC2, 0x2C, 0x8B, 0x90, 0xE9, 0x9D, 0x25, 0x33, 0x69, 0x0A, 0xA4, 0x9B, 0x5E, 0xBD, 0x4E, 0x40,
+ 0x67, 0x82, 0x73, 0x42, 0x78, 0x1F, 0xB8, 0x30, 0x29, 0x90, 0xDF, 0xDC, 0x79, 0xB3, 0x66, 0xCC, 0x64, 0xD3, 0x19, 0x5C,
+ 0x9D, 0x89, 0x17, 0x5D, 0x0C, 0xC7, 0x82, 0x19, 0x8E, 0x68, 0x45, 0xDA, 0x5F, 0xA2, 0x86, 0xD8, 0xD0, 0x84, 0x2D, 0x9B,
+ 0xF6, 0xDF, 0x7D, 0xF7, 0xE3, 0xB4, 0x07, 0xF0, 0x09, 0xF2, 0xC2, 0x63, 0x57, 0xDC, 0x82, 0x3D, 0x2E, 0x19, 0x5A, 0x07,
+ 0x21, 0xA5, 0xA2, 0xA0, 0x1E, 0x57, 0x20, 0x3C, 0xD0, 0xCD, 0x27, 0x96, 0x32, 0x6E, 0x22, 0x5B, 0x45, 0x07, 0xD2, 0x86,
+ 0x92, 0xDD, 0x00, 0x32, 0xF5, 0x54, 0xF6, 0x8D, 0x36, 0xA6, 0x9C, 0xC1, 0x96, 0x21, 0x44, 0x61, 0xFE, 0xC2, 0x6F, 0x10,
+ 0xB5, 0x25, 0xD2, 0x02, 0x31, 0x3B, 0xB1, 0x32, 0xCB, 0xB2, 0x85, 0x02, 0x43, 0x39, 0xB6, 0x7A, 0x78, 0xDB, 0xEE, 0xDD,
+ 0x57, 0xDC, 0x72, 0xF3, 0x83, 0x07, 0xF6, 0x5C, 0x45, 0x77, 0xE8, 0xE6, 0x5B, 0x1F, 0x64, 0xC4, 0x7D, 0xDB, 0x6D, 0x0F,
+ 0x1D, 0xDC, 0x7F, 0x0D, 0xAE, 0x40, 0xE1, 0xC6, 0xBF, 0x83, 0x8E, 0xDF, 0x54, 0xDF, 0x06, 0xED, 0x3C, 0x74, 0x41, 0x80,
+ 0xC6, 0x24, 0x99, 0x5B, 0x04, 0x45, 0x49, 0xD9, 0x0F, 0xF8, 0x18, 0xB9, 0x5B, 0x8A, 0x89, 0xAA, 0x41, 0x66, 0x56, 0xEE,
+ 0xAF, 0xB8, 0xEB, 0x63, 0xCD, 0xDC, 0x4B, 0x45, 0x72, 0xD5, 0x20, 0xF3, 0x58, 0xE5, 0xC3, 0x68, 0x32, 0x23, 0x86, 0x26,
+ 0x52, 0x76, 0xC6, 0xA1, 0x0E, 0x87, 0x85, 0x91, 0x10, 0xB3, 0x14, 0x1D, 0x1D, 0xAB, 0x86, 0x4C, 0x23, 0x48, 0x49, 0x4E,
+ 0xEE, 0x5C, 0xDB, 0xB9, 0xD0, 0xDA, 0x58, 0x27, 0x79, 0x02, 0x1A, 0x8C, 0xC2, 0xFD, 0x64, 0xA0, 0x4F, 0xDE, 0x82, 0x43,
+ 0x90, 0xB9, 0x83, 0xAD, 0x34, 0xEC, 0x20, 0x11, 0xD3, 0xF3, 0x1A, 0x7F, 0xC1, 0x85, 0x42, 0x22, 0x3E, 0xFD, 0xCC, 0x73,
+ 0xCE, 0x18, 0xC7, 0xD8, 0xE4, 0x81, 0x47, 0x9E, 0x7B, 0xFA, 0xA9, 0x57, 0xEF, 0xB9, 0xE7, 0xB1, 0xE3, 0x57, 0xDF, 0xC1,
+ 0x37, 0xE1, 0x1C, 0x3B, 0x76, 0x0B, 0xE3, 0x1D, 0x1C, 0x62, 0xE5, 0x92, 0x8D, 0xDD, 0x9D, 0x8B, 0xE5, 0x5B, 0x71, 0x8A,
+ 0x5B, 0x18, 0x78, 0x71, 0x1A, 0x34, 0x3D, 0x3E, 0x1A, 0x99, 0x12, 0xAE, 0x62, 0x4C, 0x7D, 0xCE, 0x58, 0x9F, 0x14, 0xD6,
+ 0xF0, 0x8B, 0xB9, 0x6B, 0xDE, 0x61, 0x12, 0x43, 0x2A, 0x06, 0xF4, 0xFC, 0x4A, 0x76, 0xB5, 0x24, 0xA4, 0x53, 0x67, 0xC0,
+ 0x88, 0x85, 0xB9, 0x5D, 0x92, 0x59, 0x49, 0x8B, 0x94, 0x6E, 0x39, 0x18, 0x78, 0xFB, 0x6D, 0x8F, 0xDC, 0x73, 0xD7, 0x13,
+ 0xF4, 0x24, 0xEE, 0xBC, 0xFB, 0xF1, 0x07, 0x1F, 0xFC, 0x3A, 0xD2, 0xBF, 0xFF, 0xFE, 0xA7, 0x09, 0x4E, 0xD7, 0x5C, 0x7D,
+ 0xC7, 0xD1, 0xCB, 0x6F, 0x5A, 0xB7, 0x76, 0x17, 0xBD, 0x13, 0x8A, 0x09, 0xF6, 0x17, 0x13, 0xC6, 0x66, 0x4E, 0x99, 0x2E,
+ 0x29, 0xBF, 0xF1, 0x39, 0x05, 0x1C, 0x47, 0xE2, 0x1E, 0x9A, 0x8F, 0xD7, 0x1B, 0xCC, 0x75, 0x18, 0x4B, 0xFC, 0xC0, 0x6B,
+ 0xF8, 0xA3, 0xC7, 0x8D, 0x42, 0x80, 0xC1, 0xBA, 0x91, 0x9A, 0xF2, 0x00, 0xB8, 0x90, 0x61, 0x8B, 0x09, 0xE8, 0x12, 0x52,
+ 0x82, 0x23, 0xF9, 0xD6, 0x25, 0x1E, 0x27, 0x23, 0xE4, 0xB5, 0x94, 0x6D, 0x29, 0xAA, 0x8A, 0x66, 0xD2, 0x6B, 0x36, 0xF5,
+ 0x45, 0xB2, 0xD1, 0xD5, 0x21, 0x16, 0x58, 0xB2, 0x85, 0x4B, 0x43, 0x12, 0x6A, 0x9E, 0x74, 0xE8, 0x4C, 0xC5, 0x48, 0x84,
+ 0x24, 0x84, 0x92, 0x2C, 0x6A, 0x77, 0x01, 0xB7, 0x10, 0x65, 0x40, 0x22, 0x9E, 0x38, 0xE9, 0xDC, 0xAF, 0xC9, 0x16, 0x87,
+ 0xAC, 0xA4, 0x7C, 0x6C, 0xF0, 0xBE, 0xFB, 0x9E, 0xBA, 0xEE, 0xF8, 0x9D, 0x00, 0xC2, 0xD1, 0x23, 0x37, 0x90, 0xA8, 0xD0,
+ 0x2D, 0xC0, 0x24, 0xA1, 0x96, 0x0E, 0x0F, 0xAD, 0x87, 0xB0, 0xC5, 0x6E, 0x03, 0xC8, 0x2F, 0x18, 0x66, 0x4E, 0xD2, 0xC8,
+ 0xD1, 0x35, 0x08, 0x1A, 0x05, 0xA8, 0x37, 0x90, 0xF0, 0x70, 0x8C, 0x1B, 0x8E, 0xC2, 0x86, 0x06, 0xC2, 0x38, 0x5C, 0x5B,
+ 0xD9, 0x4E, 0xC1, 0xB1, 0xFC, 0x4C, 0x26, 0x98, 0x9D, 0x65, 0x70, 0x5C, 0x47, 0x2D, 0xD1, 0x98, 0xD6, 0x2C, 0x95, 0x20,
+ 0x73, 0x6C, 0x58, 0x1D, 0x77, 0xDC, 0xFE, 0x28, 0x89, 0xD9, 0x93, 0x4F, 0xBE, 0x74, 0xC7, 0x6D, 0x0F, 0x73, 0x77, 0xD7,
+ 0xF6, 0x23, 0x03, 0x1D, 0xC3, 0x7D, 0xDD, 0xCB, 0xF8, 0xA7, 0xD0, 0xF1, 0xD6, 0xAF, 0xDF, 0xD5, 0x54, 0xDF, 0x45, 0x53,
+ 0x8B, 0x39, 0x2B, 0xEE, 0x45, 0x8A, 0xA1, 0x88, 0xA4, 0x0A, 0xF0, 0x62, 0x8E, 0x48, 0xDC, 0x98, 0xBF, 0x75, 0x05, 0xEB,
+ 0x1F, 0x8E, 0x1F, 0x78, 0xE3, 0xA7, 0x35, 0x5E, 0xC5, 0x10, 0x37, 0x8F, 0x14, 0x1E, 0x0A, 0xB5, 0x0F, 0xFF, 0x43, 0x67,
+ 0xF1, 0xDC, 0x15, 0x69, 0x86, 0x40, 0x71, 0x4D, 0x60, 0x8C, 0x07, 0x0F, 0xDE, 0xD0, 0x17, 0xA5, 0x01, 0xA7, 0x0C, 0x17,
+ 0xEB, 0x19, 0x5E, 0x36, 0xC7, 0x18, 0x2A, 0x98, 0x36, 0x4A, 0x35, 0x35, 0xD4, 0xEC, 0x85, 0x7E, 0x0B, 0xD0, 0xA4, 0xAD,
+ 0x2E, 0x5A, 0x9E, 0xB3, 0xA6, 0x4D, 0xA5, 0xE1, 0x7B, 0x9A, 0xCF, 0x59, 0x4C, 0xE1, 0xAF, 0xBD, 0xE6, 0xCE, 0x07, 0x1E,
+ 0x7A, 0xF6, 0xA1, 0x87, 0x9E, 0xBD, 0xFD, 0xF6, 0x07, 0xB1, 0x50, 0xBA, 0x05, 0x57, 0x1F, 0xBB, 0xF5, 0xC8, 0xA1, 0xEB,
+ 0x48, 0x64, 0xE9, 0xA6, 0x6D, 0x5C, 0xBD, 0x83, 0x4C, 0x09, 0xAE, 0x35, 0x6C, 0xC6, 0x46, 0x73, 0x42, 0x7A, 0x41, 0xAA,
+ 0x1C, 0x67, 0xC0, 0x4C, 0x38, 0x33, 0x39, 0x1D, 0xE6, 0x84, 0x94, 0x99, 0x09, 0x69, 0x24, 0x5D, 0xC2, 0x52, 0x30, 0xDF,
+ 0x85, 0x00, 0xF9, 0x1E, 0x8E, 0x17, 0x4C, 0xE1, 0xF4, 0x98, 0x1C, 0x78, 0x44, 0x9C, 0xD1, 0xC4, 0xA0, 0xA6, 0x91, 0xAF,
+ 0x67, 0xE2, 0x4B, 0xFB, 0x5A, 0x06, 0xF7, 0xEC, 0xBA, 0x02, 0x87, 0xBB, 0xFF, 0xBE, 0x67, 0x30, 0xFF, 0x9B, 0x6E, 0xB8,
+ 0x97, 0x6D, 0x77, 0xB8, 0xC8, 0xC2, 0x39, 0xC1, 0x6C, 0x4D, 0xC4, 0x2C, 0xE8, 0x11, 0x01, 0xA4, 0x2D, 0x75, 0x1D, 0xA4,
+ 0x49, 0x0D, 0x35, 0x8B, 0xF0, 0x06, 0x88, 0x81, 0xBC, 0x79, 0x96, 0xA6, 0x43, 0xC4, 0x67, 0x09, 0x06, 0xA1, 0xCC, 0x4D,
+ 0x1D, 0xF4, 0xF7, 0x3A, 0x81, 0x92, 0x0D, 0x25, 0x66, 0x10, 0x0F, 0x6C, 0x36, 0x39, 0x86, 0x99, 0xA2, 0x44, 0x25, 0x91,
+ 0x66, 0xB8, 0xD0, 0x89, 0xF9, 0x1B, 0x14, 0x90, 0x99, 0x9C, 0x8A, 0x8F, 0x4B, 0x81, 0x47, 0x1C, 0x0B, 0x8D, 0xC4, 0x7E,
+ 0x4D, 0x7B, 0xD6, 0xB7, 0xBA, 0xA2, 0x9E, 0x7F, 0x49, 0xB2, 0x61, 0xC8, 0xDF, 0x86, 0x63, 0x23, 0xA8, 0x25, 0x3D, 0x51,
+ 0x75, 0x20, 0x13, 0x3C, 0x5C, 0x75, 0x1A, 0x4A, 0x8B, 0x8E, 0x91, 0x59, 0x26, 0x6F, 0x71, 0xF8, 0xA9, 0x5A, 0xE2, 0x6A,
+ 0xC5, 0x44, 0x91, 0x45, 0xCB, 0x81, 0x61, 0x13, 0xDD, 0x18, 0x7A, 0x93, 0xF4, 0x27, 0x6E, 0xBD, 0xF9, 0x81, 0xDB, 0xEE,
+ 0x78, 0xE4, 0xE1, 0x87, 0xBE, 0xF1, 0xC8, 0x43, 0x12, 0x12, 0xEE, 0xBA, 0xF3, 0x71, 0x1E, 0x41, 0x07, 0xBB, 0x76, 0x5E,
+ 0xB1, 0x6E, 0xCD, 0x8E, 0x15, 0x4B, 0x37, 0x61, 0x9B, 0x3D, 0x9D, 0x7C, 0x6D, 0xE0, 0x80, 0xE8, 0x80, 0x6D, 0x20, 0x85,
+ 0xF5, 0x25, 0x99, 0xE5, 0x6C, 0x1B, 0x2D, 0xCD, 0xAA, 0x80, 0xA2, 0x90, 0x9B, 0x98, 0x2F, 0x47, 0x21, 0x16, 0xD7, 0x65,
+ 0xC4, 0xE6, 0xE6, 0x25, 0x71, 0xC0, 0x33, 0x67, 0xC0, 0x96, 0xC0, 0x40, 0xA5, 0xCE, 0x82, 0x3F, 0x09, 0xCB, 0x91, 0x56,
+ 0x39, 0xDC, 0x19, 0xE1, 0xA4, 0x36, 0xF4, 0xF2, 0x6A, 0xFB, 0xF7, 0x5F, 0xCD, 0x78, 0x80, 0x20, 0x74, 0xCD, 0x55, 0xB7,
+ 0xAD, 0x5A, 0xBE, 0x25, 0x3C, 0x30, 0xF6, 0x74, 0x9F, 0xB3, 0x6C, 0xDA, 0xA6, 0x17, 0x9C, 0x6D, 0x0B, 0x07, 0x60, 0xE9,
+ 0xE2, 0xB5, 0x75, 0xD5, 0x2D, 0xCA, 0x82, 0xA1, 0x1D, 0x22, 0xB5, 0x5E, 0x90, 0xF0, 0x2A, 0x94, 0x8F, 0x8D, 0x0E, 0xC2,
+ 0x43, 0x25, 0x0B, 0x38, 0x09, 0x88, 0xC8, 0x4D, 0x05, 0xB2, 0x44, 0x07, 0x63, 0xA5, 0x3F, 0x42, 0x48, 0x32, 0x24, 0x2D,
+ 0xB0, 0x3B, 0x24, 0x1C, 0xA0, 0x80, 0xB6, 0x46, 0xDA, 0x3E, 0x6B, 0x86, 0x2F, 0x0D, 0x2F, 0x18, 0x03, 0xD8, 0x29, 0x03,
+ 0x10, 0x7C, 0x85, 0xDD, 0x58, 0x58, 0x01, 0x00, 0xA2, 0xFC, 0x6F, 0x65, 0xD2, 0xA1, 0x03, 0x95, 0xBE, 0xF5, 0x24, 0x0D,
+ 0xE6, 0xFA, 0x82, 0x2E, 0xC9, 0x0E, 0xC6, 0x47, 0xB8, 0x43, 0xAA, 0x30, 0xD5, 0x8D, 0xCE, 0x34, 0xB4, 0xBF, 0x48, 0x12,
+ 0xC9, 0x77, 0x3B, 0xA1, 0x8C, 0xA9, 0x97, 0x48, 0xE7, 0x9D, 0xF1, 0x21, 0x72, 0xBF, 0xF7, 0xDE, 0x27, 0x1F, 0x78, 0xE8,
+ 0xB9, 0xFB, 0x1E, 0xF8, 0x3A, 0xA0, 0xF4, 0xC0, 0x03, 0xCF, 0x3C, 0xF2, 0xC8, 0x37, 0x58, 0x24, 0x8E, 0x97, 0x6D, 0x3B,
+ 0xC4, 0x13, 0x56, 0x0F, 0x6F, 0xE5, 0xC8, 0x6B, 0x86, 0xCF, 0x10, 0x00, 0xE8, 0x36, 0x37, 0x55, 0x89, 0x45, 0xB7, 0xD4,
+ 0x75, 0xB3, 0x69, 0x92, 0x38, 0xC1, 0xD7, 0x8A, 0x72, 0xC8, 0x3F, 0x5A, 0x61, 0x31, 0x91, 0xAF, 0xCA, 0xAF, 0xA7, 0xB6,
+ 0x90, 0x60, 0x9E, 0x51, 0x01, 0xF2, 0xB4, 0x35, 0x0D, 0xA0, 0x03, 0xF9, 0xE2, 0xE8, 0xB6, 0xC5, 0xE8, 0x92, 0xD1, 0xD8,
+ 0x75, 0xC7, 0xEF, 0x42, 0x01, 0xB7, 0xDE, 0xF9, 0x08, 0x0E, 0x91, 0x18, 0x99, 0x26, 0x89, 0x9A, 0x49, 0x11, 0x18, 0x74,
+ 0x43, 0xE5, 0x27, 0x8B, 0x33, 0xE9, 0x82, 0xA4, 0x0D, 0x64, 0x53, 0x83, 0x7D, 0x2B, 0xE8, 0x68, 0xD5, 0x54, 0xB6, 0x20,
+ 0x22, 0xD4, 0x20, 0x19, 0xAA, 0x22, 0x92, 0x64, 0x47, 0x92, 0x1A, 0x99, 0x40, 0xED, 0x44, 0x08, 0x55, 0x86, 0x4D, 0x52,
+ 0x7D, 0xDC, 0xD4, 0xC5, 0x61, 0xEF, 0x3A, 0x00, 0x12, 0x65, 0x98, 0x71, 0x0E, 0x23, 0x31, 0x8E, 0x6A, 0x13, 0xB0, 0xA2,
+ 0x9A, 0x15, 0xE2, 0x85, 0x7C, 0x43, 0x52, 0x1E, 0xE7, 0x4E, 0x32, 0x2F, 0x65, 0x76, 0xCA, 0xA8, 0x8F, 0xD4, 0x18, 0x46,
+ 0xBB, 0x28, 0x3F, 0x50, 0x38, 0x97, 0x8A, 0x36, 0x4A, 0x63, 0xD2, 0x30, 0xEE, 0xA2, 0x93, 0x13, 0xCC, 0x5D, 0x1D, 0x08,
+ 0x25, 0x4B, 0x88, 0x37, 0x86, 0xA7, 0xA5, 0xF1, 0x79, 0x34, 0x5B, 0x5B, 0x7C, 0x02, 0x50, 0xA2, 0x6E, 0x68, 0x6A, 0xEC,
+ 0x04, 0xF7, 0x89, 0xC3, 0xE4, 0x45, 0xF7, 0x3F, 0xF8, 0xEC, 0x8B, 0x2F, 0xBF, 0xF5, 0xF2, 0xCB, 0xDF, 0x7F, 0xF9, 0xD5,
+ 0xB7, 0x5F, 0xF9, 0xD6, 0x0F, 0x1F, 0x7E, 0xF4, 0x79, 0xF4, 0xF1, 0xD0, 0x83, 0xCF, 0x91, 0x3B, 0x6E, 0xD9, 0x78, 0x90,
+ 0x9A, 0x16, 0x13, 0xA6, 0x92, 0xA2, 0x90, 0xE6, 0x62, 0xED, 0xCA, 0xCB, 0xA0, 0x4A, 0x0A, 0x19, 0x82, 0x01, 0x40, 0x43,
+ 0x0F, 0x23, 0x20, 0xBE, 0x34, 0x5D, 0xBE, 0x9B, 0xB2, 0xB9, 0x8F, 0xC7, 0xE9, 0x43, 0x34, 0xD5, 0x75, 0x93, 0xF8, 0x12,
+ 0x7E, 0x07, 0x16, 0x0D, 0x2F, 0x5D, 0xBC, 0x7E, 0xCD, 0xAA, 0xED, 0x5B, 0x37, 0xEF, 0x27, 0xD2, 0xE0, 0x5E, 0x84, 0x5F,
+ 0xE2, 0xF0, 0x3D, 0x77, 0x3F, 0x49, 0xCC, 0xBF, 0xE0, 0x9C, 0x8B, 0x10, 0xF7, 0x19, 0x67, 0x9C, 0xC5, 0x84, 0x15, 0x14,
+ 0x1A, 0x7F, 0xF1, 0x85, 0x13, 0x2E, 0x18, 0xCF, 0xD6, 0x23, 0xB6, 0xE3, 0x69, 0x4A, 0x4D, 0x83, 0x84, 0xAD, 0xFA, 0xCD,
+ 0x1C, 0x5A, 0x5F, 0xDB, 0xA5, 0xDF, 0x04, 0x63, 0x0A, 0x05, 0x47, 0xD0, 0x24, 0xAF, 0x4E, 0xAD, 0xE0, 0xC9, 0x50, 0x47,
+ 0xE9, 0x40, 0x13, 0x47, 0xDB, 0x4A, 0x73, 0x87, 0x8B, 0x71, 0x89, 0x61, 0xB0, 0x77, 0x25, 0x72, 0xD2, 0x5D, 0x01, 0x3A,
+ 0xB0, 0x2F, 0x86, 0xA2, 0x9C, 0x6F, 0x06, 0x2F, 0x1C, 0xE9, 0xE3, 0x16, 0x81, 0x01, 0x41, 0x54, 0x58, 0xD8, 0xA9, 0xA1,
+ 0x96, 0x48, 0x2E, 0x2C, 0x34, 0x26, 0x08, 0x3C, 0x11, 0x51, 0xF1, 0x91, 0xB2, 0x4B, 0x54, 0x5E, 0xD6, 0xD5, 0x81, 0xF2,
+ 0x1B, 0x8D, 0x1F, 0xC8, 0x73, 0x48, 0x37, 0x75, 0x94, 0x2F, 0x89, 0x79, 0x28, 0x39, 0x92, 0x99, 0xA0, 0x05, 0x88, 0x1A,
+ 0x1C, 0xC6, 0xFC, 0x82, 0x60, 0xB0, 0x88, 0x93, 0x63, 0xE1, 0xF8, 0xAF, 0x5B, 0xB5, 0x63, 0xC3, 0xBA, 0x5D, 0x07, 0xF6,
+ 0x1D, 0x23, 0x17, 0x7A, 0xEA, 0xA9, 0x97, 0x9F, 0xFF, 0xE6, 0xF7, 0xBE, 0xFE, 0xDC, 0xEB, 0xAF, 0xBD, 0xF6, 0xF6, 0xB3,
+ 0xCF, 0xBE, 0xFA, 0xCD, 0x6F, 0xBE, 0xF1, 0xDC, 0x73, 0xAF, 0x3F, 0xF2, 0xD8, 0x0B, 0xE8, 0x86, 0xF4, 0x11, 0xDA, 0x36,
+ 0xB1, 0x81, 0xA6, 0xC2, 0xEA, 0x65, 0x9B, 0xF9, 0xDA, 0x2E, 0x88, 0xAA, 0x74, 0x17, 0x54, 0xCA, 0x24, 0xFB, 0xCB, 0x06,
+ 0xD6, 0x12, 0x33, 0xC8, 0x29, 0x71, 0x17, 0x1E, 0xA1, 0xF3, 0xC1, 0x33, 0x65, 0x28, 0x7F, 0xE0, 0x38, 0x64, 0x6F, 0xCA,
+ 0x0E, 0xDA, 0x0F, 0x87, 0x0F, 0x5E, 0x7B, 0xFC, 0xEA, 0x5B, 0xAF, 0xB9, 0xE6, 0x76, 0xDC, 0x8E, 0x71, 0x31, 0xBF, 0x82,
+ 0x78, 0x2A, 0x93, 0xB2, 0x33, 0x65, 0x50, 0x33, 0x75, 0xE2, 0x25, 0xEC, 0x56, 0x67, 0x31, 0x11, 0x63, 0x34, 0xC6, 0x67,
+ 0xE7, 0x98, 0x67, 0x65, 0x43, 0x11, 0xD5, 0x70, 0x23, 0x16, 0x69, 0x12, 0xF8, 0x2C, 0x35, 0xA0, 0xA9, 0x99, 0x25, 0x4D,
+ 0x72, 0x32, 0x51, 0x97, 0x76, 0x0E, 0x04, 0x49, 0xC0, 0x90, 0x14, 0x56, 0xB0, 0xC8, 0x2A, 0xC0, 0x9B, 0xBF, 0x8B, 0x09,
+ 0x43, 0xA5, 0x0F, 0x33, 0xB1, 0x37, 0x28, 0x0A, 0x59, 0x43, 0x4F, 0x67, 0x70, 0x48, 0x0A, 0x81, 0xF8, 0xC8, 0xE8, 0x49,
+ 0xE4, 0x81, 0xC2, 0x89, 0x17, 0x4E, 0x20, 0xA1, 0xD4, 0xC6, 0x00, 0x9D, 0x4B, 0x07, 0x8B, 0x22, 0xA3, 0x84, 0x41, 0x46,
+ 0x05, 0xE0, 0x38, 0x84, 0xBB, 0x37, 0xC8, 0xC4, 0x6A, 0x8B, 0x45, 0xC2, 0xD0, 0x0E, 0x17, 0x92, 0x1D, 0xB4, 0x7D, 0xD8,
+ 0x67, 0x1A, 0x9D, 0x30, 0x1C, 0xA9, 0xF5, 0x03, 0x44, 0x0D, 0x0C, 0x9E, 0xF8, 0x24, 0xC4, 0x52, 0x52, 0x8E, 0x86, 0xDA,
+ 0x0E, 0xEA, 0x03, 0x86, 0x88, 0x9B, 0xD6, 0xEF, 0x04, 0x19, 0x38, 0xB5, 0x02, 0x08, 0x7A, 0xEA, 0xA9, 0x17, 0x7F, 0xF4,
+ 0xA3, 0xF7, 0x7F, 0xF0, 0x83, 0x9F, 0x3F, 0xF3, 0xCC, 0xCB, 0xDF, 0x7E, 0xE3, 0xC7, 0xAF, 0xBD, 0xF6, 0x43, 0x4D, 0x1C,
+ 0xC1, 0x71, 0x34, 0xB1, 0x7F, 0xC7, 0x95, 0xDB, 0x36, 0xED, 0x67, 0xE3, 0x34, 0x0E, 0x84, 0x32, 0x56, 0x0E, 0x6F, 0xA2,
+ 0xF5, 0x8F, 0x99, 0x93, 0xED, 0xE0, 0x4F, 0x58, 0x3A, 0x7D, 0xA7, 0xDD, 0x97, 0x5D, 0x4E, 0x2B, 0xD0, 0x04, 0xF6, 0xEB,
+ 0xA9, 0xBC, 0x30, 0x79, 0x62, 0xCC, 0x7D, 0xF7, 0x3E, 0x8D, 0xA6, 0xAF, 0x3E, 0x76, 0x33, 0xA1, 0xF8, 0xAA, 0x2B, 0x6F,
+ 0xD9, 0xBC, 0x79, 0x5F, 0x62, 0x64, 0x06, 0x22, 0x86, 0x0B, 0x4B, 0x05, 0x43, 0x70, 0x62, 0x33, 0x8B, 0xB3, 0xA6, 0x4E,
+ 0xF7, 0x9D, 0x3C, 0x95, 0x4C, 0x1A, 0x65, 0xB0, 0x13, 0x04, 0x80, 0x02, 0x9F, 0x39, 0xEB, 0x8A, 0x83, 0xCE, 0x81, 0x6B,
+ 0xBA, 0x81, 0xD2, 0xBD, 0xA0, 0x49, 0x47, 0x54, 0x30, 0x0E, 0x61, 0xF0, 0x47, 0x3E, 0xA6, 0xB9, 0x8D, 0x8A, 0x0C, 0x8C,
+ 0x51, 0x98, 0x1A, 0xD1, 0x81, 0x42, 0x87, 0x75, 0x02, 0x01, 0x22, 0x73, 0x6A, 0x87, 0x39, 0x58, 0x2B, 0x64, 0x8E, 0xEF,
+ 0x6C, 0x4C, 0x9E, 0xC1, 0xF4, 0x39, 0xE7, 0x9C, 0x8D, 0x0F, 0xA2, 0x7F, 0xA2, 0xB1, 0x34, 0xEB, 0x69, 0xB9, 0xF8, 0x07,
+ 0x21, 0x38, 0x09, 0xF4, 0x80, 0x7B, 0xB0, 0x70, 0xB6, 0x14, 0x6D, 0x0C, 0xE8, 0xCB, 0xFE, 0x2C, 0xD4, 0x36, 0xE2, 0x0D,
+ 0x91, 0x44, 0x0B, 0x93, 0xC2, 0x86, 0x4B, 0x89, 0x60, 0xA8, 0xF0, 0xF8, 0x81, 0x79, 0x7F, 0x92, 0xD5, 0x85, 0x84, 0x2C,
+ 0x0C, 0x04, 0xFA, 0x18, 0xBF, 0x10, 0x81, 0xC8, 0xE8, 0x31, 0x25, 0x66, 0xF7, 0x18, 0x2C, 0x3B, 0x2C, 0xC9, 0xE2, 0x43,
+ 0x65, 0xEA, 0x1B, 0x91, 0x1E, 0x9F, 0xD3, 0xDD, 0x36, 0x48, 0xFB, 0xFE, 0xC1, 0x07, 0x9E, 0x7D, 0xF6, 0xD9, 0xD7, 0x5E,
+ 0xFE, 0xD6, 0xF7, 0x5F, 0x7C, 0xE5, 0x7B, 0xCF, 0x3D, 0xFF, 0x1D, 0x74, 0x40, 0x4F, 0x89, 0x98, 0xC1, 0xC5, 0xE5, 0x97,
+ 0xDF, 0xC0, 0x77, 0x8D, 0x23, 0x44, 0x0C, 0x99, 0x0E, 0x07, 0x2E, 0x62, 0x94, 0x77, 0xCB, 0x9D, 0x77, 0x3C, 0x76, 0xDD,
+ 0x75, 0x77, 0x91, 0x53, 0x91, 0x71, 0xDE, 0x7D, 0xEF, 0x93, 0x32, 0x97, 0xBF, 0xE5, 0x81, 0xFB, 0xEF, 0x7F, 0xF2, 0x9E,
+ 0x7B, 0x9E, 0xF8, 0xC6, 0x37, 0xBE, 0xFD, 0xCC, 0x33, 0xAF, 0x82, 0x3F, 0x38, 0x99, 0xD4, 0x83, 0x37, 0x3F, 0xC8, 0xD3,
+ 0x2E, 0xDB, 0x72, 0x28, 0x2E, 0x2C, 0x19, 0x1D, 0x40, 0x3B, 0x43, 0xF4, 0xF3, 0xA7, 0xCB, 0xE4, 0x47, 0x13, 0x68, 0xEC,
+ 0xCF, 0xB4, 0xC1, 0x67, 0x12, 0x00, 0x7C, 0xA7, 0x4F, 0x63, 0x97, 0xD1, 0x85, 0xE3, 0xCE, 0x23, 0x99, 0xF6, 0x9D, 0xCA,
+ 0x50, 0x73, 0x56, 0x70, 0x80, 0xEA, 0x20, 0x42, 0x5A, 0xB9, 0x76, 0x37, 0x86, 0xCD, 0x97, 0xDC, 0x4E, 0x06, 0x85, 0xBA,
+ 0x8F, 0x95, 0xBB, 0xBD, 0x50, 0xFB, 0x15, 0x0F, 0x40, 0x46, 0x2C, 0x34, 0x16, 0x20, 0xAD, 0x79, 0xC4, 0x6D, 0xDA, 0xBF,
+ 0x32, 0x29, 0xD5, 0x7E, 0x24, 0x78, 0xAD, 0x0A, 0xD0, 0xFE, 0x94, 0xD9, 0x6A, 0x20, 0xD8, 0xA2, 0x7F, 0x6E, 0xD4, 0x20,
+ 0x83, 0x62, 0x93, 0xB0, 0x3A, 0x65, 0x1D, 0x04, 0x1B, 0xE3, 0x01, 0xD2, 0x1B, 0x10, 0xE0, 0x32, 0x6A, 0x60, 0x47, 0x5B,
+ 0x70, 0x60, 0x08, 0x6D, 0x77, 0x94, 0x6A, 0x06, 0x2C, 0xB3, 0xE8, 0xB1, 0x10, 0xC3, 0xB1, 0x2F, 0xD4, 0xBF, 0x78, 0x70,
+ 0x2D, 0x03, 0x03, 0x3C, 0x4F, 0x53, 0x11, 0xAD, 0x9C, 0x27, 0x5C, 0x30, 0x91, 0xE9, 0x1B, 0xA5, 0x2C, 0x12, 0x7C, 0xEA,
+ 0x89, 0x6F, 0xBE, 0xF0, 0xC2, 0xB7, 0x9F, 0x7E, 0xFA, 0xA5, 0xC7, 0x1E, 0x7B, 0x01, 0x95, 0x90, 0xCB, 0xD3, 0x59, 0x7A,
+ 0xE2, 0x89, 0x17, 0xB9, 0x25, 0xA7, 0x24, 0xB4, 0xE2, 0x34, 0x8F, 0x3F, 0xF9, 0xF2, 0x53, 0x4F, 0xBC, 0x74, 0xEF, 0x83,
+ 0x5F, 0xBF, 0xFD, 0xCE, 0xC7, 0xB8, 0xFB, 0xD8, 0x63, 0xDF, 0x78, 0xFC, 0xB1, 0x17, 0x5F, 0x27, 0x9C, 0x3C, 0xFC, 0x1C,
+ 0xD2, 0x07, 0xDC, 0xF8, 0xAB, 0xEF, 0x7E, 0xFB, 0x47, 0xAF, 0xBE, 0xFA, 0xFD, 0xE7, 0x5E, 0x78, 0xFD, 0x89, 0xA7, 0x5E,
+ 0x46, 0x13, 0x94, 0x23, 0xC7, 0xAE, 0xBC, 0x95, 0xD3, 0x19, 0x60, 0xFB, 0x72, 0x78, 0x0F, 0x5F, 0x73, 0xA1, 0xF3, 0x67,
+ 0x19, 0xBA, 0xF9, 0x8A, 0x1C, 0xA4, 0x2B, 0x6E, 0x68, 0x03, 0x2C, 0x99, 0xD9, 0xCD, 0xF2, 0x65, 0xA1, 0x27, 0x54, 0xA2,
+ 0x4D, 0x59, 0x69, 0x52, 0x19, 0x92, 0x99, 0x69, 0xD5, 0x99, 0x34, 0x69, 0xA1, 0x2C, 0x15, 0x97, 0x2A, 0x46, 0x7A, 0x76,
+ 0x2A, 0x7A, 0x5B, 0xFA, 0x3A, 0xF9, 0xBB, 0xF0, 0xC8, 0xA3, 0x65, 0xB3, 0x67, 0xB8, 0x90, 0x41, 0xB5, 0x07, 0x6B, 0xC7,
+ 0x23, 0x9A, 0xB7, 0x68, 0x4B, 0xD2, 0x34, 0xCA, 0xE5, 0xB5, 0x00, 0x13, 0xD1, 0x41, 0xB0, 0x34, 0x82, 0x34, 0xF5, 0xB4,
+ 0xFB, 0x0C, 0x34, 0x5B, 0x55, 0x14, 0x92, 0x97, 0xA5, 0x69, 0x6A, 0xB4, 0x6B, 0x4A, 0x18, 0x43, 0xC6, 0xF2, 0x0B, 0x64,
+ 0x04, 0xC8, 0xC7, 0x63, 0x8C, 0x95, 0x9F, 0x53, 0xDC, 0xD5, 0xDA, 0x0D, 0xCD, 0xDD, 0x7C, 0x91, 0x47, 0x2C, 0x29, 0x0A,
+ 0x95, 0x81, 0xC6, 0x3D, 0x91, 0xFD, 0x69, 0x9A, 0x90, 0x38, 0xAD, 0xA4, 0xA9, 0x93, 0xA6, 0x81, 0xEF, 0x77, 0xDD, 0xF1,
+ 0xB0, 0xC0, 0xD1, 0xB7, 0x7F, 0xF8, 0xDE, 0xBB, 0x1F, 0xBC, 0xFB, 0xEE, 0x6F, 0x89, 0x10, 0x44, 0x6C, 0x94, 0x41, 0x90,
+ 0xE0, 0xE2, 0x95, 0x6F, 0xFD, 0xE0, 0xD5, 0x57, 0xDF, 0x7E, 0xFC, 0xF1, 0x6F, 0x3E, 0xFB, 0xF5, 0xD7, 0x09, 0xE0, 0x2F,
+ 0xBD, 0xF2, 0xD6, 0x4B, 0x2F, 0xBD, 0xF9, 0xC6, 0xDB, 0x3F, 0x79, 0xE5, 0xB5, 0xB7, 0xB0, 0x7A, 0xAA, 0x0D, 0xA6, 0xF3,
+ 0x34, 0x44, 0xF1, 0x2A, 0x3A, 0xE4, 0x8C, 0x65, 0x68, 0xCD, 0xDE, 0x76, 0xCB, 0x83, 0x37, 0xDD, 0x70, 0x9F, 0xF6, 0x85,
+ 0x40, 0x33, 0x36, 0xDB, 0x4C, 0x9A, 0x30, 0x11, 0xD7, 0x07, 0x6A, 0xE0, 0x61, 0x08, 0x01, 0x60, 0xCE, 0x02, 0x5D, 0x0B,
+ 0x67, 0xF3, 0xCD, 0x3B, 0x73, 0x64, 0x8A, 0x39, 0x7B, 0x81, 0x79, 0x7C, 0x9E, 0x9A, 0xA6, 0x88, 0xC8, 0x5F, 0x98, 0x7D,
+ 0x90, 0x9D, 0x64, 0xC0, 0x67, 0x10, 0xC9, 0xA8, 0x41, 0x96, 0x48, 0xCC, 0x3F, 0x3C, 0xCA, 0x3F, 0x82, 0x2F, 0xB7, 0xE5,
+ 0x56, 0x74, 0x60, 0x13, 0x18, 0x23, 0x29, 0x43, 0x87, 0x86, 0x36, 0x1B, 0x2A, 0xBD, 0x65, 0xF0, 0x5A, 0xC9, 0xA0, 0x2A,
+ 0x68, 0x28, 0xAB, 0xDA, 0x80, 0xD4, 0xD6, 0x23, 0xFD, 0x48, 0x1D, 0x82, 0x1B, 0x20, 0x92, 0x4A, 0x44, 0xB0, 0xC5, 0x98,
+ 0xB6, 0x83, 0x48, 0xC6, 0xEA, 0xA3, 0x23, 0x63, 0x90, 0xBB, 0xEC, 0x9F, 0x06, 0x9A, 0xA4, 0x4B, 0x01, 0xEB, 0x4C, 0x6A,
+ 0x48, 0x90, 0x87, 0x61, 0x8B, 0xA6, 0xB3, 0xF4, 0x59, 0x3B, 0x9A, 0x3B, 0x37, 0xAE, 0xDE, 0xBA, 0xA4, 0x7F, 0x19, 0x3D,
+ 0x73, 0x2C, 0x8E, 0x0E, 0x3E, 0x3B, 0xA2, 0x48, 0x7F, 0x91, 0x3D, 0x32, 0xA7, 0x7D, 0x04, 0x4B, 0x87, 0x1F, 0x02, 0xE0,
+ 0xD9, 0x67, 0x9E, 0x75, 0xFA, 0xE9, 0x6C, 0xBC, 0x35, 0x1D, 0xBD, 0xA9, 0xB3, 0xD9, 0x50, 0x86, 0x2D, 0x7F, 0xEB, 0x5B,
+ 0x6F, 0xBD, 0xF5, 0xFD, 0x9F, 0xFC, 0xE2, 0x17, 0xBF, 0x7F, 0xFE, 0xF9, 0xD7, 0x5F, 0x79, 0xE5, 0xCD, 0x37, 0xBE, 0xFF,
+ 0xD3, 0x5F, 0xFF, 0xF6, 0xCF, 0xEF, 0xBC, 0xFB, 0xAB, 0x9F, 0xFC, 0xE4, 0x97, 0xEF, 0xBF, 0xFF, 0x87, 0xA7, 0x9F, 0x66,
+ 0xAB, 0xF1, 0xDB, 0x84, 0x8D, 0x6F, 0xBD, 0xFE, 0x23, 0xA2, 0xFA, 0x4B, 0x2F, 0xBD, 0xF1, 0xF0, 0x83, 0x7C, 0xDD, 0xF8,
+ 0x8D, 0x40, 0x5C, 0x4A, 0x62, 0x16, 0x9C, 0xD4, 0xB9, 0x33, 0xE0, 0x1B, 0xD3, 0xBC, 0x0A, 0x82, 0x2D, 0x40, 0x3A, 0x4B,
+ 0x43, 0x10, 0xAE, 0x31, 0x34, 0x4B, 0x52, 0x2C, 0xEA, 0xE1, 0x85, 0xFE, 0x81, 0x97, 0x8C, 0xBF, 0x58, 0xAA, 0x96, 0x39,
+ 0x01, 0x41, 0x73, 0x11, 0x37, 0xE4, 0x14, 0x61, 0x63, 0xC8, 0xA4, 0x48, 0x59, 0x04, 0x3A, 0xBE, 0x37, 0xB3, 0x7B, 0x9D,
+ 0x9D, 0xC9, 0xBE, 0x47, 0xFF, 0x30, 0x64, 0x2D, 0xFD, 0x98, 0x20, 0x86, 0x4B, 0x22, 0x43, 0xED, 0x57, 0x5B, 0x0F, 0xD0,
+ 0x0B, 0x1F, 0xA1, 0xBB, 0x3A, 0x74, 0x78, 0xDD, 0x48, 0x23, 0x20, 0xAE, 0xCD, 0x7D, 0xED, 0x26, 0x3A, 0x95, 0x94, 0x06,
+ 0x4C, 0x67, 0xC9, 0xEB, 0xAA, 0xF4, 0xD5, 0x03, 0xB4, 0xEC, 0xD6, 0x67, 0xCA, 0xF6, 0x1B, 0x04, 0x6D, 0xA4, 0x8F, 0x21,
+ 0xB3, 0xCC, 0xB4, 0x20, 0x2E, 0x36, 0x32, 0x8A, 0x6B, 0x43, 0x76, 0x97, 0xC3, 0x1B, 0xA9, 0xE9, 0x40, 0x36, 0x92, 0x5D,
+ 0x8C, 0x40, 0xBE, 0xC3, 0xC9, 0x7C, 0x95, 0x1F, 0x1F, 0x00, 0x2C, 0xA2, 0x87, 0xC3, 0x1E, 0x7F, 0x22, 0xDB, 0xC5, 0x17,
+ 0x4F, 0x90, 0x3A, 0xE8, 0x9C, 0x73, 0x49, 0x07, 0x85, 0x38, 0x35, 0x7E, 0xA2, 0x72, 0xA7, 0xB8, 0x86, 0xCC, 0xE3, 0x38,
+ 0x84, 0xD9, 0xA9, 0xA0, 0xED, 0x65, 0x1A, 0x3B, 0x8A, 0x2D, 0x4F, 0x3C, 0xF1, 0xC2, 0xD3, 0x4F, 0xBF, 0xF2, 0xE2, 0x2B,
+ 0xDF, 0x45, 0xEE, 0x6F, 0xBE, 0xF9, 0xD3, 0x37, 0xDF, 0x7C, 0xEF, 0xAD, 0xB7, 0xDE, 0x7B, 0xE3, 0xAD, 0x77, 0x5F, 0x7A,
+ 0xE9, 0x3B, 0x8F, 0x3E, 0xF1, 0xFC, 0x95, 0x57, 0xDD, 0xCA, 0x44, 0x88, 0x3D, 0x81, 0x28, 0x18, 0xA5, 0x8E, 0x29, 0xBB,
+ 0x24, 0xFC, 0x9E, 0x77, 0x21, 0xC2, 0xAA, 0x2E, 0xAB, 0x1D, 0xEC, 0x5F, 0x43, 0x75, 0x46, 0x30, 0xCF, 0xC9, 0x2C, 0x18,
+ 0x7F, 0xC1, 0xF9, 0xC2, 0xDA, 0x33, 0xC3, 0x1F, 0x23, 0x6B, 0xC7, 0xDE, 0xED, 0xEC, 0xDE, 0xD9, 0xF4, 0xE8, 0x0E, 0x32,
+ 0xC5, 0x4C, 0x0D, 0xC3, 0x55, 0x45, 0x8F, 0x0E, 0x54, 0x1F, 0xEA, 0x13, 0xD2, 0xAF, 0x35, 0xD0, 0x64, 0x74, 0x80, 0x02,
+ 0xDC, 0x2D, 0xB5, 0xE2, 0x07, 0xB2, 0xD3, 0xDC, 0x70, 0xC4, 0x9D, 0x2D, 0x63, 0x0E, 0x77, 0xDE, 0x5B, 0x56, 0x58, 0x4D,
+ 0xDA, 0xAE, 0x88, 0x94, 0xBB, 0x41, 0xB2, 0xEF, 0x4C, 0xFD, 0x40, 0x82, 0x41, 0x88, 0x58, 0xB7, 0xBE, 0x8E, 0xB8, 0x54,
+ 0x48, 0x3C, 0xB3, 0x72, 0xCD, 0x44, 0xB5, 0x4B, 0x8C, 0x1D, 0x01, 0x71, 0xD4, 0xF7, 0xC2, 0xCD, 0x9A, 0x2F, 0x9E, 0x4B,
+ 0x8F, 0x13, 0xFE, 0x2C, 0xA2, 0xE9, 0x6C, 0xEE, 0x09, 0x5A, 0x18, 0x8C, 0xF9, 0xD3, 0xB0, 0xC3, 0xFA, 0xF8, 0xCA, 0x21,
+ 0x72, 0x41, 0x72, 0x12, 0xDA, 0x47, 0xB2, 0xC8, 0x43, 0x48, 0x0D, 0x27, 0x5D, 0x42, 0x8E, 0xA0, 0xAE, 0xC0, 0xAF, 0x18,
+ 0x1E, 0x90, 0xF2, 0xF7, 0x72, 0xF8, 0x5F, 0xF7, 0x32, 0x9A, 0x77, 0x64, 0xFA, 0xA4, 0xA4, 0xF4, 0x94, 0x40, 0x24, 0xA2,
+ 0x02, 0xD1, 0xE2, 0xF1, 0xC7, 0x9F, 0x7B, 0x0A, 0xE4, 0x79, 0xE0, 0xEB, 0x77, 0xDF, 0xFD, 0x28, 0xE7, 0xFD, 0x40, 0xDE,
+ 0xBA, 0xE8, 0x9C, 0x8B, 0x75, 0x4A, 0x61, 0xE0, 0x4D, 0x0A, 0x2E, 0xA9, 0xC0, 0xCC, 0xB5, 0x6A, 0x05, 0xCB, 0xE0, 0x1B,
+ 0x08, 0x97, 0x2D, 0x5E, 0x4B, 0x46, 0xC0, 0x46, 0x20, 0xFE, 0x23, 0xA0, 0xAF, 0x40, 0xAF, 0xB3, 0x7B, 0x61, 0x48, 0x2C,
+ 0x70, 0xB8, 0x2A, 0x0A, 0xCE, 0x6C, 0xC5, 0x61, 0xA2, 0xE9, 0x0E, 0x90, 0x9D, 0xB1, 0x9A, 0x00, 0x86, 0x44, 0x66, 0x59,
+ 0xAA, 0x03, 0xEF, 0x22, 0xD6, 0xA2, 0x03, 0x27, 0x77, 0xD4, 0x4C, 0x86, 0x7C, 0x14, 0xC4, 0xD0, 0xAD, 0x64, 0x36, 0x66,
+ 0xBA, 0xBD, 0x27, 0x69, 0xCC, 0x8D, 0x2E, 0xB8, 0xE5, 0xAE, 0x45, 0x21, 0x92, 0x28, 0xFE, 0x04, 0x89, 0xC7, 0x87, 0x02,
+ 0x65, 0xB2, 0xA4, 0x9B, 0x24, 0x9B, 0x20, 0xA4, 0x0E, 0x10, 0xAD, 0x04, 0xB3, 0x71, 0xD3, 0x99, 0x6F, 0x00, 0xF7, 0x3C,
+ 0xD8, 0xD7, 0xBE, 0x98, 0x96, 0x0B, 0x4D, 0x1E, 0x44, 0x4F, 0xFD, 0x41, 0xC5, 0x87, 0x7F, 0xA8, 0x6D, 0x32, 0xC0, 0x21,
+ 0x26, 0xCF, 0x9C, 0x32, 0x95, 0xB6, 0x30, 0xEC, 0x1D, 0xDF, 0x99, 0x1C, 0x04, 0xA0, 0xCC, 0xB5, 0xE9, 0xDC, 0x45, 0xEE,
+ 0x08, 0x65, 0xDC, 0xD9, 0x92, 0x98, 0x63, 0xA1, 0xE4, 0x08, 0xE0, 0x03, 0x1A, 0xA2, 0xD5, 0x3A, 0xFE, 0xBC, 0x0B, 0x2E,
+ 0x38, 0xE7, 0xC2, 0x49, 0x17, 0x4D, 0x86, 0x1F, 0x5F, 0x5B, 0xD9, 0xBE, 0x62, 0xF9, 0x46, 0x9A, 0x0D, 0xD4, 0x5C, 0xB7,
+ 0xDE, 0xFE, 0x08, 0xD9, 0xED, 0x50, 0xFF, 0x30, 0x81, 0x4A, 0x63, 0x3B, 0x12, 0x17, 0x35, 0x9C, 0x7E, 0x3A, 0x28, 0x77,
+ 0xCE, 0xD9, 0x5F, 0xE3, 0xFF, 0x92, 0x5F, 0x8E, 0x28, 0xC3, 0xE7, 0x34, 0xEC, 0x17, 0xA5, 0xF6, 0xF7, 0x0E, 0x2F, 0x5F,
+ 0xB2, 0x8E, 0x58, 0xC5, 0x3F, 0x95, 0x01, 0x1C, 0xA2, 0x9F, 0x2F, 0x94, 0x61, 0x97, 0x30, 0xE1, 0x0C, 0xEE, 0x2D, 0x65,
+ 0xC8, 0x12, 0x87, 0x74, 0xB4, 0xA9, 0x88, 0x8D, 0x02, 0x34, 0x30, 0x9C, 0xBC, 0x7C, 0xA4, 0xA5, 0x63, 0x3A, 0x42, 0xDE,
+ 0x10, 0x4A, 0x19, 0x25, 0xC0, 0x6D, 0x3A, 0xCC, 0x8A, 0x30, 0x2A, 0x68, 0xDB, 0xEA, 0x93, 0x71, 0x9D, 0x48, 0xDF, 0x86,
+ 0x01, 0xC8, 0xC9, 0xE6, 0x69, 0x61, 0x62, 0xFE, 0x04, 0x73, 0x8D, 0xBA, 0x72, 0x0B, 0xDC, 0x9B, 0x0B, 0xEA, 0x00, 0x09,
+ 0x2D, 0xF4, 0x0E, 0x83, 0xA4, 0xD1, 0x04, 0x97, 0x62, 0xCA, 0xF8, 0x4B, 0xA0, 0xF6, 0x73, 0xAE, 0x2E, 0x07, 0x01, 0x67,
+ 0x24, 0xA5, 0x61, 0x65, 0x00, 0x3D, 0x86, 0x4D, 0x06, 0x8C, 0x7C, 0xB1, 0xF7, 0x59, 0x97, 0x0A, 0x15, 0x85, 0x48, 0xC8,
+ 0xAF, 0xF8, 0x86, 0x15, 0x19, 0xC7, 0xCB, 0x44, 0x5E, 0x58, 0x11, 0x74, 0x55, 0xF1, 0x06, 0x60, 0x0A, 0xAB, 0x95, 0xA3,
+ 0x00, 0xCE, 0x95, 0xFD, 0x84, 0xA7, 0xFC, 0x39, 0x7F, 0xDC, 0x05, 0xA4, 0xEA, 0x42, 0x54, 0xAD, 0x6C, 0xE0, 0x84, 0x1E,
+ 0xF2, 0x16, 0x95, 0x3B, 0x2A, 0xE0, 0x96, 0xBA, 0x97, 0x89, 0x05, 0xE0, 0x36, 0x79, 0xC2, 0x45, 0x32, 0xBD, 0x18, 0x3F,
+ 0x41, 0x0E, 0xDE, 0x38, 0xEB, 0x6C, 0xED, 0x43, 0x9C, 0x77, 0xDE, 0x79, 0x6C, 0x1A, 0x1C, 0xEC, 0x5F, 0xD9, 0xB3, 0x68,
+ 0x39, 0xA7, 0x30, 0xC0, 0xC0, 0xA4, 0xCD, 0x4E, 0x6C, 0x20, 0x81, 0x36, 0x5C, 0x15, 0x93, 0xF9, 0xC8, 0x4E, 0x6C, 0xB9,
+ 0xB0, 0x3A, 0xB0, 0x33, 0x64, 0x51, 0x80, 0x0A, 0x5D, 0x5C, 0xE1, 0x14, 0xD2, 0xC7, 0x09, 0x78, 0xDC, 0x47, 0x73, 0x79,
+ 0x3A, 0x88, 0xEA, 0x07, 0xCE, 0x52, 0xE9, 0x87, 0x4B, 0x20, 0xB5, 0x6A, 0x70, 0x35, 0x21, 0xC5, 0xB0, 0xED, 0xCA, 0xAA,
+ 0xE8, 0xD5, 0x63, 0xC4, 0x0F, 0x8C, 0xB8, 0x61, 0x8E, 0xB2, 0xDC, 0x6B, 0x7D, 0xC4, 0xFC, 0xD6, 0x74, 0xE8, 0x94, 0xF0,
+ 0x0D, 0x03, 0x87, 0x4C, 0xE3, 0xDC, 0xAF, 0x8D, 0xBB, 0xF8, 0xC2, 0xF1, 0xE7, 0x8C, 0x3B, 0x57, 0x51, 0x05, 0x99, 0x02,
+ 0xF7, 0xD8, 0x3E, 0x29, 0x36, 0x26, 0x2F, 0x0C, 0x38, 0x93, 0x7E, 0x28, 0x25, 0x42, 0x77, 0xFD, 0x4B, 0x16, 0x38, 0x73,
+ 0x0E, 0xC4, 0x45, 0xCA, 0x25, 0x8C, 0x97, 0xAD, 0xFF, 0x98, 0xA7, 0xD3, 0xCB, 0x51, 0xC9, 0x49, 0x53, 0x41, 0x66, 0xA2,
+ 0x62, 0xE8, 0xA7, 0x09, 0x11, 0x5A, 0x20, 0xFE, 0xDC, 0x71, 0x08, 0x9A, 0xE9, 0x90, 0xB6, 0x7A, 0x78, 0x3E, 0x17, 0xC2,
+ 0x10, 0x9D, 0x74, 0x09, 0xCD, 0x28, 0x07, 0xEB, 0x64, 0x6E, 0x31, 0x99, 0x37, 0x30, 0x79, 0xC2, 0x78, 0x94, 0xAA, 0x6F,
+ 0x89, 0xDA, 0x93, 0xB3, 0x2E, 0x6A, 0xAB, 0xDB, 0x20, 0x81, 0x4B, 0x2B, 0x77, 0xC6, 0x6C, 0x9A, 0x02, 0xE1, 0xFE, 0x81,
+ 0xDA, 0xEB, 0xB5, 0xE9, 0x89, 0x93, 0xAA, 0x90, 0x89, 0xDA, 0x9C, 0x45, 0xE2, 0xA5, 0x2C, 0x76, 0xA3, 0x9C, 0x52, 0x01,
+ 0xF6, 0x41, 0x1F, 0x4D, 0xE1, 0x4D, 0x4F, 0x5F, 0x6C, 0x5F, 0xEA, 0x5B, 0x13, 0x48, 0xD5, 0x0F, 0x9C, 0x0B, 0x37, 0xD5,
+ 0x71, 0xA4, 0x6F, 0x9A, 0xAE, 0x32, 0x08, 0xD4, 0x00, 0x60, 0x54, 0xA2, 0x82, 0xD6, 0xA5, 0xD2, 0xD7, 0x4C, 0x54, 0x55,
+ 0xA8, 0x11, 0x1B, 0xBF, 0x31, 0xCC, 0xEA, 0x08, 0x8A, 0x17, 0x99, 0xB9, 0xFB, 0xCE, 0x45, 0xDC, 0x60, 0x0E, 0x8B, 0x8A,
+ 0x9F, 0xCF, 0x6F, 0xA4, 0x0F, 0xE0, 0xCC, 0x16, 0xEE, 0x9B, 0x61, 0x8E, 0xBA, 0x34, 0x08, 0xAE, 0xE7, 0x91, 0x08, 0x4A,
+ 0x5B, 0x7B, 0xAE, 0x34, 0x53, 0x65, 0xAF, 0xCE, 0x84, 0x89, 0xF4, 0xA9, 0x20, 0x64, 0xE8, 0xA6, 0x1D, 0xB5, 0x6B, 0xF0,
+ 0x84, 0x3D, 0xB6, 0x08, 0x17, 0x71, 0x13, 0x4E, 0x08, 0x2A, 0x36, 0x97, 0x55, 0x99, 0x9A, 0xBE, 0x9B, 0x3C, 0x93, 0x70,
+ 0xA2, 0x91, 0x06, 0x5D, 0xCE, 0x98, 0x36, 0x1D, 0x9E, 0x3A, 0x6B, 0xE6, 0xD4, 0x4B, 0xA7, 0x5D, 0x3A, 0x55, 0xE3, 0x8D,
+ 0x6C, 0x99, 0xF6, 0xF1, 0xC1, 0x59, 0x7B, 0xDA, 0x07, 0xEA, 0x6A, 0x5B, 0xD9, 0x9A, 0xC9, 0xBC, 0x81, 0x5E, 0x85, 0x04,
+ 0x30, 0x93, 0x97, 0x6B, 0xBB, 0xD7, 0x7B, 0x2B, 0xDE, 0xE0, 0xCF, 0xC4, 0x14, 0x08, 0x12, 0x03, 0x57, 0x33, 0xFF, 0x32,
+ 0x08, 0x72, 0x92, 0x1A, 0xFF, 0x30, 0x74, 0x60, 0x6C, 0x5F, 0x91, 0xC7, 0xA4, 0x43, 0x12, 0x51, 0x75, 0xAB, 0x94, 0xEC,
+ 0xF0, 0x72, 0xA4, 0x29, 0x76, 0xED, 0x9A, 0xFC, 0x48, 0x1A, 0x1A, 0xE6, 0x40, 0x90, 0x91, 0xB8, 0x81, 0xAF, 0x91, 0xE7,
+ 0xBB, 0x58, 0xE4, 0x28, 0x49, 0x58, 0x05, 0x5A, 0xAC, 0x03, 0xB2, 0xDA, 0x14, 0x22, 0xAC, 0x99, 0x02, 0x47, 0x38, 0x58,
+ 0x4A, 0xC5, 0xA5, 0xFE, 0x74, 0x68, 0x3F, 0x73, 0xE0, 0xC6, 0x8A, 0x02, 0xBC, 0x69, 0x9F, 0xB9, 0xAB, 0x89, 0xF9, 0x3C,
+ 0xE6, 0x0A, 0x60, 0x88, 0x7C, 0xE3, 0x42, 0x69, 0xCD, 0x84, 0x8B, 0x27, 0x22, 0x5D, 0x92, 0x57, 0xDA, 0x09, 0xF4, 0x97,
+ 0x94, 0x7A, 0x8E, 0x86, 0x68, 0xEF, 0xD0, 0xE8, 0x57, 0xB9, 0x5B, 0xE9, 0x6B, 0xEF, 0x53, 0x3C, 0x60, 0xE2, 0x94, 0xE9,
+ 0x97, 0x4C, 0x85, 0x11, 0x0D, 0xAC, 0xCD, 0x21, 0xD8, 0x50, 0x1B, 0x4E, 0x95, 0xF2, 0x4A, 0xD8, 0xC1, 0x53, 0x67, 0x12,
+ 0x5A, 0xA6, 0x5E, 0x32, 0xE1, 0xDC, 0x73, 0xCF, 0xE5, 0x0F, 0x39, 0x5E, 0x9A, 0x96, 0x1F, 0x0E, 0xC1, 0x76, 0x04, 0x66,
+ 0x4D, 0xD2, 0x9E, 0xB1, 0xB5, 0x91, 0x76, 0x84, 0xC4, 0xDE, 0x05, 0xFA, 0xA3, 0xFC, 0xB8, 0x36, 0x81, 0xD7, 0x4D, 0xDC,
+ 0x4D, 0x26, 0x39, 0x92, 0x0E, 0x69, 0x52, 0x64, 0x9F, 0x6F, 0x92, 0x57, 0x74, 0x60, 0x48, 0xE7, 0xD2, 0x47, 0x93, 0xAA,
+ 0xCA, 0xDD, 0xDB, 0xED, 0x11, 0xA5, 0xB5, 0x6E, 0xB1, 0x6B, 0x4D, 0x3D, 0xDD, 0x20, 0x71, 0xCA, 0x5F, 0xF1, 0xA0, 0xC4,
+ 0x61, 0x8F, 0x43, 0x8C, 0x84, 0x13, 0x69, 0x0A, 0x69, 0x6F, 0x4E, 0x48, 0x38, 0x14, 0xC6, 0x86, 0xF9, 0x23, 0x20, 0xA3,
+ 0x92, 0x35, 0x35, 0x8E, 0x44, 0x57, 0x60, 0x57, 0x93, 0x3F, 0x87, 0x2D, 0x6B, 0xE6, 0x0A, 0xCE, 0x69, 0x24, 0xEC, 0x2D,
+ 0x98, 0x3D, 0x7F, 0xF2, 0xC5, 0x93, 0x38, 0xED, 0x44, 0xE8, 0x30, 0x45, 0x95, 0x08, 0x1A, 0x60, 0xE1, 0x70, 0x6C, 0x36,
+ 0x56, 0xA8, 0x69, 0xB3, 0xA4, 0xE3, 0x3D, 0xE9, 0x12, 0xD4, 0x00, 0xB8, 0x5B, 0x2F, 0x51, 0x8C, 0xE2, 0xF9, 0xB4, 0xBF,
+ 0x78, 0x0E, 0x7B, 0x28, 0x67, 0x4F, 0x15, 0xE6, 0x1D, 0x1D, 0x08, 0x86, 0xF2, 0x08, 0x57, 0x6A, 0xDD, 0x99, 0xF3, 0x84,
+ 0x23, 0x6C, 0xCE, 0x9D, 0xE1, 0x45, 0x50, 0x98, 0xFF, 0x82, 0x40, 0x36, 0xFE, 0x51, 0x36, 0xE1, 0x82, 0xC4, 0x15, 0x22,
+ 0x0A, 0xAE, 0x20, 0x52, 0x0E, 0x16, 0x3E, 0x92, 0x65, 0xCF, 0x69, 0xE0, 0x15, 0xF9, 0xBA, 0x7C, 0xBA, 0x91, 0x60, 0xA0,
+ 0x2C, 0x23, 0x17, 0xA9, 0x22, 0x8D, 0xE8, 0xB5, 0x7A, 0x70, 0x74, 0xE0, 0xF6, 0x76, 0x4C, 0xF2, 0xEE, 0x81, 0x14, 0x95,
+ 0xB5, 0x57, 0xD0, 0x5E, 0x33, 0x1F, 0xF3, 0x4C, 0xEF, 0x5D, 0x22, 0xB3, 0xA2, 0xBF, 0xB3, 0xF4, 0xE8, 0x04, 0x43, 0x6D,
+ 0x97, 0x4E, 0xBA, 0x61, 0x7F, 0x08, 0x19, 0xC4, 0xD0, 0x31, 0x75, 0x6E, 0xA3, 0x24, 0x59, 0x14, 0xE0, 0xE4, 0xDD, 0x9A,
+ 0xEA, 0x99, 0xDF, 0x2A, 0x7B, 0x50, 0x2F, 0x48, 0x0A, 0x79, 0xCE, 0x8C, 0x89, 0x93, 0xE9, 0x30, 0x92, 0x8F, 0x42, 0x44,
+ 0x64, 0xCB, 0x22, 0x62, 0x25, 0x96, 0x22, 0xAF, 0xA9, 0x97, 0x4E, 0x9E, 0x3E, 0x79, 0x86, 0xA0, 0x0A, 0x11, 0xDB, 0x85,
+ 0x14, 0x30, 0x07, 0xF4, 0x17, 0x44, 0x3A, 0x43, 0xE2, 0x30, 0xEE, 0x42, 0x7F, 0x6D, 0xDA, 0xE4, 0x4B, 0x44, 0x01, 0xE2,
+ 0x79, 0xC2, 0x81, 0xC4, 0x17, 0x1D, 0xBA, 0xBC, 0xE9, 0x3A, 0x68, 0x47, 0x88, 0xDF, 0x4E, 0x9F, 0x3A, 0x8D, 0x36, 0xF5,
+ 0xD9, 0xE7, 0x7C, 0xAD, 0xA3, 0xB9, 0x8B, 0x29, 0x1B, 0x69, 0x02, 0xA2, 0x04, 0x06, 0x70, 0x5C, 0xCA, 0x55, 0xCB, 0x95,
+ 0x73, 0xA7, 0x66, 0xA1, 0xDA, 0xFA, 0x75, 0x62, 0xB2, 0xAB, 0x09, 0xAB, 0x12, 0xC4, 0x8D, 0xA3, 0xA8, 0xE8, 0x23, 0xA9,
+ 0x90, 0xD9, 0xF9, 0xC3, 0x19, 0x1E, 0x01, 0x21, 0x3E, 0x0E, 0xCF, 0xC0, 0x40, 0xD0, 0xC9, 0x62, 0x1D, 0x91, 0xA3, 0x8B,
+ 0xFB, 0xDE, 0x20, 0xEC, 0x7D, 0xBE, 0xA1, 0x4A, 0x8C, 0xC2, 0x9F, 0x91, 0x58, 0x6D, 0x14, 0xA0, 0x69, 0x95, 0x33, 0x6E,
+ 0x65, 0x76, 0x16, 0x14, 0xE6, 0xE4, 0x76, 0xC6, 0x21, 0x2C, 0x59, 0x53, 0xE4, 0x6E, 0x96, 0x00, 0xAE, 0xE6, 0xDA, 0x7E,
+ 0x41, 0x28, 0xCC, 0xE5, 0x92, 0x06, 0x20, 0x5F, 0x71, 0xFF, 0x90, 0x28, 0x7A, 0x35, 0x6D, 0x75, 0x8B, 0x7C, 0x67, 0xCC,
+ 0x3B, 0xFF, 0x9C, 0xAF, 0xCD, 0x98, 0x3C, 0x0D, 0xB3, 0x25, 0x79, 0xD5, 0x8E, 0xA6, 0x30, 0xAB, 0x09, 0xDA, 0x53, 0x50,
+ 0xCA, 0x14, 0x70, 0x89, 0xE4, 0x47, 0x63, 0x80, 0x86, 0x01, 0x8D, 0x01, 0x73, 0xA6, 0xE9, 0xAE, 0x10, 0x89, 0x3D, 0x0A,
+ 0x80, 0x1A, 0xF3, 0x69, 0x07, 0xE1, 0x8E, 0xB4, 0x83, 0x78, 0xDC, 0xE0, 0xD2, 0x74, 0x9A, 0x45, 0xB1, 0x31, 0x89, 0x9C,
+ 0xE0, 0x49, 0x37, 0x05, 0xF9, 0xF2, 0xB9, 0x64, 0xAF, 0xD5, 0x5C, 0x3F, 0x15, 0xAE, 0x70, 0x8A, 0xE8, 0x42, 0x2B, 0x75,
+ 0x8E, 0xCF, 0x65, 0x13, 0x21, 0x25, 0x37, 0x62, 0xFE, 0x41, 0xC1, 0xAE, 0xD5, 0x87, 0x21, 0x7A, 0xBD, 0xD6, 0xC7, 0x95,
+ 0x95, 0x64, 0x74, 0x70, 0x92, 0xED, 0xDB, 0xA2, 0xD7, 0x03, 0xFD, 0x1E, 0xBB, 0x76, 0x0C, 0xDC, 0x09, 0x06, 0x4E, 0x19,
+ 0x61, 0x32, 0x1F, 0x96, 0xA4, 0x40, 0xBA, 0x1F, 0xDA, 0x85, 0x2C, 0x6F, 0x6A, 0xEB, 0x90, 0x70, 0x4C, 0xD3, 0x4A, 0xB9,
+ 0x69, 0x9A, 0xD2, 0x39, 0xF4, 0x58, 0x76, 0x4F, 0xBA, 0xD2, 0x47, 0x01, 0x26, 0xEE, 0x29, 0x41, 0x5C, 0x46, 0x6C, 0x14,
+ 0x44, 0xD8, 0x26, 0xD7, 0x98, 0x1B, 0x92, 0x85, 0xD1, 0xC5, 0x60, 0x12, 0x60, 0x31, 0x59, 0xEC, 0x34, 0xD3, 0xD1, 0x14,
+ 0x30, 0xD1, 0x76, 0x26, 0x08, 0x83, 0x26, 0x78, 0xDC, 0x54, 0x12, 0x13, 0xC9, 0x38, 0x49, 0x75, 0x8C, 0x07, 0x4C, 0x21,
+ 0xE5, 0xB5, 0x3B, 0x0F, 0x04, 0x06, 0x09, 0x33, 0x6C, 0x87, 0x22, 0x02, 0x99, 0x9E, 0x8F, 0x1B, 0x75, 0x44, 0x2B, 0xF8,
+ 0x07, 0x81, 0x8A, 0x66, 0xD1, 0xF8, 0x8B, 0x26, 0xB0, 0x9B, 0x2C, 0x92, 0x24, 0x3E, 0x34, 0x8A, 0xEF, 0xDA, 0x06, 0x55,
+ 0x98, 0x1B, 0xB3, 0x97, 0x4D, 0x5A, 0x6F, 0x48, 0x9F, 0xB2, 0x5F, 0x67, 0xC8, 0x66, 0x76, 0xE6, 0x74, 0xE0, 0x49, 0xDF,
+ 0xCD, 0x49, 0x42, 0x22, 0x74, 0x0A, 0x66, 0x28, 0xD6, 0x01, 0xC1, 0x62, 0xF8, 0xDC, 0x85, 0xF0, 0x6B, 0x58, 0xEF, 0x8E,
+ 0x0E, 0x6C, 0x20, 0xD5, 0x4C, 0xC6, 0x26, 0xA3, 0x5E, 0x09, 0x8E, 0xF1, 0x86, 0xFF, 0xF5, 0xAE, 0x4D, 0x8D, 0x3C, 0x19,
+ 0x91, 0x53, 0x5E, 0x38, 0x9C, 0x0C, 0x13, 0xA9, 0xC4, 0x25, 0xDD, 0x61, 0x32, 0xAE, 0xAD, 0x6A, 0x40, 0xF4, 0x32, 0xD4,
+ 0x84, 0x39, 0xCB, 0x46, 0x46, 0x37, 0xCF, 0xD3, 0x44, 0x50, 0x82, 0x21, 0xC7, 0x27, 0x9A, 0xF2, 0x02, 0xF9, 0x72, 0xC6,
+ 0x3C, 0xA9, 0x3A, 0x94, 0x5B, 0xB3, 0xD5, 0x09, 0x1E, 0xF5, 0x6C, 0x0E, 0x1E, 0x91, 0xED, 0x66, 0xB2, 0xE1, 0x69, 0x16,
+ 0xF5, 0x84, 0xD0, 0xF7, 0xA6, 0x39, 0x59, 0x2C, 0x7A, 0x02, 0x7C, 0x58, 0xD8, 0xF5, 0xFC, 0xE9, 0x8E, 0xED, 0x6B, 0xDE,
+ 0xE5, 0x6C, 0x1B, 0x61, 0x88, 0xAD, 0xCB, 0x34, 0x7F, 0x84, 0x7C, 0x6F, 0x1C, 0x82, 0x97, 0x42, 0x0D, 0x24, 0xC1, 0x7C,
+ 0x77, 0x6F, 0x73, 0x5D, 0x2B, 0x0E, 0xC7, 0xD9, 0x84, 0x6B, 0x86, 0xD7, 0xF1, 0x7E, 0x50, 0x1E, 0x34, 0x53, 0xA6, 0xF6,
+ 0xB6, 0x78, 0x62, 0x5C, 0x33, 0x12, 0x1E, 0xDC, 0x70, 0x2D, 0x9F, 0xD4, 0x60, 0x8E, 0x90, 0xFB, 0x02, 0x8D, 0x4F, 0xAB,
+ 0xF4, 0xF5, 0x6E, 0x40, 0xB0, 0x8F, 0x05, 0xFD, 0xFF, 0x55, 0xB2, 0x63, 0x9F, 0x60, 0x8A, 0x2F, 0x6F, 0xAD, 0x20, 0x68,
+ 0x63, 0x96, 0x4D, 0x58, 0xB5, 0x33, 0x6A, 0xDF, 0xA2, 0x62, 0x91, 0xD3, 0xC8, 0xC5, 0x0F, 0x4C, 0x3A, 0xA1, 0xB9, 0x9D,
+ 0x96, 0x33, 0x7A, 0xA1, 0xDB, 0x48, 0x25, 0xB8, 0x29, 0x79, 0xD6, 0x58, 0x10, 0x92, 0x05, 0xAF, 0x98, 0xEB, 0x71, 0x8E,
+ 0x0E, 0x81, 0x9A, 0x13, 0x10, 0xEA, 0x6B, 0x5A, 0x31, 0x6D, 0x8C, 0x1A, 0x04, 0x77, 0x13, 0x59, 0x8C, 0x3A, 0x00, 0x30,
+ 0x71, 0x1A, 0xCB, 0xBA, 0x1D, 0xCA, 0x6C, 0x93, 0x47, 0x8E, 0xF3, 0xA6, 0x89, 0x73, 0x98, 0xD4, 0x8B, 0xED, 0x4A, 0x22,
+ 0x62, 0x9B, 0x74, 0xC9, 0x8E, 0x01, 0x67, 0x88, 0xED, 0xEC, 0x21, 0x20, 0x29, 0xD0, 0xFE, 0xA8, 0x32, 0xB7, 0x27, 0x8C,
+ 0xBF, 0x68, 0xE6, 0xF4, 0x59, 0x9C, 0x27, 0x05, 0x48, 0xD2, 0xDA, 0x7A, 0xF9, 0x1B, 0xDF, 0x3E, 0xB2, 0xEB, 0x30, 0xED,
+ 0x23, 0x82, 0x13, 0x72, 0xE4, 0x73, 0xC9, 0x18, 0xCA, 0x24, 0x7E, 0x4E, 0x39, 0x16, 0x28, 0xF8, 0xC3, 0x3E, 0x03, 0xC5,
+ 0x2B, 0xB5, 0x77, 0xC7, 0xEF, 0x9D, 0x8E, 0xA7, 0xB1, 0x36, 0x3E, 0xA0, 0x3F, 0x3A, 0x30, 0x3D, 0x89, 0xFF, 0xE7, 0xE5,
+ 0x84, 0x59, 0x39, 0x34, 0xCA, 0x36, 0xEC, 0xBC, 0x74, 0x1A, 0x2D, 0x1D, 0xEC, 0x23, 0x9E, 0x0E, 0x07, 0x56, 0x63, 0x66,
+ 0xDC, 0x32, 0x43, 0x96, 0x63, 0x2A, 0x24, 0xB5, 0x30, 0x18, 0xCA, 0x3B, 0xA6, 0x93, 0xAA, 0x59, 0x93, 0xB5, 0x26, 0xAD,
+ 0x3F, 0x75, 0x17, 0x23, 0x45, 0xC9, 0x70, 0xDF, 0x72, 0xBE, 0x10, 0x65, 0xEA, 0xA4, 0x4B, 0x39, 0xD8, 0x17, 0x40, 0xB8,
+ 0xE8, 0xC2, 0xF3, 0x01, 0x74, 0xDD, 0x62, 0xA7, 0xB9, 0xEC, 0x08, 0xAD, 0x5A, 0x76, 0x82, 0x38, 0x1D, 0x66, 0xCB, 0x80,
+ 0x17, 0xDC, 0x37, 0xD6, 0xAD, 0xE6, 0x6F, 0xB7, 0x28, 0x39, 0xBB, 0x94, 0x4C, 0xE2, 0xAF, 0x14, 0x1B, 0x93, 0x20, 0x38,
+ 0x0D, 0x51, 0xFE, 0x5C, 0x5C, 0xE1, 0x9C, 0xB3, 0x21, 0x4F, 0x34, 0xD7, 0xB6, 0x93, 0xD1, 0x72, 0xA8, 0xD8, 0x5F, 0x7E,
+ 0xFB, 0x4F, 0xCE, 0xD6, 0x36, 0x53, 0x2C, 0x3F, 0x09, 0x12, 0xC1, 0xA2, 0x00, 0xC5, 0x22, 0x69, 0x65, 0x8A, 0x85, 0x89,
+ 0x19, 0xF1, 0x2B, 0x46, 0x23, 0x6E, 0x39, 0xED, 0x6C, 0x40, 0x53, 0x50, 0xB2, 0x08, 0xEC, 0xC3, 0x8E, 0x54, 0x8B, 0x18,
+ 0x5F, 0xA1, 0x89, 0x31, 0x11, 0x42, 0xC7, 0x35, 0x1A, 0x69, 0xED, 0xC2, 0x16, 0x46, 0x5A, 0x1A, 0x9E, 0x5F, 0x9D, 0xCC,
+ 0xE9, 0x90, 0x5E, 0xB7, 0x91, 0xBE, 0xEA, 0xC0, 0x82, 0xA9, 0x06, 0xB7, 0x91, 0x24, 0xCF, 0x98, 0x09, 0x82, 0x43, 0x28,
+ 0x04, 0xE1, 0xAD, 0x6B, 0x2F, 0x5B, 0x3B, 0xB4, 0x76, 0xC6, 0xE4, 0xC9, 0x64, 0x44, 0x44, 0x63, 0x6A, 0x28, 0x42, 0xAB,
+ 0xEE, 0xE8, 0xB3, 0x02, 0x95, 0x64, 0xD7, 0x74, 0xF0, 0x0D, 0xF1, 0xDD, 0xD9, 0x14, 0x66, 0x68, 0x32, 0xEC, 0x38, 0x93,
+ 0x7D, 0xB2, 0xDA, 0x6A, 0x96, 0xDE, 0x27, 0x7B, 0x31, 0x3D, 0x1B, 0x95, 0x40, 0x15, 0xA7, 0xEF, 0xE6, 0xA6, 0x6A, 0xF6,
+ 0x45, 0xF8, 0x5B, 0x06, 0xAB, 0x13, 0x2E, 0xBC, 0x00, 0x9E, 0xC7, 0xBA, 0xE5, 0x5B, 0xF9, 0x38, 0xA8, 0xEA, 0x91, 0xFB,
+ 0x9E, 0x42, 0x0D, 0x9C, 0xAE, 0x46, 0x2C, 0x09, 0x99, 0x1B, 0xE0, 0x04, 0x86, 0xE0, 0x60, 0x97, 0x00, 0x27, 0x70, 0x6A,
+ 0x44, 0x4F, 0x2D, 0xED, 0x0C, 0x5A, 0xB8, 0x1B, 0x21, 0x35, 0xB6, 0x1B, 0xFF, 0xDC, 0x58, 0x88, 0x0E, 0xBE, 0xDC, 0x09,
+ 0xE8, 0x77, 0x9A, 0xF3, 0x85, 0xC6, 0x00, 0x8E, 0x07, 0x61, 0x14, 0x67, 0x1C, 0xB4, 0xF1, 0xE8, 0x43, 0x2A, 0x32, 0x75,
+ 0x91, 0x53, 0x29, 0x40, 0x06, 0x9F, 0xDA, 0xBE, 0x66, 0xB9, 0x07, 0xAF, 0xC9, 0x70, 0x43, 0xCA, 0x1C, 0x13, 0x2A, 0x24,
+ 0xC3, 0x33, 0xFB, 0x29, 0x40, 0x15, 0x42, 0x31, 0x65, 0x1D, 0x27, 0xCD, 0xEE, 0xBB, 0x6C, 0x3F, 0x39, 0xD2, 0x7C, 0xDF,
+ 0x05, 0x1C, 0x30, 0x07, 0x5E, 0x11, 0x66, 0x49, 0x8D, 0x4C, 0x2B, 0x9F, 0x8C, 0xD6, 0xD9, 0x6E, 0xE7, 0xCC, 0x4F, 0xDC,
+ 0x7A, 0x42, 0xB3, 0x5E, 0x50, 0xDE, 0xB9, 0x35, 0x6D, 0x67, 0x31, 0x73, 0x77, 0xCF, 0x8C, 0xED, 0xBB, 0xE9, 0xE6, 0x19,
+ 0xBB, 0x9C, 0xED, 0x0B, 0xF2, 0x64, 0xF1, 0x2D, 0xFE, 0x11, 0xF9, 0x18, 0xF1, 0xBF, 0x83, 0x6F, 0x75, 0x6E, 0x19, 0x00,
+ 0x00, 0x71, 0xC7, 0xB7, 0xBF, 0xFD, 0xCE, 0x2F, 0x7E, 0xFC, 0x6B, 0xBE, 0x28, 0x42, 0x66, 0x50, 0xF3, 0x16, 0x90, 0xE9,
+ 0xE9, 0x10, 0x5F, 0x58, 0x6B, 0xEE, 0x5E, 0x33, 0x4D, 0x61, 0xBD, 0xDD, 0x24, 0x6F, 0x0E, 0xA2, 0x8F, 0x8F, 0xD5, 0xC1,
+ 0x28, 0x7B, 0x37, 0xAC, 0xD8, 0x51, 0x08, 0x33, 0x62, 0xF5, 0x66, 0x7A, 0xAC, 0xD2, 0xD7, 0xD4, 0xD3, 0x1A, 0x3E, 0x9D,
+ 0x8C, 0x93, 0x45, 0xEF, 0x65, 0x38, 0xC9, 0xC9, 0x1E, 0x86, 0x58, 0x20, 0x24, 0x1C, 0x65, 0xDD, 0x38, 0xBD, 0x2D, 0x13,
+ 0x15, 0xA4, 0x8A, 0xD6, 0xC0, 0x80, 0xA9, 0xFA, 0xCD, 0x9D, 0x43, 0x71, 0x94, 0x95, 0x92, 0xB1, 0x61, 0xD5, 0x36, 0x36,
+ 0x7A, 0x80, 0x03, 0xD0, 0x49, 0x61, 0x34, 0xC1, 0x28, 0x20, 0x71, 0x64, 0xB7, 0x29, 0x1F, 0xDE, 0x14, 0x74, 0xCE, 0x1E,
+ 0xBC, 0x11, 0x5B, 0xF6, 0x96, 0x17, 0x5A, 0x5B, 0x8C, 0xDE, 0x9E, 0x67, 0xC5, 0xED, 0x08, 0x45, 0xB7, 0x81, 0xF8, 0x33,
+ 0x9D, 0x95, 0xA5, 0xB9, 0xB2, 0x2A, 0x4C, 0x51, 0x8E, 0xA8, 0x43, 0xF8, 0x01, 0x58, 0xD6, 0xAF, 0xD9, 0x0E, 0xD5, 0x9E,
+ 0x8C, 0x8B, 0x23, 0x41, 0x7E, 0xF6, 0xD6, 0xAF, 0x9E, 0x7C, 0xF0, 0x19, 0xBE, 0xA2, 0x59, 0xBE, 0x60, 0x6F, 0x8E, 0x9F,
+ 0x26, 0xA3, 0xB6, 0x7B, 0xE1, 0x74, 0xF1, 0x0C, 0x6F, 0xCA, 0xCD, 0xAD, 0x47, 0x36, 0x65, 0xDA, 0x07, 0x1D, 0x1D, 0x9C,
+ 0x52, 0xD0, 0x63, 0x9A, 0x13, 0x5F, 0xA2, 0x8C, 0x11, 0x2C, 0xD2, 0x90, 0x7B, 0xB2, 0xF9, 0x5B, 0x92, 0xE5, 0x28, 0x6E,
+ 0x13, 0x1E, 0x80, 0xC9, 0x07, 0x38, 0x5D, 0x3C, 0x33, 0xE5, 0x90, 0x90, 0x60, 0xEA, 0x78, 0xD9, 0x31, 0x00, 0x62, 0x82,
+ 0xC2, 0xB2, 0xD7, 0x2C, 0x38, 0x9C, 0x93, 0x05, 0x39, 0xCD, 0x95, 0xAC, 0x86, 0xFD, 0x26, 0xCB, 0xFA, 0xD7, 0xCD, 0x9B,
+ 0xE3, 0x37, 0xFE, 0x82, 0x71, 0xD2, 0xD1, 0x23, 0x41, 0x74, 0x2B, 0x6A, 0x95, 0x9A, 0x57, 0xB2, 0xA7, 0xBC, 0xD6, 0xDC,
+ 0xD7, 0x9A, 0xBF, 0xDE, 0x75, 0xCC, 0xD6, 0x95, 0x94, 0xAD, 0x0D, 0x9D, 0xE2, 0x9C, 0x33, 0x17, 0xD0, 0x01, 0xB5, 0xC7,
+ 0x25, 0x53, 0x20, 0x14, 0xB5, 0x34, 0x77, 0x2E, 0x1D, 0x5A, 0xA3, 0xFB, 0x0F, 0x39, 0x93, 0xE5, 0xAD, 0x37, 0x7E, 0xC6,
+ 0xE1, 0x93, 0x58, 0x12, 0x9E, 0x84, 0xB6, 0x8C, 0x1A, 0xC0, 0x7D, 0xC9, 0x7F, 0xD4, 0xCC, 0xED, 0xBF, 0xF0, 0x7A, 0x80,
+ 0xF7, 0xAD, 0xFA, 0x7C, 0xA9, 0x64, 0x47, 0x63, 0xFD, 0xD8, 0xA7, 0xB9, 0x21, 0xD7, 0x43, 0xE1, 0x93, 0x04, 0xD9, 0x91,
+ 0xB2, 0x7B, 0x81, 0xA3, 0x68, 0xEC, 0xB5, 0x9E, 0xA1, 0x6C, 0x0E, 0x61, 0x76, 0xD8, 0xCD, 0x40, 0xCC, 0x57, 0xD9, 0x94,
+ 0xB2, 0x90, 0xBA, 0x51, 0x9A, 0x5C, 0xA6, 0xCF, 0x45, 0xAB, 0x3D, 0x94, 0x0C, 0x52, 0x1A, 0xB7, 0x1C, 0x97, 0x19, 0x93,
+ 0xC2, 0x79, 0x65, 0xDC, 0x25, 0x1F, 0xE7, 0x2C, 0x4B, 0x1A, 0x44, 0xE3, 0xCE, 0x3E, 0x8B, 0xC6, 0x8E, 0x89, 0x04, 0xEC,
+ 0x9F, 0x95, 0x6D, 0x1D, 0x76, 0xC4, 0x3D, 0x22, 0x5C, 0x4F, 0xD9, 0x61, 0x3F, 0xFC, 0x08, 0x16, 0x5B, 0xB9, 0xBB, 0xE9,
+ 0xAF, 0x3A, 0x9F, 0xD5, 0xD0, 0x68, 0x3F, 0x30, 0xC7, 0xE7, 0xCE, 0x9E, 0x3F, 0x7B, 0x96, 0x2F, 0x93, 0x54, 0xFA, 0xA6,
+ 0xEB, 0x56, 0x6C, 0x21, 0x33, 0x06, 0xA0, 0xC0, 0x52, 0xCE, 0xA2, 0x7C, 0xEE, 0xF1, 0x17, 0xF9, 0x86, 0x1C, 0xB3, 0xB7,
+ 0x4E, 0xF6, 0xF3, 0x3A, 0xD5, 0x8C, 0x47, 0xA3, 0x56, 0xEB, 0x5E, 0xB8, 0xB3, 0xD7, 0x5F, 0xAE, 0x83, 0x53, 0x01, 0xBD,
+ 0x88, 0x52, 0xD1, 0xC9, 0x00, 0xCE, 0xC9, 0xBB, 0x1B, 0xC6, 0xA0, 0x90, 0x23, 0xF1, 0x11, 0xDD, 0x40, 0x0A, 0x17, 0xE9,
+ 0xC3, 0x3B, 0x1B, 0xA1, 0x7B, 0x98, 0x93, 0x0E, 0x8C, 0xF4, 0x0D, 0x81, 0xC3, 0x0C, 0xC1, 0x09, 0x9B, 0x7C, 0x66, 0xCE,
+ 0x98, 0xE1, 0x96, 0x66, 0xA2, 0x20, 0xF2, 0x8C, 0x39, 0x74, 0x2E, 0x39, 0x06, 0x96, 0x5C, 0xF3, 0xE2, 0xF3, 0xCF, 0xD3,
+ 0xB6, 0x76, 0xF0, 0x3C, 0xC1, 0x22, 0xA5, 0x77, 0x78, 0xAD, 0x5E, 0x2B, 0x20, 0x5B, 0x5E, 0x38, 0x96, 0x38, 0x5A, 0xDC,
+ 0x6E, 0xB7, 0x59, 0x23, 0xA7, 0x2C, 0xDD, 0xB2, 0xCA, 0x2C, 0xCC, 0xB6, 0x49, 0x6C, 0x93, 0x4A, 0x7A, 0x85, 0xC6, 0x15,
+ 0xE8, 0x41, 0xD1, 0x8E, 0x65, 0xCC, 0x89, 0x1A, 0x0A, 0xF2, 0x4B, 0x69, 0xF6, 0x31, 0x9B, 0x62, 0x0C, 0x7E, 0x68, 0xD7,
+ 0x15, 0x30, 0xD8, 0x99, 0xCB, 0x92, 0xFB, 0x4A, 0x91, 0x4F, 0xF7, 0xD4, 0x6C, 0x86, 0x35, 0xFF, 0x9A, 0x0B, 0x61, 0x00,
+ 0x7D, 0xD9, 0xFA, 0x4A, 0x3F, 0x30, 0x28, 0x7F, 0x4A, 0xB2, 0xAA, 0x91, 0xB5, 0x8C, 0x71, 0xC4, 0xF6, 0x45, 0x2B, 0xCE,
+ 0x66, 0xAB, 0x11, 0x1D, 0x18, 0xCE, 0x96, 0x2C, 0xDD, 0x88, 0x42, 0x88, 0x36, 0x94, 0x02, 0x48, 0x02, 0x6E, 0x89, 0xE0,
+ 0x8E, 0xB6, 0x9D, 0xEE, 0xAE, 0x0E, 0xAB, 0xB5, 0xFF, 0x1E, 0x04, 0xDA, 0xA2, 0x00, 0x7A, 0x7F, 0x94, 0x48, 0xA4, 0x92,
+ 0x7C, 0x78, 0x40, 0x09, 0x4E, 0x27, 0xDF, 0x92, 0x7A, 0xCE, 0x99, 0x67, 0x91, 0x0E, 0xA1, 0x03, 0xD3, 0xDA, 0x73, 0xC8,
+ 0xA9, 0xD6, 0xFC, 0x15, 0x55, 0x74, 0xD9, 0x60, 0xE8, 0xA4, 0x86, 0xAE, 0x62, 0xB4, 0x4C, 0xB5, 0x0F, 0xEA, 0x05, 0x82,
+ 0xD3, 0x84, 0x7D, 0xA4, 0x37, 0x65, 0xE2, 0x87, 0x09, 0x09, 0x7E, 0xCC, 0xF1, 0x25, 0x3B, 0x9A, 0xC5, 0x7E, 0xFF, 0x19,
+ 0xB4, 0xC7, 0x09, 0x45, 0x9C, 0x47, 0xC4, 0x56, 0x35, 0x4E, 0x2F, 0xA1, 0x42, 0xA4, 0x24, 0xEA, 0x6E, 0xED, 0xAE, 0xAF,
+ 0xA8, 0x97, 0x49, 0x70, 0x64, 0x02, 0xCD, 0x12, 0x23, 0x7D, 0x67, 0xB8, 0x6F, 0x33, 0xAE, 0x93, 0xBD, 0x41, 0xBD, 0x6D,
+ 0x94, 0x0E, 0xD4, 0xCC, 0x9D, 0xA5, 0x71, 0x55, 0xEF, 0x9E, 0x2A, 0xBD, 0xF1, 0xCE, 0x35, 0xA3, 0x43, 0xA5, 0x93, 0x65,
+ 0x3D, 0xC3, 0x4D, 0xFF, 0x9D, 0x2E, 0x8A, 0x66, 0xA2, 0xD1, 0x81, 0xA2, 0x15, 0xC9, 0x85, 0x5C, 0x9A, 0x8D, 0x42, 0xD0,
+ 0x48, 0x7D, 0x10, 0x00, 0xFF, 0x40, 0x86, 0xE0, 0xE4, 0x42, 0x34, 0x64, 0x98, 0xE5, 0x2E, 0x98, 0x2E, 0x65, 0x2A, 0xAE,
+ 0xC0, 0x07, 0x6B, 0x6E, 0xE8, 0xA4, 0x44, 0x9A, 0xE3, 0x3B, 0x97, 0x69, 0x0C, 0x6D, 0x09, 0xD9, 0xD6, 0x0A, 0x51, 0x7E,
+ 0xC1, 0x88, 0x0E, 0x2C, 0xA6, 0x5B, 0xF9, 0x9E, 0xF2, 0x42, 0xAA, 0x10, 0x53, 0xB2, 0x7A, 0x73, 0x76, 0xF5, 0x1B, 0x1B,
+ 0x24, 0xA5, 0x43, 0x65, 0x06, 0xC5, 0xAA, 0x03, 0x4D, 0xBD, 0x24, 0xBB, 0x9D, 0x35, 0x4F, 0x5B, 0x17, 0x74, 0x9F, 0x52,
+ 0xE2, 0x12, 0x38, 0x77, 0xB8, 0xB7, 0x7B, 0x19, 0x7B, 0x1A, 0x68, 0xE1, 0x91, 0x68, 0xD1, 0xC7, 0x25, 0x18, 0x40, 0x45,
+ 0x0C, 0x09, 0x08, 0xE3, 0x11, 0x0D, 0x2A, 0x8E, 0x4B, 0x2D, 0x90, 0x7D, 0x89, 0x5F, 0xB6, 0x7C, 0x94, 0x64, 0x38, 0x86,
+ 0x12, 0xFC, 0x25, 0x42, 0x3F, 0x45, 0xA2, 0xE9, 0x6C, 0x78, 0x73, 0x50, 0x5E, 0x37, 0xBC, 0x99, 0x17, 0x74, 0x77, 0x80,
+ 0x4A, 0x0E, 0x3A, 0xC2, 0xE6, 0x70, 0x48, 0x06, 0xEC, 0x01, 0xD6, 0x83, 0x86, 0xDC, 0x21, 0x9F, 0x04, 0x80, 0xC8, 0x85,
+ 0xA6, 0x35, 0x14, 0x10, 0x48, 0x5F, 0x81, 0x84, 0x8F, 0x31, 0xA7, 0x9C, 0xE3, 0xE1, 0x17, 0xC2, 0xC9, 0x05, 0x70, 0xBC,
+ 0x96, 0x0C, 0xAE, 0x66, 0x5A, 0x00, 0xAD, 0x85, 0x36, 0x1C, 0x4D, 0x21, 0x9C, 0xC3, 0x9B, 0xE3, 0x7B, 0x43, 0xAB, 0x7A,
+ 0x80, 0x54, 0x49, 0xA3, 0x1D, 0x42, 0x4B, 0x6E, 0x5D, 0xF6, 0x57, 0x5A, 0x2B, 0x8D, 0xB8, 0x85, 0xD9, 0xC4, 0xC9, 0x3F,
+ 0x55, 0xE9, 0x43, 0x02, 0x97, 0xF3, 0x17, 0xE6, 0x91, 0x7A, 0x4A, 0x0D, 0x48, 0x04, 0x9A, 0x33, 0x63, 0xAA, 0x1E, 0xB7,
+ 0x47, 0x75, 0xC2, 0x97, 0x57, 0x32, 0xF1, 0x87, 0xBA, 0x8A, 0xDC, 0xB5, 0xE5, 0x27, 0x66, 0x31, 0x67, 0x01, 0x24, 0x78,
+ 0x5C, 0x41, 0x62, 0x83, 0x47, 0xEE, 0x36, 0x69, 0xB6, 0x9A, 0xB0, 0x31, 0xCC, 0xC7, 0x15, 0x77, 0x18, 0x15, 0x96, 0x0D,
+ 0xAA, 0x56, 0x07, 0x58, 0xB7, 0x3E, 0x08, 0xDB, 0xCE, 0x71, 0x0B, 0x8F, 0xAF, 0x08, 0x97, 0x42, 0xAC, 0x5B, 0x46, 0x02,
+ 0x9C, 0x9E, 0x61, 0x44, 0xAF, 0xB9, 0xBF, 0xEC, 0xB2, 0x53, 0xE9, 0x9B, 0x23, 0xCE, 0xA4, 0xA9, 0x6B, 0x9E, 0x13, 0xC5,
+ 0xC1, 0xE2, 0x12, 0xA2, 0x17, 0xBA, 0xFB, 0xB9, 0x8D, 0xA4, 0x14, 0x82, 0x90, 0x05, 0xE7, 0x7E, 0x18, 0xE4, 0x99, 0x03,
+ 0x49, 0x82, 0x9D, 0xE2, 0x6C, 0x1E, 0xE1, 0xA0, 0x45, 0x1C, 0x42, 0xBE, 0x4A, 0xA2, 0x67, 0x98, 0x34, 0x9F, 0x0F, 0x8F,
+ 0xEF, 0x83, 0x09, 0x4A, 0xEC, 0x39, 0x19, 0x8B, 0xA4, 0x31, 0xE0, 0x91, 0xA9, 0x0A, 0x17, 0x41, 0x47, 0xFA, 0x3B, 0xD2,
+ 0x37, 0x7D, 0x7C, 0x93, 0xB0, 0x9F, 0x14, 0x1E, 0xBC, 0x09, 0x12, 0x4A, 0xF5, 0x92, 0x56, 0x4C, 0x07, 0x49, 0x0A, 0x6F,
+ 0xDE, 0x1B, 0x13, 0x1E, 0x3A, 0x86, 0x34, 0xCC, 0xD9, 0xFC, 0xC4, 0x57, 0xF4, 0xC9, 0xD9, 0x5D, 0x1D, 0x43, 0x20, 0x27,
+ 0x61, 0x0C, 0x25, 0x81, 0xA2, 0x69, 0x09, 0xF2, 0x65, 0xB8, 0x58, 0x92, 0x57, 0xEE, 0xE8, 0x43, 0x96, 0x7B, 0x72, 0x88,
+ 0x05, 0x28, 0xC1, 0xA2, 0xFF, 0xD5, 0xE4, 0x2D, 0x45, 0x1B, 0x3C, 0xB1, 0xD7, 0x5E, 0x4B, 0x77, 0xDB, 0xB6, 0xA2, 0x24,
+ 0xE7, 0xDA, 0x94, 0xEC, 0x23, 0x51, 0xD7, 0x90, 0xF1, 0x0D, 0xCD, 0xCF, 0xB4, 0x28, 0xCC, 0x84, 0x4F, 0x27, 0x79, 0x52,
+ 0xD6, 0x63, 0x98, 0xA6, 0x1C, 0x53, 0xB7, 0xA5, 0xFC, 0xA1, 0x3D, 0xC9, 0xAE, 0xA6, 0xF2, 0xA2, 0x0A, 0x3E, 0x61, 0x5B,
+ 0x43, 0x37, 0xFE, 0xCE, 0x4E, 0x79, 0xE6, 0xFE, 0xD2, 0xF8, 0x9C, 0x78, 0x11, 0x79, 0xBA, 0x6C, 0x7D, 0xE0, 0x6C, 0x14,
+ 0x90, 0xDA, 0xCF, 0x1F, 0x3B, 0xD5, 0x3F, 0x74, 0xDA, 0x2F, 0x27, 0xE9, 0x40, 0x48, 0x9F, 0xEE, 0xD0, 0x51, 0x2F, 0x88,
+ 0xBA, 0xB6, 0x7F, 0x60, 0x11, 0xC9, 0xE6, 0x4E, 0xF2, 0x04, 0xB7, 0xB6, 0xB0, 0xCD, 0x0C, 0xAB, 0x03, 0xD3, 0xB7, 0xF0,
+ 0x45, 0xBE, 0xE7, 0x9D, 0x2B, 0x93, 0x4E, 0x42, 0x05, 0x5F, 0xEE, 0xCB, 0xEE, 0xE5, 0xBE, 0x9E, 0x15, 0x75, 0x15, 0x2D,
+ 0x14, 0xF0, 0xD8, 0x1C, 0x86, 0xCB, 0xB1, 0xB4, 0xB8, 0x82, 0x7A, 0x06, 0xEF, 0xD3, 0x51, 0x27, 0xBE, 0x35, 0x52, 0xC7,
+ 0x18, 0x8E, 0x8C, 0xB9, 0xEB, 0xEA, 0xC0, 0x86, 0x50, 0x97, 0x15, 0xAC, 0x7B, 0x16, 0x14, 0x58, 0xC2, 0x42, 0xCC, 0x16,
+ 0x06, 0x17, 0x5E, 0x04, 0xDF, 0x21, 0x8E, 0xB9, 0xF4, 0x55, 0xEF, 0xB5, 0xE9, 0xD6, 0x2A, 0x29, 0x4F, 0x68, 0x74, 0x66,
+ 0xD1, 0xEB, 0x97, 0xB2, 0x4B, 0x1E, 0x34, 0x5D, 0x14, 0x9D, 0x74, 0xB3, 0x4C, 0x73, 0x74, 0xA4, 0x97, 0x22, 0xEF, 0xC9,
+ 0x2F, 0xF0, 0xD2, 0x09, 0x93, 0x92, 0x12, 0x52, 0xD9, 0x70, 0xCA, 0xA6, 0x81, 0xBE, 0xCE, 0x25, 0x1C, 0xBE, 0xCE, 0x4E,
+ 0xF1, 0xB6, 0xBA, 0x4E, 0xDE, 0x3D, 0xE3, 0x17, 0xE6, 0xBD, 0xC4, 0x67, 0x9A, 0xCC, 0x4E, 0x69, 0xE6, 0x29, 0x77, 0x6D,
+ 0x10, 0x36, 0xB0, 0x26, 0xB0, 0x63, 0x8D, 0xDD, 0x1A, 0xB8, 0xC5, 0x1C, 0xD4, 0xA0, 0xBF, 0xB5, 0x0D, 0x35, 0xAB, 0x03,
+ 0x5B, 0x30, 0xDB, 0xB2, 0x4E, 0x7B, 0x47, 0x96, 0x5D, 0x20, 0x85, 0xC2, 0xD4, 0x69, 0x4C, 0x4C, 0xD9, 0x0C, 0xC2, 0x90,
+ 0x8E, 0x3F, 0xE4, 0x6B, 0x8C, 0xD9, 0xE3, 0x0E, 0xCF, 0x9E, 0x6F, 0x5C, 0xE0, 0x5B, 0xD2, 0x38, 0xDA, 0x87, 0x33, 0xCA,
+ 0xF9, 0xBC, 0x7C, 0xD9, 0x83, 0xF4, 0x51, 0x4C, 0xDC, 0xD2, 0x13, 0x74, 0x3C, 0xE4, 0xB0, 0x11, 0x8A, 0x98, 0x8F, 0x2B,
+ 0x6B, 0x91, 0x78, 0x8C, 0xC3, 0x8B, 0x37, 0x47, 0xB3, 0x1B, 0x29, 0x3B, 0xE8, 0x14, 0x38, 0xB2, 0xDF, 0x5C, 0xC6, 0x14,
+ 0xA1, 0xCE, 0x28, 0x46, 0x03, 0xAC, 0xA4, 0xF6, 0x86, 0xCA, 0x6A, 0xC6, 0x78, 0x96, 0x55, 0x29, 0xE0, 0xA3, 0x8D, 0x75,
+ 0x3B, 0x53, 0x95, 0x51, 0x9F, 0x9F, 0x3B, 0xE5, 0xF0, 0x13, 0x14, 0x72, 0x86, 0x33, 0x9C, 0xE5, 0xE8, 0x27, 0x4D, 0x05,
+ 0xDE, 0x22, 0xD3, 0x47, 0x76, 0x3E, 0xCB, 0x96, 0x8D, 0x8E, 0xC5, 0x8B, 0x3A, 0x06, 0x98, 0x56, 0xF2, 0x7D, 0x9C, 0x6C,
+ 0xEA, 0xC3, 0x09, 0x68, 0x4E, 0x10, 0x12, 0x01, 0x22, 0x6D, 0xF4, 0x5B, 0x20, 0xD2, 0xD0, 0x67, 0x21, 0x88, 0xC0, 0x8E,
+ 0x0E, 0xA2, 0xFC, 0x46, 0x02, 0x2F, 0x56, 0xEF, 0x55, 0xB6, 0xD7, 0xE4, 0xBD, 0x75, 0x93, 0xBD, 0x1E, 0xDB, 0xB1, 0x30,
+ 0x0D, 0x28, 0xC1, 0xA2, 0xD9, 0xFE, 0x42, 0xEF, 0x9D, 0xE9, 0x2B, 0x04, 0xA7, 0xC9, 0xD3, 0x74, 0xE8, 0x4F, 0x5B, 0x5B,
+ 0x09, 0x83, 0x6C, 0x8A, 0xE9, 0x6A, 0xEA, 0xE9, 0x69, 0x1F, 0xE2, 0xC4, 0x07, 0xF6, 0x67, 0x00, 0x4D, 0xD3, 0xC6, 0x4F,
+ 0x32, 0xFD, 0x41, 0x39, 0xD1, 0x08, 0x8F, 0xD1, 0x45, 0x35, 0x43, 0x80, 0xD1, 0x60, 0xA6, 0x1F, 0xC1, 0xC7, 0x63, 0xD4,
+ 0x4E, 0x7B, 0xC7, 0xA9, 0x9E, 0x3C, 0xE3, 0x21, 0x45, 0x1E, 0xE1, 0x14, 0x29, 0xBD, 0x57, 0xC9, 0xC3, 0x2E, 0x83, 0xD5,
+ 0xBD, 0x70, 0xE8, 0xC4, 0x1A, 0x0F, 0xC5, 0x21, 0xA4, 0x7F, 0x62, 0x0A, 0x2E, 0xB7, 0x00, 0x96, 0x81, 0x81, 0x6C, 0xA2,
+ 0x37, 0xF3, 0x23, 0x33, 0x52, 0xD6, 0x8F, 0x2D, 0x2E, 0x29, 0x2D, 0x17, 0xD9, 0x80, 0xC6, 0xB4, 0x9D, 0xFE, 0x33, 0x9C,
+ 0x5F, 0xD2, 0x50, 0xCE, 0xD5, 0x85, 0xCA, 0x40, 0xDE, 0x4D, 0x2E, 0xC8, 0x16, 0x7E, 0xA6, 0x95, 0x7A, 0xD4, 0x8D, 0x1E,
+ 0x3B, 0xA1, 0x7E, 0x6D, 0xCB, 0x63, 0xAF, 0x64, 0x2D, 0xC2, 0x8C, 0x98, 0xB9, 0xF9, 0x5F, 0x72, 0xAC, 0x87, 0x69, 0x99,
+ 0xA9, 0x97, 0x8C, 0x29, 0xD9, 0x6C, 0x5E, 0x64, 0xB1, 0xC8, 0xB6, 0x2B, 0xB4, 0x1D, 0x6B, 0x4E, 0x08, 0x93, 0xD1, 0x1B,
+ 0xA6, 0x00, 0x19, 0x00, 0xDA, 0x80, 0x50, 0x37, 0x7C, 0x7C, 0xA0, 0x45, 0x31, 0x1A, 0xE2, 0xCF, 0xD9, 0x7B, 0xCB, 0xE1,
+ 0x19, 0x55, 0xC5, 0x55, 0xA4, 0x0F, 0x0C, 0xF2, 0x78, 0x82, 0x39, 0xCD, 0xCB, 0x99, 0x93, 0x8F, 0x16, 0xBD, 0xC7, 0x0F,
+ 0x64, 0x8B, 0x88, 0x96, 0xAC, 0x9C, 0xF4, 0x69, 0xB6, 0x2A, 0x58, 0x5E, 0xAA, 0x5E, 0x48, 0x47, 0x41, 0x4F, 0x56, 0x30,
+ 0xA2, 0xB7, 0x4B, 0xE3, 0xAD, 0x76, 0x3D, 0x47, 0x96, 0x6C, 0x92, 0x36, 0xDA, 0xC2, 0x75, 0x9C, 0xA2, 0x57, 0x76, 0x15,
+ 0x68, 0xFE, 0x23, 0x2A, 0x31, 0x07, 0x68, 0xE8, 0xB2, 0x75, 0xBC, 0x8A, 0x52, 0x0A, 0x31, 0xDF, 0x79, 0x1C, 0x87, 0x88,
+ 0x9B, 0x6B, 0xA6, 0x2B, 0xC7, 0xA3, 0x91, 0x9A, 0xCF, 0xF2, 0xE5, 0x43, 0xE2, 0x07, 0x7C, 0x6C, 0x93, 0x11, 0x8D, 0x38,
+ 0x81, 0x0D, 0x71, 0x5E, 0x73, 0xF6, 0x26, 0xFE, 0x9A, 0xF6, 0x48, 0x00, 0x70, 0xB9, 0x40, 0x7A, 0xD7, 0xA9, 0xC5, 0xDC,
+ 0x0B, 0xEF, 0x9F, 0x7B, 0x2B, 0x29, 0x7D, 0x7D, 0xB7, 0x89, 0x2D, 0x63, 0x09, 0xBF, 0xD9, 0xB3, 0x51, 0xC3, 0xEC, 0x59,
+ 0x12, 0x99, 0xB1, 0x09, 0x26, 0xA3, 0xCA, 0x9D, 0xE1, 0x07, 0x72, 0xD4, 0xE4, 0xF1, 0x72, 0x5C, 0x1D, 0xAF, 0x80, 0x81,
+ 0xF3, 0xC5, 0x33, 0x1C, 0x65, 0x2A, 0xE9, 0x83, 0xAF, 0x58, 0x8C, 0xEE, 0x16, 0x70, 0x6F, 0x1D, 0x82, 0xB0, 0xA2, 0x93,
+ 0x0F, 0xC2, 0x22, 0x54, 0x3A, 0x0B, 0x36, 0xB6, 0x5C, 0xEB, 0x6D, 0xB4, 0x0A, 0xDD, 0x09, 0xAD, 0x1E, 0xBE, 0xFC, 0x29,
+ 0x44, 0xEF, 0x12, 0xEA, 0xB5, 0xE1, 0xA3, 0x1B, 0x1F, 0x74, 0x49, 0x12, 0x82, 0x67, 0x08, 0xEB, 0x46, 0xA4, 0x4F, 0x37,
+ 0x54, 0xA5, 0x6F, 0x9D, 0x40, 0xDE, 0xB1, 0x41, 0x21, 0x4D, 0xC0, 0x99, 0xCE, 0x63, 0x5C, 0x7C, 0x3C, 0xD8, 0x25, 0x4A,
+ 0x8C, 0xC0, 0xD9, 0xF9, 0x9C, 0x66, 0x6F, 0xC5, 0x74, 0x02, 0xB2, 0xE8, 0xC0, 0xD3, 0xFA, 0x57, 0x3F, 0xD0, 0x57, 0x73,
+ 0x9A, 0xF2, 0xE6, 0x5A, 0x01, 0x4A, 0x27, 0xD2, 0xD2, 0x31, 0x5E, 0x10, 0x44, 0x6A, 0x24, 0x77, 0xDD, 0x69, 0x9D, 0x37,
+ 0x0B, 0xB2, 0xD7, 0xB6, 0x53, 0x34, 0xA6, 0x65, 0xA4, 0x31, 0xD9, 0x0C, 0xD7, 0x84, 0x8C, 0x23, 0x47, 0x21, 0x4D, 0x57,
+ 0xFE, 0xCB, 0x64, 0x06, 0x79, 0x32, 0xA7, 0x3E, 0x13, 0x96, 0xA4, 0x28, 0x83, 0xE1, 0x33, 0xE6, 0x42, 0xE8, 0xE2, 0x6D,
+ 0x93, 0xC5, 0x3A, 0x07, 0xAC, 0x29, 0x22, 0xCD, 0x95, 0xBA, 0xD2, 0x65, 0x68, 0x3B, 0xD0, 0x24, 0x3A, 0xD0, 0x2A, 0x49,
+ 0x8D, 0x5A, 0xF3, 0x16, 0x79, 0xC4, 0xC4, 0x52, 0xBB, 0x1C, 0x47, 0x31, 0xB3, 0x53, 0x39, 0x9A, 0xC4, 0xD1, 0x87, 0x1C,
+ 0xCD, 0x11, 0x11, 0x10, 0x24, 0xD3, 0x22, 0x13, 0x63, 0x95, 0xD9, 0x61, 0xCD, 0xDF, 0x99, 0xC3, 0x38, 0xF9, 0x0F, 0xD9,
+ 0x67, 0x90, 0x4E, 0x53, 0x9D, 0x96, 0x96, 0x6D, 0x09, 0x2C, 0x90, 0xDD, 0x25, 0x0A, 0x44, 0x7C, 0x36, 0x3E, 0x18, 0x3A,
+ 0xA0, 0x16, 0xA5, 0x51, 0x4C, 0xC4, 0x33, 0x6C, 0x14, 0x61, 0x24, 0x9A, 0x13, 0xFB, 0xA6, 0x31, 0xA1, 0x14, 0xFE, 0x8B,
+ 0x3B, 0x1B, 0xF0, 0xF6, 0xE9, 0x1C, 0x5B, 0xF6, 0x60, 0x0E, 0xA5, 0x16, 0xA2, 0x57, 0x4D, 0xA8, 0xCF, 0x49, 0xBC, 0x75,
+ 0xFD, 0xE0, 0x94, 0xD8, 0xE5, 0x3C, 0xC7, 0xD3, 0x73, 0x55, 0x53, 0x55, 0xF8, 0x56, 0xDE, 0xB5, 0xB3, 0xE3, 0x63, 0xE6,
+ 0x1C, 0xBA, 0xD9, 0x44, 0x05, 0x48, 0xB1, 0x4A, 0xDF, 0x3B, 0xE3, 0xAC, 0x33, 0xCF, 0xE4, 0x20, 0x4D, 0xC3, 0xE3, 0x13,
+ 0xF6, 0xC6, 0x84, 0x89, 0x62, 0x34, 0x72, 0xC4, 0xA0, 0x97, 0xAC, 0xA6, 0xA3, 0x0E, 0x3F, 0x07, 0x97, 0x24, 0x42, 0x04,
+ 0xF8, 0x58, 0x41, 0xE3, 0x10, 0xA6, 0x99, 0xEC, 0x88, 0x5E, 0x65, 0x6D, 0xEF, 0x6A, 0x5B, 0xDF, 0xBB, 0x5C, 0x71, 0x43,
+ 0xE9, 0x96, 0x52, 0x4B, 0x3D, 0x40, 0x27, 0x47, 0x0E, 0xE1, 0x40, 0x20, 0x88, 0x91, 0x9E, 0x0C, 0xB5, 0x19, 0xF8, 0xA9,
+ 0x0E, 0xBC, 0xB9, 0xA0, 0xB7, 0x2D, 0xA3, 0x89, 0x87, 0x30, 0x4A, 0xA6, 0xCD, 0x20, 0x24, 0x38, 0x1F, 0x89, 0x7D, 0x78,
+ 0x67, 0x9E, 0x41, 0xAB, 0x52, 0x28, 0x78, 0xC6, 0xA6, 0x24, 0x2B, 0xD5, 0x61, 0x99, 0x71, 0x05, 0x5B, 0xEF, 0x8C, 0xD4,
+ 0x68, 0x7E, 0xC2, 0xC3, 0x90, 0x42, 0xD7, 0x08, 0x5D, 0x8E, 0x88, 0x12, 0x11, 0xCC, 0x93, 0x67, 0xB2, 0x29, 0xE3, 0x54,
+ 0x4D, 0x9B, 0x93, 0x43, 0xB1, 0x3E, 0x4D, 0x11, 0x52, 0x27, 0x39, 0x6A, 0x25, 0xFA, 0xAF, 0x9D, 0x8D, 0x37, 0xBE, 0xB3,
+ 0x67, 0x31, 0xDE, 0x44, 0x0D, 0xB2, 0x3D, 0x70, 0x32, 0xEF, 0x19, 0xBB, 0x41, 0xF4, 0xEA, 0x01, 0xB8, 0x2F, 0xEA, 0x21,
+ 0x8C, 0xB9, 0x3A, 0x10, 0x3F, 0xD0, 0x1D, 0x22, 0x06, 0x8E, 0x9C, 0x53, 0x95, 0x54, 0xB5, 0xFF, 0x17, 0x16, 0x99, 0xD1,
+ 0x86, 0x7F, 0x90, 0x34, 0x08, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
+};
+
+NPT_UInt8 Platinum_48x48_jpg[3041] =
+{
+ 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00,
+ 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xDB, 0x00, 0x43, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xC0,
+ 0x00, 0x11, 0x08, 0x00, 0x30, 0x00, 0x30, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, 0xC4, 0x00,
+ 0x1D, 0x00, 0x00, 0x01, 0x04, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x03, 0x04, 0x01, 0x02, 0x0A, 0xFF, 0xC4, 0x00, 0x31, 0x10, 0x00, 0x01, 0x04, 0x02, 0x01, 0x03, 0x02,
+ 0x05, 0x03, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x11, 0x08, 0x12, 0x21,
+ 0x00, 0x31, 0x09, 0x13, 0x14, 0x41, 0x71, 0x15, 0x51, 0x61, 0x16, 0x22, 0x17, 0x32, 0x81, 0x91, 0xA1, 0xC1, 0xF0, 0xFF,
+ 0xC4, 0x00, 0x1A, 0x01, 0x00, 0x02, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x03, 0x00, 0x01, 0x04, 0x05, 0x06, 0xFF, 0xC4, 0x00, 0x30, 0x11, 0x01, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04,
+ 0x06, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x21, 0x00, 0x03, 0x31, 0x12, 0x41, 0x51, 0x61, 0x71,
+ 0x04, 0x13, 0x22, 0x91, 0x32, 0x42, 0x81, 0xA1, 0xD1, 0xF0, 0xB1, 0x14, 0x15, 0x23, 0xE1, 0xF1, 0xC1, 0xFF, 0xDA, 0x00,
+ 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00, 0xAF, 0x09, 0xB2, 0x4E, 0x79, 0xFE, 0xF5, 0xF6, 0xFD,
+ 0xFE, 0xC9, 0xE7, 0xF7, 0xF2, 0xBF, 0xBF, 0xB7, 0x1F, 0xB2, 0xF8, 0xF5, 0xEB, 0x19, 0xA3, 0xFF, 0x00, 0x55, 0xFB, 0x3F,
+ 0xCE, 0x47, 0xB6, 0xBB, 0x44, 0x26, 0xF8, 0x3C, 0x77, 0xB7, 0xD8, 0xE3, 0xFF, 0x00, 0xBE, 0x71, 0xA1, 0x13, 0xE4, 0x6B,
+ 0xC2, 0xA7, 0x7F, 0xF1, 0xC7, 0x3C, 0xFB, 0xAF, 0xF0, 0xA8, 0xAB, 0xED, 0xCF, 0xB7, 0xB2, 0x7F, 0x3E, 0x85, 0x92, 0x94,
+ 0xF9, 0xBF, 0x6E, 0x7F, 0x9F, 0xDB, 0x45, 0xF2, 0xB8, 0xB9, 0x57, 0xB6, 0x5F, 0xD6, 0xC7, 0xD3, 0xB3, 0xDF, 0xC6, 0xB0,
+ 0x63, 0x7B, 0x6E, 0xA7, 0x02, 0xCE, 0xF0, 0x5B, 0xEC, 0x90, 0x2A, 0xEB, 0x4C, 0x70, 0x4C, 0xCF, 0x17, 0x5B, 0xC0, 0x2E,
+ 0x7E, 0x72, 0xD2, 0x95, 0x59, 0x25, 0xD8, 0x51, 0x4C, 0x2D, 0xCB, 0x87, 0x7C, 0x73, 0xC7, 0x48, 0x5B, 0xE4, 0x88, 0x5B,
+ 0xA9, 0xA0, 0x7B, 0x25, 0x82, 0xA2, 0x73, 0x49, 0x8D, 0xDD, 0xD0, 0xF9, 0xCD, 0xBD, 0x3A, 0x08, 0xF5, 0x74, 0xF5, 0x34,
+ 0xCA, 0xEB, 0xA6, 0xFE, 0x92, 0xF0, 0xD1, 0x68, 0xAD, 0x60, 0xCD, 0x78, 0x93, 0x08, 0x46, 0x49, 0x77, 0xD3, 0x22, 0x2F,
+ 0x28, 0x87, 0x8E, 0xCD, 0x7E, 0x1A, 0x39, 0x0C, 0xE1, 0xD4, 0xA9, 0xF8, 0x8C, 0xF5, 0x17, 0xD3, 0x36, 0xD7, 0xEA, 0x02,
+ 0x3B, 0x2E, 0x98, 0xB0, 0xD8, 0xF5, 0xDE, 0x2E, 0x4E, 0x0D, 0x8C, 0x4D, 0x97, 0x61, 0x62, 0x86, 0x2D, 0x78, 0x98, 0xB6,
+ 0xC9, 0x81, 0x85, 0x09, 0x9A, 0x63, 0xE2, 0x08, 0x13, 0xBE, 0x82, 0x16, 0xD7, 0x12, 0xC0, 0x60, 0x99, 0x41, 0x64, 0x22,
+ 0x12, 0x4B, 0x26, 0xB0, 0x84, 0x61, 0xBE, 0xB5, 0xF1, 0x22, 0x36, 0x9D, 0xCD, 0x8B, 0xDB, 0xDD, 0x9F, 0x54, 0x8B, 0x32,
+ 0xAF, 0x48, 0x35, 0x9F, 0x5A, 0xFF, 0x00, 0x26, 0x68, 0xD0, 0x7C, 0x3F, 0xD1, 0xB7, 0x5B, 0x8F, 0x54, 0x99, 0x2C, 0x5B,
+ 0xB7, 0xA1, 0x31, 0x27, 0x9A, 0xBA, 0xE1, 0x57, 0x25, 0x95, 0x9D, 0x57, 0xB4, 0xFB, 0x50, 0x59, 0xAA, 0x23, 0xC4, 0x5B,
+ 0x89, 0x43, 0x1E, 0x41, 0x06, 0x52, 0x6D, 0xA9, 0x19, 0xBF, 0xEB, 0x56, 0xEE, 0x9E, 0x7C, 0x5A, 0x4C, 0x7C, 0x10, 0xC2,
+ 0xC5, 0xBF, 0xA6, 0xDC, 0x3B, 0x28, 0x20, 0x88, 0x7B, 0xD6, 0x17, 0x76, 0x99, 0x14, 0x46, 0x4F, 0x78, 0x64, 0xA4, 0xC9,
+ 0x4F, 0x30, 0xE3, 0x55, 0xD7, 0x45, 0x21, 0x57, 0xF3, 0xA5, 0xD6, 0xCB, 0x21, 0xC5, 0x21, 0x5E, 0x39, 0xF5, 0xEC, 0x1D,
+ 0xF2, 0xF9, 0xD1, 0xFC, 0xDC, 0xDB, 0x17, 0x25, 0x55, 0x1F, 0x8B, 0xA9, 0x3A, 0xBA, 0xB9, 0xC9, 0x8A, 0xA2, 0x3F, 0x7A,
+ 0xD0, 0x72, 0x2E, 0x5C, 0xE4, 0x54, 0xEF, 0xE3, 0xF0, 0xBF, 0x9F, 0x0B, 0xCF, 0x3C, 0xFB, 0xF0, 0xBF, 0xC7, 0x8F, 0xB7,
+ 0xA2, 0x77, 0x1F, 0x57, 0xC5, 0xBE, 0xBF, 0xC7, 0xDE, 0x83, 0xD7, 0x53, 0xE6, 0xCB, 0xC0, 0x79, 0xE7, 0x3C, 0xFA, 0xDF,
+ 0x7F, 0x2D, 0xE9, 0x4E, 0xEB, 0xBE, 0xEF, 0x1D, 0xEE, 0x55, 0x5F, 0x64, 0xF2, 0xBC, 0xFF, 0x00, 0x3E, 0xEA, 0xBF, 0x9E,
+ 0x3D, 0x39, 0xDD, 0x2B, 0xB6, 0x78, 0x6F, 0xFB, 0x79, 0xFF, 0x00, 0xBF, 0x3A, 0x63, 0x28, 0x1D, 0xFF, 0x00, 0x46, 0xBC,
+ 0xF1, 0x87, 0xD8, 0xF3, 0xCE, 0x81, 0xDE, 0x5F, 0x97, 0x52, 0x34, 0x85, 0x7D, 0x34, 0xB2, 0xAC, 0x6C, 0x49, 0x5B, 0x0A,
+ 0xB9, 0x62, 0x74, 0xCD, 0x45, 0x45, 0x56, 0x31, 0xF2, 0x27, 0x6B, 0x16, 0x46, 0xA2, 0xB5, 0x8F, 0x7A, 0x2B, 0x11, 0xEA,
+ 0xD5, 0x7A, 0xF6, 0xF7, 0x7A, 0x5C, 0xB7, 0x51, 0x29, 0xBF, 0xD8, 0xE3, 0xB6, 0x32, 0xE3, 0xD8, 0x78, 0xE3, 0x42, 0xEE,
+ 0x54, 0x8B, 0x8F, 0x39, 0xC9, 0x46, 0x2C, 0xA1, 0x30, 0xF7, 0x7B, 0xE0, 0xCE, 0xA5, 0x4C, 0xDD, 0x25, 0x33, 0xAA, 0xBD,
+ 0x39, 0x95, 0xEC, 0xBE, 0x92, 0x2D, 0xC8, 0xDC, 0x38, 0xBE, 0x3F, 0x57, 0x24, 0x5B, 0x23, 0x5C, 0x4E, 0xD1, 0x44, 0xDF,
+ 0x5A, 0x89, 0xF3, 0x8C, 0xD8, 0x6C, 0x63, 0xCE, 0x75, 0xF8, 0x8D, 0x8E, 0x7B, 0xEC, 0x74, 0x29, 0xE6, 0x54, 0x13, 0x63,
+ 0xE0, 0x23, 0xD9, 0x50, 0x10, 0x0C, 0x82, 0x1D, 0x7F, 0x51, 0x86, 0xCD, 0x2A, 0x0C, 0xEC, 0xB3, 0xDD, 0x37, 0x31, 0x3A,
+ 0x05, 0xA2, 0x47, 0xE1, 0x5A, 0xCC, 0x6D, 0xCC, 0x66, 0x19, 0xE9, 0x41, 0xBA, 0x4E, 0xA3, 0x3A, 0x09, 0x6E, 0x46, 0x69,
+ 0x19, 0xA6, 0xDC, 0xAE, 0x89, 0x52, 0xC2, 0x77, 0x76, 0x5F, 0xE5, 0x53, 0x20, 0xD2, 0xDD, 0x0C, 0xBB, 0x30, 0xFB, 0x33,
+ 0xA2, 0xFE, 0xA7, 0xF4, 0x4E, 0x33, 0xAD, 0xB7, 0xB6, 0xE8, 0xC1, 0x6D, 0x31, 0xAC, 0x77, 0x7C, 0x57, 0xD9, 0x9F, 0x40,
+ 0x4D, 0x8B, 0x25, 0x88, 0xC2, 0x2C, 0xF1, 0x70, 0x31, 0x7A, 0x3C, 0x88, 0xAB, 0x21, 0x64, 0x8A, 0x39, 0x42, 0x5B, 0xC3,
+ 0xE2, 0x75, 0xED, 0x63, 0xA7, 0x6B, 0x56, 0xC8, 0x12, 0x9C, 0x7C, 0x3D, 0xF0, 0x3D, 0x92, 0xBC, 0x46, 0xE5, 0x29, 0x75,
+ 0x12, 0x96, 0x19, 0x11, 0x15, 0x25, 0xD3, 0x1B, 0x6A, 0x8F, 0xC5, 0x48, 0xBC, 0xDB, 0xDA, 0xB4, 0xAD, 0xB8, 0x8F, 0x51,
+ 0x19, 0x12, 0x76, 0xC0, 0x91, 0x1B, 0x68, 0x55, 0x13, 0x17, 0x20, 0x39, 0x4E, 0x1E, 0xCF, 0x66, 0x78, 0x88, 0x08, 0x8D,
+ 0xA8, 0x43, 0xE0, 0x73, 0x7B, 0x93, 0xFC, 0xCA, 0x9E, 0x7C, 0xA2, 0x2A, 0x72, 0xBE, 0x15, 0xBC, 0xB5, 0x5A, 0xA8, 0x9E,
+ 0x55, 0x51, 0x5A, 0xEE, 0x38, 0x5E, 0x7D, 0x33, 0x06, 0x78, 0xFB, 0xFF, 0x00, 0xE2, 0xFE, 0xF5, 0xED, 0xA3, 0x62, 0xC2,
+ 0x87, 0x0B, 0xC6, 0x39, 0xE6, 0xDF, 0xB9, 0xC6, 0x39, 0xD2, 0x6C, 0x9B, 0x27, 0x35, 0x55, 0xBD, 0xDC, 0x2A, 0x73, 0xEF,
+ 0xCF, 0xDB, 0xF6, 0xE7, 0x85, 0x4F, 0x7F, 0x1F, 0xED, 0xC7, 0xAB, 0xD5, 0x6B, 0xAD, 0xCD, 0xF9, 0xC3, 0x04, 0x4C, 0x95,
+ 0xCA, 0xC5, 0x31, 0xB1, 0x48, 0xB0, 0x7C, 0xC7, 0x48, 0xD6, 0x2C, 0x88, 0xD5, 0x56, 0xA4, 0x8E, 0x85, 0x7E, 0x6B, 0x58,
+ 0xE5, 0x4E, 0xD7, 0xBE, 0x35, 0x49, 0x18, 0x8A, 0xAF, 0x8F, 0x87, 0xB5, 0x17, 0xD0, 0xCA, 0xE9, 0x4A, 0xB3, 0x25, 0x96,
+ 0x5F, 0xAF, 0x0D, 0x79, 0xA4, 0x6B, 0x87, 0x51, 0xF4, 0xE7, 0x15, 0x60, 0x9C, 0xF7, 0x1A, 0xBA, 0xF7, 0xFD, 0x1D, 0x3D,
+ 0x5B, 0x1B, 0xAC, 0x8D, 0x37, 0xB7, 0x75, 0x56, 0x3F, 0x8B, 0x1B, 0xD2, 0x81, 0x3A, 0x43, 0x75, 0x62, 0x21, 0x54, 0xD4,
+ 0xA6, 0x6F, 0xAD, 0x32, 0x28, 0xAD, 0xB5, 0x9E, 0xC9, 0xAF, 0x01, 0xB0, 0x86, 0x61, 0x59, 0xA6, 0x20, 0x7B, 0x88, 0x22,
+ 0x8F, 0x2F, 0x9C, 0x46, 0x3C, 0xD6, 0xE5, 0xD8, 0xBA, 0xE3, 0x01, 0x5B, 0xD8, 0x23, 0xD2, 0xFF, 0x00, 0x15, 0x26, 0x42,
+ 0x7E, 0xB4, 0x64, 0x9B, 0x8D, 0xB6, 0x4C, 0xEF, 0xD3, 0xF4, 0xCE, 0xB2, 0xFE, 0x19, 0xC7, 0xB7, 0x38, 0x94, 0x2B, 0xB1,
+ 0x2E, 0x35, 0x51, 0xDC, 0xDD, 0x16, 0x33, 0xFA, 0xE3, 0x27, 0x1D, 0x5D, 0x2F, 0x4B, 0xCD, 0xC5, 0xC3, 0x45, 0x62, 0x32,
+ 0x8B, 0xEE, 0x77, 0x79, 0xB4, 0x2E, 0x2D, 0x6B, 0xD3, 0x56, 0xB9, 0xA8, 0xEB, 0xFF, 0x00, 0x43, 0xF5, 0x8D, 0xAC, 0x31,
+ 0x5D, 0xA8, 0xFA, 0xC9, 0x29, 0x28, 0xF4, 0xFE, 0x30, 0xFD, 0x93, 0x26, 0xC3, 0xB2, 0xB0, 0x92, 0xF0, 0x31, 0xA6, 0x1E,
+ 0xD8, 0xB4, 0xC2, 0xC4, 0xD7, 0xB3, 0x4B, 0x8A, 0x0E, 0xD3, 0x4A, 0x2A, 0x07, 0x64, 0x97, 0x21, 0xA0, 0xD6, 0xA7, 0x63,
+ 0x76, 0xAD, 0x46, 0x59, 0x9D, 0x56, 0x43, 0x08, 0x12, 0x59, 0xFC, 0xBE, 0xA8, 0x4E, 0x0D, 0xCC, 0x4F, 0x97, 0x26, 0xCA,
+ 0xEE, 0xDC, 0xE2, 0x94, 0x0A, 0x22, 0xA3, 0x46, 0x35, 0x5F, 0xF1, 0x6E, 0x3D, 0x2C, 0x65, 0x2E, 0x98, 0xAC, 0xE4, 0xB0,
+ 0x20, 0xE1, 0xA2, 0xAD, 0x91, 0x72, 0xC0, 0xD0, 0x88, 0xA6, 0x07, 0x56, 0xEF, 0xAB, 0x3E, 0x30, 0xB8, 0x77, 0x53, 0x58,
+ 0x19, 0xDA, 0x8B, 0xE2, 0x2D, 0x84, 0xB3, 0x70, 0xE1, 0xF7, 0x67, 0x8F, 0x75, 0x53, 0x7D, 0x8B, 0x14, 0x15, 0x06, 0x71,
+ 0x83, 0xDF, 0x80, 0xC7, 0xC1, 0x0D, 0xBE, 0x3C, 0xF7, 0x04, 0x3D, 0x3A, 0x3C, 0x81, 0x66, 0x20, 0x63, 0x00, 0x6C, 0x91,
+ 0x02, 0x50, 0x72, 0xAC, 0x24, 0xC7, 0x3C, 0x5F, 0x30, 0x57, 0xB3, 0xFD, 0x2C, 0x64, 0x46, 0x5F, 0x0F, 0x38, 0xC2, 0x79,
+ 0x25, 0x07, 0xB8, 0xF6, 0xAB, 0x3A, 0xBC, 0x92, 0x1B, 0xCF, 0x9E, 0x33, 0x91, 0xF9, 0x72, 0xEB, 0xD9, 0x94, 0xB6, 0xD3,
+ 0x91, 0x6C, 0x4E, 0xF9, 0xC3, 0x5C, 0x73, 0xFF, 0x00, 0xAB, 0xAE, 0xA7, 0x77, 0xAF, 0xC1, 0x2F, 0x34, 0xD1, 0x74, 0x15,
+ 0x74, 0x7A, 0xAF, 0x69, 0xD5, 0xE5, 0x3A, 0xA6, 0x80, 0xAA, 0x7C, 0x2E, 0x8B, 0x0F, 0x3E, 0x83, 0x18, 0xB6, 0xD8, 0x12,
+ 0xD9, 0xD9, 0x4E, 0x73, 0x1B, 0xB2, 0x72, 0xF5, 0x0E, 0xFC, 0xF6, 0xC1, 0xFA, 0xC9, 0x24, 0x1C, 0x7E, 0x40, 0x1D, 0x6B,
+ 0xB2, 0x10, 0x6B, 0xC8, 0x26, 0xB6, 0x9E, 0x41, 0x43, 0xFA, 0x16, 0x57, 0xAD, 0xD8, 0xF8, 0x9D, 0xBB, 0x65, 0x28, 0x31,
+ 0x93, 0x52, 0x93, 0x9A, 0xED, 0xF4, 0x9C, 0x38, 0xF3, 0x8F, 0xBA, 0xAC, 0xDA, 0x97, 0xC5, 0x75, 0x49, 0x67, 0x19, 0x45,
+ 0xCC, 0x94, 0xEA, 0x0E, 0x98, 0xFE, 0x53, 0x05, 0xA6, 0x02, 0xF3, 0xCF, 0x7B, 0x7C, 0x9D, 0x49, 0x93, 0xA5, 0xF4, 0xC6,
+ 0x5C, 0xC5, 0x5E, 0x2D, 0x30, 0x76, 0x66, 0x16, 0x70, 0x94, 0xE0, 0x92, 0x59, 0x81, 0xD3, 0x8A, 0x54, 0xEF, 0x94, 0x7A,
+ 0x81, 0xCD, 0x3C, 0xA3, 0x4E, 0x2E, 0x3A, 0xB8, 0x55, 0xA1, 0x29, 0x47, 0x18, 0x51, 0x73, 0xC9, 0x0B, 0xE6, 0x26, 0x69,
+ 0x25, 0x7A, 0xAF, 0xA0, 0x27, 0x24, 0xC5, 0x17, 0x90, 0x2A, 0xCE, 0xE1, 0x58, 0x7B, 0x97, 0x8C, 0xFB, 0x5E, 0x9C, 0xA5,
+ 0xFB, 0xE4, 0x30, 0x7A, 0xF0, 0x70, 0xE7, 0x27, 0x6F, 0x05, 0x3A, 0xDF, 0x9A, 0xC9, 0x8A, 0x8B, 0xDE, 0xA9, 0xC7, 0x85,
+ 0xF2, 0xE4, 0x4F, 0x6F, 0xBF, 0x95, 0xE3, 0xD9, 0x7D, 0xBD, 0xFF, 0x00, 0xED, 0x9D, 0x63, 0x78, 0xEF, 0x59, 0xE2, 0x9F,
+ 0x2D, 0x63, 0xBF, 0x9F, 0xE2, 0x7F, 0x3E, 0x3D, 0xBF, 0xBE, 0x9A, 0x04, 0x69, 0x01, 0x24, 0x13, 0x4C, 0xAC, 0x47, 0x35,
+ 0x18, 0xF7, 0xAA, 0xB5, 0xA8, 0xE5, 0x54, 0x46, 0xAA, 0xAF, 0x6F, 0x6F, 0x2A, 0xE5, 0x5E, 0x17, 0xB5, 0x13, 0x9E, 0x57,
+ 0x8E, 0x3C, 0xAA, 0x7A, 0x5A, 0x99, 0x68, 0x3E, 0xFE, 0xB7, 0xFD, 0xF6, 0xAE, 0xFA, 0x9A, 0x79, 0x3A, 0x67, 0xD7, 0x16,
+ 0xDB, 0x83, 0x03, 0xDE, 0x78, 0x9E, 0xB1, 0xCB, 0x30, 0x3B, 0xAF, 0xD1, 0x4F, 0x03, 0x67, 0x65, 0x98, 0x4D, 0x4E, 0x55,
+ 0xF5, 0x19, 0x92, 0x94, 0x35, 0x6C, 0x18, 0x90, 0x79, 0x00, 0xD8, 0xC9, 0x02, 0x86, 0x32, 0x53, 0x8F, 0x09, 0x2D, 0x1A,
+ 0xFA, 0xE6, 0xB6, 0x63, 0x8B, 0x22, 0xC5, 0xF4, 0xE1, 0x5A, 0xA0, 0xA3, 0xC2, 0x0A, 0x4D, 0xA7, 0xE0, 0xF6, 0xCD, 0xDD,
+ 0xBD, 0xF8, 0x43, 0x72, 0x19, 0x94, 0x67, 0xD2, 0x3D, 0xC3, 0xA4, 0xBF, 0xCA, 0x47, 0x9B, 0x72, 0xAD, 0x0D, 0x70, 0xE4,
+ 0x9E, 0xE6, 0xDC, 0x77, 0x2F, 0x85, 0xFA, 0x57, 0xF2, 0xF3, 0xDE, 0xB3, 0x6F, 0x49, 0x58, 0x4C, 0x73, 0x8C, 0xC4, 0x2C,
+ 0x8E, 0x2D, 0x91, 0x41, 0x74, 0x55, 0x74, 0x43, 0x1E, 0x3A, 0x0A, 0x44, 0xA3, 0xAC, 0x4B, 0x14, 0xF1, 0x3B, 0xFB, 0x5E,
+ 0xE4, 0x72, 0x2C, 0x6A, 0x88, 0xA8, 0x8E, 0x56, 0xAB, 0xD7, 0x84, 0xED, 0x5E, 0x79, 0x6A, 0xFD, 0xBD, 0x64, 0xDC, 0x96,
+ 0xF4, 0x67, 0xD2, 0xC5, 0x2A, 0x54, 0xE1, 0x28, 0x2A, 0xF2, 0x7A, 0xE0, 0x5B, 0x3D, 0x79, 0xD6, 0x82, 0x05, 0x64, 0xA6,
+ 0xB9, 0xBB, 0xE7, 0xF6, 0xAE, 0x3F, 0xB9, 0xD5, 0x9E, 0x74, 0x5B, 0xAB, 0x6F, 0xB2, 0xEC, 0x67, 0x28, 0xD9, 0xF9, 0x76,
+ 0x33, 0x79, 0x7B, 0x47, 0x87, 0x53, 0x5B, 0x98, 0x88, 0x24, 0xB6, 0x55, 0x90, 0xAD, 0xF5, 0x5D, 0x5C, 0xE5, 0xD4, 0x46,
+ 0x5D, 0xBD, 0x57, 0x16, 0x75, 0x50, 0xBA, 0xCE, 0x30, 0x19, 0x3D, 0x98, 0x6E, 0x69, 0x61, 0x8D, 0x24, 0xE4, 0xB6, 0x56,
+ 0xA3, 0x58, 0xAD, 0xEA, 0x7C, 0x1E, 0xDA, 0xED, 0x4B, 0x72, 0x71, 0xBE, 0xA2, 0x44, 0x46, 0xB2, 0x87, 0x6E, 0x28, 0x5C,
+ 0x59, 0xE3, 0x35, 0xD9, 0x1B, 0xB3, 0x76, 0xD2, 0x31, 0x97, 0x4C, 0x97, 0x15, 0x4A, 0x1C, 0x2E, 0x4A, 0xB7, 0xD9, 0xC7,
+ 0x27, 0x7D, 0x57, 0x5D, 0xEE, 0xC8, 0xDA, 0x39, 0xF1, 0xB6, 0x97, 0xD9, 0xD4, 0xB8, 0x79, 0x39, 0x06, 0x42, 0x54, 0x76,
+ 0x57, 0x27, 0x55, 0xE1, 0x35, 0x54, 0xB6, 0x43, 0xD8, 0xB5, 0x5C, 0xB3, 0x0E, 0x3D, 0x88, 0x12, 0xC6, 0x5C, 0xEE, 0x8A,
+ 0x47, 0xBC, 0x62, 0xCC, 0xB7, 0x7D, 0x9D, 0x8D, 0xAC, 0x90, 0x34, 0xDB, 0x72, 0xCE, 0x3F, 0xB8, 0x87, 0x72, 0x19, 0xEE,
+ 0x4A, 0xFA, 0x88, 0x1D, 0x56, 0x9D, 0x31, 0x23, 0xD3, 0x9E, 0x05, 0x73, 0x5E, 0x5B, 0x6F, 0xBF, 0x1A, 0x74, 0x63, 0x22,
+ 0xBE, 0xBB, 0xA3, 0x21, 0x10, 0xF1, 0x8A, 0x0B, 0xE0, 0xA3, 0xC1, 0xC1, 0xE3, 0x9B, 0x29, 0xCE, 0x9B, 0x95, 0x12, 0x51,
+ 0x51, 0x5C, 0xC7, 0xC4, 0xF6, 0x96, 0x08, 0xD6, 0x11, 0xFC, 0xB7, 0x3A, 0x37, 0x7C, 0xC8, 0xA1, 0x2D, 0xAE, 0x8E, 0x22,
+ 0x58, 0xE8, 0xDB, 0xF2, 0x49, 0x46, 0xBD, 0x58, 0xD5, 0x95, 0x8E, 0x64, 0x8C, 0x91, 0xED, 0x59, 0x39, 0x82, 0x53, 0xDB,
+ 0x2B, 0x1B, 0x05, 0xA7, 0x16, 0x9E, 0x31, 0x2F, 0x5E, 0xE3, 0xA3, 0x4B, 0xC5, 0xA7, 0x0D, 0x9F, 0xAE, 0x3F, 0xBE, 0x9E,
+ 0xDA, 0xC1, 0x21, 0x6E, 0x08, 0x07, 0x7D, 0x43, 0xA5, 0x21, 0x58, 0xC5, 0x59, 0x15, 0x1A, 0x92, 0xCD, 0x22, 0xAB, 0xBB,
+ 0x9E, 0xFE, 0xC6, 0xF6, 0x77, 0xBD, 0x51, 0x5C, 0xF4, 0x89, 0x8B, 0x1A, 0x3B, 0x84, 0x8E, 0x3E, 0xDE, 0x5B, 0xC4, 0xEB,
+ 0x7A, 0x6B, 0x37, 0x76, 0xE1, 0x68, 0xEF, 0xC2, 0x16, 0x9C, 0x56, 0x6F, 0x06, 0x2B, 0x57, 0xA5, 0x6E, 0x8B, 0xEA, 0x8B,
+ 0x64, 0x74, 0xBD, 0xB3, 0x3F, 0xC4, 0x9D, 0x01, 0x85, 0xE1, 0xD9, 0x2E, 0x4F, 0x61, 0x5A, 0xCC, 0x4E, 0xCE, 0x4D, 0xBF,
+ 0x8C, 0x4A, 0x78, 0x19, 0x0D, 0x15, 0x85, 0x88, 0x85, 0xDA, 0xE2, 0x54, 0xD4, 0x61, 0xDB, 0x57, 0x17, 0x48, 0x06, 0x48,
+ 0x68, 0x55, 0x8C, 0x2E, 0xFA, 0xD0, 0xF5, 0xB8, 0x1A, 0x30, 0x45, 0x70, 0xC1, 0x88, 0xC6, 0x4F, 0x33, 0xCB, 0x6B, 0x7E,
+ 0x5B, 0x13, 0x65, 0xB3, 0x02, 0x6C, 0xAA, 0x0B, 0x31, 0x2E, 0x37, 0xF8, 0x63, 0x1B, 0xC5, 0xB5, 0xF5, 0x36, 0x88, 0x3E,
+ 0x75, 0x9B, 0x77, 0x6A, 0x5B, 0xC6, 0x40, 0xA5, 0x4E, 0x49, 0x49, 0x38, 0xE1, 0xC1, 0xE2, 0xD7, 0xD4, 0x4A, 0xD5, 0x83,
+ 0xE6, 0x9F, 0x13, 0x6F, 0x86, 0x36, 0x7D, 0x53, 0x7D, 0x97, 0xE4, 0x1D, 0x1C, 0xF5, 0x11, 0x5B, 0xB9, 0x0B, 0x80, 0x62,
+ 0x71, 0xDD, 0x7C, 0x16, 0x41, 0x85, 0xC3, 0xAF, 0x72, 0xAC, 0x8E, 0x46, 0x32, 0x1B, 0x31, 0x84, 0xCF, 0x60, 0x20, 0xDB,
+ 0xBC, 0x73, 0x1C, 0x0A, 0xC7, 0xE6, 0x94, 0xC9, 0xAC, 0xB1, 0xDB, 0x12, 0x66, 0xA4, 0x86, 0x19, 0x06, 0x85, 0x49, 0x9D,
+ 0x62, 0x66, 0xDF, 0xF7, 0x1D, 0x89, 0x17, 0x2D, 0xA9, 0x33, 0x0C, 0x0C, 0x62, 0xDB, 0x74, 0x7D, 0x77, 0x55, 0xEB, 0x47,
+ 0x16, 0x1A, 0xCB, 0x19, 0x7C, 0x44, 0x3A, 0x61, 0x1D, 0xC7, 0xA7, 0x88, 0xDC, 0x6E, 0x49, 0x79, 0xE9, 0xBC, 0x1D, 0xB3,
+ 0x8A, 0x32, 0x6A, 0x1C, 0xEF, 0x9E, 0xAD, 0x05, 0xEA, 0x73, 0x4F, 0x62, 0x98, 0x2E, 0x1F, 0xAD, 0xCF, 0xE9, 0x7C, 0x1D,
+ 0x69, 0xB0, 0x1D, 0x91, 0xDF, 0xE0, 0x78, 0x2E, 0xCC, 0xC8, 0xAE, 0x29, 0x33, 0xD7, 0x65, 0x54, 0x9F, 0xA7, 0xD0, 0xE6,
+ 0xF2, 0x5E, 0x20, 0xB8, 0xED, 0xD2, 0xD8, 0x62, 0x16, 0x94, 0x52, 0x56, 0x2D, 0x49, 0x9F, 0x34, 0x2A, 0xF9, 0x6F, 0x21,
+ 0xB1, 0xAF, 0x73, 0x54, 0x8E, 0xD8, 0xF3, 0xEF, 0xFC, 0x5B, 0xF1, 0x3B, 0x21, 0x12, 0x5B, 0x0C, 0x26, 0x5C, 0x09, 0x7E,
+ 0x28, 0xA7, 0xD1, 0x21, 0x08, 0xB5, 0x19, 0x46, 0x91, 0x2B, 0x23, 0x8D, 0x3B, 0x6F, 0x6A, 0x4E, 0xE4, 0x9D, 0xEB, 0x92,
+ 0xC7, 0x96, 0x5F, 0x94, 0xF1, 0x55, 0x8C, 0xB6, 0x01, 0x9A, 0x5E, 0x0D, 0x47, 0x15, 0xB0, 0xB6, 0x26, 0x47, 0x91, 0x6E,
+ 0x67, 0xD7, 0xD8, 0x4A, 0xD8, 0x5A, 0x51, 0xAF, 0x1E, 0x01, 0xA7, 0x3A, 0x68, 0x61, 0x64, 0x0E, 0x34, 0xD6, 0x8D, 0x1C,
+ 0x51, 0x4F, 0x64, 0x53, 0x63, 0x6C, 0xB6, 0x06, 0xA4, 0x51, 0x48, 0x79, 0x4B, 0x21, 0x73, 0x31, 0x48, 0x9A, 0x57, 0xBD,
+ 0x31, 0xA7, 0x33, 0x6E, 0x5C, 0xDD, 0x03, 0xC1, 0xF5, 0x21, 0x46, 0x79, 0x5B, 0xE6, 0xD4, 0xB5, 0xD6, 0xC8, 0xC6, 0x80,
+ 0xE6, 0xBD, 0x8A, 0x3F, 0x63, 0xF5, 0xA3, 0xDB, 0x44, 0x9C, 0x62, 0x7B, 0xAB, 0xBF, 0x3F, 0x7F, 0xC7, 0x9F, 0x0B, 0xC7,
+ 0xDB, 0xFE, 0x3F, 0x21, 0xD1, 0x2A, 0xE3, 0x3E, 0xE7, 0xF7, 0xFC, 0xFF, 0x00, 0x37, 0xAD, 0x49, 0xCC, 0x6A, 0xB5, 0x51,
+ 0xDC, 0xB9, 0x17, 0x9E, 0x3D, 0x95, 0x3F, 0xD5, 0x3F, 0xF2, 0xA7, 0x0B, 0xC2, 0xF3, 0xC7, 0xAB, 0x22, 0x0D, 0xAD, 0x01,
+ 0x63, 0x66, 0x7C, 0x51, 0xCF, 0xEC, 0xFD, 0x9B, 0x25, 0x27, 0x25, 0x77, 0xE2, 0xBD, 0xDD, 0x0E, 0x5C, 0x8B, 0x19, 0x0E,
+ 0x86, 0xC6, 0x20, 0xEF, 0xE9, 0x0E, 0xCC, 0x2E, 0xE7, 0x9F, 0x1E, 0x83, 0x1A, 0x88, 0x79, 0x88, 0xBE, 0xC6, 0xEB, 0xA1,
+ 0x9A, 0x02, 0x2C, 0xF2, 0x72, 0x64, 0x96, 0x14, 0x0A, 0xAC, 0x52, 0x81, 0x46, 0x89, 0x54, 0x44, 0x32, 0x4B, 0x61, 0x60,
+ 0x69, 0x90, 0x45, 0x0A, 0x8E, 0x10, 0x96, 0x48, 0x55, 0xB2, 0x8F, 0x4A, 0xC5, 0x3A, 0x97, 0xA6, 0x30, 0x3F, 0x14, 0x4E,
+ 0x65, 0x35, 0x68, 0xE2, 0xC0, 0x2D, 0x16, 0xFB, 0x36, 0xB6, 0x63, 0x2E, 0x83, 0x9B, 0xFA, 0xAD, 0xA4, 0x3C, 0xF9, 0xA7,
+ 0x01, 0xEF, 0xEB, 0xA0, 0x6C, 0xA8, 0xAC, 0xE2, 0x17, 0x38, 0x78, 0x3B, 0xE2, 0x62, 0x7C, 0xB4, 0x46, 0x35, 0x15, 0x8D,
+ 0x6B, 0x51, 0xAD, 0x6B, 0x79, 0x4E, 0x51, 0xA8, 0xDE, 0x1B, 0xE3, 0x9E, 0x53, 0xEF, 0xED, 0xCA, 0x80, 0x3B, 0x1F, 0x63,
+ 0x4C, 0xAA, 0xCF, 0xDB, 0xF5, 0x7D, 0x5F, 0x37, 0xFE, 0x03, 0x4A, 0x2C, 0x4F, 0x3D, 0x97, 0x54, 0x66, 0x74, 0x59, 0xD8,
+ 0xD5, 0x42, 0x5D, 0x09, 0x51, 0x34, 0xB0, 0x5E, 0x51, 0x1B, 0x58, 0x1D, 0xC8, 0x57, 0xB8, 0xDD, 0x84, 0x2E, 0x12, 0xF2,
+ 0xAC, 0xBA, 0x73, 0xF8, 0x0A, 0xDA, 0x29, 0xC3, 0x7A, 0xBD, 0x6B, 0x0B, 0x7C, 0x31, 0xD8, 0x36, 0x37, 0x80, 0xD2, 0x82,
+ 0x90, 0xB6, 0x9C, 0x31, 0x46, 0x7F, 0x2E, 0x44, 0x9F, 0xA8, 0xBA, 0x91, 0x43, 0x71, 0x79, 0x2B, 0x03, 0x5C, 0x82, 0x9E,
+ 0xF9, 0xD0, 0x4E, 0xEA, 0xCE, 0x63, 0x9A, 0xAB, 0xB3, 0x84, 0xAF, 0x6F, 0xF1, 0xA1, 0xF7, 0x59, 0x16, 0x25, 0x67, 0x72,
+ 0x7C, 0xF8, 0x55, 0xCD, 0x4D, 0xBE, 0x3C, 0x4C, 0xAE, 0x36, 0xB1, 0x29, 0xCA, 0xB5, 0x36, 0x2A, 0xB0, 0x8C, 0x98, 0x89,
+ 0x05, 0xA3, 0x2E, 0x5B, 0xC0, 0x81, 0xB8, 0x65, 0x85, 0x58, 0xCD, 0x8A, 0x12, 0x20, 0xB3, 0x89, 0xF6, 0x51, 0x44, 0xA3,
+ 0xA1, 0xE4, 0x94, 0x63, 0xA6, 0x26, 0x69, 0x36, 0x37, 0x51, 0x91, 0x28, 0xB9, 0x02, 0xEB, 0x3D, 0x9E, 0xA0, 0xC8, 0x72,
+ 0x52, 0xE4, 0xCE, 0xA4, 0x27, 0xD6, 0x08, 0xD9, 0xE8, 0xF1, 0x8E, 0x5B, 0x01, 0x6F, 0xD3, 0x1D, 0xEB, 0x8D, 0x7F, 0xFF,
+ 0xD9
+};
+
+NPT_UInt8 Platinum_48x48_png[4681] =
+{
+ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x30, 0x08, 0x02, 0x00, 0x00, 0x00, 0xD8, 0x60, 0x6E, 0xD0, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47,
+ 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC,
+ 0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00,
+ 0xFA, 0x00, 0x00, 0x00, 0x80, 0xE8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xEA, 0x60, 0x00, 0x00, 0x3A, 0x98, 0x00, 0x00,
+ 0x17, 0x70, 0x9C, 0xBA, 0x51, 0x3C, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x12, 0x00, 0x00,
+ 0x0B, 0x12, 0x01, 0xD2, 0xDD, 0x7E, 0xFC, 0x00, 0x00, 0x11, 0xB2, 0x49, 0x44, 0x41, 0x54, 0x58, 0x47, 0x6D, 0x98, 0x09,
+ 0x90, 0x5C, 0xD5, 0x75, 0x86, 0x9F, 0x90, 0x10, 0x48, 0x02, 0x84, 0x00, 0xED, 0xB3, 0xAF, 0xBD, 0x4F, 0x77, 0xCF, 0xF4,
+ 0xEC, 0x7B, 0xEF, 0x33, 0xBD, 0xCE, 0xDA, 0x3D, 0x3D, 0xDD, 0xB3, 0xF6, 0xEC, 0xDA, 0x46, 0x1A, 0xA1, 0x0D, 0xA1, 0x65,
+ 0x8C, 0x30, 0x94, 0x04, 0x8C, 0x25, 0x90, 0xC0, 0x06, 0x51, 0x91, 0x64, 0x04, 0xA2, 0x2C, 0x88, 0x21, 0x18, 0x12, 0x0C,
+ 0x49, 0x2C, 0x82, 0x4C, 0xC0, 0x31, 0x06, 0x93, 0x18, 0x2A, 0x94, 0x43, 0x62, 0xA8, 0x72, 0x01, 0x55, 0x10, 0x6C, 0x19,
+ 0xA4, 0xC9, 0x77, 0xDF, 0x1D, 0x35, 0x63, 0xC7, 0x5D, 0xA7, 0x5E, 0xBD, 0x7E, 0xCB, 0x3D, 0xFF, 0xFD, 0xCF, 0x39, 0xFF,
+ 0x39, 0xDD, 0x0B, 0xC6, 0xFA, 0xB7, 0x28, 0xEA, 0x67, 0xC1, 0x95, 0xD9, 0x2B, 0x0B, 0xC4, 0xC9, 0xEC, 0x15, 0xBE, 0xCC,
+ 0xF2, 0x91, 0xD7, 0x95, 0xD9, 0x05, 0xB3, 0x0A, 0x97, 0xAE, 0x88, 0x4B, 0x7C, 0x16, 0x28, 0x0B, 0xAF, 0x28, 0xB3, 0xD7,
+ 0x88, 0x27, 0xB8, 0xB9, 0x70, 0xE1, 0xC2, 0xEB, 0xAE, 0xBB, 0x6E, 0xE1, 0x82, 0xD9, 0x25, 0x37, 0x2C, 0xF9, 0xFA, 0x4F,
+ 0xB3, 0x57, 0xAE, 0x5C, 0xF9, 0xD3, 0x1F, 0xFE, 0xF8, 0xD5, 0xA5, 0x3F, 0x7E, 0xF3, 0xCD, 0x37, 0xCA, 0x65, 0xF1, 0x8A,
+ 0x82, 0x2D, 0x10, 0x9F, 0x85, 0x8B, 0x16, 0x70, 0xF7, 0xEB, 0xCB, 0xB3, 0x0B, 0x2E, 0x5F, 0x11, 0x37, 0x38, 0xB0, 0xB6,
+ 0x58, 0xE4, 0x9A, 0x05, 0xCA, 0x37, 0x72, 0xB5, 0xCB, 0xF8, 0x1E, 0xE9, 0xDD, 0x24, 0x2D, 0xD9, 0xB3, 0x61, 0xB8, 0x67,
+ 0x23, 0x36, 0x94, 0xD8, 0x30, 0x14, 0xDF, 0x38, 0x98, 0x98, 0x48, 0xC6, 0xC7, 0x92, 0x71, 0x8E, 0x13, 0x03, 0x5D, 0xE3,
+ 0x83, 0xDD, 0xA3, 0x03, 0xB1, 0x91, 0xFE, 0xAE, 0x61, 0x69, 0x7D, 0xD1, 0xA1, 0xDE, 0xAE, 0x21, 0x4E, 0x46, 0x7B, 0xC6,
+ 0x26, 0x7A, 0x27, 0x4E, 0x3D, 0x76, 0xFA, 0xE3, 0x8F, 0x3F, 0x7E, 0xFD, 0xB5, 0x8B, 0x7B, 0x77, 0xEE, 0x9B, 0x1C, 0xD9,
+ 0x92, 0x8C, 0x0D, 0xF5, 0xB4, 0xF5, 0xC7, 0x5B, 0x7A, 0x63, 0xA1, 0x44, 0x77, 0x28, 0xC1, 0x49, 0x5F, 0x67, 0x6F, 0xC4,
+ 0x17, 0xE9, 0x0A, 0x74, 0xF5, 0xB4, 0xF6, 0x44, 0x03, 0x89, 0x88, 0x3F, 0xD6, 0xE1, 0xEB, 0xC4, 0xB8, 0xD8, 0xDE, 0xDC,
+ 0xD1, 0xD1, 0xD4, 0xD1, 0xD6, 0xD4, 0xDE, 0xEA, 0x6D, 0xC3, 0x14, 0xDC, 0x4B, 0x10, 0xB8, 0xC7, 0x2B, 0xEE, 0x39, 0x0E,
+ 0x76, 0x8F, 0x0F, 0xC4, 0xC6, 0x40, 0xC0, 0x51, 0x20, 0x88, 0x8E, 0xF5, 0xC5, 0x86, 0xB1, 0x44, 0x6C, 0xA8, 0x37, 0x92,
+ 0xEC, 0xE9, 0x1C, 0xEC, 0xEB, 0x18, 0xEC, 0x6D, 0x1F, 0xE0, 0x38, 0x10, 0xED, 0x4F, 0xC6, 0x06, 0x7F, 0xF5, 0xCB, 0x77,
+ 0x66, 0x67, 0x2F, 0xB3, 0xCB, 0xBF, 0x7B, 0xEE, 0x85, 0xF1, 0xBE, 0xB1, 0x91, 0xEE, 0x91, 0x78, 0xB8, 0x27, 0x16, 0x8C,
+ 0x47, 0x03, 0xDD, 0x9D, 0xC1, 0xEE, 0x78, 0x38, 0x1E, 0x68, 0xF4, 0xFD, 0xF8, 0x47, 0xCF, 0x3D, 0x74, 0xFF, 0x43, 0xCD,
+ 0x75, 0xDE, 0x58, 0x30, 0x06, 0x88, 0xCE, 0xE6, 0xCE, 0x8E, 0xA6, 0x36, 0x15, 0x4A, 0x2B, 0x38, 0x5A, 0x3C, 0xAD, 0x61,
+ 0x67, 0xB8, 0xC5, 0xD5, 0xA2, 0x0C, 0x26, 0x04, 0x0E, 0xE9, 0x7B, 0x20, 0x2E, 0x69, 0x18, 0xC5, 0xB7, 0xA4, 0x41, 0x30,
+ 0x11, 0x49, 0xF6, 0x46, 0x86, 0x53, 0x20, 0xC0, 0xD1, 0xDB, 0xD6, 0x9F, 0x68, 0xED, 0x63, 0xDF, 0xDD, 0xE1, 0x9E, 0x88,
+ 0xAF, 0xA3, 0xBF, 0x2B, 0x79, 0x6C, 0xE6, 0x04, 0x31, 0x02, 0x10, 0xC8, 0x46, 0xE3, 0xC3, 0xFD, 0x1D, 0xBD, 0x5D, 0x81,
+ 0xEE, 0xA8, 0xBF, 0x33, 0xEA, 0x8F, 0xE2, 0x9B, 0xDD, 0xBB, 0x2A, 0x1D, 0x67, 0x7F, 0x78, 0x6E, 0xCF, 0xD4, 0x1D, 0x8E,
+ 0xF2, 0x46, 0x10, 0x08, 0xF7, 0xDE, 0xB6, 0x90, 0x47, 0x9C, 0x60, 0x9C, 0x04, 0x3C, 0x2D, 0x41, 0x77, 0x4B, 0xC0, 0x1D,
+ 0x54, 0x54, 0xF7, 0x02, 0x41, 0x5F, 0x2C, 0x29, 0xDD, 0xAB, 0xC7, 0xE1, 0x44, 0xC7, 0x80, 0x04, 0x21, 0x8E, 0x80, 0x50,
+ 0x71, 0x10, 0x88, 0x44, 0x4B, 0xAF, 0x84, 0xD2, 0x05, 0x01, 0xC1, 0x48, 0x53, 0xAD, 0x07, 0x40, 0x5B, 0x37, 0x6E, 0x3B,
+ 0x7F, 0xF6, 0x3C, 0x80, 0xFE, 0xF9, 0x1F, 0x5F, 0x4B, 0xB4, 0xC5, 0xC1, 0xD1, 0xE1, 0x6B, 0x57, 0xAD, 0x13, 0xC7, 0x4D,
+ 0xF6, 0x66, 0x67, 0x95, 0xA3, 0x58, 0x6B, 0xAD, 0xB3, 0xD5, 0x72, 0xE2, 0x77, 0x05, 0x70, 0x8C, 0xFB, 0xA0, 0x27, 0xC4,
+ 0xD1, 0xEF, 0x09, 0xF2, 0x35, 0xE0, 0x0A, 0x07, 0xDC, 0x01, 0x6E, 0x29, 0xF8, 0x56, 0xA3, 0x30, 0x24, 0xDD, 0xCB, 0x58,
+ 0xCC, 0x59, 0x5B, 0xBF, 0x00, 0xD1, 0xDA, 0x07, 0x1F, 0x82, 0x92, 0x70, 0x0F, 0x68, 0x80, 0x12, 0x0B, 0x77, 0xC7, 0x02,
+ 0x3D, 0x9D, 0xFE, 0x48, 0x4B, 0x73, 0xAB, 0xBB, 0xDE, 0xD3, 0x50, 0x56, 0x7F, 0xE7, 0xEE, 0xEF, 0x8E, 0xF5, 0x6F, 0x38,
+ 0x77, 0xF6, 0xFC, 0xF7, 0x0E, 0x3F, 0x14, 0xB4, 0xFB, 0x83, 0x8D, 0xBE, 0x60, 0x53, 0x58, 0xEE, 0x1E, 0x67, 0x1E, 0xBB,
+ 0xB7, 0xDA, 0x56, 0x1D, 0xF6, 0xB5, 0x36, 0xD6, 0xD8, 0xEB, 0xCA, 0xEB, 0x9A, 0x1C, 0x81, 0x66, 0x97, 0x5F, 0x60, 0xF2,
+ 0x84, 0x38, 0x02, 0x42, 0x9A, 0xCF, 0xE9, 0xC7, 0x94, 0x94, 0x7B, 0x1C, 0x43, 0x80, 0x34, 0x89, 0x00, 0xF7, 0x12, 0x87,
+ 0xA4, 0x24, 0x1A, 0x4E, 0x90, 0xA4, 0x18, 0x99, 0x41, 0x56, 0x46, 0x9A, 0x3A, 0x59, 0x8E, 0x25, 0x0A, 0xB3, 0xF3, 0x87,
+ 0x06, 0x36, 0x6E, 0x1A, 0xBD, 0x7D, 0xB0, 0x2B, 0x99, 0x68, 0x49, 0xD4, 0x57, 0x34, 0x34, 0x56, 0x35, 0xCE, 0xD1, 0xE0,
+ 0x09, 0x71, 0xE2, 0x75, 0x34, 0x01, 0x08, 0xAB, 0xB0, 0x56, 0x38, 0xEB, 0xDD, 0x5E, 0x47, 0x33, 0x6F, 0xCD, 0x07, 0x21,
+ 0xA1, 0x34, 0x3B, 0x7C, 0x98, 0x92, 0x68, 0x1D, 0x50, 0x4D, 0xE5, 0x40, 0x0D, 0x87, 0x04, 0x01, 0x02, 0x41, 0x46, 0x28,
+ 0x41, 0x68, 0x24, 0x08, 0x4E, 0x44, 0x98, 0xFC, 0x31, 0x91, 0xAA, 0xFE, 0x08, 0x99, 0x11, 0x72, 0x05, 0x59, 0xC2, 0x6A,
+ 0x30, 0x97, 0x17, 0x57, 0xEC, 0xD8, 0x76, 0xB0, 0xB6, 0xA4, 0xAE, 0xCC, 0x5C, 0xD6, 0x50, 0xD9, 0x50, 0x53, 0x5A, 0xE3,
+ 0x6D, 0x6C, 0xC2, 0x87, 0x8C, 0x02, 0x21, 0xF3, 0xD4, 0xBA, 0x6B, 0xCB, 0xEA, 0xEC, 0x55, 0x2E, 0x18, 0x05, 0x1F, 0x6F,
+ 0xA5, 0x10, 0x48, 0x1C, 0x3C, 0x23, 0x4D, 0x89, 0xB7, 0xF4, 0x4B, 0xDF, 0x29, 0x04, 0x12, 0xC4, 0x7C, 0x03, 0xC1, 0x55,
+ 0x4B, 0x00, 0x48, 0xD0, 0xE3, 0x13, 0x80, 0x60, 0xC8, 0xDB, 0xE8, 0x6D, 0xAC, 0xA8, 0xCD, 0x5A, 0x9F, 0x39, 0x3A, 0xB4,
+ 0xC5, 0x59, 0xEF, 0x32, 0x14, 0x68, 0xEA, 0x2A, 0x1B, 0xC0, 0xE7, 0x69, 0xF0, 0x48, 0xAF, 0x00, 0x6A, 0x76, 0xF9, 0x78,
+ 0xCC, 0xD3, 0xE0, 0x15, 0x68, 0x1A, 0x05, 0x9A, 0xF9, 0x26, 0x71, 0x70, 0x5D, 0x9A, 0xF2, 0x17, 0xBE, 0x65, 0xAD, 0x0A,
+ 0x83, 0x09, 0xE1, 0xB8, 0xAB, 0xD3, 0xD7, 0x85, 0x7B, 0x28, 0xE1, 0x84, 0x2B, 0xE8, 0x0A, 0xCF, 0x48, 0xFD, 0x08, 0xBB,
+ 0x5B, 0xF0, 0xE4, 0xAC, 0x75, 0xE5, 0x65, 0xE4, 0x34, 0x7B, 0xC2, 0x6D, 0x81, 0x48, 0x7E, 0x66, 0x6E, 0x55, 0x69, 0x75,
+ 0xB9, 0xA5, 0x9C, 0x8B, 0xB8, 0x91, 0x98, 0x30, 0xD5, 0x6B, 0x93, 0x6A, 0x73, 0x4C, 0xCC, 0x07, 0x21, 0xA1, 0x48, 0xC4,
+ 0x0A, 0xF5, 0x89, 0x54, 0xA8, 0x69, 0x11, 0x17, 0x5B, 0x57, 0x8F, 0x94, 0x09, 0x06, 0x82, 0x36, 0x21, 0x5F, 0xED, 0x68,
+ 0x86, 0x94, 0x2F, 0x4E, 0xC2, 0xCE, 0x56, 0x6E, 0xF5, 0x53, 0xEC, 0xBE, 0x68, 0xC8, 0x1B, 0x66, 0xF7, 0xA4, 0x85, 0x45,
+ 0x5F, 0x64, 0x35, 0x16, 0x47, 0x5B, 0xE3, 0xB9, 0xE9, 0x99, 0xD0, 0x53, 0x66, 0x2D, 0x77, 0xD4, 0x38, 0xBD, 0x76, 0xB7,
+ 0x60, 0xC2, 0x35, 0x97, 0x1C, 0x02, 0x81, 0xE3, 0xAF, 0xA0, 0x91, 0x38, 0xA4, 0xB9, 0xEA, 0xDC, 0xCA, 0xB7, 0x1C, 0xA8,
+ 0x64, 0x48, 0x93, 0x32, 0x2A, 0x4D, 0x6A, 0x28, 0xD5, 0xEB, 0xB7, 0xFB, 0x20, 0xE6, 0xFC, 0x53, 0xCF, 0x4C, 0x8D, 0x6F,
+ 0x6B, 0xF3, 0xB4, 0x20, 0x89, 0x5D, 0x81, 0x08, 0x11, 0x71, 0x35, 0xB8, 0xAB, 0x4A, 0xAA, 0x35, 0xB9, 0x85, 0xED, 0x2D,
+ 0x51, 0x6D, 0x6E, 0x61, 0xA9, 0xA5, 0xAC, 0xA2, 0xB8, 0x0C, 0x40, 0x44, 0x4D, 0x50, 0xE2, 0x14, 0x01, 0xF2, 0x39, 0x45,
+ 0x96, 0xA4, 0xE2, 0xE2, 0xB1, 0x0B, 0x3E, 0x52, 0x50, 0xC0, 0x01, 0xA3, 0x18, 0x6F, 0x01, 0x28, 0xC2, 0xBE, 0x29, 0x19,
+ 0x7C, 0x0B, 0xF5, 0x54, 0x8F, 0xF0, 0x21, 0x05, 0xAD, 0xD5, 0xD3, 0x41, 0xE9, 0xAA, 0xF5, 0x19, 0xE0, 0x85, 0x86, 0xCA,
+ 0xC6, 0x03, 0xBB, 0x0F, 0xBC, 0xF3, 0xF6, 0xBB, 0x33, 0xF7, 0xCE, 0xB4, 0x37, 0xB7, 0x25, 0x5A, 0x84, 0x0A, 0x07, 0x9D,
+ 0x7E, 0x47, 0xA5, 0x5D, 0x9B, 0xA7, 0xC1, 0x77, 0x9D, 0xAD, 0xA6, 0xBE, 0xA2, 0xBE, 0xA2, 0xA4, 0xD2, 0x5D, 0xA3, 0xE6,
+ 0x6F, 0xE3, 0x9F, 0xC5, 0xC8, 0xD7, 0x08, 0x49, 0xDF, 0x46, 0x07, 0x1C, 0x29, 0x28, 0x12, 0x8D, 0x00, 0xD4, 0xD2, 0xD4,
+ 0x8E, 0xE3, 0x79, 0x26, 0x84, 0x9C, 0xAF, 0x5C, 0x0F, 0x7B, 0x3B, 0x38, 0x07, 0x0D, 0xDA, 0x05, 0x3D, 0xEE, 0xBA, 0xA6,
+ 0x32, 0x63, 0x69, 0xA9, 0xC1, 0x36, 0x31, 0xB8, 0xE9, 0xAD, 0x8B, 0x6F, 0xBE, 0xF9, 0xE6, 0x1B, 0xD3, 0xBB, 0x0E, 0xC4,
+ 0xC3, 0x31, 0x60, 0xD1, 0x04, 0x50, 0x23, 0xA0, 0xEF, 0xDF, 0x75, 0x60, 0xFF, 0xCE, 0x69, 0x7B, 0x99, 0x9D, 0xDC, 0x12,
+ 0x85, 0x26, 0x4C, 0x84, 0x49, 0x66, 0x31, 0xE7, 0x92, 0x18, 0x69, 0xF3, 0x89, 0x91, 0x68, 0xEC, 0xD5, 0x0E, 0x85, 0x55,
+ 0x64, 0x2B, 0x91, 0x12, 0x2E, 0x8E, 0xDE, 0x30, 0x27, 0x32, 0x4C, 0xE1, 0xA6, 0x16, 0x7F, 0x53, 0x18, 0x40, 0x42, 0x6D,
+ 0x55, 0x86, 0xCC, 0x85, 0x86, 0xC2, 0xAC, 0xC2, 0x48, 0x28, 0xF6, 0xDC, 0xF9, 0xE7, 0x2F, 0x5F, 0xBE, 0xFC, 0xDA, 0x6B,
+ 0xAF, 0x6F, 0x9F, 0x98, 0x1A, 0x49, 0x0C, 0x0F, 0xC7, 0x93, 0xDB, 0x36, 0x4C, 0x7D, 0xF0, 0xC1, 0x7F, 0xFE, 0xE2, 0xCD,
+ 0xB7, 0x81, 0xD8, 0xE6, 0x0D, 0x8B, 0x30, 0x39, 0xBD, 0xEC, 0x24, 0xE8, 0x0C, 0xB4, 0xBA, 0x85, 0x10, 0xAB, 0x57, 0xA8,
+ 0x38, 0xE2, 0x25, 0xD2, 0x25, 0xC5, 0x4A, 0x63, 0x95, 0x1D, 0x28, 0x18, 0x27, 0x4A, 0xD8, 0x1D, 0x82, 0x03, 0x10, 0xC8,
+ 0x56, 0x22, 0xE4, 0xBC, 0x29, 0x0C, 0x8E, 0x4E, 0x7F, 0x47, 0x2C, 0xDC, 0x45, 0x7F, 0xA6, 0xF5, 0x70, 0x9D, 0xE4, 0x65,
+ 0x09, 0x00, 0x21, 0xB5, 0x60, 0xCA, 0x5C, 0x9F, 0xC6, 0x2B, 0x27, 0x66, 0x1E, 0xFE, 0xEA, 0xAB, 0x2F, 0x3F, 0xFF, 0xFC,
+ 0xF3, 0xA7, 0x4E, 0x3D, 0x75, 0xF2, 0x91, 0xC7, 0xFF, 0xE3, 0xBD, 0xDF, 0xD0, 0x3D, 0x2E, 0x5D, 0xBA, 0x74, 0xE4, 0xD0,
+ 0x91, 0xDE, 0xB6, 0x44, 0xBB, 0xA7, 0x25, 0xE0, 0xF0, 0x87, 0x9D, 0xC1, 0xCE, 0xE6, 0xF6, 0x56, 0x57, 0x88, 0x10, 0xB3,
+ 0xB2, 0xCF, 0x4D, 0xC5, 0x11, 0x35, 0x91, 0xC8, 0x12, 0x90, 0xC4, 0x81, 0xB1, 0x38, 0xA6, 0xA4, 0xC4, 0x5B, 0x6A, 0x06,
+ 0xFB, 0x08, 0x78, 0x83, 0xF4, 0x04, 0xF6, 0xC4, 0x5A, 0xDD, 0xA1, 0xAE, 0xBE, 0xF6, 0x1E, 0x56, 0x64, 0x69, 0x77, 0xA3,
+ 0x97, 0xF7, 0xD1, 0x37, 0x34, 0xB7, 0x48, 0xAB, 0x5F, 0x75, 0xCB, 0xAD, 0x91, 0xD6, 0xAE, 0xC3, 0x77, 0xDF, 0xF7, 0xC9,
+ 0x27, 0x9F, 0xA8, 0xE3, 0x0D, 0x9F, 0x6F, 0xBE, 0xFE, 0xFA, 0x6B, 0xCE, 0xDF, 0xFD, 0xD5, 0xAF, 0xB7, 0x0C, 0x6F, 0x1E,
+ 0x89, 0x25, 0x7B, 0x5A, 0xBA, 0x07, 0x3A, 0xFB, 0x06, 0x23, 0xFD, 0x87, 0xEF, 0x3A, 0xBC, 0x71, 0x70, 0xA2, 0xA7, 0x35,
+ 0xCE, 0xF6, 0x20, 0x2C, 0xE8, 0x22, 0x76, 0x1E, 0x7B, 0xED, 0x1C, 0x2B, 0x12, 0x0A, 0x86, 0xCA, 0x2B, 0x52, 0x27, 0xE6,
+ 0x8B, 0x37, 0xB0, 0xDC, 0x55, 0xCE, 0x1D, 0x1B, 0x6F, 0x7F, 0xE9, 0xF9, 0x17, 0x0F, 0xEE, 0x99, 0xA6, 0x94, 0x08, 0x01,
+ 0x98, 0x44, 0x4A, 0xD6, 0xB8, 0xD9, 0x0A, 0x42, 0x5C, 0x55, 0x52, 0x65, 0x28, 0xD0, 0xDD, 0x76, 0xEB, 0x8A, 0x8D, 0x23,
+ 0x93, 0x7B, 0x6F, 0xDF, 0xFB, 0xC6, 0xC5, 0xB7, 0x7E, 0xF7, 0xBB, 0x4F, 0xDE, 0xFF, 0xCD, 0x87, 0xFF, 0xFE, 0xDE, 0x07,
+ 0xBF, 0xFF, 0xFD, 0xA7, 0x8C, 0x22, 0xAF, 0xBC, 0xFC, 0xEA, 0xD6, 0x89, 0x6D, 0xDB, 0x27, 0xB6, 0x4D, 0x8E, 0x4F, 0x7E,
+ 0x7F, 0xE6, 0x61, 0x50, 0x3E, 0xFB, 0xF4, 0xDF, 0x4E, 0xF4, 0x33, 0x3C, 0x8D, 0xC5, 0x82, 0x51, 0x9A, 0xBF, 0xB3, 0xC2,
+ 0xCE, 0xF6, 0x40, 0x20, 0x71, 0xD4, 0x95, 0xD7, 0x53, 0x0D, 0x1C, 0x95, 0x94, 0x68, 0x5E, 0xD5, 0x89, 0x26, 0x7B, 0xB5,
+ 0xDD, 0x53, 0xDF, 0x3C, 0x39, 0xBE, 0xF5, 0xDD, 0x77, 0xDF, 0x63, 0xA1, 0x7F, 0xB9, 0xF0, 0x3A, 0x29, 0xE2, 0xAB, 0xF3,
+ 0x86, 0x9C, 0x7E, 0x77, 0xBD, 0xDB, 0x5E, 0xE3, 0x6E, 0xA8, 0x70, 0x50, 0x4D, 0x50, 0x95, 0xB1, 0x66, 0x9D, 0xC7, 0xE9,
+ 0xDB, 0x3C, 0x32, 0x15, 0x6F, 0xED, 0x26, 0x97, 0xEF, 0xBF, 0x77, 0xE6, 0xF1, 0x47, 0x4F, 0xBF, 0xFA, 0xCA, 0x85, 0x2F,
+ 0xBF, 0xFC, 0x52, 0x8E, 0x22, 0x0C, 0x6E, 0x3F, 0x7E, 0xF6, 0xB9, 0x2F, 0xBE, 0xF8, 0x82, 0xAF, 0xFF, 0xFB, 0x87, 0xAF,
+ 0x9E, 0x7E, 0xE2, 0x47, 0xFB, 0x76, 0xEE, 0xDF, 0x3A, 0xB1, 0xF5, 0xFB, 0x0F, 0x3E, 0x7C, 0xF4, 0xF0, 0x31, 0x51, 0x8F,
+ 0xD6, 0x8A, 0xBA, 0xCA, 0x7A, 0x96, 0x22, 0x13, 0xB0, 0xDA, 0xB2, 0x5A, 0x45, 0xEC, 0x5B, 0x55, 0x49, 0x21, 0x12, 0x75,
+ 0x22, 0xD7, 0xAA, 0x2B, 0xEB, 0x4C, 0x46, 0x7D, 0x77, 0x47, 0xEF, 0x68, 0xDF, 0xC4, 0xF7, 0x8E, 0x1C, 0xFB, 0xB7, 0xB7,
+ 0x7E, 0xF9, 0xFE, 0xFB, 0xEF, 0x43, 0x03, 0xC3, 0x83, 0xC8, 0xC4, 0x7A, 0xEA, 0xD9, 0x0D, 0x85, 0xEC, 0xD2, 0x92, 0x5F,
+ 0xE4, 0xAD, 0xF5, 0x35, 0x37, 0xF8, 0x98, 0x72, 0xBA, 0x42, 0xB1, 0x81, 0xE8, 0xE0, 0xA6, 0xE1, 0xC9, 0xC3, 0x87, 0x1E,
+ 0xF8, 0xC9, 0xF3, 0xFF, 0xA0, 0x82, 0x60, 0x64, 0x53, 0xC7, 0xD8, 0xAB, 0x1F, 0x82, 0xFA, 0xD9, 0x67, 0x9F, 0x71, 0x7C,
+ 0xE3, 0xE2, 0xBF, 0x92, 0xA3, 0x26, 0x8D, 0x81, 0xE8, 0xB3, 0x37, 0x28, 0x07, 0x8A, 0x38, 0x96, 0x57, 0x2B, 0x12, 0x8D,
+ 0xD4, 0x28, 0xA1, 0x4E, 0x55, 0x0E, 0x78, 0x43, 0xDF, 0x6E, 0xBE, 0x69, 0xB9, 0x26, 0x2F, 0xBF, 0xA6, 0xBC, 0xCE, 0xE7,
+ 0x0A, 0x4D, 0x8E, 0x4D, 0xDD, 0x7D, 0xF0, 0x1E, 0x31, 0x3C, 0xD8, 0x6A, 0xA1, 0xD7, 0xDF, 0xD0, 0xCC, 0x08, 0x36, 0x92,
+ 0x18, 0xDA, 0x33, 0xB5, 0x67, 0xFA, 0x8E, 0x69, 0xC8, 0x2F, 0xB3, 0x42, 0x9A, 0xCB, 0x6B, 0x0F, 0xB6, 0xF9, 0x98, 0x29,
+ 0x27, 0xB6, 0x6F, 0xDC, 0xF9, 0xD0, 0xCC, 0x89, 0xD7, 0x7E, 0x76, 0xF1, 0xB7, 0x1F, 0xFE, 0xF7, 0x47, 0x1F, 0xFD, 0xCF,
+ 0x87, 0x1F, 0xFE, 0xF6, 0xA3, 0xFF, 0xFA, 0xF8, 0xD3, 0x4F, 0x3F, 0xBF, 0x74, 0xE9, 0x0F, 0x60, 0x7B, 0xF5, 0xEF, 0x5F,
+ 0x41, 0x54, 0x4D, 0xF9, 0x3A, 0x5B, 0x51, 0x71, 0x65, 0x71, 0x25, 0xD1, 0x07, 0x16, 0x68, 0x30, 0x4E, 0x14, 0x21, 0x5F,
+ 0x2A, 0x31, 0xB2, 0x0E, 0x49, 0x11, 0x18, 0x82, 0x49, 0x7D, 0x7E, 0x21, 0x69, 0x7B, 0xE3, 0xB2, 0x1B, 0x56, 0xDC, 0x7C,
+ 0x53, 0xDA, 0xBA, 0x74, 0xB3, 0xB1, 0x04, 0xB9, 0x2B, 0x31, 0x59, 0x2B, 0x8B, 0xAB, 0x18, 0xFC, 0xC8, 0x98, 0xAB, 0x23,
+ 0xE2, 0xAF, 0x19, 0x93, 0x59, 0xB4, 0xBE, 0xAA, 0x91, 0xAC, 0xEF, 0xEA, 0x48, 0x32, 0xEE, 0x0D, 0xC4, 0xC7, 0x37, 0x0D,
+ 0x6F, 0xDB, 0xBE, 0x79, 0xD7, 0xBE, 0x5D, 0xD3, 0x0F, 0xDC, 0x7B, 0xEC, 0xFE, 0x7B, 0x8E, 0x1E, 0x7D, 0xE0, 0xF8, 0x63,
+ 0xC7, 0x4F, 0x9E, 0x3D, 0xF3, 0xF4, 0x83, 0x0F, 0x1C, 0x1F, 0xEA, 0x4E, 0x46, 0xDB, 0x62, 0x05, 0x59, 0x79, 0x78, 0xA1,
+ 0xEB, 0x49, 0x40, 0xD5, 0xA5, 0x95, 0x72, 0x44, 0x51, 0xE6, 0xCB, 0x25, 0x59, 0x06, 0x20, 0x18, 0xE2, 0xA1, 0x32, 0x73,
+ 0xB9, 0xCD, 0x64, 0x2B, 0x36, 0x14, 0x43, 0x2C, 0x2F, 0xE7, 0x64, 0x64, 0x92, 0xC5, 0x00, 0xA2, 0x67, 0xF5, 0x44, 0x93,
+ 0xBB, 0xA7, 0xEE, 0x3C, 0x76, 0xFF, 0x83, 0x3F, 0x38, 0xFE, 0xE8, 0xD6, 0xE1, 0xAD, 0x84, 0x8C, 0xC4, 0x6C, 0xAC, 0x71,
+ 0xD0, 0xD4, 0x90, 0x99, 0xA0, 0xB7, 0x3D, 0xDC, 0x1C, 0x8D, 0xB6, 0xF6, 0xF5, 0x77, 0x8F, 0x0D, 0xF7, 0x6D, 0x60, 0x5A,
+ 0x1F, 0xE9, 0xDF, 0x48, 0x9E, 0x8D, 0x0D, 0x6E, 0x1E, 0x4F, 0x6E, 0xE9, 0x8D, 0x0C, 0x78, 0xAA, 0x5D, 0x3C, 0x66, 0xD0,
+ 0xE9, 0x6B, 0xAC, 0x95, 0x60, 0x62, 0x87, 0xF4, 0x63, 0x9A, 0x4F, 0xA5, 0xAD, 0x0A, 0xBF, 0x4A, 0x4A, 0x9D, 0x52, 0xD2,
+ 0x94, 0xAA, 0x23, 0xE0, 0x97, 0x16, 0x95, 0x42, 0x2C, 0x53, 0x4E, 0xA9, 0xA5, 0x9C, 0xAF, 0x58, 0x7E, 0x76, 0xCE, 0xBA,
+ 0x35, 0x6B, 0xE3, 0x9D, 0x03, 0xBB, 0x77, 0xDE, 0xC5, 0xC4, 0x12, 0x76, 0xB5, 0x09, 0x21, 0xA9, 0x71, 0xD4, 0x94, 0xD7,
+ 0x36, 0x54, 0xDB, 0xC1, 0x04, 0x4F, 0x58, 0xB3, 0x3D, 0xD0, 0xCA, 0x40, 0x1D, 0xEE, 0x69, 0x0B, 0x77, 0x73, 0x12, 0xF2,
+ 0x47, 0x82, 0x8E, 0xB6, 0x90, 0xB3, 0x35, 0xE4, 0x0A, 0x33, 0x1B, 0x39, 0x6A, 0x1C, 0x6C, 0xCF, 0x58, 0x60, 0xAC, 0xB2,
+ 0x55, 0xC0, 0x4A, 0x55, 0x69, 0x25, 0x68, 0x08, 0x5F, 0x85, 0xB5, 0x52, 0x49, 0x69, 0xB6, 0x04, 0x24, 0x8B, 0x90, 0xFC,
+ 0x27, 0xCB, 0xC4, 0xA3, 0x25, 0xE2, 0x39, 0x69, 0xEC, 0x06, 0x64, 0x90, 0x94, 0x95, 0x96, 0xCE, 0x6F, 0xA8, 0xF1, 0x91,
+ 0x2D, 0x07, 0xF6, 0x1D, 0xF1, 0x39, 0xC2, 0x0C, 0x40, 0xB4, 0x77, 0x10, 0xDB, 0xCC, 0x65, 0xD5, 0x65, 0xB5, 0x55, 0xA5,
+ 0x35, 0xE5, 0xA4, 0x6A, 0x65, 0x03, 0x41, 0xAC, 0xAD, 0xA8, 0x27, 0xB7, 0x40, 0x09, 0x62, 0x3A, 0x8F, 0xE8, 0xFC, 0xCE,
+ 0x20, 0x7B, 0xD8, 0xB9, 0x69, 0xD7, 0x03, 0x47, 0x8E, 0xF9, 0x5D, 0x7E, 0x8B, 0xC1, 0x4A, 0x10, 0xAC, 0x7A, 0x2B, 0xD1,
+ 0x60, 0xE7, 0xB8, 0x50, 0x52, 0xC4, 0xD0, 0x20, 0xA5, 0x5C, 0xD6, 0x97, 0xDB, 0xA5, 0x30, 0xCC, 0x65, 0xBE, 0x9A, 0xFF,
+ 0xA9, 0x19, 0x94, 0x37, 0x4B, 0x8C, 0x25, 0xA4, 0x57, 0xB1, 0xA5, 0x74, 0xCF, 0xAE, 0x43, 0x38, 0x80, 0x1B, 0x92, 0x1A,
+ 0x34, 0x56, 0x63, 0x09, 0x66, 0x31, 0x14, 0x9B, 0xF5, 0x16, 0xE1, 0xC9, 0x68, 0x29, 0x36, 0x95, 0x70, 0x4B, 0x88, 0x4D,
+ 0xB5, 0x88, 0xA9, 0xB7, 0x21, 0xD0, 0x19, 0xEE, 0xE9, 0x08, 0xC4, 0xFD, 0xCE, 0xD0, 0xD4, 0x86, 0x1D, 0xF7, 0x4C, 0x1F,
+ 0x21, 0x82, 0x2D, 0x9E, 0x70, 0x5F, 0xF7, 0x00, 0xBC, 0xB0, 0x2C, 0xBB, 0x55, 0xA4, 0x6C, 0x33, 0x05, 0x8B, 0x3C, 0x90,
+ 0x80, 0x04, 0x43, 0xC2, 0x54, 0x4C, 0x42, 0x1B, 0xE4, 0x11, 0x58, 0xF0, 0x24, 0x83, 0x98, 0xBD, 0x3E, 0xBD, 0xD9, 0x13,
+ 0x1C, 0xEC, 0xDD, 0x44, 0x98, 0xC4, 0x5A, 0x45, 0x36, 0x89, 0xC3, 0x90, 0x6F, 0xD0, 0xE5, 0xEA, 0xB4, 0x39, 0x5A, 0x4D,
+ 0xB6, 0x46, 0x93, 0xAB, 0xD5, 0xE5, 0xEB, 0x4D, 0x5A, 0x23, 0x77, 0xA1, 0xD0, 0x5E, 0xEB, 0x6C, 0x76, 0x86, 0x49, 0xF9,
+ 0xDD, 0x3B, 0x0F, 0x1D, 0xBE, 0xEF, 0x91, 0xCE, 0xF6, 0xDE, 0xF4, 0xF5, 0x59, 0x85, 0xF9, 0x05, 0x56, 0xB3, 0xAD, 0xAE,
+ 0xD6, 0xC1, 0x3A, 0x66, 0x93, 0x85, 0x4A, 0x52, 0x50, 0xB9, 0x94, 0x6C, 0x4B, 0xDD, 0x14, 0x6C, 0x7F, 0x8B, 0xE9, 0x5B,
+ 0xC9, 0x92, 0x02, 0x0D, 0xAB, 0x0C, 0xD1, 0x56, 0x83, 0x09, 0xFE, 0x2B, 0x6D, 0xD5, 0xF8, 0x70, 0x3B, 0xFC, 0xE5, 0xC5,
+ 0x95, 0x24, 0x3B, 0x68, 0x18, 0xF8, 0x99, 0x1E, 0x73, 0xD2, 0xB2, 0x72, 0xD2, 0x32, 0x18, 0xD6, 0x72, 0x33, 0xF2, 0xE8,
+ 0xC4, 0x45, 0x9A, 0xA2, 0xB2, 0x92, 0xAA, 0x86, 0x2A, 0x27, 0x99, 0xBE, 0x61, 0x7C, 0xC7, 0xC3, 0xC7, 0xCF, 0xEC, 0xDE,
+ 0x71, 0xF0, 0xDA, 0x6B, 0xAF, 0xBD, 0x65, 0xC5, 0xF2, 0xF4, 0xB5, 0xEB, 0xD2, 0xD6, 0xAC, 0x5D, 0xBF, 0x7A, 0x4D, 0xE6,
+ 0xBA, 0x8C, 0xFC, 0xAC, 0x3C, 0x0A, 0x48, 0x51, 0x99, 0xA8, 0xAB, 0xAB, 0xA8, 0x61, 0x7E, 0x80, 0x12, 0x19, 0x29, 0xA9,
+ 0x9B, 0x52, 0x3A, 0xE5, 0x51, 0x46, 0x0D, 0x86, 0x08, 0xB9, 0x51, 0x63, 0x22, 0x25, 0x71, 0x56, 0x63, 0x6B, 0xEC, 0x89,
+ 0x8D, 0xF9, 0x9B, 0xDA, 0x49, 0x17, 0x38, 0xD0, 0x17, 0x50, 0x8F, 0x39, 0x39, 0xE9, 0xD9, 0xD9, 0xEB, 0x33, 0xB3, 0xD6,
+ 0xA5, 0xC1, 0x22, 0xC8, 0xB8, 0x62, 0xD2, 0x16, 0x21, 0x19, 0xA8, 0x14, 0x75, 0xB7, 0x7D, 0xF2, 0xE0, 0x23, 0x27, 0x7E,
+ 0xE8, 0x71, 0x06, 0x56, 0xDC, 0x78, 0x13, 0x0D, 0x51, 0xA4, 0x76, 0xA1, 0xDE, 0x50, 0xA8, 0x07, 0x8A, 0x59, 0x67, 0x2A,
+ 0xD2, 0x1A, 0x15, 0xE9, 0xEF, 0xAA, 0x63, 0x71, 0xAE, 0xCA, 0x94, 0x40, 0x30, 0x67, 0x65, 0xE8, 0x84, 0x40, 0x03, 0x3D,
+ 0x24, 0x10, 0x0F, 0xD4, 0x57, 0x35, 0x50, 0x47, 0x1B, 0xC6, 0xA6, 0xF6, 0xEF, 0x3B, 0xB2, 0x63, 0xFB, 0x34, 0x51, 0xF0,
+ 0x39, 0x5A, 0xC9, 0xA4, 0x22, 0x9D, 0x59, 0x97, 0xAF, 0x45, 0x23, 0xF2, 0x33, 0xB3, 0x31, 0xA8, 0xE2, 0x1C, 0x8D, 0x25,
+ 0x6A, 0xAC, 0x80, 0x66, 0x26, 0xFB, 0x36, 0x4D, 0x6D, 0xDD, 0x77, 0xCF, 0xDD, 0x0F, 0x76, 0x47, 0xFB, 0x69, 0x3B, 0x16,
+ 0x9D, 0x85, 0xC1, 0x01, 0x10, 0x20, 0x63, 0x08, 0x06, 0x10, 0xA6, 0xCC, 0xC9, 0x76, 0xF9, 0x9C, 0x56, 0x0A, 0x40, 0x65,
+ 0xB8, 0x17, 0x68, 0xE6, 0x6A, 0x52, 0x15, 0x2E, 0x59, 0x68, 0xEC, 0x83, 0x42, 0x23, 0x9D, 0xF5, 0x5A, 0x93, 0xA3, 0xC1,
+ 0xF3, 0xC8, 0x89, 0x33, 0x67, 0xCF, 0x3E, 0x47, 0xAD, 0x25, 0xFB, 0x26, 0x49, 0x58, 0xD2, 0x8B, 0x75, 0x09, 0x90, 0x49,
+ 0xA3, 0x23, 0x1B, 0xF8, 0x05, 0x42, 0x10, 0xF9, 0x4A, 0x11, 0x51, 0x62, 0xC9, 0xBE, 0xCD, 0x77, 0xEC, 0xFE, 0xEE, 0xA1,
+ 0x83, 0x33, 0xB7, 0x4F, 0x1D, 0xE8, 0x8B, 0x8F, 0xC3, 0x0A, 0xEE, 0xB9, 0xA5, 0x26, 0x80, 0x59, 0x9C, 0xE8, 0xAD, 0x94,
+ 0x82, 0x22, 0x65, 0x9B, 0x63, 0x6D, 0x89, 0x50, 0x27, 0x59, 0xE7, 0xE8, 0x0D, 0x8E, 0x49, 0x17, 0xBE, 0x4A, 0x93, 0x17,
+ 0x29, 0x9C, 0x8C, 0x75, 0xEB, 0x6F, 0xBA, 0x71, 0xD9, 0x75, 0xD7, 0x2E, 0xA6, 0xF2, 0x35, 0xF9, 0x86, 0xB3, 0x4F, 0x3C,
+ 0x7F, 0xE2, 0xC4, 0xE9, 0x5D, 0x3B, 0xBE, 0xD3, 0x1B, 0x1D, 0x0D, 0x3A, 0x43, 0x24, 0x80, 0x14, 0x88, 0x8A, 0xA2, 0x72,
+ 0x55, 0xF4, 0x44, 0x67, 0xA0, 0x26, 0xC2, 0x4D, 0x5D, 0x07, 0xEF, 0x3C, 0x72, 0xF2, 0xB1, 0xA7, 0x9F, 0x7C, 0xF2, 0xF9,
+ 0x13, 0x0F, 0x9D, 0x82, 0x2A, 0x39, 0x2F, 0x14, 0x9B, 0x6C, 0x24, 0x9F, 0xA8, 0x47, 0xA3, 0xC5, 0x66, 0xB0, 0x94, 0x1A,
+ 0x05, 0xA0, 0xB9, 0x70, 0x08, 0x97, 0xD6, 0x52, 0x6E, 0x40, 0x03, 0xDB, 0x92, 0x05, 0x05, 0x08, 0xC4, 0x4A, 0x35, 0x55,
+ 0x84, 0x8C, 0x25, 0xC5, 0xBA, 0x22, 0xA2, 0xCE, 0x48, 0x8F, 0x76, 0x2F, 0xBF, 0xF1, 0xE6, 0xFB, 0x0E, 0x3F, 0x72, 0xFA,
+ 0xF4, 0x33, 0x33, 0xF7, 0xFF, 0x00, 0x4C, 0x23, 0xFD, 0x9B, 0x3B, 0x9A, 0xA3, 0x08, 0xF7, 0xD5, 0xCA, 0xB5, 0xBB, 0x6B,
+ 0x3C, 0x0C, 0x0E, 0x41, 0x77, 0x47, 0xBC, 0x33, 0x09, 0xEE, 0xC7, 0x1F, 0x7F, 0x1A, 0x85, 0x84, 0x5D, 0xAF, 0x27, 0x10,
+ 0x69, 0x4F, 0x58, 0x8D, 0x16, 0x96, 0xA2, 0x66, 0xD5, 0x06, 0x20, 0x30, 0x91, 0xA0, 0x8A, 0x24, 0x40, 0xB6, 0x15, 0x8B,
+ 0xDE, 0xC8, 0x0F, 0x6F, 0xE6, 0x26, 0x46, 0x02, 0x7C, 0x43, 0xA9, 0x0A, 0xA8, 0x42, 0x1A, 0x80, 0x78, 0x19, 0x7A, 0x81,
+ 0x4B, 0xE0, 0xF3, 0x32, 0xB2, 0x48, 0xD5, 0x93, 0x27, 0xCF, 0xBD, 0xFC, 0xCA, 0x5B, 0x2F, 0xBE, 0x78, 0xE1, 0xD1, 0x47,
+ 0x9F, 0xDC, 0xB5, 0xEB, 0xAE, 0xB1, 0xA1, 0x6D, 0xC0, 0x4A, 0x44, 0x86, 0x22, 0xA1, 0x78, 0xA7, 0xAF, 0xBB, 0xAB, 0xAD,
+ 0x7F, 0xA8, 0x77, 0xE3, 0x50, 0xFF, 0xE6, 0x1D, 0x3B, 0xA6, 0x9F, 0x38, 0xF7, 0x02, 0xBF, 0xDD, 0xF8, 0x7B, 0x6A, 0xD1,
+ 0x42, 0xF1, 0xBF, 0x18, 0xD1, 0xE9, 0x6E, 0xEB, 0x11, 0xA9, 0xA3, 0x35, 0x4B, 0x86, 0x30, 0xA2, 0x26, 0x00, 0x49, 0x34,
+ 0x34, 0xAF, 0xA2, 0x02, 0xBD, 0xD9, 0x54, 0x8C, 0x9A, 0x15, 0x64, 0xE7, 0x6B, 0x72, 0x0A, 0xC0, 0x5B, 0x66, 0xB1, 0x71,
+ 0x1D, 0x13, 0x0F, 0x88, 0xF3, 0x32, 0xF2, 0x9A, 0x6D, 0x91, 0xAA, 0xDA, 0xAC, 0xFC, 0xBE, 0xC4, 0xE8, 0xE8, 0xD0, 0xA6,
+ 0x1D, 0x53, 0xFB, 0x5E, 0x7C, 0xE1, 0x67, 0xAF, 0xBF, 0xF1, 0x0E, 0xE1, 0x80, 0xB0, 0x83, 0xFB, 0x8F, 0x1C, 0xFA, 0xCE,
+ 0xCC, 0xF4, 0x81, 0xFB, 0xEE, 0xBE, 0xFB, 0xE8, 0xD1, 0x99, 0xC7, 0x4E, 0x9D, 0x3A, 0xFF, 0xEC, 0xB3, 0x2F, 0x9F, 0x3B,
+ 0xF7, 0xC2, 0xC3, 0xC7, 0x4F, 0xE7, 0xE5, 0x14, 0xAE, 0x5A, 0xB1, 0x92, 0xBA, 0xCB, 0x5A, 0xB7, 0x8E, 0xB8, 0x1B, 0xF5,
+ 0x26, 0x40, 0x10, 0x38, 0xB2, 0x5B, 0xCD, 0x21, 0x21, 0xD9, 0x8A, 0x8A, 0x46, 0xEC, 0x9E, 0x00, 0x71, 0x9B, 0xA7, 0x73,
+ 0x33, 0x33, 0xC4, 0x43, 0xFA, 0x22, 0x98, 0xE4, 0x22, 0xB7, 0x30, 0xA2, 0x59, 0x66, 0xB1, 0x70, 0x51, 0xA7, 0xD1, 0x57,
+ 0xDA, 0x2A, 0x28, 0xB4, 0xBA, 0x9A, 0x46, 0x9D, 0xC6, 0x28, 0xFF, 0xF5, 0xD3, 0x16, 0x18, 0xCF, 0x9C, 0x7A, 0xE6, 0xED,
+ 0xB7, 0x3F, 0xB8, 0x78, 0xF1, 0xDD, 0x7F, 0xBA, 0xF0, 0xD6, 0xAB, 0xAF, 0xFE, 0xFC, 0x27, 0x2F, 0x31, 0xFE, 0xBF, 0xF3,
+ 0xEC, 0xF9, 0x97, 0xC0, 0x77, 0xD7, 0xF4, 0x7D, 0xC7, 0x1F, 0xFC, 0x9B, 0xA3, 0x33, 0x27, 0xAB, 0x2A, 0x6A, 0x33, 0x57,
+ 0xAD, 0xD5, 0xE5, 0x69, 0x0A, 0xB3, 0x73, 0x75, 0x79, 0x05, 0xD9, 0xE9, 0x19, 0x85, 0x39, 0x05, 0xF0, 0x6D, 0xD1, 0x59,
+ 0xC1, 0x84, 0x15, 0x6B, 0x2D, 0x0A, 0x9E, 0x48, 0xC0, 0x52, 0x53, 0x05, 0xBE, 0x41, 0x00, 0x2B, 0x25, 0xEA, 0x6D, 0xC0,
+ 0x95, 0x98, 0xCC, 0x12, 0x90, 0x3C, 0x12, 0x2C, 0xD0, 0xF3, 0x87, 0x41, 0xC0, 0x1B, 0x02, 0xCD, 0xFA, 0xB5, 0x69, 0x37,
+ 0x2C, 0x5D, 0xB6, 0x6E, 0xD5, 0xEA, 0xB5, 0x2B, 0x57, 0x81, 0xA9, 0xCC, 0x56, 0xB9, 0x7F, 0xEF, 0xA1, 0xBD, 0x7B, 0x0E,
+ 0x9D, 0x39, 0x73, 0xFE, 0xC2, 0x85, 0x5F, 0xFC, 0xF4, 0xA7, 0x3F, 0x9F, 0x9A, 0xBC, 0x63, 0xED, 0xEA, 0x34, 0x89, 0x78,
+ 0xE9, 0xD2, 0x1B, 0xBA, 0xA3, 0x83, 0xF1, 0xAE, 0x24, 0x35, 0x01, 0xC1, 0x18, 0xA2, 0x65, 0x2A, 0x34, 0x59, 0x34, 0x46,
+ 0x00, 0x89, 0x82, 0xD7, 0x5A, 0xA4, 0x29, 0x32, 0x58, 0x15, 0x45, 0xF4, 0x73, 0xD1, 0xDE, 0x00, 0x21, 0xC3, 0xC9, 0x09,
+ 0x5F, 0x4B, 0xCD, 0x25, 0xA0, 0x11, 0x47, 0x73, 0x09, 0xC9, 0xAE, 0xCF, 0xD7, 0xA2, 0xCE, 0x19, 0x69, 0x99, 0x8C, 0x6F,
+ 0x69, 0xAB, 0xD6, 0xA0, 0xCB, 0xE8, 0x0D, 0x8A, 0xBC, 0x62, 0xF9, 0xCD, 0xCB, 0x97, 0xDD, 0x20, 0x7D, 0x2F, 0x5E, 0x7C,
+ 0x3D, 0x71, 0xAF, 0x2C, 0xAF, 0x59, 0xB4, 0x68, 0x11, 0x7F, 0x89, 0xAE, 0x5C, 0x71, 0xCB, 0xAA, 0x95, 0xB7, 0x5E, 0x73,
+ 0x8D, 0xB2, 0x76, 0xF5, 0xBA, 0x64, 0xFF, 0x06, 0x7D, 0x01, 0x8A, 0xA0, 0x55, 0xB5, 0x47, 0xC8, 0x8F, 0x48, 0x47, 0x8D,
+ 0x99, 0x34, 0x82, 0x02, 0x64, 0x8C, 0x13, 0x45, 0x10, 0xA0, 0xFA, 0x2B, 0xB5, 0xAA, 0xEE, 0xCD, 0x56, 0x70, 0xCC, 0x41,
+ 0x31, 0x97, 0x90, 0x37, 0xEA, 0x15, 0x01, 0x91, 0x77, 0x48, 0x64, 0xDA, 0x2A, 0x4A, 0xAF, 0x72, 0xAE, 0x21, 0x93, 0x38,
+ 0xA2, 0xC8, 0x94, 0x24, 0xFE, 0x16, 0x2F, 0x5E, 0xB4, 0xEA, 0xB6, 0x95, 0xCB, 0x96, 0x2C, 0x95, 0xC8, 0xF8, 0x77, 0x36,
+ 0x7D, 0x4D, 0x5A, 0x56, 0xDA, 0x7A, 0x1E, 0xE0, 0x67, 0x13, 0x74, 0xD2, 0x89, 0xD9, 0xBF, 0x36, 0x37, 0x5F, 0xCA, 0xE0,
+ 0x55, 0x6E, 0x04, 0x0E, 0x91, 0xDA, 0x5A, 0x8B, 0xA5, 0xB0, 0x48, 0x49, 0x71, 0x30, 0x0F, 0x87, 0x15, 0x10, 0x5C, 0x97,
+ 0x65, 0x25, 0x4C, 0x9D, 0xD4, 0x84, 0xE8, 0xA9, 0x3B, 0x13, 0x62, 0x5F, 0xA0, 0x83, 0x30, 0x0C, 0x4C, 0xA4, 0xBF, 0xAB,
+ 0xDA, 0xB9, 0x7A, 0xE5, 0x2A, 0x1A, 0x53, 0x76, 0x5A, 0x16, 0xC7, 0xA5, 0x4B, 0x97, 0xC2, 0x13, 0xD1, 0xCC, 0x4D, 0x47,
+ 0xB2, 0x73, 0x31, 0xB8, 0x24, 0xB2, 0x06, 0x9D, 0x11, 0xCD, 0xA3, 0x1A, 0x8C, 0x1A, 0x1A, 0x90, 0xD8, 0xA1, 0x54, 0x67,
+ 0x0C, 0x28, 0x98, 0x50, 0x6A, 0xE1, 0x58, 0x0D, 0xD6, 0xFF, 0xB7, 0x12, 0x22, 0xA8, 0x5E, 0x17, 0xB9, 0xC5, 0xFB, 0x6A,
+ 0x89, 0xCE, 0xB1, 0x4D, 0x26, 0xEA, 0x8B, 0xF4, 0x79, 0xA2, 0x07, 0x91, 0x58, 0xB0, 0x9D, 0xBE, 0x7A, 0x6D, 0x61, 0xAE,
+ 0x68, 0x1A, 0xE8, 0x53, 0xE6, 0xDA, 0xF5, 0x74, 0x06, 0xE8, 0xA4, 0x75, 0x40, 0xA1, 0x21, 0x57, 0x70, 0x49, 0xB9, 0x00,
+ 0x97, 0x9E, 0x3F, 0x36, 0x30, 0x6E, 0x56, 0x19, 0x62, 0x4D, 0x21, 0xD6, 0x1A, 0x33, 0x50, 0xE4, 0xB2, 0x48, 0xBC, 0xF2,
+ 0x57, 0x70, 0x98, 0xAC, 0x20, 0x90, 0x38, 0xA4, 0x15, 0x1B, 0x8B, 0x64, 0x62, 0xC9, 0x5A, 0x10, 0xB0, 0x74, 0x66, 0x53,
+ 0x9E, 0x68, 0x87, 0x9D, 0xA1, 0x4E, 0x06, 0x1D, 0x1A, 0x2A, 0x1C, 0x68, 0x0B, 0x75, 0xB8, 0xC7, 0x90, 0x4D, 0x68, 0x03,
+ 0x04, 0x88, 0xE7, 0xDA, 0x67, 0x81, 0x8E, 0x36, 0x42, 0xE0, 0xD0, 0x94, 0x2D, 0xA3, 0xDB, 0x66, 0xEE, 0x39, 0x06, 0x6D,
+ 0x42, 0x78, 0xB4, 0xA2, 0xA1, 0xD2, 0xEC, 0x30, 0x15, 0x90, 0x41, 0x00, 0x4A, 0x39, 0x9E, 0x77, 0x42, 0x0E, 0xAB, 0x13,
+ 0xD6, 0x3C, 0x13, 0x7F, 0x02, 0x19, 0x08, 0xB6, 0x0A, 0x48, 0x53, 0x44, 0x6E, 0x32, 0x89, 0xF2, 0x1B, 0xC1, 0x66, 0x2E,
+ 0x81, 0x12, 0x19, 0x47, 0x59, 0x41, 0xF2, 0x3C, 0x15, 0x56, 0xF6, 0x6D, 0x2C, 0xD4, 0xF2, 0x3C, 0x84, 0xE5, 0x66, 0xE7,
+ 0x30, 0x43, 0xEE, 0xDD, 0xBE, 0x7F, 0xF3, 0xF8, 0x24, 0xDD, 0x97, 0x35, 0x65, 0xE8, 0xD5, 0xB7, 0xB4, 0x84, 0x52, 0xA1,
+ 0x9A, 0xE6, 0x70, 0xD0, 0x16, 0xE6, 0xB9, 0x4F, 0x69, 0xB9, 0xC5, 0x70, 0x15, 0x9C, 0xA1, 0x44, 0xA5, 0x47, 0x18, 0x12,
+ 0x0A, 0x38, 0x7C, 0xF0, 0x23, 0x89, 0x89, 0x16, 0x3E, 0x24, 0x9A, 0xD4, 0x46, 0xD9, 0xAE, 0x1C, 0x27, 0x52, 0x69, 0xC7,
+ 0xC3, 0x3C, 0xB0, 0xFA, 0xD6, 0xDB, 0x6A, 0xAA, 0xEA, 0xF9, 0xE7, 0x2A, 0xDA, 0xD2, 0x45, 0x03, 0xE5, 0x4F, 0x1C, 0x40,
+ 0x00, 0x85, 0xD7, 0x59, 0x93, 0xA3, 0x22, 0xA7, 0xAD, 0x39, 0x3E, 0x0C, 0xA2, 0xCF, 0xCD, 0xC5, 0x88, 0x51, 0x57, 0xF6,
+ 0xE1, 0xB9, 0x6E, 0x2C, 0x64, 0x54, 0x96, 0x03, 0xAF, 0xC9, 0x94, 0x0F, 0x37, 0xB7, 0xF3, 0x9B, 0x49, 0x64, 0xEB, 0x55,
+ 0x3E, 0xA4, 0x7B, 0x91, 0xA4, 0x1A, 0x71, 0x14, 0x6D, 0x51, 0x0D, 0x84, 0x10, 0x9E, 0x7C, 0x2D, 0xD1, 0x24, 0xC9, 0x96,
+ 0xDF, 0x78, 0x53, 0x7B, 0x30, 0xD6, 0x58, 0xE7, 0xA2, 0xE1, 0xCB, 0x28, 0xAB, 0xB2, 0x04, 0xA3, 0xFC, 0xBE, 0xD1, 0x29,
+ 0x73, 0x4D, 0xC4, 0x60, 0x16, 0xC3, 0xF6, 0x9F, 0x21, 0x50, 0xE7, 0x01, 0x3D, 0xC9, 0xAB, 0xFA, 0x10, 0x61, 0x12, 0x91,
+ 0xC2, 0x0D, 0xA3, 0x1D, 0xB4, 0x6F, 0x48, 0x4E, 0xC6, 0x3B, 0xFB, 0x56, 0xAE, 0xBC, 0x15, 0x1F, 0x0C, 0x1B, 0x2C, 0x9A,
+ 0x2A, 0x19, 0x89, 0x49, 0xB2, 0xF5, 0x17, 0x80, 0x74, 0xD9, 0x05, 0x6B, 0xF8, 0x4B, 0x60, 0xF9, 0xCD, 0xFC, 0xFF, 0xD7,
+ 0xD5, 0xD6, 0xEB, 0x73, 0x04, 0x0B, 0x33, 0x72, 0x99, 0xA2, 0x74, 0x05, 0x28, 0x48, 0x01, 0xA0, 0x95, 0xB9, 0x41, 0x64,
+ 0xAE, 0x9B, 0xCC, 0x49, 0xB8, 0x4C, 0xDE, 0x94, 0x89, 0x18, 0xA9, 0x68, 0x64, 0xBC, 0x11, 0x46, 0x4D, 0x81, 0xD6, 0xDD,
+ 0xE8, 0x41, 0x66, 0x56, 0xDF, 0xB2, 0x4A, 0x26, 0xB2, 0x88, 0x97, 0xC6, 0x20, 0x94, 0xF7, 0x2A, 0x0E, 0x09, 0x25, 0x65,
+ 0xEC, 0x5E, 0xD6, 0x5A, 0x6E, 0x66, 0x16, 0x9A, 0xB4, 0x78, 0xF1, 0x62, 0x66, 0x6D, 0x9B, 0xB9, 0x94, 0x11, 0x56, 0x74,
+ 0x46, 0x55, 0xD2, 0xA8, 0x47, 0x65, 0x9E, 0x57, 0x21, 0x97, 0xB2, 0x88, 0x30, 0xF2, 0x9F, 0x82, 0x44, 0xAC, 0x38, 0x49,
+ 0x65, 0x03, 0xF1, 0x66, 0x13, 0x50, 0xB2, 0x6C, 0xD9, 0x32, 0x54, 0xF8, 0xFA, 0xEB, 0xAF, 0x47, 0xA6, 0x19, 0xE6, 0x65,
+ 0x7E, 0x08, 0x62, 0x0A, 0x45, 0x74, 0xF8, 0x99, 0x2C, 0xC2, 0x34, 0x0F, 0x8D, 0x48, 0xEA, 0x02, 0x11, 0x1D, 0x4D, 0x4E,
+ 0x1E, 0x72, 0x40, 0x03, 0x59, 0xB2, 0x64, 0x89, 0x90, 0xF5, 0x45, 0xD7, 0x32, 0x4D, 0x23, 0xB3, 0x5C, 0x97, 0x0C, 0xFD,
+ 0x1F, 0x2E, 0xB6, 0xCD, 0xAB, 0xF2, 0x82, 0x27, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60,
+ 0x82
+};
+
diff --git a/lib/libUPnP/Platinum/Source/Core/PltMimeType.cpp b/lib/libUPnP/Platinum/Source/Core/PltMimeType.cpp
new file mode 100644
index 0000000..a466595
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltMimeType.cpp
@@ -0,0 +1,162 @@
+/*****************************************************************
+|
+| Platinum - AV Media MimeType
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMimeType.h"
+#include "PltHttp.h"
+//#include "NptLogging.h"
+
+//NPT_SET_LOCAL_LOGGER("platinum.media.server.mimetype")
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+const NPT_HttpFileRequestHandler_FileTypeMapEntry
+PLT_HttpFileRequestHandler_DefaultFileTypeMap[] = {
+ {"l16", "audio/L16;rate=44100;channels=2"},
+ {"l16m", "audio/L16;rate=44100;channels=1"},
+
+ {"wav", "audio/wav"},
+ {"wavm", "audio/wav"},
+ {"alac", "audio/x-alac"},
+ //{"wavm", "audio/x-wav"},
+};
+
+const NPT_HttpFileRequestHandler_FileTypeMapEntry
+PLT_HttpFileRequestHandler_360FileTypeMap[] = {
+ {"l16", "audio/L16"},
+ {"l16m", "audio/L16;rate=44100;channels=1"},
+ {"avi", "video/avi"},
+ {"divx", "video/avi"},
+ {"xvid", "video/avi"},
+ {"mov", "video/quicktime"}
+};
+
+const NPT_HttpFileRequestHandler_FileTypeMapEntry
+PLT_HttpFileRequestHandler_PS3FileTypeMap[] = {
+ {"avi", "video/x-msvideo"},
+ {"divx", "video/x-msvideo"},
+ {"xvid", "video/x-msvideo"},
+ {"mov", "video/mp4"}
+};
+
+const NPT_HttpFileRequestHandler_FileTypeMapEntry
+PLT_HttpFileRequestHandler_SonosFileTypeMap[] = {
+ {"wav", "audio/wav"},
+};
+
+/*----------------------------------------------------------------------
+ | PLT_MimeType::GetMimeType
+ +---------------------------------------------------------------------*/
+const char*
+PLT_MimeType::GetMimeType(const NPT_String& filename,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetMimeType(filename, context?PLT_HttpHelper::GetDeviceSignature(context->GetRequest()):PLT_DEVICE_UNKNOWN);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MimeType::GetMimeType
++---------------------------------------------------------------------*/
+const char*
+PLT_MimeType::GetMimeType(const NPT_String& filename,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ int last_dot = filename.ReverseFind('.');
+ if (last_dot >= 0) { // passing just the extension is ok (ex .mp3)
+ NPT_String extension = filename.GetChars()+last_dot+1;
+ return GetMimeTypeFromExtension(extension, signature);
+ }
+
+ return "application/octet-stream";
+}
+
+/*----------------------------------------------------------------------
+ | PLT_MimeType::GetMimeTypeFromExtension
+ +---------------------------------------------------------------------*/
+const char*
+PLT_MimeType::GetMimeTypeFromExtension(const NPT_String& extension,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetMimeTypeFromExtension(extension, context?PLT_HttpHelper::GetDeviceSignature(context->GetRequest()):PLT_DEVICE_UNKNOWN);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MimeType::GetMimeTypeFromExtension
++---------------------------------------------------------------------*/
+const char*
+PLT_MimeType::GetMimeTypeFromExtension(const NPT_String& extension,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ if (signature != PLT_DEVICE_UNKNOWN) {
+ // look for special case for 360
+ if (signature == PLT_DEVICE_XBOX_360 || signature == PLT_DEVICE_XBOX_ONE) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_360FileTypeMap); i++) {
+ if (extension.Compare(PLT_HttpFileRequestHandler_360FileTypeMap[i].extension, true) == 0) {
+ return PLT_HttpFileRequestHandler_360FileTypeMap[i].mime_type;
+ }
+ }
+
+ // fallback to default if not found
+ } else if (signature == PLT_DEVICE_PS3) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_PS3FileTypeMap); i++) {
+ if (extension.Compare(PLT_HttpFileRequestHandler_PS3FileTypeMap[i].extension, true) == 0) {
+ return PLT_HttpFileRequestHandler_PS3FileTypeMap[i].mime_type;
+ }
+ }
+
+ // fallback to default if not found
+ } else if (signature == PLT_DEVICE_SONOS) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_SonosFileTypeMap); i++) {
+ if (extension.Compare(PLT_HttpFileRequestHandler_SonosFileTypeMap[i].extension, true) == 0) {
+ return PLT_HttpFileRequestHandler_SonosFileTypeMap[i].mime_type;
+ }
+ }
+
+ // fallback to default if not found
+ }
+ }
+
+ // dlna custom ones
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_DefaultFileTypeMap); i++) {
+ if (extension.Compare(PLT_HttpFileRequestHandler_DefaultFileTypeMap[i].extension, true) == 0) {
+ return PLT_HttpFileRequestHandler_DefaultFileTypeMap[i].mime_type;
+ }
+ }
+
+ const char* type = NPT_HttpFileRequestHandler::GetDefaultContentType(extension);
+ return type?type:"application/octet-stream";
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltMimeType.h b/lib/libUPnP/Platinum/Source/Core/PltMimeType.h
new file mode 100644
index 0000000..0af0a89
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltMimeType.h
@@ -0,0 +1,75 @@
+/*****************************************************************
+|
+| Platinum - AV Media MimeType
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Media MimeType.
+ */
+
+#ifndef _PLT_MIMETYPE_H_
+#define _PLT_MIMETYPE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_HttpRequestContext;
+
+/*----------------------------------------------------------------------
+| PLT_MimeType
++---------------------------------------------------------------------*/
+class PLT_MimeType
+{
+public:
+ virtual ~PLT_MimeType() {}
+
+ static const char* GetMimeType(const NPT_String& filename,
+ const PLT_HttpRequestContext* context = NULL);
+ static const char* GetMimeType(const NPT_String& filename,
+ PLT_DeviceSignature signature = PLT_DEVICE_UNKNOWN);
+
+ static const char* GetMimeTypeFromExtension(const NPT_String& extension,
+ const PLT_HttpRequestContext* context = NULL);
+ static const char* GetMimeTypeFromExtension(const NPT_String& extension,
+ PLT_DeviceSignature signature = PLT_DEVICE_UNKNOWN);
+
+private:
+ PLT_MimeType() {}
+
+};
+
+#endif /* _PLT_MIMETYPE_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp b/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp
new file mode 100644
index 0000000..d22dc02
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp
@@ -0,0 +1,598 @@
+/*****************************************************************
+|
+| Platinum - AV Media Item
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltProtocolInfo.h"
+#include "PltMimeType.h"
+#include "PltHttp.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.protocolinfo")
+
+/*----------------------------------------------------------------------
+| defines
++---------------------------------------------------------------------*/
+#define PLT_FIELD_ALPHA "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+#define PLT_FIELD_NUM "0123456789"
+
+#define PLT_SP_FLAG_MASK 0x80000000
+#define PLT_LOP_NPT_MASK 0x40000000
+#define PLT_LOP_BYTES_MASK 0x20000000
+#define PLT_PLAYCONTAINER_PARAM_MASK 0x10000000
+#define PLT_S0_INCREASING_MASK 0x08000000
+#define PLT_SN_INCREASING_MASK 0x04000000
+#define PLT_RTSP_PAUSE_MASK 0x02000000
+#define PLT_TM_S_MASK 0x01000000
+#define PLT_TM_I_MASK 0x00800000
+#define PLT_TM_B_MASK 0x00400000
+#define PLT_HTTP_STALLING_MASK 0x00200000
+#define PLT_DLNA_V1_5_FLAG_MASK 0x00100000
+#define PLT_LP_FLAG_MASK 0x00010000
+#define PLT_CLEARTEXTBYTESEEK_FULL_MASK 0x00008000
+#define PLT_LOP_CLEARTEXTBYTES_MASK 0x00004000
+
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+static const char PLT_DLNAPNCharsToValidate[] = PLT_FIELD_ALPHA PLT_FIELD_NUM "_";
+static const char PLT_DLNAPSCharsToValidate[] = PLT_FIELD_NUM "-,/";
+static const char PLT_DLNAFlagCharsToValidate[] = "01";
+static const char PLT_DLNAHexCharsToValidate[] = PLT_FIELD_NUM "ABCDEFabcdef";
+static const char PLT_DLNAOTherNameCharsToValidate[] = PLT_FIELD_ALPHA PLT_FIELD_NUM;
+static const char PLT_DLNAOTherValueCharsToValidate[] = PLT_FIELD_ALPHA PLT_FIELD_NUM "_-+,";
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_DefaultDlnaMap[] = {
+ {"image/gif", "DLNA.ORG_PN=GIF_LRG"},
+ {"image/jpeg", "DLNA.ORG_PN=JPEG_LRG"},
+ {"image/jp2", "DLNA.ORG_PN=JPEG_LRG"},
+ {"image/png", "DLNA.ORG_PN=PNG_LRG"},
+ {"image/bmp", "DLNA.ORG_PN=BMP_LRG"},
+ {"image/tiff", "DLNA.ORG_PN=TIFF_LRG"},
+ {"audio/L16", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/L16;rate=44100;channels=2", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/L16;rate=44100;channels=1", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/L16;rate=32000;channels=1", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mpeg", "DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mp4", "DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/x-ms-wma", "DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/wav", "DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"}, // UVerse
+ {"audio/x-wav", "DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/avi", "DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/mp4", "DLNA.ORG_PN=MPEG4_P2_SP_AAC;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/mpeg", "DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/quicktime","DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-ms-wmv", "DLNA.ORG_PN=WMVHIGH_BASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-msvideo","DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-ms-asf", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-matroska","DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+ {"video/x-flv", "DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_360DlnaMap[] = {
+ {"video/quicktime","DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/mp4", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/wav", "DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mp4", "DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mpeg", "DLNA.ORG_PN=MP3;DLNA.ORG_OP=01"},
+ {"audio/x-ms-wma", "DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0"}
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_SonosDlnaMap[] = {
+ {"audio/wav", "*"}
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_PS3DlnaMap[] = {
+ {"image/jpg", "DLNA.ORG_OP=01"},
+ {"image/png", "DLNA.ORG_OP=01"}
+};
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo::PLT_ProtocolInfo() :
+ m_Valid(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+/*PLT_ProtocolInfo::PLT_ProtocolInfo(NPT_String protocol_info) :
+ m_Valid(false)
+{
+ SetProtocolInfo(protocol_info);
+}*/
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo::PLT_ProtocolInfo(const char* protocol_info) :
+ m_Valid(false)
+{
+ SetProtocolInfo(protocol_info);
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo::PLT_ProtocolInfo(const char* protocol,
+ const char* mask,
+ const char* content_type,
+ const char* extra) :
+ m_Protocol(protocol),
+ m_Mask(mask),
+ m_ContentType(content_type),
+ m_Extra(extra),
+ m_Valid(false)
+{
+ ValidateExtra();
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::SetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::SetProtocolInfo(const char* protocol_info)
+{
+ if (!protocol_info || protocol_info[0] == '\0')
+ return NPT_ERROR_INVALID_PARAMETERS;
+
+ NPT_List<NPT_String> parts = NPT_String(protocol_info).Split(":");
+ if (parts.GetItemCount() != 4)
+ return NPT_ERROR_INVALID_SYNTAX;
+
+ NPT_List<NPT_String>::Iterator part = parts.GetFirstItem();
+ m_Protocol = *part++;
+ m_Mask = *part++;
+ m_ContentType = *part++;
+ m_Extra = *part;
+
+ return ValidateExtra();
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ParseExtra
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::ParseExtra(NPT_List<FieldEntry>& entries)
+{
+ if (m_Extra == "*") return NPT_SUCCESS;
+
+ // remove extra characters which could cause parsing errors
+ m_Extra.Trim(";");
+
+ NPT_List<NPT_String> fields = m_Extra.Split(";");
+ NPT_List<NPT_String>::Iterator field = fields.GetFirstItem();
+ if (!field) NPT_CHECK_SEVERE(NPT_ERROR_INVALID_SYNTAX);
+
+ while (field) {
+ NPT_List<NPT_String> entry = (*field).Split("=");
+ if (entry.GetItemCount() != 2) NPT_CHECK_SEVERE(NPT_ERROR_INVALID_SYNTAX);
+ entries.Add(FieldEntry(*entry.GetFirstItem(), *entry.GetLastItem()));
+ ++field;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ValidateField
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::ValidateField(const char* val,
+ const char* valid_chars,
+ NPT_Cardinal num_chars /* = 0 */)
+{
+ if (!valid_chars || !val || val[0] == '\0')
+ return NPT_ERROR_INVALID_PARAMETERS;
+
+ // shortcut
+ if (num_chars && NPT_StringLength(val) != num_chars)
+ return NPT_ERROR_INVALID_SYNTAX;
+
+ while (val) {
+ char c = *val++;
+ if (c == '\0') return NPT_SUCCESS;
+
+ // look for character in valid chars
+ const char* p = valid_chars;
+ while (*p != c && ++p) {};
+
+ // reached end of valid chars means we didn't find it
+ if (!p) break;
+ }
+
+ return NPT_ERROR_INVALID_SYNTAX;
+
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ValidateExtra
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::ValidateExtra()
+{
+ if (m_Extra != "*") {
+ m_Valid = false;
+
+ NPT_List<FieldEntry> entries;
+ NPT_CHECK(ParseExtra(entries));
+
+ NPT_List<FieldEntry>::Iterator entry =
+ entries.GetFirstItem();
+
+ // parse other optional fields
+ PLT_ProtocolInfoParserState state = PLT_PROTINFO_PARSER_STATE_START;
+ for (;entry;entry++) {
+ if (entry->m_Key == "DLNA.ORG_PN") {
+ // pn-param only allowed as first param
+ if (state > PLT_PROTINFO_PARSER_STATE_START) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAPNCharsToValidate), failure);
+
+ m_DLNA_PN = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_PN;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_OP") {
+ // op-param only allowed after pn-param
+ if (state > PLT_PROTINFO_PARSER_STATE_PN) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAFlagCharsToValidate,
+ 2), failure);
+
+ m_DLNA_OP = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_OP;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_PS") {
+ // ps-param only allowed after op-param
+ if (state > PLT_PROTINFO_PARSER_STATE_OP) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAPSCharsToValidate), failure);
+
+ m_DLNA_PS = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_PS;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_CI") {
+ // ci-param only allowed after ps-param
+ if (state > PLT_PROTINFO_PARSER_STATE_PS) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAFlagCharsToValidate,
+ 1), failure);
+
+ m_DLNA_CI = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_CI;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_FLAGS") {
+ // flags-param only allowed after ci-param
+ if (state > PLT_PROTINFO_PARSER_STATE_CI) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAHexCharsToValidate,
+ 32), failure);
+
+ m_DLNA_FLAGS = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_FLAGS;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_MAXSP") {
+ // maxsp-param only allowed after flags-param
+ if (state > PLT_PROTINFO_PARSER_STATE_FLAGS) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_FIELD_NUM "."), failure);
+
+ m_DLNA_MAXSP = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_MAXSP;
+ continue;
+ } else {
+ // don't switch state for unknown value so we don't break parsing next ones
+ // Sony TVs for example have DLNA.ORG_PN=xx;SONY.COM_PN=xx;DLNA.ORG_FLAGS=xxx
+ //state = PLT_PROTINFO_PARSER_STATE_OTHER;
+
+ // validate key first which should IANA_*<"a"-"z","A"-"Z","0"-"9">
+ int index = entry->m_Key.Find("_");
+ if (index == -1) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate key
+ if (NPT_FAILED(ValidateField(
+ entry->m_Key.GetChars()+index,
+ PLT_DLNAOTherNameCharsToValidate))) {
+ NPT_LOG_WARNING_2("Invalid protocolinfo 4th field other param: %s=%s",
+ (const char*)entry->m_Key,
+ (const char*)entry->m_Value);
+ continue;
+ }
+
+ // validate value
+ if (NPT_FAILED(ValidateField(
+ entry->m_Value,
+ PLT_DLNAOTherValueCharsToValidate))) {
+
+ NPT_LOG_WARNING_2("Invalid protocolinfo 4th field other param: %s=%s",
+ (const char*)entry->m_Key,
+ (const char*)entry->m_Value);
+ continue;
+ }
+
+ m_DLNA_OTHER.Add(*entry);
+ continue;
+ }
+ }
+ }
+
+ m_Valid = true;
+ return NPT_SUCCESS;
+
+failure:
+ NPT_LOG_WARNING_1("Failure to parse Protocol Info Extras:%s", m_Extra.GetChars());
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ToString
++---------------------------------------------------------------------*/
+NPT_String
+PLT_ProtocolInfo::ToString() const
+{
+ NPT_String output = m_Protocol + ":";
+ output += m_Mask + ":";
+ output += m_ContentType + ":";
+ // if it wasn't valid or extra is not DLNA, just use it as is
+ if (!m_Valid || m_Extra == "*") {
+ output += m_Extra;
+ } else {
+ bool add_semicolon = false;
+ if (!m_DLNA_PN.IsEmpty()) {
+ output += "DLNA.ORG_PN=" + m_DLNA_PN;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_OP.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_OP=" + m_DLNA_OP;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_PS.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_PS=" + m_DLNA_PS;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_CI.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_CI=" + m_DLNA_CI;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_FLAGS.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_FLAGS=" + m_DLNA_FLAGS;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_MAXSP.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_MAXSP=" + m_DLNA_MAXSP;
+ add_semicolon = true;
+ }
+ if (m_DLNA_OTHER.GetItemCount()) {
+ for (NPT_List<FieldEntry>::Iterator iter = m_DLNA_OTHER.GetFirstItem();
+ iter;
+ iter++) {
+ if (add_semicolon) output += ";";
+ output += iter->m_Key + "=" + iter->m_Value;
+ add_semicolon = true;
+ }
+ }
+ }
+
+ return output;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::Match
++---------------------------------------------------------------------*/
+bool
+PLT_ProtocolInfo::Match(const PLT_ProtocolInfo& other) const
+{
+ // we need the first 3 params
+ if (m_Protocol != '*' &&
+ other.GetProtocol() != '*' &&
+ m_Protocol != other.GetProtocol()) return false;
+
+ if (m_Mask != '*' &&
+ other.GetMask() != '*' &&
+ m_Mask != other.GetMask()) return false;
+
+ if (m_ContentType != '*' &&
+ other.GetContentType() != '*' &&
+ m_ContentType != other.GetContentType()) return false;
+
+ // match DLNAPn of 4th item if not '*'
+ if (m_Extra == '*' ||
+ other.GetExtra() == '*' ||
+ (!m_DLNA_PN.IsEmpty() && m_DLNA_PN == other.GetDLNA_PN())) return true;
+
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetMimeTypeFromProtocolInfo
++---------------------------------------------------------------------*/
+NPT_String
+PLT_ProtocolInfo::GetMimeTypeFromProtocolInfo(const char* protocol_info)
+{
+ /*NPT_String info = protocol_info;
+ NPT_List<NPT_String> fragments = info.Split(":");
+ if (fragments.GetItemCount() != 4) return "";
+ return *fragments.GetItem(2);*/
+
+ PLT_ProtocolInfo info(protocol_info);
+ return info.m_ContentType;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetDlnaExtension
++---------------------------------------------------------------------*/
+const char*
+PLT_ProtocolInfo::GetDlnaExtension(const char* mime_type,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetDlnaExtension(mime_type,
+ context?PLT_HttpHelper::GetDeviceSignature(context->GetRequest()):PLT_DEVICE_UNKNOWN);
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetDlnaExtension
++---------------------------------------------------------------------*/
+const char*
+PLT_ProtocolInfo::GetDlnaExtension(const char* mime_type,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ NPT_String _mime_type = mime_type;
+
+ if (signature != PLT_DEVICE_UNKNOWN) {
+ // look for special case for 360
+ if (signature == PLT_DEVICE_XBOX_360 || signature == PLT_DEVICE_XBOX_ONE || signature == PLT_DEVICE_WMP) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_360DlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_360DlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_360DlnaMap[i].dlna_ext;
+ }
+ }
+ } else if (signature == PLT_DEVICE_SONOS) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_SonosDlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_SonosDlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_SonosDlnaMap[i].dlna_ext;
+ }
+ }
+ } else if (signature == PLT_DEVICE_PS3) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_PS3DlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_PS3DlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_PS3DlnaMap[i].dlna_ext;
+ }
+ }
+
+ return "DLNA.ORG_OP=01"; // Should we try default dlna instead?
+ }
+ }
+
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_DefaultDlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_DefaultDlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_DefaultDlnaMap[i].dlna_ext;
+ }
+ }
+
+ return "*";
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfoFromMimeType
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfoFromMimeType(const char* mime_type,
+ bool with_dlna_extension /* = true */,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ return PLT_ProtocolInfo("http-get:*:"+NPT_String(mime_type)+":"+ \
+ (with_dlna_extension?GetDlnaExtension(mime_type, signature):"*"));
+}
+
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfoFromMimeType
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfoFromMimeType(const char* mime_type,
+ bool with_dlna_extension /* = true */,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetProtocolInfoFromMimeType(mime_type,
+ with_dlna_extension,
+ context?PLT_HttpHelper::GetDeviceSignature(context->GetRequest()):PLT_DEVICE_UNKNOWN);
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfo(const char* filename,
+ bool with_dlna_extension /* = true */,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ return GetProtocolInfoFromMimeType(PLT_MimeType::GetMimeType(filename, signature),
+ with_dlna_extension,
+ signature);
+}
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfo(const char* filename,
+ bool with_dlna_extension /* = true */,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetProtocolInfoFromMimeType(PLT_MimeType::GetMimeType(filename, context),
+ with_dlna_extension,
+ context);
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.h b/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.h
new file mode 100644
index 0000000..d86ef0c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.h
@@ -0,0 +1,158 @@
+/*****************************************************************
+|
+| Platinum - AV Media Protocol Info
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Media Object Protocol Info.
+ */
+
+#ifndef _PLT_PROTOCOL_INFO_H_
+#define _PLT_PROTOCOL_INFO_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_HttpRequestContext;
+
+/*----------------------------------------------------------------------
+| typedefs
++---------------------------------------------------------------------*/
+typedef struct PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry {
+ const char* mime_type;
+ const char* dlna_ext;
+} PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry ;
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+/**
+ The PLT_ProtocolInfo class holds information about the protocol info of a
+ given UPnP Media Item resource.
+ */
+class PLT_ProtocolInfo
+{
+public:
+ class FieldEntry {
+ public:
+ FieldEntry(const char* key, const char* value) :
+ m_Key(key), m_Value(value) {}
+ NPT_String m_Key;
+ NPT_String m_Value;
+ };
+
+ // class methods
+ static NPT_String GetMimeTypeFromProtocolInfo(const char* protocol_info);
+
+ static const char* GetDlnaExtension(const char* mime_type,
+ const PLT_HttpRequestContext* context = NULL);
+ static const char* GetDlnaExtension(const char* mime_type,
+ PLT_DeviceSignature signature = PLT_DEVICE_UNKNOWN);
+
+ static PLT_ProtocolInfo GetProtocolInfo(const char* filename,
+ bool with_dlna_extension = true,
+ const PLT_HttpRequestContext* context = NULL);
+ static PLT_ProtocolInfo GetProtocolInfo(const char* filename,
+ bool with_dlna_extension = true,
+ PLT_DeviceSignature signature = PLT_DEVICE_UNKNOWN);
+
+ static PLT_ProtocolInfo GetProtocolInfoFromMimeType(const char* mime_type,
+ bool with_dlna_extension = true,
+ const PLT_HttpRequestContext* context = NULL);
+ static PLT_ProtocolInfo GetProtocolInfoFromMimeType(const char* mime_type,
+ bool with_dlna_extension = true,
+ PLT_DeviceSignature signature = PLT_DEVICE_UNKNOWN);
+
+ // methods
+ PLT_ProtocolInfo();
+ //PLT_ProtocolInfo(NPT_String protocol_info);
+ PLT_ProtocolInfo(const char* protocol_info);
+ PLT_ProtocolInfo(const char* protocol,
+ const char* mask,
+ const char* content_type,
+ const char* extra);
+ const NPT_String& GetProtocol() const { return m_Protocol; }
+ const NPT_String& GetMask() const { return m_Mask; }
+ const NPT_String& GetContentType() const { return m_ContentType; }
+ const NPT_String& GetExtra() const { return m_Extra; }
+
+ const NPT_String& GetDLNA_PN() const { return m_DLNA_PN; }
+
+ bool IsValid() { return m_Valid; }
+
+ NPT_String ToString() const;
+
+ bool Match(const PLT_ProtocolInfo& other) const;
+
+private:
+ typedef enum {
+ PLT_PROTINFO_PARSER_STATE_START,
+ PLT_PROTINFO_PARSER_STATE_PN,
+ PLT_PROTINFO_PARSER_STATE_OP,
+ PLT_PROTINFO_PARSER_STATE_PS,
+ PLT_PROTINFO_PARSER_STATE_CI,
+ PLT_PROTINFO_PARSER_STATE_FLAGS,
+ PLT_PROTINFO_PARSER_STATE_MAXSP,
+ PLT_PROTINFO_PARSER_STATE_OTHER
+ } PLT_ProtocolInfoParserState;
+
+ NPT_Result SetProtocolInfo(const char* protocol_info);
+ NPT_Result ValidateField(const char* val,
+ const char* valid_chars,
+ NPT_Cardinal num_chars = 0); // 0 means variable number of chars
+ NPT_Result ParseExtra(NPT_List<FieldEntry>& entries);
+ NPT_Result ValidateExtra();
+
+private:
+ NPT_String m_Protocol;
+ NPT_String m_Mask;
+ NPT_String m_ContentType;
+ NPT_String m_Extra;
+
+ NPT_String m_DLNA_PN; // DLNA.ORG_PN Parameter (pn-param)
+ NPT_String m_DLNA_OP; // Operations Parameter (op-param)
+ NPT_String m_DLNA_PS; // Server-Side PlaySpeeds Parameter (ps-param)
+ NPT_String m_DLNA_CI; // Conversion Indicator Flag (ci-param)
+ NPT_String m_DLNA_FLAGS; // Flags Parameter (flags-param)
+ NPT_String m_DLNA_MAXSP; // Maximum RTSP Speed Header value (maxsp-param)
+ NPT_List<FieldEntry> m_DLNA_OTHER; // Vendor-defined 4th field Parameters (other-param)
+
+ bool m_Valid;
+};
+
+#endif /* _PLT_PROTOCOL_INFO_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltService.cpp b/lib/libUPnP/Platinum/Source/Core/PltService.cpp
new file mode 100644
index 0000000..b86fb23
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltService.cpp
@@ -0,0 +1,920 @@
+/*****************************************************************
+|
+| Platinum - Service
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltService.h"
+#include "PltSsdp.h"
+#include "PltUPnP.h"
+#include "PltDeviceData.h"
+#include "PltUtilities.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.service")
+
+/*----------------------------------------------------------------------
+| PLT_Service::PLT_Service
++---------------------------------------------------------------------*/
+PLT_Service::PLT_Service(PLT_DeviceData* device,
+ const char* type,
+ const char* id,
+ const char* name,
+ const char* last_change_namespace /* = NULL */) :
+ m_Device(device),
+ m_ServiceType(type),
+ m_ServiceID(id),
+ m_ServiceName(name),
+ m_EventTask(NULL),
+ m_EventingPaused(false),
+ m_LastChangeNamespace(last_change_namespace)
+{
+ if (name) InitURLs(name);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::~PLT_Service
++---------------------------------------------------------------------*/
+PLT_Service::~PLT_Service()
+{
+ Cleanup();
+}
+
+/*----------------------------------------------------------------------
+ | PLT_Service::Cleanup
+ +---------------------------------------------------------------------*/
+ void
+ PLT_Service::Cleanup()
+ {
+ m_ActionDescs.Apply(NPT_ObjectDeleter<PLT_ActionDesc>());
+ m_StateVars.Apply(NPT_ObjectDeleter<PLT_StateVariable>());
+
+ m_ActionDescs.Clear();
+ m_StateVars.Clear();
+ m_Subscribers.Clear();
+ }
+
+/*----------------------------------------------------------------------
+| PLT_Service::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::GetSCPDXML(NPT_String& scpd)
+{
+ NPT_Result res;
+
+ // it is required to have at least 1 state variable
+ if (m_StateVars.GetItemCount() == 0) return NPT_FAILURE;
+
+ NPT_XmlElementNode* spec = NULL;
+ NPT_XmlElementNode* actionList = NULL;
+ NPT_XmlElementNode* top = new NPT_XmlElementNode("scpd");
+ NPT_XmlElementNode* serviceStateTable = NULL;
+ NPT_CHECK_LABEL_SEVERE(res = top->SetNamespaceUri("", "urn:schemas-upnp-org:service-1-0"), cleanup);
+
+ // add spec version
+ spec = new NPT_XmlElementNode("specVersion");
+ NPT_CHECK_LABEL_SEVERE(res = top->AddChild(spec), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "major", "1"), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::AddChildText(spec, "minor", "0"), cleanup);
+
+ // add actions
+ actionList = new NPT_XmlElementNode("actionList");
+ NPT_CHECK_LABEL_SEVERE(res = top->AddChild(actionList), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = m_ActionDescs.ApplyUntil(
+ PLT_GetSCPDXMLIterator<PLT_ActionDesc>(actionList),
+ NPT_UntilResultNotEquals(NPT_SUCCESS)), cleanup);
+
+ // add service state table
+ serviceStateTable = new NPT_XmlElementNode("serviceStateTable");
+ NPT_CHECK_LABEL_SEVERE(res = top->AddChild(serviceStateTable), cleanup);
+ NPT_CHECK_LABEL_SEVERE(res = m_StateVars.ApplyUntil(
+ PLT_GetSCPDXMLIterator<PLT_StateVariable>(serviceStateTable),
+ NPT_UntilResultNotEquals(NPT_SUCCESS)), cleanup);
+
+ // serialize node
+ NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*top, scpd, true, 2), cleanup);
+
+cleanup:
+ delete top;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::ToXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::GetDescription(NPT_XmlElementNode* parent, NPT_XmlElementNode** service_out /* = NULL */)
+{
+ NPT_XmlElementNode* service = new NPT_XmlElementNode("service");
+ if (service_out) {
+ *service_out = service;
+ }
+ NPT_CHECK_SEVERE(parent->AddChild(service));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "serviceType", m_ServiceType));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "serviceId", m_ServiceID));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "SCPDURL", GetSCPDURL()));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "controlURL", GetControlURL()));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(service, "eventSubURL", GetEventSubURL()));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::InitURLs
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::InitURLs(const char* service_name)
+{
+ m_SCPDURL = service_name;
+ m_SCPDURL += "/" + m_Device->GetUUID() + NPT_String("/scpd.xml");
+ m_ControlURL = service_name;
+ m_ControlURL += "/" + m_Device->GetUUID() + NPT_String("/control.xml");
+ m_EventSubURL = service_name;
+ m_EventSubURL += "/" + m_Device->GetUUID() + NPT_String("/event.xml");
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::SetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::SetSCPDXML(const char* scpd)
+{
+ if (scpd == NULL) return NPT_ERROR_INVALID_PARAMETERS;
+
+ Cleanup();
+
+ NPT_XmlParser parser;
+ NPT_XmlNode* tree = NULL;
+ NPT_Result res;
+ NPT_Array<NPT_XmlElementNode*> stateVariables;
+ NPT_Array<NPT_XmlElementNode*> actions;
+ NPT_XmlElementNode* root;
+ NPT_XmlElementNode* actionList;
+ NPT_XmlElementNode* stateTable;
+
+ res = parser.Parse(scpd, tree);
+ NPT_CHECK_LABEL_FATAL(res, failure);
+
+ // make sure root tag is right
+ root = tree->AsElementNode();
+ if (!root || NPT_String::Compare(root->GetTag(), "scpd") != 0) {
+ NPT_LOG_SEVERE("Invalid scpd root tag name");
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // make sure we have required children presents
+ stateTable = PLT_XmlHelper::GetChild(root, "serviceStateTable");
+ if (!stateTable ||
+ stateTable->GetChildren().GetItemCount() == 0 ||
+ NPT_FAILED(PLT_XmlHelper::GetChildren(stateTable,
+ stateVariables,
+ "stateVariable"))) {
+ NPT_LOG_SEVERE("No state variables found");
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ for (int k = 0 ; k < (int)stateVariables.GetItemCount(); k++) {
+ NPT_String name, type, send;
+ PLT_XmlHelper::GetChildText(stateVariables[k], "name", name);
+ PLT_XmlHelper::GetChildText(stateVariables[k], "dataType", type);
+ PLT_XmlHelper::GetAttribute(stateVariables[k], "sendEvents", send);
+
+ if (name.GetLength() == 0 || type.GetLength() == 0) {
+ NPT_LOG_SEVERE_1("Invalid state variable name or type at position %d", k+1);
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ PLT_StateVariable* variable = new PLT_StateVariable(this);
+ m_StateVars.Add(variable);
+
+ variable->m_Name = name;
+ variable->m_DataType = type;
+ variable->m_IsSendingEvents = IsTrue(send);
+ PLT_XmlHelper::GetChildText(stateVariables[k], "defaultValue", variable->m_DefaultValue);
+
+ NPT_XmlElementNode* allowedValueList = PLT_XmlHelper::GetChild(stateVariables[k], "allowedValueList");
+ if (allowedValueList) {
+ NPT_Array<NPT_XmlElementNode*> allowedValues;
+ PLT_XmlHelper::GetChildren(allowedValueList, allowedValues, "allowedValue");
+ for (int l = 0 ; l < (int)allowedValues.GetItemCount(); l++) {
+ const NPT_String* text = allowedValues[l]->GetText();
+ if (text) {
+ variable->m_AllowedValues.Add(new NPT_String(*text));
+ }
+ }
+ } else {
+ NPT_XmlElementNode* allowedValueRange = PLT_XmlHelper::GetChild(stateVariables[k], "allowedValueRange");
+ if (allowedValueRange) {
+ NPT_String min, max, step;
+ PLT_XmlHelper::GetChildText(allowedValueRange, "minimum", min);
+ PLT_XmlHelper::GetChildText(allowedValueRange, "maximum", max);
+ PLT_XmlHelper::GetChildText(allowedValueRange, "step", step);
+
+ // these are required but try to be nice
+ // in case bad devices provide nothing
+ if (min.GetLength() == 0) {
+ if (variable->m_DataType == "ui1" ||
+ variable->m_DataType == "ui2" ||
+ variable->m_DataType == "ui4") {
+ min = NPT_String::FromInteger(0);
+ } else if (variable->m_DataType == "i1") {
+ min = NPT_String::FromInteger(-128);
+ } else if (variable->m_DataType == "i2") {
+ min = NPT_String::FromInteger(-32768);
+ } else if (variable->m_DataType == "i4" ||
+ variable->m_DataType == "int") {
+ min = NPT_String::FromInteger(-2147483647 - 1);
+ } else {
+ NPT_LOG_SEVERE_1("Invalid variable data type %s", variable->m_DataType.GetChars());
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+ }
+ if (max.GetLength() == 0) {
+ if (variable->m_DataType == "ui1") {
+ max = NPT_String::FromInteger(0xff);
+ } else if (variable->m_DataType == "ui2") {
+ max = NPT_String::FromInteger(0xffff);
+ } else if (variable->m_DataType == "ui4") {
+ max = NPT_String::FromInteger(0xffffffff);
+ } else if (variable->m_DataType == "i1") {
+ max = NPT_String::FromInteger(0x7f);
+ } else if (variable->m_DataType == "i2") {
+ max = NPT_String::FromInteger(0x7fff);
+ } else if (variable->m_DataType == "i4" ||
+ variable->m_DataType == "int") {
+ max = NPT_String::FromInteger(0x7fffffff);
+ } else {
+ NPT_LOG_SEVERE_1("Invalid variable data type %s", variable->m_DataType.GetChars());
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+ }
+
+ variable->m_AllowedValueRange = new NPT_AllowedValueRange;
+ NPT_ParseInteger32(min, variable->m_AllowedValueRange->min_value);
+ NPT_ParseInteger32(max, variable->m_AllowedValueRange->max_value);
+ variable->m_AllowedValueRange->step = -1;
+
+ if (step.GetLength() != 0) {
+ NPT_ParseInteger(step, variable->m_AllowedValueRange->step);
+ }
+ }
+ }
+ }
+
+ // actions
+ actionList = PLT_XmlHelper::GetChild(root, "actionList");
+ if (actionList) {
+ res = PLT_XmlHelper::GetChildren(actionList, actions, "action");
+ NPT_CHECK_LABEL_SEVERE(res, failure);
+
+ for (int i = 0 ; i < (int)actions.GetItemCount(); i++) {
+ NPT_String action_name;
+ PLT_XmlHelper::GetChildText(actions[i], "name", action_name);
+ if (action_name.GetLength() == 0) {
+ NPT_LOG_SEVERE_1("Invalid action name for action number %d", i+1);
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ PLT_ActionDesc* action_desc = new PLT_ActionDesc(action_name, this);
+ m_ActionDescs.Add(action_desc);
+
+ // action arguments
+ NPT_XmlElementNode* argumentList = PLT_XmlHelper::GetChild(actions[i], "argumentList");
+ if (argumentList == NULL || !argumentList->GetChildren().GetItemCount())
+ continue; // no arguments is ok I guess
+
+ NPT_Array<NPT_XmlElementNode*> arguments;
+ NPT_CHECK_LABEL_SEVERE(PLT_XmlHelper::GetChildren(argumentList, arguments, "argument"), failure);
+
+ bool ret_value_found = false;
+ for (int j = 0 ; j < (int)arguments.GetItemCount(); j++) {
+ NPT_String name, direction, relatedStateVar;
+ PLT_XmlHelper::GetChildText(arguments[j], "name", name);
+ PLT_XmlHelper::GetChildText(arguments[j], "direction", direction);
+ PLT_XmlHelper::GetChildText(arguments[j], "relatedStateVariable", relatedStateVar);
+
+ if (name.GetLength() == 0 || direction.GetLength() == 0 || relatedStateVar.GetLength() == 0) {
+ NPT_LOG_SEVERE_1("Invalid argument for action %s", (const char*)action_name);
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // make sure the related state variable exists
+ PLT_StateVariable* variable = FindStateVariable(relatedStateVar);
+ if (variable == NULL) {
+ NPT_LOG_SEVERE_1("State variable not found %s", (const char*)relatedStateVar);
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ bool ret_value = false;
+ NPT_XmlElementNode* ret_val_node = PLT_XmlHelper::GetChild(arguments[j], "retVal");
+ if (ret_val_node) {
+ // verify this is the only retVal we've had
+ if (ret_value_found) {
+ NPT_LOG_SEVERE("Return argument already found");
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ } else {
+ ret_value = true;
+ ret_value_found = true;
+ }
+ }
+ action_desc->GetArgumentDescs().Add(new PLT_ArgumentDesc(name, j, direction, variable, ret_value));
+ }
+ }
+ }
+
+ // delete the tree
+ delete tree;
+ return NPT_SUCCESS;
+
+failure:
+ NPT_LOG_FATAL_1("Failed to parse scpd: %s", scpd);
+ if (tree) delete tree;
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::GetSCPDURL
++---------------------------------------------------------------------*/
+NPT_String
+PLT_Service::GetSCPDURL(bool absolute /* = false */)
+{
+ NPT_HttpUrl url = GetDevice()->NormalizeURL(m_SCPDURL);
+ return absolute?url.ToString():url.ToRequestString();
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::GetControlURL
++---------------------------------------------------------------------*/
+NPT_String
+PLT_Service::GetControlURL(bool absolute /* = false */)
+{
+ NPT_HttpUrl url = GetDevice()->NormalizeURL(m_ControlURL);
+ return absolute?url.ToString():url.ToRequestString();
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::GetEventSubURL
++---------------------------------------------------------------------*/
+NPT_String
+PLT_Service::GetEventSubURL(bool absolute /* = false */)
+{
+ NPT_HttpUrl url = GetDevice()->NormalizeURL(m_EventSubURL);
+ return absolute?url.ToString():url.ToRequestString();
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::ForceVersion
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::ForceVersion(NPT_Cardinal version)
+{
+ if (version < 1) return NPT_FAILURE;
+
+ m_ServiceType = m_ServiceType.SubString(0, m_ServiceType.GetLength()-1);
+ m_ServiceType += NPT_String::FromIntegerU(version);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::FindActionDesc
++---------------------------------------------------------------------*/
+PLT_ActionDesc*
+PLT_Service::FindActionDesc(const char* name)
+{
+ PLT_ActionDesc* action = NULL;
+ NPT_ContainerFind(m_ActionDescs, PLT_ActionDescNameFinder(name), action);
+ return action;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::FindStateVariable
++---------------------------------------------------------------------*/
+PLT_StateVariable*
+PLT_Service::FindStateVariable(const char* name)
+{
+ PLT_StateVariable* stateVariable = NULL;
+ NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+ return stateVariable;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::GetStateVariableValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::GetStateVariableValue(const char* name, NPT_String& value)
+{
+ PLT_StateVariable* stateVariable = FindStateVariable(name);
+ NPT_CHECK_POINTER_FATAL(stateVariable);
+ value = stateVariable->GetValue();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::IsSubscribable
++---------------------------------------------------------------------*/
+bool
+PLT_Service::IsSubscribable()
+{
+ NPT_List<PLT_StateVariable*>::Iterator var = m_StateVars.GetFirstItem();
+ while (var) {
+ if ((*var)->IsSendingEvents()) return true;
+ ++var;
+ }
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::SetStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::SetStateVariable(const char* name, const char* value, const bool clearonsend /*=false*/)
+{
+ PLT_StateVariable* stateVariable = NULL;
+ NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+ if (stateVariable == NULL)
+ return NPT_FAILURE;
+
+ return stateVariable->SetValue(value, clearonsend);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::SetStateVariableRate
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::SetStateVariableRate(const char* name, NPT_TimeInterval rate)
+{
+ PLT_StateVariable* stateVariable = NULL;
+ NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+ if (stateVariable == NULL)
+ return NPT_FAILURE;
+
+ return stateVariable->SetRate(rate);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::SetStateVariableExtraAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::SetStateVariableExtraAttribute(const char* name,
+ const char* key,
+ const char* value)
+{
+ PLT_StateVariable* stateVariable = NULL;
+ NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+ if (stateVariable == NULL)
+ return NPT_FAILURE;
+
+ return stateVariable->SetExtraAttribute(key, value);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::IncStateVariable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::IncStateVariable(const char* name)
+{
+ PLT_StateVariable* stateVariable = NULL;
+ NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
+ if (stateVariable == NULL)
+ return NPT_FAILURE;
+
+ NPT_String value = stateVariable->GetValue();
+ NPT_Int32 num;
+ if (value.GetLength() == 0 || NPT_FAILED(value.ToInteger(num))) {
+ return NPT_FAILURE;
+ }
+
+ // convert value to int
+ return stateVariable->SetValue(NPT_String::FromInteger(num+1));
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::ProcessNewSubscription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::ProcessNewSubscription(PLT_TaskManagerReference task_manager,
+ const NPT_SocketAddress& addr,
+ const NPT_String& callback_urls,
+ int timeout,
+ NPT_HttpResponse& response)
+{
+ NPT_LOG_FINE_2("New subscription for %s (timeout = %d)", m_EventSubURL.GetChars(), timeout);
+
+// // first look if we don't have a subscriber with same callbackURL
+// PLT_EventSubscriber* subscriber = NULL;
+// if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers, PLT_EventSubscriberFinderByCallbackURL(strCallbackURL),
+// subscriber))) {
+// // update local interface and timeout
+// subscriber->m_local_if.SetIpAddress((unsigned long) addr.GetIpAddress());
+// subscriber->m_ExpirationTime = NPT_Time(NULL) + timeout;
+//
+// PLT_UPnPMessageHelper::SetSID("uuid:" + subscriber->m_sid);
+// PLT_UPnPMessageHelper::SetTimeOut(timeout);
+// return NPT_SUCCESS;
+// }
+//
+ // reject if we have too many subscribers already
+ if (m_Subscribers.GetItemCount() > 30) {
+ response.SetStatus(500, "Internal Server Error");
+ return NPT_FAILURE;
+ }
+
+ //TODO: prevent hacking by making sure callbackurl is not ourselves?
+
+ // generate a unique subscriber ID
+ NPT_String sid;
+ PLT_UPnPMessageHelper::GenerateGUID(sid);
+ sid = "uuid:" + sid;
+
+ PLT_EventSubscriberReference subscriber(new PLT_EventSubscriber(task_manager, this, sid, timeout));
+ // parse the callback URLs
+ bool reachable = false;
+ if (callback_urls[0] == '<') {
+ char* szURLs = (char*)(const char*)callback_urls;
+ char* brackL = szURLs;
+ char* brackR = szURLs;
+ while (++brackR < szURLs + callback_urls.GetLength()) {
+ if (*brackR == '>') {
+ NPT_String strCallbackURL = NPT_String(brackL+1, (NPT_Size)(brackR-brackL-1));
+ NPT_HttpUrl url(strCallbackURL);
+
+ if (url.IsValid()) {
+ subscriber->AddCallbackURL(strCallbackURL);
+ reachable = true;
+ }
+ brackL = ++brackR;
+ }
+ }
+ }
+
+ if (reachable == false) {
+ NPT_CHECK_LABEL_FATAL(NPT_FAILURE, cleanup);
+ }
+
+ // keep track of which interface we receive the request, we will use this one
+ // when notifying
+ subscriber->SetLocalIf(addr);
+
+ PLT_UPnPMessageHelper::SetSID(response, subscriber->GetSID());
+ PLT_UPnPMessageHelper::SetTimeOut(response, timeout);
+
+ {
+ NPT_AutoLock lock(m_Lock);
+
+ // new subscriber should get all vars in the LastChange var
+ UpdateLastChange(m_StateVars);
+
+ // send all state vars to sub immediately
+ NPT_Result res = subscriber->Notify(m_StateVars);
+
+ // reset LastChange var to what was really just changed
+ UpdateLastChange(m_StateVarsChanged);
+
+ // make sure the event worked before spawning our recurrent task
+ NPT_CHECK_LABEL_FATAL(res, cleanup);
+
+ // schedule a recurring event notification task if not running already
+ if (!m_EventTask) {
+ PLT_ServiceEventTask *task = new PLT_ServiceEventTask(this);
+ NPT_CHECK_SEVERE(task_manager->StartTask(task));
+
+ m_EventTask = task;
+ }
+
+ m_Subscribers.Add(subscriber);
+ }
+
+ return NPT_SUCCESS;
+
+cleanup:
+ response.SetStatus(412, "Precondition Failed");
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::ProcessRenewSubscription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::ProcessRenewSubscription(const NPT_SocketAddress& addr,
+ const NPT_String& sid,
+ int timeout_secs,
+ NPT_HttpResponse& response)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ NPT_LOG_FINE_2("Renewing subscription for %s (sub=%s)",
+ m_EventSubURL.GetChars(),
+ sid.GetChars());
+
+ // first look if we don't have a subscriber with same callbackURL
+ PLT_EventSubscriberReference subscriber;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers,
+ PLT_EventSubscriberFinderBySID(sid),
+ subscriber))) {
+
+ NPT_TimeStamp now, expiration;
+ NPT_System::GetCurrentTimeStamp(now);
+ expiration = subscriber->GetExpirationTime();
+
+ // renew subscriber if it has not expired
+ if (expiration > now ) {
+ // update local interface and timeout
+ subscriber->SetLocalIf(addr);
+ subscriber->SetTimeout(timeout_secs);
+
+ PLT_UPnPMessageHelper::SetSID(response, subscriber->GetSID());
+ PLT_UPnPMessageHelper::SetTimeOut(response, timeout_secs);
+ return NPT_SUCCESS;
+ } else {
+ NPT_LOG_FINE_1("Subscriber \"%s\" didn't renew in time", (const char*)subscriber->GetSID());
+ m_Subscribers.Remove(subscriber);
+ }
+ }
+
+ NPT_LOG_WARNING_1("Failed to renew subscription for %s!", sid.GetChars());
+
+ // didn't find a valid Subscriber in our list
+ response.SetStatus(412, "Precondition Failed");
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::ProcessCancelSubscription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::ProcessCancelSubscription(const NPT_SocketAddress& /* addr */,
+ const NPT_String& sid,
+ NPT_HttpResponse& response)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // first look if we don't have a subscriber with same callbackURL
+ PLT_EventSubscriberReference sub;
+ if (NPT_SUCCEEDED(NPT_ContainerFind(m_Subscribers,
+ PLT_EventSubscriberFinderBySID(sid),
+ sub))) {
+ NPT_LOG_FINE_2("Cancelling subscription for %s (sub=%s)",
+ m_EventSubURL.GetChars(),
+ sid.GetChars());
+
+ // remove sub
+ m_Subscribers.Remove(sub);
+ return NPT_SUCCESS;
+ }
+
+ NPT_LOG_WARNING_1("Cancelling subscription for unknown subscriber %s!", sid.GetChars());
+
+ // didn't find a valid Subscriber in our list
+ response.SetStatus(412, "Precondition Failed");
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::AddChanged
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::AddChanged(PLT_StateVariable* var)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // no event task means no subscribers yet, so don't bother
+ // Note: this will take care also when setting default state
+ // variables values during init and avoid being published
+ if (!m_EventTask) return NPT_SUCCESS;
+
+ if (var->IsSendingEvents()) {
+ if (!m_StateVarsToPublish.Contains(var)) m_StateVarsToPublish.Add(var);
+ } else if (var->IsSendingEvents(true)) {
+ if (!m_StateVarsChanged.Contains(var)) m_StateVarsChanged.Add(var);
+
+ UpdateLastChange(m_StateVarsChanged);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::UpdateLastChange
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::UpdateLastChange(NPT_List<PLT_StateVariable*>& vars)
+{
+ PLT_StateVariable* var = FindStateVariable("LastChange");
+ if (var == NULL) return NPT_FAILURE;
+
+ NPT_ASSERT(m_LastChangeNamespace.GetLength() > 0);
+
+ if (vars.GetItemCount() == 0) {
+ // no vars to update, remove LastChange from vars to publish
+ m_StateVarsToPublish.Remove(var);
+ return NPT_SUCCESS;
+ }
+
+ NPT_Reference<NPT_XmlElementNode> top(new NPT_XmlElementNode("Event"));
+ NPT_CHECK_SEVERE(top->SetNamespaceUri("", m_LastChangeNamespace));
+
+ NPT_XmlElementNode* instance = new NPT_XmlElementNode("InstanceID");
+ NPT_CHECK_SEVERE(top->AddChild(instance));
+ NPT_CHECK_SEVERE(instance->SetAttribute("val", "0"));
+
+ // build list of changes
+ NPT_CHECK_SEVERE(vars.ApplyUntil(
+ PLT_LastChangeXMLIterator(instance),
+ NPT_UntilResultNotEquals(NPT_SUCCESS)));
+
+ // serialize node
+ NPT_String value;
+ NPT_CHECK_SEVERE(PLT_XmlHelper::Serialize(*top, value, false));
+
+ // set the state change directly instead of calling SetValue
+ // to avoid recursive lock, instead add LastChange var directly
+ var->m_Value = value;
+
+ // add to list of vars scheduled to be published next time if not already there
+ if (!m_StateVarsToPublish.Contains(var)) m_StateVarsToPublish.Add(var);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::PauseEventing
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::PauseEventing(bool pause /* = TRUE */)
+{
+ NPT_AutoLock lock(m_Lock);
+ m_EventingPaused = pause;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::NotifyChanged
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Service::NotifyChanged()
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // no eventing for now
+ if (m_EventingPaused) return NPT_SUCCESS;
+
+ // pick the vars that are ready to be published
+ // based on their moderation rate and last publication
+ NPT_List<PLT_StateVariable*> vars_ready;
+ NPT_List<PLT_StateVariable*>::Iterator iter = m_StateVarsToPublish.GetFirstItem();
+ while (iter) {
+ PLT_StateVariable* var = *iter;
+ if (var->IsReadyToPublish()) {
+ vars_ready.Add(var);
+ m_StateVarsToPublish.Erase(iter++);
+
+ // clear last changed list if we're about to send LastChange var
+ if (!var->GetName().Compare("LastChange")) m_StateVarsChanged.Clear();
+
+ continue;
+ }
+
+ ++iter;
+ }
+
+ // if nothing to publish then bail out now
+ // we'll clean up expired subscribers when we have something to publish
+ if (vars_ready.GetItemCount() == 0) return NPT_SUCCESS;
+
+ // send vars that are ready to go and remove old subscribers
+ NPT_List<PLT_EventSubscriberReference>::Iterator sub_iter = m_Subscribers.GetFirstItem();
+ while (sub_iter) {
+ PLT_EventSubscriberReference sub = *sub_iter;
+
+ NPT_TimeStamp now, expiration;
+ NPT_System::GetCurrentTimeStamp(now);
+ expiration = sub->GetExpirationTime();
+
+ // forget sub if it didn't renew subscription in time or if notification failed
+ if (expiration == NPT_TimeStamp() || now < expiration + NPT_TimeStamp(30.f)) {
+ // TODO: Notification is asynchronous, so we won't know if it failed until
+ // the subscriber m_SubscriberTask is done
+ NPT_Result res = vars_ready.GetItemCount()?sub->Notify(vars_ready):NPT_SUCCESS;
+ if (NPT_SUCCEEDED(res)) {
+ ++sub_iter;
+ continue;
+ }
+ }
+
+ m_Subscribers.Erase(sub_iter++);
+ }
+
+ // some state variables must be cleared immediatly after sending
+ iter = vars_ready.GetFirstItem();
+ while (iter) {
+ PLT_StateVariable* var = *iter;
+ var->OnSendCompleted();
+ ++iter;
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ServiceSCPDURLFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceSCPDURLFinder::operator()(PLT_Service* const & service) const
+{
+ return m_URL.Compare(service->GetSCPDURL(m_URL.StartsWith("http://")?true:false), true)?false:true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ServiceControlURLFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceControlURLFinder::operator()(PLT_Service* const & service) const
+{
+ return m_URL.Compare(service->GetControlURL(m_URL.StartsWith("http://")?true:false), true)?false:true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ServiceEventSubURLFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceEventSubURLFinder::operator()(PLT_Service* const & service) const
+{
+ return m_URL.Compare(service->GetEventSubURL(m_URL.StartsWith("http://")?true:false), true)?false:true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ServiceIDFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceIDFinder::operator()(PLT_Service* const & service) const
+{
+ return m_Id.Compare(service->GetServiceID(), true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ServiceTypeFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceTypeFinder::operator()(PLT_Service* const & service) const
+{
+ // DLNA: match any version if last char is '*'
+ if (m_Type.EndsWith("*")) {
+ return m_Type.CompareN(service->GetServiceType(), m_Type.GetLength()-1, true) ? false : true;
+ }
+
+ return m_Type.Compare(service->GetServiceType(), true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ServiceNameFinder::operator()
++---------------------------------------------------------------------*/
+bool
+PLT_ServiceNameFinder::operator()(PLT_Service* const & service) const
+{
+ return m_Name.Compare(service->GetServiceName(), true) ? false : true;
+}
+
+/*----------------------------------------------------------------------
+| PLT_GetLastChangeXMLIterator::operator()
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_LastChangeXMLIterator::operator()(PLT_StateVariable* const &var) const
+{
+ // only add vars that are indirectly evented
+ if (!var->IsSendingEvents(true)) return NPT_SUCCESS;
+
+ NPT_XmlElementNode* variable = new NPT_XmlElementNode((const char*)var->GetName());
+ NPT_CHECK_SEVERE(m_Node->AddChild(variable));
+ NPT_CHECK_SEVERE(var->Serialize(*variable));
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltService.h b/lib/libUPnP/Platinum/Source/Core/PltService.h
new file mode 100644
index 0000000..ebca195
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltService.h
@@ -0,0 +1,522 @@
+/*****************************************************************
+|
+| Platinum - Service
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Service
+ */
+
+#ifndef _PLT_SERVICE_H_
+#define _PLT_SERVICE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltEvent.h"
+#include "PltArgument.h"
+#include "PltStateVariable.h"
+#include "PltAction.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_DeviceData;
+
+/*----------------------------------------------------------------------
+| PLT_Service class
++---------------------------------------------------------------------*/
+/**
+ UPnP Service.
+ The PLT_Service class holds information about a UPnP service of a given device.
+ It maintains a list of actions and state variables. A PLT_DeviceData instance can own
+ one or more PLT_Service instances. When a PLT_Service is advertised as part of a
+ a UPnP Device (PLT_DeviceHost), it also maintains a list of subscribers to nofify when
+ state variables change.
+ */
+class PLT_Service
+{
+public:
+ // methods
+ /**
+ Create an instance of a UPnP Service either hosted or discovered.
+ @param device Pointer to the PLT_DeviceData the service is associated to
+ @param type String representing the UPnP service type
+ @param id String representing the UPnP service id
+ @param name A String to create unique service SCPD, control and eventing urls
+ @param last_change_namespace A String for the LastChange state variable namespace if any
+ */
+ PLT_Service(PLT_DeviceData* device,
+ const char* type,
+ const char* id,
+ const char* name,
+ const char* last_change_namespace = NULL);
+ virtual ~PLT_Service();
+
+ // methods
+ /**
+ When service is hosted by a PLT_DeviceHost, this setups the SCPD, control and event urls.
+ @param service_name the service name used to format unique urls
+ */
+ NPT_Result InitURLs(const char* service_name);
+
+ /**
+ Verify the service has been properly initialized or is a valid discovered service.
+ @return true if valid.
+ */
+ bool IsValid() { return (m_ActionDescs.GetItemCount() > 0); }
+
+ /**
+ When a PLT_DeviceHost needs to change more than one state variables at a time
+ but would rather send only one event with all state variable changes, this can be
+ used to pause and resume the automatic eventing.
+ @param pause Flag to indicate if eventing should be paused or resumed
+ */
+ NPT_Result PauseEventing(bool pause = true);
+
+ // class methods
+ static bool IsTrue(const NPT_String& value) {
+ if (value.Compare("1", true) &&
+ value.Compare("true", true) &&
+ value.Compare("yes", true)) {
+ return false;
+ }
+ return true;
+ }
+
+ // accessor methods
+ /**
+ Set the SCPD url for control points to be able to fetch the SCPD xml document.
+ @param url relative path of SCPD url
+ */
+ NPT_Result SetSCPDURL(const char* url) { m_SCPDURL = url; return NPT_SUCCESS; }
+
+ /*
+ Set the Service Control url for control points to be able to invoke actions.
+ @param url relative path of control url
+ */
+ NPT_Result SetControlURL(const char* url) { m_ControlURL = url; return NPT_SUCCESS; };
+
+ /**
+ Set the Service Event subscription url for control points to be able to subscribe
+ to events.
+ @param url relative path of even url
+ */
+ NPT_Result SetEventSubURL(const char* url) { m_EventSubURL = url; return NPT_SUCCESS; };
+
+ /**
+ Return the SCPD url associated with this service.
+ @param absolute flag to indicate if absolute url including ip and port should
+ be returned
+ @return SCPD url
+ */
+ NPT_String GetSCPDURL(bool absolute = false);
+
+ /**
+ Return the Control url associated with this service.
+ @param absolute flag to indicate if absolute url including ip and port should
+ be returned
+ @return Control url
+ */
+ NPT_String GetControlURL(bool absolute = false);
+
+ /**
+ Return the Event subscription url associated with this service.
+ @param absolute flag to indicate if absolute url including ip and port should
+ be returned
+ @return Event url
+ */
+ NPT_String GetEventSubURL(bool absolute = false);
+
+ /**
+ Return the service id.
+ @return service id
+ */
+ const NPT_String& GetServiceID() const { return m_ServiceID; }
+
+ /**
+ Return the service type.
+ @return service type
+ */
+ const NPT_String& GetServiceType() const { return m_ServiceType; }
+
+ /**
+ Return the service friendly name.
+ @return service name
+ */
+ const NPT_String& GetServiceName() const { return m_ServiceName; }
+
+ /**
+ Return the PLT_DeviceData* the service is associated with.
+ @return PLT_DeviceData pointer
+ */
+ PLT_DeviceData* GetDevice() { return m_Device; }
+
+ /**
+ When a control point discover a new service with a higher version number
+ than it can work with, a lower version can be set to force backward
+ compatibility.
+ @param version Integer specifying the version to use
+ */
+ NPT_Result ForceVersion(NPT_Cardinal version);
+
+ /**
+ Return the service SCPD xml document.
+ @param xml String to receive document
+ */
+ NPT_Result GetSCPDXML(NPT_String& xml);
+
+ /**
+ Set the service SCPD xml document.
+ @param xml String SCPD xml document
+ */
+ NPT_Result SetSCPDXML(const char* xml);
+
+ /**
+ Populate the UPnP Device description document with service information.
+ @param parent XML Element where to insert the service XML Element
+ @param service Pointer to service XML Element node newly created so it can be
+ extended with additional non standard information.
+ */
+ NPT_Result GetDescription(NPT_XmlElementNode* parent, NPT_XmlElementNode** service = NULL);
+
+ /**
+ Set a new value for a given state variable. The service keeps track of which
+ state variables have changed and events are being triggered by a PLT_ServiceEventTask
+ when necessary.
+ @param name state variable name
+ @param value new State Variable value.
+ @param clearonsend whether the State Variable should clear immediatly in ::OnSendingCompleted
+ */
+ NPT_Result SetStateVariable(const char* name, const char* value, const bool clearonsend = false);
+
+ /**
+ Certain state variables notifications must not be sent faster than a certain
+ rate according to the UPnP specs. This sets the rate for a given state variable.
+ @param name state variable name
+ @param rate a time interval specifying the minimum interval allowed between
+ notifications.
+ */
+ NPT_Result SetStateVariableRate(const char* name, NPT_TimeInterval rate);
+
+ /**
+ Certain state variables require extra xml attributes when serialized.
+ @param name state variable name
+ @param key the attribute name
+ @param value the attribute value
+ */
+ NPT_Result SetStateVariableExtraAttribute(const char* name, const char* key, const char* value);
+
+ /**
+ Helper function to increment a state variable representing a number.
+ @param name state variable name
+ */
+ NPT_Result IncStateVariable(const char* name);
+
+ /**
+ Return the PLT_StateVariable pointer given a state variable name.
+ @param name state variable name
+ @return PLT_StateVariable pointer
+ */
+ PLT_StateVariable* FindStateVariable(const char* name);
+
+ /**
+ Return the state variable value given a state variable name.
+ @param name state variable name
+ @param value state variable value output
+ */
+ NPT_Result GetStateVariableValue(const char* name, NPT_String& value);
+
+ /**
+ Return whether a service is capable of sending events.
+ @return true if sending events
+ */
+ bool IsSubscribable();
+
+ /**
+ Return the list of state variables.
+ @return list of state variable pointers.
+ */
+ const NPT_List<PLT_StateVariable*>& GetStateVariables() const { return m_StateVars; }
+
+ /**
+ Return the PLT_ActionDesc given an action name
+ @param name action name
+ @return PLT_ActioDesc pointer
+ */
+ PLT_ActionDesc* FindActionDesc(const char* name);
+
+ /**
+ Return an array of actions descriptions PLT_ActionDesc.
+ @return array of PLT_ActionDesc pointers.
+ */
+ const NPT_Array<PLT_ActionDesc*>& GetActionDescs() const { return m_ActionDescs; }
+
+private:
+ /**
+ A task to send events.
+ The PLT_ServiceEventTask is started when receiving a first subscription. It
+ monitors if some state variables have changed and sends events to all
+ subscribers if so.
+ */
+ class PLT_ServiceEventTask : public PLT_ThreadTask {
+ public:
+ PLT_ServiceEventTask(PLT_Service* service) : m_Service(service) {}
+
+ void DoRun() override {
+ while (!IsAborting(100)) m_Service->NotifyChanged();
+ }
+
+ private:
+ PLT_Service* m_Service;
+ };
+
+ // methods
+ void Cleanup();
+
+ /**
+ Called by a PLT_StateVariable to keep track of what events need to be
+ sent by the PLT_ServiceEventTask task.
+ @param var PLT_StateVariable pointer
+ */
+ NPT_Result AddChanged(PLT_StateVariable* var);
+
+ /**
+ Certain UPnP services combine state variable changes into one single
+ state variable called "LastChange". This function updates the LastChange
+ state variable by looking through the list passed for state variables that
+ are not individually evented.
+ */
+ NPT_Result UpdateLastChange(NPT_List<PLT_StateVariable*>& vars);
+
+ /**
+ Send state variable change events to all subscribers.
+ */
+ NPT_Result NotifyChanged();
+
+ // Events
+ /**
+ Called by PLT_DeviceHost when it receives a request for a new subscription.
+ */
+ NPT_Result ProcessNewSubscription(
+ PLT_TaskManagerReference task_manager,
+ const NPT_SocketAddress& addr,
+ const NPT_String& callback_urls,
+ int timeout,
+ NPT_HttpResponse& response);
+
+ /**
+ Called by PLT_DeviceHost when it receives a request renewing an existing
+ subscription.
+ */
+ NPT_Result ProcessRenewSubscription(
+ const NPT_SocketAddress& addr,
+ const NPT_String& sid,
+ int timeout,
+ NPT_HttpResponse& response);
+
+ /**
+ Called by PLT_DeviceHost when it receives a request to cancel an existing
+ subscription.
+ */
+ NPT_Result ProcessCancelSubscription(
+ const NPT_SocketAddress& addr,
+ const NPT_String& sid,
+ NPT_HttpResponse& response);
+
+
+protected:
+ // friends that need to call private functions
+ friend class PLT_StateVariable; // AddChanged
+ friend class PLT_DeviceHost; // ProcessXXSubscription
+
+ //members
+ PLT_DeviceData* m_Device;
+ NPT_String m_ServiceType;
+ NPT_String m_ServiceID;
+ NPT_String m_ServiceName;
+ NPT_String m_SCPDURL;
+ NPT_String m_ControlURL;
+ NPT_String m_EventSubURL;
+ PLT_ServiceEventTask* m_EventTask;
+ NPT_Array<PLT_ActionDesc*> m_ActionDescs;
+ NPT_List<PLT_StateVariable*> m_StateVars;
+ NPT_Mutex m_Lock;
+ NPT_List<PLT_StateVariable*> m_StateVarsChanged;
+ NPT_List<PLT_StateVariable*> m_StateVarsToPublish;
+ NPT_List<PLT_EventSubscriberReference> m_Subscribers;
+ bool m_EventingPaused;
+ NPT_String m_LastChangeNamespace;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ServiceSCPDURLFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ServiceSCPDURLFinder class returns an instance of a PLT_Service given a
+ service SCPD url.
+ */
+class PLT_ServiceSCPDURLFinder
+{
+public:
+ // methods
+ PLT_ServiceSCPDURLFinder(const char* url) : m_URL(url) {}
+ virtual ~PLT_ServiceSCPDURLFinder() {}
+ bool operator()(PLT_Service* const & service) const;
+
+private:
+ // members
+ NPT_String m_URL;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ServiceControlURLFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ServiceControlURLFinder class returns an instance of a PLT_Service
+ given a service control url.
+ */
+class PLT_ServiceControlURLFinder
+{
+public:
+ // methods
+ PLT_ServiceControlURLFinder(const char* url) : m_URL(url) {}
+ virtual ~PLT_ServiceControlURLFinder() {}
+ bool operator()(PLT_Service* const & service) const;
+
+private:
+ // members
+ NPT_String m_URL;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ServiceEventSubURLFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ServiceEventSubURLFinder class returns an instance of a PLT_Service
+ given a service event subscription url.
+ */
+class PLT_ServiceEventSubURLFinder
+{
+public:
+ // methods
+ PLT_ServiceEventSubURLFinder(const char* url) : m_URL(url) {}
+ virtual ~PLT_ServiceEventSubURLFinder() {}
+ bool operator()(PLT_Service* const & service) const;
+
+private:
+ // members
+ NPT_String m_URL;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ServiceIDFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ServiceIDFinder class returns an instance of a PLT_Service given a
+ service id.
+ */
+class PLT_ServiceIDFinder
+{
+public:
+ // methods
+ PLT_ServiceIDFinder(const char* id) : m_Id(id) {}
+ virtual ~PLT_ServiceIDFinder() {}
+ bool operator()(PLT_Service* const & service) const;
+
+private:
+ // members
+ NPT_String m_Id;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ServiceTypeFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ServiceTypeFinder class returns an instance of a PLT_Service given a
+ service type.
+ */
+class PLT_ServiceTypeFinder
+{
+public:
+ // methods
+ PLT_ServiceTypeFinder(const char* type) : m_Type(type) {}
+ virtual ~PLT_ServiceTypeFinder() {}
+ bool operator()(PLT_Service* const & service) const;
+
+private:
+ // members
+ NPT_String m_Type;
+};
+
+/*----------------------------------------------------------------------
+| PLT_ServiceNameFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_ServiceNameFinder class returns an instance of a PLT_Service given a
+ service name.
+ */
+class PLT_ServiceNameFinder
+{
+public:
+ // methods
+ PLT_ServiceNameFinder(const char* name) : m_Name(name) {}
+ virtual ~PLT_ServiceNameFinder() {}
+ bool operator()(PLT_Service* const & service) const;
+
+private:
+ // members
+ NPT_String m_Name;
+};
+
+/*----------------------------------------------------------------------
+| PLT_LastChangeXMLIterator
++---------------------------------------------------------------------*/
+/**
+ The PLT_LastChangeXMLIterator class is used to serialize the LastChange variable
+ changes into xml given a list of state variables.
+ */
+class PLT_LastChangeXMLIterator
+{
+public:
+ // methods
+ PLT_LastChangeXMLIterator(NPT_XmlElementNode* node) : m_Node(node) {}
+ virtual ~PLT_LastChangeXMLIterator() {}
+
+ NPT_Result operator()(PLT_StateVariable* const & var) const;
+
+private:
+ NPT_XmlElementNode* m_Node;
+};
+
+#endif /* _PLT_SERVICE_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltSsdp.cpp b/lib/libUPnP/Platinum/Source/Core/PltSsdp.cpp
new file mode 100644
index 0000000..fda6f35
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltSsdp.cpp
@@ -0,0 +1,513 @@
+/*****************************************************************
+|
+| Platinum - SSDP
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltSsdp.h"
+#include "PltDatagramStream.h"
+#include "PltDeviceHost.h"
+#include "PltUPnP.h"
+#include "PltHttp.h"
+#include "PltVersion.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.ssdp")
+
+/*----------------------------------------------------------------------
+| PLT_SsdpSender::SendSsdp
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpSender::SendSsdp(NPT_HttpRequest& request,
+ const char* usn,
+ const char* target,
+ NPT_UdpSocket& socket,
+ bool notify,
+ const NPT_SocketAddress* addr /* = NULL */)
+{
+ NPT_CHECK_SEVERE(FormatPacket(request, usn, target, socket, notify));
+
+ // logging
+ NPT_String prefix = NPT_String::Format("Sending SSDP %s packet for %s",
+ (const char*)request.GetMethod(),
+ usn);
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINER, prefix, &request);
+
+ // use a memory stream to write all the data
+ NPT_MemoryStream stream;
+ NPT_Result res = request.Emit(stream);
+ NPT_CHECK(res);
+
+ // copy stream into a data packet and send it
+ NPT_LargeSize size;
+ stream.GetSize(size);
+ if (size != (NPT_Size)size) NPT_CHECK(NPT_ERROR_OUT_OF_RANGE);
+
+ NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size);
+ NPT_CHECK_WARNING(socket.Send(packet, addr));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpSender::SendSsdp
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpSender::SendSsdp(NPT_HttpResponse& response,
+ const char* usn,
+ const char* target,
+ NPT_UdpSocket& socket,
+ bool notify,
+ const NPT_SocketAddress* addr /* = NULL */)
+{
+ NPT_CHECK_SEVERE(FormatPacket(response, usn, target, socket, notify));
+
+ // logging
+ NPT_String prefix = NPT_String::Format("Sending SSDP Response:");
+ PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINER, prefix, &response);
+
+ // use a memory stream to write all the data
+ NPT_MemoryStream stream;
+ NPT_Result res = response.Emit(stream);
+ if (NPT_FAILED(res)) return res;
+
+ // copy stream into a data packet and send it
+ NPT_LargeSize size;
+ stream.GetSize(size);
+ if (size != (NPT_Size)size) NPT_CHECK(NPT_ERROR_OUT_OF_RANGE);
+
+ NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size);
+ NPT_CHECK_WARNING(socket.Send(packet, addr));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpSender::FormatPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpSender::FormatPacket(NPT_HttpMessage& message,
+ const char* usn,
+ const char* target,
+ NPT_UdpSocket& socket,
+ bool notify)
+{
+ NPT_COMPILER_UNUSED(socket);
+
+ PLT_UPnPMessageHelper::SetUSN(message, usn);
+ if (notify) {
+ PLT_UPnPMessageHelper::SetNT(message, target);
+ } else {
+ PLT_UPnPMessageHelper::SetST(message, target);
+ PLT_UPnPMessageHelper::SetDate(message);
+ }
+ //PLT_HttpHelper::SetContentLength(message, 0);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpDeviceSearchResponseInterfaceIterator class
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpDeviceSearchResponseInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const
+{
+ const NPT_SocketAddress* remote_addr = &m_RemoteAddr;
+
+ NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr =
+ net_if->GetAddresses().GetFirstItem();
+ if (!niaddr) return NPT_SUCCESS;
+
+ // don't try to bind on port 1900 or connect will fail later
+ NPT_UdpSocket socket(NPT_SOCKET_FLAG_CANCELLABLE);
+ //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_SsdpDeviceSearchResponseTask::DoRun()
++---------------------------------------------------------------------*/
+void
+PLT_SsdpDeviceSearchResponseTask::DoRun()
+{
+ NPT_List<NPT_NetworkInterface*> if_list;
+ NPT_CHECK_LABEL_WARNING(PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list, true),
+ done);
+
+ if_list.Apply(PLT_SsdpDeviceSearchResponseInterfaceIterator(
+ m_Device,
+ m_RemoteAddr,
+ m_ST));
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+
+done:
+ return;
+}
+
+/*----------------------------------------------------------------------
+| 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_SOCKET_FLAG_CANCELLABLE);
+ NPT_UdpSocket broadcast_socket(NPT_SOCKET_FLAG_CANCELLABLE);
+ NPT_UdpSocket* socket;
+
+ if (m_Broadcast) {
+ url = NPT_HttpUrl((*niaddr).GetBroadcastAddress().ToString(), 1900, "*");
+ socket = &broadcast_socket;
+ } else {
+ url = NPT_HttpUrl("239.255.255.250", 1900, "*");
+ NPT_CHECK_SEVERE(multicast_socket.SetInterface(addr));
+ socket = &multicast_socket;
+ multicast_socket.SetTimeToLive(PLT_Constants::GetInstance().GetAnnounceMulticastTimeToLive());
+ }
+
+ NPT_HttpRequest req(url, "NOTIFY", NPT_HTTP_PROTOCOL_1_1);
+ PLT_HttpHelper::SetHost(req, "239.255.255.250:1900");
+
+ // Location header valid only for ssdp:alive or ssdp:update messages
+ if (m_Type != PLT_ANNOUNCETYPE_BYEBYE) {
+ PLT_UPnPMessageHelper::SetLocation(req, m_Device->GetDescriptionUrl(addr.ToString()));
+ }
+
+ NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_Type));
+
+#if defined(PLATINUM_UPNP_SPECS_STRICT)
+ // delay alive only as we don't want to delay when stopping
+ if (m_Type != PLT_ANNOUNCETYPE_BYEBYE) {
+ NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY_GROUP));
+ }
+
+ NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_Type));
+#endif
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpDeviceAnnounceUnicastTask::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_SsdpDeviceAnnounceTask::DoRun()
+{
+ NPT_List<NPT_NetworkInterface*> if_list;
+
+ while (1) {
+ NPT_CHECK_LABEL_FATAL(PLT_UPnPMessageHelper::GetNetworkInterfaces(if_list, false),
+ cleanup);
+
+ // if we're announcing our arrival, sends a byebye first (NMPR compliance)
+ if (m_IsByeByeFirst == true) {
+ m_IsByeByeFirst = false;
+
+ if (m_ExtraBroadcast) {
+ if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(m_Device, PLT_ANNOUNCETYPE_BYEBYE, true));
+ }
+
+ // multicast now
+ if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(m_Device, PLT_ANNOUNCETYPE_BYEBYE, false));
+
+ // schedule to announce alive in 200 ms
+ if (IsAborting(200)) break;
+ }
+
+ if (m_ExtraBroadcast) {
+ if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(m_Device, PLT_ANNOUNCETYPE_ALIVE, true));
+ }
+
+ // multicast now
+ if_list.Apply(PLT_SsdpAnnounceInterfaceIterator(m_Device, PLT_ANNOUNCETYPE_ALIVE, false));
+
+
+cleanup:
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+ if_list.Clear();
+
+ if (IsAborting((NPT_Timeout)m_Repeat.ToMillis())) break;
+ };
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpListenTask::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpListenTask::GetInputStream(NPT_InputStreamReference& stream)
+{
+ if (!m_Datagram.IsNull()) {
+ stream = m_Datagram;
+ return NPT_SUCCESS;
+ } else {
+ NPT_InputStreamReference input_stream;
+ NPT_Result res = m_Socket->GetInputStream(input_stream);
+ if (NPT_FAILED(res)) {
+ return res;
+ }
+ // for datagrams, we can't simply read from the socket directly
+ // we need to read datagram into a buffer
+ m_Datagram = new PLT_InputDatagramStream((NPT_UdpSocket*)m_Socket);
+ stream = m_Datagram;
+ return NPT_SUCCESS;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpListenTask::GetInfo
++---------------------------------------------------------------------*/
+void
+PLT_SsdpListenTask::DoAbort()
+{
+ PLT_HttpServerSocketTask::DoAbort();
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpListenTask::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpListenTask::GetInfo(NPT_SocketInfo& info)
+{
+ if (m_Datagram.IsNull()) return NPT_FAILURE;
+ return m_Datagram->GetInfo(info);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpListenTask::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpListenTask::SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_COMPILER_UNUSED(response);
+
+ NPT_AutoLock lock(m_Mutex);
+ m_Listeners.Apply(PLT_SsdpPacketListenerIterator(request, context));
+
+ // return error since we don't have anything to respond
+ // as we use a separate task to respond with ssdp
+ return NPT_ERROR_TERMINATED;
+}
+
+/*----------------------------------------------------------------------
+| 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_SsdpSearchTask::~PLT_SsdpSearchTask
++---------------------------------------------------------------------*/
+PLT_SsdpSearchTask::~PLT_SsdpSearchTask()
+{
+ delete m_Socket;
+ delete m_Request;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpSearchTask::DoAbort
++---------------------------------------------------------------------*/
+void
+PLT_SsdpSearchTask::DoAbort()
+{
+ m_Socket->Cancel();
+}
+
+/*----------------------------------------------------------------------
+| 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);
+ if (IsAborting(0))
+ break;
+
+ NPT_System::Sleep(NPT_TimeInterval(.15f));
+ }
+
+ 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;
+}
+
+/*----------------------------------------------------------------------
+| PLT_CtrlPointGetDescriptionTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpSearchTask::ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(request);
+ return m_Listener->ProcessSsdpSearchResponse(res, context, response);
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltSsdp.h b/lib/libUPnP/Platinum/Source/Core/PltSsdp.h
new file mode 100644
index 0000000..0bbbd75
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltSsdp.h
@@ -0,0 +1,389 @@
+/*****************************************************************
+|
+| Platinum - SSDP
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP SSDP
+ */
+
+#ifndef _PLT_SSDP_H_
+#define _PLT_SSDP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltThreadTask.h"
+#include "PltHttpServerTask.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_DeviceHost;
+
+/*----------------------------------------------------------------------
+| PLT_SsdpAnnounceType
++---------------------------------------------------------------------*/
+typedef enum {
+ PLT_ANNOUNCETYPE_BYEBYE,
+ PLT_ANNOUNCETYPE_ALIVE,
+ PLT_ANNOUNCETYPE_UPDATE
+} PLT_SsdpAnnounceType;
+
+/*----------------------------------------------------------------------
+| PLT_SsdpPacketListener class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpPacketListener class is an interface for handling SSDP packets
+ (M-SEARCH and NOTIFY).
+ */
+class PLT_SsdpPacketListener
+{
+public:
+ virtual ~PLT_SsdpPacketListener() {}
+ virtual NPT_Result OnSsdpPacket(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context) = 0;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpSearchResponseListener class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpSearchResponseListener class is an interface for handling SSDP M-SEARCH
+ responses.
+ */
+class PLT_SsdpSearchResponseListener
+{
+public:
+ virtual ~PLT_SsdpSearchResponseListener() {}
+ virtual NPT_Result ProcessSsdpSearchResponse(NPT_Result res,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) = 0;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpSender class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpSender class provides a mechanism to format and send SSDP packets.
+ */
+class PLT_SsdpSender
+{
+public:
+ static NPT_Result SendSsdp(NPT_HttpRequest& request,
+ const char* usn,
+ const char* nt,
+ NPT_UdpSocket& socket,
+ bool notify,
+ const NPT_SocketAddress* addr = NULL);
+
+ static NPT_Result SendSsdp(NPT_HttpResponse& response,
+ const char* usn,
+ const char* nt,
+ NPT_UdpSocket& socket,
+ bool notify,
+ const NPT_SocketAddress* addr = NULL);
+
+private:
+ static NPT_Result FormatPacket(NPT_HttpMessage& message,
+ const char* usn,
+ const char* nt,
+ NPT_UdpSocket& socket,
+ bool notify);
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpDeviceSearchResponseInterfaceIterator class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpDeviceSearchResponseInterfaceIterator class looks for the best network
+ interface to use then sends a SSDP M-SEARCH response.
+ */
+class PLT_SsdpDeviceSearchResponseInterfaceIterator
+{
+public:
+ PLT_SsdpDeviceSearchResponseInterfaceIterator(PLT_DeviceHost* device,
+ NPT_SocketAddress remote_addr,
+ const char* st) :
+ m_Device(device), m_RemoteAddr(remote_addr), m_ST(st) {}
+ virtual ~PLT_SsdpDeviceSearchResponseInterfaceIterator() {}
+
+ NPT_Result operator()(NPT_NetworkInterface*& if_addr) const;
+
+private:
+ PLT_DeviceHost* m_Device;
+ NPT_SocketAddress m_RemoteAddr;
+ NPT_String m_ST;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpDeviceSearchResponseTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpDeviceSearchResponseTask class is used by a PLT_DeviceHost to respond
+ to SSDP M-SEARCH requests from UPnP ControlPoints.
+ */
+class PLT_SsdpDeviceSearchResponseTask : public PLT_ThreadTask
+{
+public:
+ PLT_SsdpDeviceSearchResponseTask(PLT_DeviceHost* device,
+ NPT_SocketAddress remote_addr,
+ const char* st) :
+ m_Device(device), m_RemoteAddr(remote_addr), m_ST(st) {}
+
+protected:
+ ~PLT_SsdpDeviceSearchResponseTask() override {}
+
+ // PLT_ThreadTask methods
+ void DoRun() override;
+
+protected:
+ PLT_DeviceHost* m_Device;
+ NPT_SocketAddress m_RemoteAddr;
+ NPT_String m_ST;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpAnnounceInterfaceIterator class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpAnnounceInterfaceIterator class is used to send SSDP announcements
+ given a list of network interaces.
+ */
+class PLT_SsdpAnnounceInterfaceIterator
+{
+public:
+ PLT_SsdpAnnounceInterfaceIterator(PLT_DeviceHost* device, PLT_SsdpAnnounceType type, bool broadcast = false) :
+ m_Device(device), m_Type(type), m_Broadcast(broadcast) {}
+
+ NPT_Result operator()(NPT_NetworkInterface*& if_addr) const;
+
+private:
+ PLT_DeviceHost* m_Device;
+ PLT_SsdpAnnounceType m_Type;
+ bool m_Broadcast;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpInitMulticastIterator class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpInitMulticastIterator class is used to join a multicast group
+ given a list of IP addresses.
+ */
+class PLT_SsdpInitMulticastIterator
+{
+public:
+ PLT_SsdpInitMulticastIterator(NPT_UdpMulticastSocket* socket) :
+ m_Socket(socket) {}
+
+ NPT_Result operator()(NPT_IpAddress& if_addr) const {
+ NPT_IpAddress addr;
+ addr.ResolveName("239.255.255.250");
+ // OSX bug, since we're reusing the socket, we need to leave group first
+ // before joining it
+ m_Socket->LeaveGroup(addr, if_addr);
+ return m_Socket->JoinGroup(addr, if_addr);
+ }
+
+private:
+ NPT_UdpMulticastSocket* m_Socket;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpDeviceAnnounceTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpDeviceAnnounceTask class is a task to send UPnP Device SSDP announcements
+ (alive or byebye). It can be setup to automatically repeat after an interval.
+ */
+class PLT_SsdpDeviceAnnounceTask : public PLT_ThreadTask
+{
+public:
+ PLT_SsdpDeviceAnnounceTask(PLT_DeviceHost* device,
+ NPT_TimeInterval repeat,
+ bool is_byebye_first = false,
+ bool extra_broadcast = false) :
+ m_Device(device),
+ m_Repeat(repeat),
+ m_IsByeByeFirst(is_byebye_first),
+ m_ExtraBroadcast(extra_broadcast) {}
+
+protected:
+ ~PLT_SsdpDeviceAnnounceTask() override {}
+
+ // PLT_ThreadTask methods
+ void DoRun() override;
+
+protected:
+ PLT_DeviceHost* m_Device;
+ NPT_TimeInterval m_Repeat;
+ bool m_IsByeByeFirst;
+ bool m_ExtraBroadcast;
+};
+
+/*----------------------------------------------------------------------
+| PLT_NetworkInterfaceAddressSearchIterator class
++---------------------------------------------------------------------*/
+/**
+ The PLT_NetworkInterfaceAddressSearchIterator class returns the network interface
+ given an IP address.
+ */
+class PLT_NetworkInterfaceAddressSearchIterator
+{
+public:
+ PLT_NetworkInterfaceAddressSearchIterator(NPT_String ip) : m_Ip(ip) {}
+ virtual ~PLT_NetworkInterfaceAddressSearchIterator() {}
+
+ NPT_Result operator()(NPT_NetworkInterface*& addr) const {
+ NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = addr->GetAddresses().GetFirstItem();
+ if (!niaddr) return NPT_FAILURE;
+
+ return (m_Ip.Compare((*niaddr).GetPrimaryAddress().ToString(), true) == 0) ? NPT_SUCCESS : NPT_FAILURE;
+ }
+
+private:
+ NPT_String m_Ip;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpPacketListenerIterator class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpPacketListenerIterator class iterates through a list of
+ PLT_SsdpPacketListener instances to notify of a new SSDP incoming packet.
+ */
+class PLT_SsdpPacketListenerIterator
+{
+public:
+ PLT_SsdpPacketListenerIterator(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context) :
+ m_Request(request), m_Context(context) {}
+
+ NPT_Result operator()(PLT_SsdpPacketListener*& listener) const {
+ return listener->OnSsdpPacket(m_Request, m_Context);
+ }
+
+private:
+ NPT_HttpRequest& m_Request;
+ const NPT_HttpRequestContext& m_Context;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpListenTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpListenTask class is used to listen for incoming SSDP packets and
+ keep track of a list of PLT_SsdpPacketListener listeners to notify when a new
+ SSDP packet has arrived.
+ */
+class PLT_SsdpListenTask : public PLT_HttpServerSocketTask
+{
+public:
+ PLT_SsdpListenTask(NPT_Socket* socket) :
+ PLT_HttpServerSocketTask(socket, true) {
+ // Change read time out for UDP because iPhone 3.0 seems to hang
+ // after reading everything from the socket even though
+ // more stuff arrived
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+ m_Socket->SetReadTimeout(10000);
+#endif
+ }
+
+ NPT_Result AddListener(PLT_SsdpPacketListener* listener) {
+ NPT_AutoLock lock(m_Mutex);
+ m_Listeners.Add(listener);
+ return NPT_SUCCESS;
+ }
+
+ NPT_Result RemoveListener(PLT_SsdpPacketListener* listener) {
+ NPT_AutoLock lock(m_Mutex);
+ m_Listeners.Remove(listener);
+ return NPT_SUCCESS;
+ }
+
+ // PLT_Task methods
+ void DoAbort() override;
+
+protected:
+ ~PLT_SsdpListenTask() override {}
+
+ // PLT_HttpServerSocketTask methods
+ NPT_Result GetInputStream(NPT_InputStreamReference& stream) override;
+ NPT_Result GetInfo(NPT_SocketInfo& info) override;
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+protected:
+ PLT_InputDatagramStreamReference m_Datagram;
+ NPT_List<PLT_SsdpPacketListener*> m_Listeners;
+ NPT_Mutex m_Mutex;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpSearchTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_SsdpSearchTask class is a task used by a PLT_CtrlPoint to issue a SSDP
+ M-SEARCH request. It can be set to repeat at a certain frequencey.
+ */
+class PLT_SsdpSearchTask : public PLT_ThreadTask
+{
+public:
+ PLT_SsdpSearchTask(NPT_UdpSocket* socket,
+ PLT_SsdpSearchResponseListener* listener,
+ NPT_HttpRequest* request,
+ NPT_TimeInterval frequency = NPT_TimeInterval(0.)); // pass 0 for one time
+
+protected:
+ ~PLT_SsdpSearchTask() override;
+
+ // PLT_ThreadTask methods
+ void DoAbort() override;
+ void DoRun() override;
+
+ virtual NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response);
+
+private:
+ PLT_SsdpSearchResponseListener* m_Listener;
+ NPT_HttpRequest* m_Request;
+ NPT_TimeInterval m_Frequency;
+ bool m_Repeat;
+ NPT_UdpSocket* m_Socket;
+};
+
+#endif /* _PLT_SSDP_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltStateVariable.cpp b/lib/libUPnP/Platinum/Source/Core/PltStateVariable.cpp
new file mode 100644
index 0000000..f733d5c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltStateVariable.cpp
@@ -0,0 +1,269 @@
+/*****************************************************************
+|
+| Platinum - Service State Variable
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltStateVariable.h"
+#include "PltService.h"
+#include "PltUtilities.h"
+#include "PltUPnP.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.statevariable")
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::PLT_StateVariable
++---------------------------------------------------------------------*/
+PLT_StateVariable::PLT_StateVariable(PLT_Service* service) :
+ m_Service(service),
+ m_AllowedValueRange(NULL),
+ m_IsSendingEvents(false),
+ m_IsSendingEventsIndirectly(true),
+ m_ShouldClearOnSend(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::~PLT_StateVariable
++---------------------------------------------------------------------*/
+PLT_StateVariable::~PLT_StateVariable()
+{
+ m_AllowedValues.Apply(NPT_ObjectDeleter<NPT_String>());
+ if (m_AllowedValueRange) delete m_AllowedValueRange;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::GetSCPDXML
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::GetSCPDXML(NPT_XmlElementNode* node)
+{
+ NPT_XmlElementNode* variable = new NPT_XmlElementNode("stateVariable");
+ NPT_CHECK_SEVERE(node->AddChild(variable));
+
+ NPT_CHECK_SEVERE(variable->SetAttribute("sendEvents", m_IsSendingEvents?"yes":"no"));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(variable, "name", m_Name));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(variable, "dataType", m_DataType));
+ if (m_DefaultValue.GetLength()) {
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(variable, "defaultValue", m_DefaultValue));
+ }
+
+ if (m_AllowedValues.GetItemCount()) {
+ NPT_XmlElementNode* allowedValueList = new NPT_XmlElementNode("allowedValueList");
+ NPT_CHECK_SEVERE(variable->AddChild(allowedValueList));
+ for( int l = 0 ; l < (int)m_AllowedValues.GetItemCount(); l++) {
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(allowedValueList, "allowedValue", (*m_AllowedValues[l])));
+ }
+ } else if (m_AllowedValueRange) {
+ NPT_XmlElementNode* range = new NPT_XmlElementNode("allowedValueRange");
+ NPT_CHECK_SEVERE(variable->AddChild(range));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(range, "minimum", NPT_String::FromInteger(m_AllowedValueRange->min_value)));
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(range, "maximum", NPT_String::FromInteger(m_AllowedValueRange->max_value)));
+ if (m_AllowedValueRange->step != -1) {
+ NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(range, "step", NPT_String::FromInteger(m_AllowedValueRange->step)));
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::GetService
++---------------------------------------------------------------------*/
+PLT_Service*
+PLT_StateVariable::GetService()
+{
+ return m_Service;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::IsSendingEvents
++---------------------------------------------------------------------*/
+bool
+PLT_StateVariable::IsSendingEvents(bool indirectly /* = false */)
+{
+ if (indirectly) {
+ return (!m_IsSendingEvents &&
+ !m_Name.StartsWith("A_ARG_TYPE_") &&
+ m_IsSendingEventsIndirectly);
+ }
+
+ return m_IsSendingEvents;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::DisableIndirectEventing
++---------------------------------------------------------------------*/
+void
+PLT_StateVariable::DisableIndirectEventing()
+{
+ m_IsSendingEventsIndirectly = false;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::SetRate
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::SetRate(NPT_TimeInterval rate)
+{
+ if (!IsSendingEvents()) return NPT_FAILURE;
+
+ m_Rate = rate;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::SetValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::SetValue(const char* value, const bool clearonsend /*=false*/)
+{
+ if (value == NULL) {
+ return NPT_FAILURE;
+ }
+
+ // update only if it's different
+ if (m_Value != value) {
+ NPT_Result res = ValidateValue(value);
+ if (NPT_FAILED(res)) {
+ return res;
+ }
+
+ m_Value = value;
+ m_ShouldClearOnSend = clearonsend;
+ m_Service->AddChanged(this);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::IsReadyToPublish
++---------------------------------------------------------------------*/
+bool
+PLT_StateVariable::IsReadyToPublish()
+{
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+
+ if (m_Rate == NPT_TimeStamp() || m_LastEvent + m_Rate <= now ) {
+ m_LastEvent = now;
+ return true;
+ }
+
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::OnSendCompleted
++---------------------------------------------------------------------*/
+void
+PLT_StateVariable::OnSendCompleted()
+{
+ if(m_ShouldClearOnSend)
+ m_Value = m_DefaultValue;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::ValidateValue
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::ValidateValue(const char* value)
+{
+ if (m_DataType.Compare("string", true) == 0) {
+ // if we have a value allowed restriction, make sure the value is in our list
+ if (m_AllowedValues.GetItemCount()) {
+ // look for a comma separated list
+ NPT_String _value = value;
+ NPT_List<NPT_String> values = _value.Split(",");
+ NPT_List<NPT_String>::Iterator val = values.GetFirstItem();
+ while (val) {
+ val->Trim(" ");
+ if (!m_AllowedValues.Find(NPT_StringFinder(*val))) {
+#if defined(NPT_CONFIG_ENABLE_LOGGING)
+ NPT_LOG_WARNING_2("Invalid value of %s for state variable %s",
+ (const char*)*val,
+ (const char*)m_Name);
+ for (unsigned long i=0; i < m_AllowedValues.GetItemCount(); i++) {
+ NPT_String *val2 = *m_AllowedValues.GetItem(i);
+ NPT_LOG_WARNING_1("Allowed: %s", (const char*)*val2);
+ }
+#endif
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+ ++val;
+ }
+ }
+ }
+
+ // TODO: there are more to it than allowed values, we need to test for range, etc..
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::Find
++---------------------------------------------------------------------*/
+PLT_StateVariable*
+PLT_StateVariable::Find(NPT_List<PLT_StateVariable*>& vars, const char* name)
+{
+ PLT_StateVariable* stateVariable = NULL;
+ NPT_ContainerFind(vars, PLT_StateVariableNameFinder(name), stateVariable);
+ return stateVariable;
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::SetExtraAttribute
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::SetExtraAttribute(const char* name, const char* value)
+{
+ return m_ExtraAttributes.Put(NPT_String(name), NPT_String(value));
+}
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable::Serialize
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_StateVariable::Serialize(NPT_XmlElementNode& node)
+{
+ NPT_List<NPT_Map<NPT_String, NPT_String>::Entry*>::Iterator entry =
+ m_ExtraAttributes.GetEntries().GetFirstItem();
+ while (entry) {
+ const NPT_String& key = (*entry)->GetKey();
+ const NPT_String& value = (*entry)->GetValue();
+ node.SetAttribute(key, value);
+ ++entry;
+ }
+ return node.SetAttribute("val", GetValue());
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltStateVariable.h b/lib/libUPnP/Platinum/Source/Core/PltStateVariable.h
new file mode 100644
index 0000000..465e95c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltStateVariable.h
@@ -0,0 +1,231 @@
+/*****************************************************************
+|
+| Platinum - Service State Variable
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP State Variable
+ */
+
+#ifndef _PLT_STATE_VARIABLE_H_
+#define _PLT_STATE_VARIABLE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_Argument;
+class PLT_Service;
+
+/*----------------------------------------------------------------------
+| NPT_AllowedValueRange struct
++---------------------------------------------------------------------*/
+/**
+ The NPT_AllowedValueRange struct holds the min, max and step value allowed of
+ a UPnP Service state variable.
+ */
+typedef struct {
+ NPT_Int32 min_value;
+ NPT_Int32 max_value;
+ NPT_Int32 step;
+} NPT_AllowedValueRange;
+
+/*----------------------------------------------------------------------
+| PLT_StateVariable class
++---------------------------------------------------------------------*/
+/**
+ The PLT_StateVariable class maintains the state of a UPnP Service state variable.
+ It is used by a PLT_DeviceHost instance to notify subscribers of a change or by a
+ subscriber (PLT_CtrlPoint) when a service state variable change notification
+ has been received.
+ */
+class PLT_StateVariable
+{
+public:
+ PLT_StateVariable(PLT_Service* service);
+ ~PLT_StateVariable();
+
+ /**
+ Populate the SCPD xml document with state variable information.
+ @param node XML Element where to insert the state variable XML Element
+ */
+ NPT_Result GetSCPDXML(NPT_XmlElementNode* node);
+
+ /**
+ Return the PLT_Service that this state variable is associated with.
+ @return PLT_Service pointer.
+ */
+ PLT_Service* GetService();
+
+ /**
+ Return whether the state variable is eventable directly or indirectly. A state
+ variable sends events indirectly when part of the "LastChange" state variable.
+ @param indirectly Boolean to test if the state variable is sending events indirectly
+ @return Whether the state variable sends events according to the input flag specified.
+ */
+ bool IsSendingEvents(bool indirectly = false);
+
+ /**
+ Force the state variable to send events directly.
+ */
+ void DisableIndirectEventing();
+
+ /**
+ Certain state variables notifications must not be sent faster than a certain
+ rate according to the UPnP specs. This sets the rate for a given state variable.
+ @param rate time interval to respect between notifications.
+ */
+ NPT_Result SetRate(NPT_TimeInterval rate);
+
+ /**
+ Set the state variable value. The value is first validated to make sure
+ it is an allowed value. Once the value is validated, it is marked for eventing by
+ calling the PLT_Service AddChanged function.
+ @param value new state variable value. Can be a comma separated list of values.
+ @param clearonsend whether the statevariable should be cleared immediatly after sending
+ */
+ NPT_Result SetValue(const char* value, const bool clearonsend = false);
+
+ /**
+ Validate the new value of the state variable.
+ @param value new state variable value. Can be a comma separated list of values.
+ */
+ NPT_Result ValidateValue(const char* value);
+
+ /**
+ Certain state variables require extra xml attributes when serialized.
+ @param name the attribute name
+ @param value the attribute value
+ */
+ NPT_Result SetExtraAttribute(const char* name, const char* value);
+
+ /**
+ Return the state variable name.
+ @return state variable name.
+ */
+ const NPT_String& GetName() const { return m_Name; }
+
+ /**
+ Return the current state variable value.
+ @return state variable current value.
+ */
+ const NPT_String& GetValue() const { return m_Value; }
+
+ /**
+ Return the state variable data type.
+ @return state variable data type.
+ */
+ const NPT_String& GetDataType() const { return m_DataType; }
+
+ /**
+ Return the state variable allowed value range if any.
+ @return state variable value range pointer or null if none.
+ */
+ const NPT_AllowedValueRange* GetAllowedValueRange() const { return m_AllowedValueRange; }
+
+ /**
+ Helper function to return a state variable given a list of state variables
+ and a state variable name.
+ @param vars list of state variables
+ @param name state variable name to look for
+ @return PLT_StateVariable pointer.
+ */
+ static PLT_StateVariable* Find(NPT_List<PLT_StateVariable*>& vars,
+ const char* name);
+
+protected:
+ /**
+ Return whether the state variable value changed and subscribers need to
+ be notified.
+ */
+ bool IsReadyToPublish();
+
+ /**
+ * If this statevariable should clear after sending to all subscribers, clears the value without
+ * eventing the change
+ */
+ void OnSendCompleted();
+
+ /**
+ Serialize the state variable into xml.
+ */
+ NPT_Result Serialize(NPT_XmlElementNode& node);
+
+protected:
+ friend class PLT_Service;
+ friend class PLT_LastChangeXMLIterator;
+
+ //members
+ PLT_Service* m_Service;
+ NPT_AllowedValueRange* m_AllowedValueRange;
+ NPT_String m_Name;
+ NPT_String m_DataType;
+ NPT_String m_DefaultValue;
+ bool m_IsSendingEvents;
+ bool m_IsSendingEventsIndirectly;
+ bool m_ShouldClearOnSend;
+ NPT_TimeInterval m_Rate;
+ NPT_TimeStamp m_LastEvent;
+ NPT_Array<NPT_String*> m_AllowedValues;
+ NPT_String m_Value;
+
+ NPT_Map<NPT_String,NPT_String> m_ExtraAttributes;
+};
+
+/*----------------------------------------------------------------------
+| PLT_StateVariableNameFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_StateVariableNameFinder class returns the PLT_StateVariable instance
+ given a state variable name.
+ */
+class PLT_StateVariableNameFinder
+{
+public:
+ // methods
+ PLT_StateVariableNameFinder(const char* name) : m_Name(name) {}
+ virtual ~PLT_StateVariableNameFinder() {}
+
+ bool operator()(const PLT_StateVariable* const & state_variable) const {
+ return state_variable->GetName().Compare(m_Name, true) ? false : true;
+ }
+
+private:
+ // members
+ NPT_String m_Name;
+};
+
+#endif /* _PLT_STATE_VARIABLE_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltTaskManager.cpp b/lib/libUPnP/Platinum/Source/Core/PltTaskManager.cpp
new file mode 100644
index 0000000..368a057
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltTaskManager.cpp
@@ -0,0 +1,236 @@
+/*****************************************************************
+|
+| Platinum - Task Manager
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltThreadTask.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.taskmanager")
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager::PLT_TaskManager
++---------------------------------------------------------------------*/
+PLT_TaskManager::PLT_TaskManager(NPT_Cardinal max_items /* = 0 */) :
+ m_Queue(NULL),
+ m_MaxTasks(max_items),
+ m_RunningTasks(0),
+ m_Stopping(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager::~PLT_TaskManager
++---------------------------------------------------------------------*/
+PLT_TaskManager::~PLT_TaskManager()
+{
+ Abort();
+}
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager::StartTask
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_TaskManager::StartTask(PLT_ThreadTask* task,
+ NPT_TimeInterval* delay /* = NULL*/,
+ bool auto_destroy /* = true */)
+{
+ NPT_CHECK_POINTER_SEVERE(task);
+ return task->Start(this, delay, auto_destroy);
+}
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager::Reset
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_TaskManager::Reset()
+{
+ NPT_AutoLock lock(m_TasksLock);
+ m_Stopping = false;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager::Abort
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_TaskManager::Abort()
+{
+ NPT_Cardinal num_running_tasks;
+
+ do {
+ {
+ NPT_AutoLock lock(m_TasksLock);
+
+ m_Stopping = true;
+
+ // unblock the queue if any by deleting it
+ if (m_Queue) {
+ int* val = NULL;
+ while(NPT_SUCCEEDED(m_Queue->Pop(val, 0))) delete val;
+
+ delete m_Queue;
+ m_Queue = NULL;
+ }
+ }
+
+ // abort all running tasks
+ {
+ NPT_AutoLock lock(m_TasksLock);
+
+ NPT_List<PLT_ThreadTask*>::Iterator task = m_Tasks.GetFirstItem();
+ while (task) {
+ // stop task if it's not already stopping
+ if (!(*task)->IsAborting(0)) {
+ (*task)->Stop(false);
+ }
+ ++task;
+ }
+
+ num_running_tasks = m_Tasks.GetItemCount();
+ }
+
+ if (num_running_tasks == 0)
+ break;
+
+ NPT_System::Sleep(NPT_TimeInterval(0.05));
+ } while (1);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager::AddTask
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_TaskManager::AddTask(PLT_ThreadTask* task)
+{
+ NPT_Result result = NPT_SUCCESS;
+ int *val = NULL;
+
+ // verify we're not stopping or maxed out number of running tasks
+ do {
+ m_TasksLock.Lock();
+
+ // returning an error if we're stopping
+ if (m_Stopping) {
+ m_TasksLock.Unlock();
+ delete val;
+ if (task->m_AutoDestroy) delete task;
+ NPT_CHECK_WARNING(NPT_ERROR_INTERRUPTED);
+ }
+
+ if (m_MaxTasks) {
+ val = val?val:new int;
+
+ if (!m_Queue) {
+ m_Queue = new NPT_Queue<int>(m_MaxTasks);
+ }
+
+
+ // try to add to queue but don't block forever if queue is full
+ result = m_Queue->Push(val, 20);
+ if (NPT_SUCCEEDED(result)) break;
+
+ // release lock if it's a failure
+ // this gives a chance for the taskmanager
+ // to abort the queue if full
+ m_TasksLock.Unlock();
+
+ // if it failed due to something other than a timeout
+ // it probably means the queue is aborting
+ if (result != NPT_ERROR_TIMEOUT) {
+ delete val;
+ if (task->m_AutoDestroy) delete task;
+ NPT_CHECK_WARNING(result);
+ }
+ }
+ } while (result == NPT_ERROR_TIMEOUT);
+
+ // start task now
+ if (NPT_FAILED(result = task->StartThread())) {
+ m_TasksLock.Unlock();
+
+ // Remove task from queue and delete task if autodestroy is set
+ RemoveTask(task);
+
+ return result;
+ }
+
+ NPT_LOG_FINER_3("[TaskManager 0x%p] %d/%d running tasks", (void*)this, ++m_RunningTasks, m_MaxTasks);
+
+ // keep track of running task
+ result = m_Tasks.Add(task);
+
+ m_TasksLock.Unlock();
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager::RemoveTask
++---------------------------------------------------------------------*/
+// called by a PLT_ThreadTask::Run when done
+NPT_Result
+PLT_TaskManager::RemoveTask(PLT_ThreadTask* task)
+{
+ NPT_Result result = NPT_SUCCESS;
+
+ {
+ NPT_AutoLock lock(m_TasksLock);
+
+ if (m_Queue) {
+ int* val = NULL;
+ result = m_Queue->Pop(val, 100);
+
+ // if for some reason the queue is empty, don't block forever
+ if (NPT_SUCCEEDED(result)) {
+ delete val;
+ } else {
+ NPT_LOG_WARNING_1("Failed to pop task from queue %d", result);
+ }
+ }
+
+ NPT_LOG_FINER_3("[TaskManager 0x%p] %d/%d running tasks", (void*)this, --m_RunningTasks, m_MaxTasks);
+ m_Tasks.Remove(task);
+ }
+
+ // cleanup task only if auto-destroy flag was set
+ // otherwise it's the owner's responsability to
+ // clean it up
+ if (task->m_AutoDestroy) delete task;
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltTaskManager.h b/lib/libUPnP/Platinum/Source/Core/PltTaskManager.h
new file mode 100644
index 0000000..aa1a58d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltTaskManager.h
@@ -0,0 +1,116 @@
+/*****************************************************************
+|
+| Platinum - Task Manager
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ Runnable Tasks Manager
+ */
+
+#ifndef _PLT_TASKMANAGER_H_
+#define _PLT_TASKMANAGER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_ThreadTask;
+
+/*----------------------------------------------------------------------
+| PLT_TaskManager class
++---------------------------------------------------------------------*/
+/**
+ The PLT_TaskManager class maintains a list of runnable tasks. During shutdown, it
+ can stop all running tasks. Additionally, it can limit the number of
+ tasks that can run at any given time.
+ */
+class PLT_TaskManager
+{
+public:
+ /**
+ Create a new Task Manager.
+ @param max_tasks Maximum number of concurrent tasks that the task manager
+ will allow. When the value is reached, a thread calling AddTask will block until
+ a task has finished.
+ */
+ PLT_TaskManager(NPT_Cardinal max_tasks = 0);
+ virtual ~PLT_TaskManager();
+
+ /**
+ Start a new new task and associates it with this task manager.
+ @param task new task
+ @param delay optional time interval to wait before launching the new task
+ @param auto_destroy a flag to indicate if the task is owned by someone else
+ and thus should not destroy itself when done.
+ */
+ virtual NPT_Result StartTask(PLT_ThreadTask* task,
+ NPT_TimeInterval* delay = NULL,
+ bool auto_destroy = true);
+
+ /**
+ Stop all tasks associated with this task manager.
+ */
+ NPT_Result Abort();
+
+ /**
+ Reset task manager after an Abort so new tasks can be queued.
+ */
+ NPT_Result Reset();
+
+ /**
+ Returns the max number of concurrent tasks allowed. 0 for no limit.
+ */
+ NPT_Cardinal GetMaxTasks() { return m_MaxTasks; }
+
+private:
+ friend class PLT_ThreadTask;
+
+ // called by PLT_ThreadTask
+ NPT_Result AddTask(PLT_ThreadTask* task);
+ NPT_Result RemoveTask(PLT_ThreadTask* task);
+
+private:
+ NPT_List<PLT_ThreadTask*> m_Tasks;
+ NPT_Mutex m_TasksLock;
+ NPT_Queue<int>* m_Queue;
+ NPT_Cardinal m_MaxTasks;
+ NPT_Cardinal m_RunningTasks;
+ bool m_Stopping;
+};
+
+typedef NPT_Reference<PLT_TaskManager> PLT_TaskManagerReference;
+
+#endif /* _PLT_TASKMANAGER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltThreadTask.cpp b/lib/libUPnP/Platinum/Source/Core/PltThreadTask.cpp
new file mode 100644
index 0000000..1ae6064
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltThreadTask.cpp
@@ -0,0 +1,190 @@
+/*****************************************************************
+|
+| Platinum - Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltThreadTask.h"
+#include "PltTaskManager.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.threadtask")
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask::PLT_ThreadTask
++---------------------------------------------------------------------*/
+PLT_ThreadTask::PLT_ThreadTask() :
+ m_TaskManager(NULL),
+ m_Thread(NULL),
+ m_AutoDestroy(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask::~PLT_ThreadTask
++---------------------------------------------------------------------*/
+PLT_ThreadTask::~PLT_ThreadTask()
+{
+ if (!m_AutoDestroy) delete m_Thread;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTask::Start(PLT_TaskManager* task_manager,/* = NULL */
+ NPT_TimeInterval* delay, /* = NULL */
+ bool auto_destroy /* = true */)
+{
+ m_Abort.SetValue(0);
+ m_AutoDestroy = auto_destroy;
+ m_Delay = delay?*delay:NPT_TimeStamp(0.);
+ m_TaskManager = task_manager;
+
+ if (m_TaskManager) {
+ NPT_CHECK_SEVERE(m_TaskManager->AddTask(this));
+ return NPT_SUCCESS;
+ } else {
+ NPT_Result result = StartThread();
+
+ // suicide now if task is to auto destroy when finish
+ if (NPT_FAILED(result) && m_AutoDestroy) {
+ delete this;
+ }
+ return result;
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask::StartThread
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTask::StartThread()
+{
+ m_Started.SetValue(0);
+
+ m_Thread = new NPT_Thread((NPT_Runnable&)*this, m_AutoDestroy);
+ NPT_Result result = m_Thread->Start();
+ if (NPT_FAILED(result)) {
+
+ // delete thread manually in case m_AutoDestroy was true
+ if (m_AutoDestroy) {
+ delete m_Thread;
+ m_Thread = NULL;
+ }
+
+ NPT_CHECK_FATAL(result);
+ }
+
+ return m_Started.WaitUntilEquals(1, NPT_TIMEOUT_INFINITE);
+}
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTask::Stop(bool blocking /* = true */)
+{
+ // keep variable around in case
+ // we get destroyed
+ bool auto_destroy = m_AutoDestroy;
+
+ // tell thread we want to die
+ m_Abort.SetValue(1);
+ DoAbort();
+
+ // return without waiting if non blocking or not started
+ if (!blocking || !m_Thread) return NPT_SUCCESS;
+
+ // if auto-destroy, the thread may be already dead by now
+ // so we can't wait on m_Thread.
+ // only Task Manager will know when task is finished
+ return auto_destroy?NPT_FAILURE:m_Thread->Wait();
+}
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask::Kill
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ThreadTask::Kill()
+{
+ Stop();
+
+ // A task can only be destroyed manually
+ // when the m_AutoDestroy is false
+ // otherwise the Task Manager takes
+ // care of deleting it when the thread exits
+ NPT_ASSERT(m_AutoDestroy == false);
+ if (!m_AutoDestroy) delete this;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask::Run
++---------------------------------------------------------------------*/
+void
+PLT_ThreadTask::Run()
+{
+ m_Started.SetValue(1);
+
+ // wait before starting task if necessary
+ if ((float)m_Delay > 0.f) {
+ // more than 100ms, loop so we can abort it
+ if ((float)m_Delay > 0.1f) {
+ NPT_TimeStamp start, now;
+ NPT_System::GetCurrentTimeStamp(start);
+ do {
+ NPT_System::GetCurrentTimeStamp(now);
+ if (now >= start + m_Delay) break;
+ } while (!IsAborting(100));
+ } else {
+ NPT_System::Sleep(m_Delay);
+ }
+ }
+
+ // loop
+ if (!IsAborting(0)) {
+ DoInit();
+ DoRun();
+ }
+
+ // notify the Task Manager we're done
+ // it will destroy us if m_AutoDestroy is true
+ if (m_TaskManager) {
+ m_TaskManager->RemoveTask(this);
+ } else if (m_AutoDestroy) {
+ // destroy ourselves otherwise
+ delete this;
+ }
+}
diff --git a/lib/libUPnP/Platinum/Source/Core/PltThreadTask.h b/lib/libUPnP/Platinum/Source/Core/PltThreadTask.h
new file mode 100644
index 0000000..49bda3d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltThreadTask.h
@@ -0,0 +1,140 @@
+/*****************************************************************
+|
+| Platinum - Thread Tasks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ Runnable Task
+ */
+
+#ifndef _PLT_THREADTASK_H_
+#define _PLT_THREADTASK_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltTaskManager.h"
+
+/*----------------------------------------------------------------------
+| PLT_ThreadTask class
++---------------------------------------------------------------------*/
+/**
+ The PLT_ThreadTask class is a base class for executing a given task in a worker
+ thread. A PLT_ThreadTask is usually always associated to a PLT_TaskManager
+ which maintains a list to stop and destroy tasks when finished.
+ */
+class PLT_ThreadTask : public NPT_Runnable
+{
+public:
+ friend class PLT_TaskManager;
+
+ /**
+ When a task is not managed by a PLT_TaskManager, the owner must call
+ this to stop and destroy it.
+ */
+ NPT_Result Kill();
+
+protected:
+ /**
+ Return whether this task is in the process of stopping.
+ @param timeout number of milliseconds to wait
+ @return boolean indicating if the task is stopping
+ */
+ virtual bool IsAborting(NPT_Timeout timeout) {
+ return NPT_SUCCEEDED(m_Abort.WaitUntilEquals(1, timeout));
+ }
+
+ /**
+ Start a task by associating it with a task manager.
+ @param task_manager PLT_TaskManager pointer
+ @param delay optional time interval to wait before launching the new task
+ @param auto_destroy a flag to indicate if the task is owned by someone else
+ and thus should not destroy itself when done.
+ */
+ NPT_Result Start(PLT_TaskManager* task_manager = NULL,
+ NPT_TimeInterval* delay = NULL,
+ bool auto_destroy = true);
+ /**
+ Stop the task. This is either called by a task manager or the Kill method.
+ @param blocking Whether the method should block until the task has finished.
+ */
+ NPT_Result Stop(bool blocking = true);
+
+ /**
+ This method to override in derived classes is called when the task is about
+ to start.
+ */
+ virtual void DoInit() {}
+
+ /**
+ This method to override in derived classes is called when the task is about
+ to stop.
+ */
+ virtual void DoAbort() {}
+
+ /**
+ This method to override in derived classes is the main task loop.
+ */
+ virtual void DoRun() {}
+
+ /**
+ A PLT_ThreadTask base class is never instantiated directly.
+ */
+ PLT_ThreadTask();
+
+ /**
+ The task manager will destroy the task when finished if m_AutoDestroy is
+ true otherwise the owner of this task must use the Kill method.
+ */
+ ~PLT_ThreadTask() override;
+
+private:
+ NPT_Result StartThread();
+
+ // NPT_Thread methods
+ void Run() override;
+
+protected:
+ // members
+ PLT_TaskManager* m_TaskManager;
+
+private:
+ // members
+ NPT_SharedVariable m_Started;
+ NPT_SharedVariable m_Abort;
+ NPT_Thread* m_Thread;
+ bool m_AutoDestroy;
+ NPT_TimeInterval m_Delay;
+};
+
+#endif /* _PLT_THREADTASK_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp b/lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp
new file mode 100644
index 0000000..e0b1e8b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp
@@ -0,0 +1,298 @@
+/*****************************************************************
+|
+| Platinum - UPnP Engine
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltVersion.h"
+#include "PltUPnP.h"
+#include "PltDeviceHost.h"
+#include "PltCtrlPoint.h"
+#include "PltSsdp.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.upnp")
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_CtrlPointStartIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_CtrlPointStartIterator
+{
+public:
+ PLT_UPnP_CtrlPointStartIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_CtrlPointStartIterator() {}
+
+ NPT_Result operator()(PLT_CtrlPointReference& ctrl_point) const {
+ NPT_CHECK_SEVERE(ctrl_point->Start(m_ListenTask));
+ return NPT_SUCCESS;
+ }
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_CtrlPointStopIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_CtrlPointStopIterator
+{
+public:
+ PLT_UPnP_CtrlPointStopIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_CtrlPointStopIterator() {}
+
+ NPT_Result operator()(PLT_CtrlPointReference& ctrl_point) const {
+ return ctrl_point->Stop(m_ListenTask);
+ }
+
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_DeviceStartIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_DeviceStartIterator
+{
+public:
+ PLT_UPnP_DeviceStartIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_DeviceStartIterator() {}
+
+ NPT_Result operator()(PLT_DeviceHostReference& device_host) const {
+
+ // We should always increment the boot id on restart
+ // so it is used in place of boot id during initial announcement
+ device_host->SetBootId(device_host->GenerateNextBootId());
+ device_host->SetNextBootId(0);
+
+ NPT_CHECK_SEVERE(device_host->Start(m_ListenTask));
+ return NPT_SUCCESS;
+ }
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_DeviceStopIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_DeviceStopIterator
+{
+public:
+ PLT_UPnP_DeviceStopIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_DeviceStopIterator() {}
+
+ NPT_Result operator()(PLT_DeviceHostReference& device_host) const {
+ return device_host->Stop(m_ListenTask);
+ }
+
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::PLT_UPnP
++---------------------------------------------------------------------*/
+PLT_UPnP::PLT_UPnP() :
+ m_TaskManager(NULL),
+ m_Started(false),
+ m_SsdpListenTask(NULL),
+ m_IgnoreLocalUUIDs(true)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::~PLT_UPnP
++---------------------------------------------------------------------*/
+PLT_UPnP::~PLT_UPnP()
+{
+ Stop();
+
+ m_CtrlPoints.Clear();
+ m_Devices.Clear();
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::Start()
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::Start()
+{
+ NPT_LOG_INFO("Starting UPnP...");
+
+ NPT_AutoLock lock(m_Lock);
+
+ if (m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ NPT_List<NPT_IpAddress> ips;
+ PLT_UPnPMessageHelper::GetIPAddresses(ips);
+
+ /* Create multicast socket and bind on 1900. If other apps didn't
+ play nicely by setting the REUSE_ADDR flag, this could fail */
+ NPT_Reference<NPT_UdpMulticastSocket> socket(new NPT_UdpMulticastSocket(NPT_SOCKET_FLAG_CANCELLABLE));
+ NPT_CHECK_SEVERE(socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900), true));
+
+ /* Join multicast group for every ip we found */
+ NPT_CHECK_SEVERE(ips.ApplyUntil(PLT_SsdpInitMulticastIterator(socket.AsPointer()),
+ NPT_UntilResultNotEquals(NPT_SUCCESS)));
+
+ /* create the ssdp listener */
+ m_SsdpListenTask = new PLT_SsdpListenTask(socket.AsPointer());
+ socket.Detach();
+ NPT_Reference<PLT_TaskManager> taskManager(new PLT_TaskManager());
+ NPT_CHECK_SEVERE(taskManager->StartTask(m_SsdpListenTask));
+
+ /* start devices & ctrlpoints */
+ m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStartIterator(m_SsdpListenTask));
+ m_Devices.Apply(PLT_UPnP_DeviceStartIterator(m_SsdpListenTask));
+
+ m_TaskManager = taskManager;
+ m_Started = true;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::Stop()
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ NPT_LOG_INFO("Stopping UPnP...");
+
+ // Stop ctrlpoints and devices first
+ m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStopIterator(m_SsdpListenTask));
+ m_Devices.Apply(PLT_UPnP_DeviceStopIterator(m_SsdpListenTask));
+
+ // stop remaining tasks
+ m_TaskManager->Abort();
+ m_SsdpListenTask = NULL;
+ m_TaskManager = NULL;
+
+ m_Started = false;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::AddDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::AddDevice(PLT_DeviceHostReference& device)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // tell all our controllers to ignore this device
+ if (m_IgnoreLocalUUIDs) {
+ for (NPT_List<PLT_CtrlPointReference>::Iterator iter =
+ m_CtrlPoints.GetFirstItem();
+ iter;
+ iter++) {
+ (*iter)->IgnoreUUID(device->GetUUID());
+ }
+ }
+
+ if (m_Started) {
+ NPT_LOG_INFO("Starting Device...");
+ NPT_CHECK_SEVERE(device->Start(m_SsdpListenTask));
+ }
+
+ m_Devices.Add(device);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::RemoveDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::RemoveDevice(PLT_DeviceHostReference& device)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (m_Started) {
+ device->Stop(m_SsdpListenTask);
+ }
+
+ return m_Devices.Remove(device);
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::AddCtrlPoint
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::AddCtrlPoint(PLT_CtrlPointReference& ctrl_point)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // tell the control point to ignore our own running devices
+ if (m_IgnoreLocalUUIDs) {
+ for (NPT_List<PLT_DeviceHostReference>::Iterator iter =
+ m_Devices.GetFirstItem();
+ iter;
+ iter++) {
+ ctrl_point->IgnoreUUID((*iter)->GetUUID());
+ }
+ }
+
+ if (m_Started) {
+ NPT_LOG_INFO("Starting Ctrlpoint...");
+ NPT_CHECK_SEVERE(ctrl_point->Start(m_SsdpListenTask));
+ }
+
+ m_CtrlPoints.Add(ctrl_point);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::RemoveCtrlPoint
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::RemoveCtrlPoint(PLT_CtrlPointReference& ctrl_point)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (m_Started) {
+ ctrl_point->Stop(m_SsdpListenTask);
+ }
+
+ return m_CtrlPoints.Remove(ctrl_point);
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Core/PltUPnP.h b/lib/libUPnP/Platinum/Source/Core/PltUPnP.h
new file mode 100644
index 0000000..7822bf3
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltUPnP.h
@@ -0,0 +1,143 @@
+/*****************************************************************
+|
+| Platinum - UPnP Engine
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Devices and ControlPoints Manager
+ */
+
+#ifndef _PLT_UPNP_H_
+#define _PLT_UPNP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltCtrlPoint.h"
+#include "PltDeviceHost.h"
+#include "PltUtilities.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define PLT_DLNA_SSDP_DELAY 0.05f
+#define PLT_DLNA_SSDP_DELAY_GROUP 0.2f
+
+/*----------------------------------------------------------------------
+| forward definitions
++---------------------------------------------------------------------*/
+class PLT_SsdpListenTask;
+
+/*----------------------------------------------------------------------
+| PLT_UPnP class
++---------------------------------------------------------------------*/
+/**
+ The PLT_UPnP class maintains a list of devices (PLT_DeviceHost) to advertise and/or
+ control points (PLT_CtrlPoint).
+ */
+class PLT_UPnP
+{
+public:
+ /**
+ Create a UPnP instance.
+ */
+ PLT_UPnP();
+ ~PLT_UPnP();
+
+ /**
+ Add and start a device inside this UPnP context.
+ @param device device to start.
+ */
+ NPT_Result AddDevice(PLT_DeviceHostReference& device);
+
+ /**
+ Add and start a control point inside this UPnP context.
+ @param ctrlpoint control point to start.
+ */
+ NPT_Result AddCtrlPoint(PLT_CtrlPointReference& ctrlpoint);
+
+ /**
+ Remove an existing device from this UPnP context.
+ @param device device to stop.
+ */
+ NPT_Result RemoveDevice(PLT_DeviceHostReference& device);
+
+ /**
+ Remove an existing control point from this UPnP context.
+ @param ctrlpoint control point to stop.
+ */
+ NPT_Result RemoveCtrlPoint(PLT_CtrlPointReference& ctrlpoint);
+
+ /**
+ Start the UPnP context and all existing devices and control points
+ associated with it.
+ */
+ NPT_Result Start();
+
+ /**
+ Stop the UPnP context and all existing devices and control points
+ associated with it.
+ */
+ NPT_Result Stop();
+
+ /**
+ Return the UPnP Engine state.
+ @return True if the UPnP engine is running.
+ */
+ bool IsRunning() { return m_Started; }
+
+ /**
+ When a device and a control point are added to the same UPnP context, it is
+ desired that the device be not discovered by the control point. For example when
+ creating a combo UPnP Renderer/CtrlPoint. This methods tells the control point
+ to ignore devices associated with the same UPnP context.
+ @param ignore boolean to ignore devices in context
+ */
+ void SetIgnoreLocalUUIDs(bool ignore) { m_IgnoreLocalUUIDs = ignore; }
+
+private:
+ // members
+ NPT_Mutex m_Lock;
+ NPT_List<PLT_DeviceHostReference> m_Devices;
+ NPT_List<PLT_CtrlPointReference> m_CtrlPoints;
+ NPT_Reference<PLT_TaskManager> m_TaskManager;
+
+ // Since we can only have one socket listening on port 1900,
+ // we create it in here and we will attach every control points
+ // and devices to it when they're added
+ bool m_Started;
+ PLT_SsdpListenTask* m_SsdpListenTask;
+ bool m_IgnoreLocalUUIDs;
+};
+
+#endif /* _PLT_UPNP_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Core/PltUtilities.h b/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
new file mode 100644
index 0000000..4677f5b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltUtilities.h
@@ -0,0 +1,766 @@
+/*****************************************************************
+|
+| Platinum - Utilities
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_UTILITIES_H_
+#define _PLT_UTILITIES_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_XmlAttributeFinder
++---------------------------------------------------------------------*/
+/**
+ The PLT_XmlAttributeFinder class is used to determine if an attribute
+ exists given an xml element node, an attribute name and namespace.
+ */
+class PLT_XmlAttributeFinder
+{
+public:
+ // if 'namespc' is NULL, we're looking for ANY namespace
+ // if 'namespc' is '\0', we're looking for NO namespace
+ // if 'namespc' is non-empty, look for that SPECIFIC namespace
+ PLT_XmlAttributeFinder(const NPT_XmlElementNode& element,
+ const char* name,
+ const char* namespc) :
+ m_Element(element), m_Name(name), m_Namespace(namespc) {}
+
+ bool operator()(const NPT_XmlAttribute* const & attribute) const {
+ if (attribute->GetName() == m_Name) {
+ if (m_Namespace) {
+ const NPT_String& prefix = attribute->GetPrefix();
+ if (m_Namespace[0] == '\0') {
+ // match if the attribute has NO namespace
+ return prefix.IsEmpty();
+ } else {
+ // match if the attribute has the SPECIFIC namespace
+ // we're looking for
+ const NPT_String* namespc = m_Element.GetNamespaceUri(prefix);
+ return namespc && *namespc == m_Namespace;
+ }
+ } else {
+ // ANY namespace will match
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+private:
+ const NPT_XmlElementNode& m_Element;
+ const char* m_Name;
+ const char* m_Namespace;
+};
+
+/*----------------------------------------------------------------------
+| PLT_XmlHelper
++---------------------------------------------------------------------*/
+/**
+ The PLT_XmlHelper class is a set of utility functions for manipulating
+ xml documents and DOM trees.
+ */
+class PLT_XmlHelper
+{
+public:
+
+ // static methods
+
+ static NPT_Result Parse(const NPT_String& xml, NPT_XmlElementNode*& tree) {
+ // reset tree
+ tree = NULL;
+
+ // parse body
+ NPT_XmlParser parser;
+ NPT_XmlNode* node;
+ NPT_Result result = parser.Parse(xml, node);
+ if (NPT_FAILED(result)) {
+ //NPT_LOG_FINEST_1("Failed to parse %s", xml.IsEmpty()?"(empty string)":xml.GetChars());
+ NPT_CHECK(result);
+ }
+
+ tree = node->AsElementNode();
+ if (!tree) {
+ delete node;
+ return NPT_FAILURE;
+ }
+
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result GetChildText(NPT_XmlElementNode* node,
+ const char* tag,
+ NPT_String& value,
+ const char* namespc = "",
+ NPT_Cardinal max_size = 1024) {
+ value = "";
+
+ if (!node) return NPT_FAILURE;
+
+ // special case "" means we look for the same namespace as the parent
+ if (namespc && namespc[0] == '\0') {
+ namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+ }
+
+ NPT_XmlElementNode* child = node->GetChild(tag, namespc);
+ if (!child) return NPT_FAILURE;
+
+ const NPT_String* text = child->GetText();
+ // DLNA 7.3.17
+ if (text)
+ value = text->SubString(0, max_size);
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result RemoveAttribute(NPT_XmlElementNode* node,
+ const char* name,
+ const char* namespc = "") {
+ if (!node) return NPT_FAILURE;
+
+ // special case "" means we look for the same namespace as the parent
+ if (namespc && namespc[0] == '\0') {
+ namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+ }
+
+ NPT_List<NPT_XmlAttribute*>::Iterator attribute;
+ attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
+ if (!attribute) return NPT_FAILURE;
+
+ delete *attribute;
+ NPT_CHECK(node->GetAttributes().Erase(attribute));
+
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result GetAttribute(NPT_XmlElementNode* node,
+ const char* name,
+ NPT_XmlAttribute*& attr,
+ const char* namespc = "") {
+ attr = NULL;
+
+ if (!node) return NPT_FAILURE;
+
+ // special case "" means we look for the same namespace as the parent
+ if (namespc && namespc[0] == '\0') {
+ namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+ }
+
+ NPT_List<NPT_XmlAttribute*>::Iterator attribute;
+ attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
+ if (!attribute) {
+ //NPT_Debug("Failed to find attribute [%s]:%s", namespc, name);
+ return NPT_FAILURE;
+ }
+
+ attr = (*attribute);
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result GetAttribute(NPT_XmlElementNode* node,
+ const char* name,
+ NPT_String& value,
+ const char* namespc = "",
+ NPT_Cardinal max_size = 1024) {
+ value = "";
+
+ NPT_XmlAttribute* attribute = NULL;
+ NPT_Result result = GetAttribute(node, name, attribute, namespc);
+ if (NPT_FAILED(result)) return result;
+
+ if (!attribute) return NPT_FAILURE;
+ // DLNA 7.3.17 truncate to 1024 bytes
+ value = attribute->GetValue().SubString(0, max_size);
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result SetAttribute(NPT_XmlElementNode* node,
+ const char* name,
+ const char* value,
+ const char* namespc = "") {
+ NPT_XmlAttribute* attribute = NULL;
+ NPT_CHECK(GetAttribute(node, name, attribute, namespc));
+ if (!attribute) return NPT_FAILURE;
+
+ attribute->SetValue(value);
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result AddChildText(NPT_XmlElementNode* node,
+ const char* tag,
+ const char* text,
+ const char* prefix = NULL) {
+ if (!node) return NPT_FAILURE;
+ NPT_XmlElementNode* child = new NPT_XmlElementNode(prefix, tag);
+ child->AddText(text);
+ return node->AddChild(child);
+ }
+
+ static bool IsMatch(const NPT_XmlNode* const & node, const char* tag, const char* namespc_mapped) {
+ // if m_Namespace is NULL, we're looking for ANY namespace
+ // if m_Namespace is '\0', we're looking for NO namespace
+ // if m_Namespace is non-empty, look for that SPECIFIC namespace
+
+ const NPT_XmlElementNode* element = node->AsElementNode();
+ // is tag the same (case sensitive)?
+ if (element && element->GetTag() == tag) {
+ if (namespc_mapped) {
+ // look for a SPECIFIC namespace or NO namespace
+ const NPT_String* namespc = element->GetNamespace();
+ if (namespc) {
+ // the element has a namespace, match if it is equal to
+ // what we're looking for
+ return *namespc == namespc_mapped;
+ } else {
+ // the element does not have a namespace, match if we're
+ // looking for NO namespace
+ return namespc_mapped[0] == '\0';
+ }
+ } else {
+ // ANY namespace will match
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static NPT_Result GetChildren(NPT_XmlElementNode* node,
+ NPT_Array<NPT_XmlElementNode*>& children,
+ const char* tag,
+ const char* namespc = "") {
+ if (!node) return NPT_FAILURE;
+
+ // special case "" means we look for the same namespace as the parent
+ if (namespc && namespc[0] == '\0') {
+ namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+ }
+
+ const char* namespc_mapped = (namespc==NULL)?"":(namespc[0]=='*' && namespc[1]=='\0')?NULL:namespc;
+
+ // get all children first
+ NPT_List<NPT_XmlNode*>& allchildren = node->GetChildren();
+
+ // iterate through children and add only elements with matching tag
+ NPT_List<NPT_XmlNode*>::Iterator child = allchildren.GetFirstItem();
+ while (child) {
+ if (IsMatch(*child, tag, namespc_mapped)) {
+ children.Add((*child)->AsElementNode());
+ }
+ ++child;
+ }
+ return NPT_SUCCESS;
+ }
+
+ static NPT_XmlElementNode* GetChild(NPT_XmlElementNode* node,
+ const char* tag,
+ const char* namespc = "") {
+ if (!node) return NULL;
+
+ // special case "" means we look for the same namespace as the parent
+ if (namespc && namespc[0] == '\0') {
+ namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
+ }
+
+ return node->GetChild(tag, namespc);
+ }
+
+ static NPT_Result GetChild(NPT_XmlElementNode* parent,
+ NPT_XmlElementNode*& child,
+ NPT_Ordinal n = 0) {
+ if (!parent) return NPT_FAILURE;
+
+ // reset child
+ child = NULL;
+
+ // get all children first
+ NPT_List<NPT_XmlNode*>::Iterator children = parent->GetChildren().GetFirstItem();
+ while (children) {
+ if ((*children)->AsElementNode() && n-- == 0) {
+ child = (*children)->AsElementNode();
+ return NPT_SUCCESS;
+ }
+ children++;
+ }
+
+ return NPT_FAILURE;
+ }
+
+ static NPT_Result Serialize(NPT_XmlNode& node, NPT_String& xml, bool add_header = true, NPT_Int8 indentation = 0) {
+ NPT_XmlWriter writer(indentation);
+ NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
+ NPT_CHECK(writer.Serialize(node, *stream, add_header));
+ return NPT_SUCCESS;
+ }
+
+ static NPT_String Serialize(NPT_XmlNode& node, bool add_header = true, NPT_Int8 indentation = 0) {
+ NPT_XmlWriter writer(indentation);
+ NPT_String xml;
+ NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
+ if (NPT_FAILED(writer.Serialize(node, *stream, add_header))) {
+ NPT_Debug("Failed to serialize xml node");
+ return "";
+ }
+
+ return xml;
+ }
+private:
+ // members
+};
+
+/*----------------------------------------------------------------------
+| NPT_StringFinder
++---------------------------------------------------------------------*/
+/**
+ The NPT_StringFinder class is used to determine if a string is found
+ as part of a list of strings.
+ */
+class NPT_StringFinder
+{
+public:
+ // methods
+ explicit NPT_StringFinder(NPT_String& value, bool ignore_case = false) :
+ m_Value(value.GetChars()), m_IgnoreCase(ignore_case) {}
+
+ explicit NPT_StringFinder(const char* value, bool ignore_case = false) :
+ m_Value(value), m_IgnoreCase(ignore_case) {}
+
+ virtual ~NPT_StringFinder() {}
+
+ bool operator()(const NPT_String* const & value) const {
+ return value->Compare(m_Value, m_IgnoreCase) ? false : true;
+ }
+ bool operator()(const NPT_String& value) const {
+ return value.Compare(m_Value, m_IgnoreCase) ? false : true;
+ }
+
+private:
+ // members
+ const char* m_Value;
+ bool m_IgnoreCase;
+};
+
+/*----------------------------------------------------------------------
+| NPT_IpAddressFinder
++---------------------------------------------------------------------*/
+/**
+ The NPT_IpAddressFinder class is used to determine if a IP Address is found
+ as part of a list of IP Addresses.
+ */
+class NPT_IpAddressFinder
+{
+public:
+ // methods
+ NPT_IpAddressFinder(NPT_IpAddress ip) : m_Value(ip) {}
+ virtual ~NPT_IpAddressFinder() {}
+
+ bool operator()(const NPT_IpAddress* const & value) const {
+ return *value == m_Value;
+ }
+ bool operator()(const NPT_IpAddress& value) const {
+ return value == m_Value;
+ }
+
+private:
+ // members
+ NPT_IpAddress m_Value;
+};
+
+
+/*----------------------------------------------------------------------
+| PLT_UPnPMessageHelper class
++---------------------------------------------------------------------*/
+/**
+ The PLT_UPnPMessageHelper class is a set of utility functions for manipulating
+ specific UPnP HTTP headers.
+ */
+class PLT_UPnPMessageHelper
+{
+public:
+ // methods
+ static const NPT_String* GetST(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("ST");
+ }
+ static NPT_Result SetST(NPT_HttpMessage& message,
+ const char* st) {
+ return message.GetHeaders().SetHeader("ST", st);
+ }
+
+ static const NPT_String* GetNT(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("NT");
+ }
+ static NPT_Result SetNT(NPT_HttpMessage& message,
+ const char* nt) {
+ return message.GetHeaders().SetHeader("NT", nt);
+ }
+
+ static const NPT_String* GetNTS(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("NTS");
+ }
+ static NPT_Result SetNTS(NPT_HttpMessage& message,
+ const char* nts) {
+ return message.GetHeaders().SetHeader("NTS", nts);
+ }
+
+ static const NPT_String* GetMAN(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("MAN");
+ }
+ static NPT_Result SetMAN(NPT_HttpMessage& message,
+ const char* man) {
+ return message.GetHeaders().SetHeader("MAN", man);
+ }
+
+ static const NPT_String* GetLocation(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("Location");
+ }
+ static NPT_Result SetLocation(NPT_HttpMessage& message,
+ const char* location) {
+ return message.GetHeaders().SetHeader("Location", location);
+ }
+
+ static const NPT_String* GetServer(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_SERVER);
+ }
+ static NPT_Result SetServer(NPT_HttpMessage& message,
+ const char* server,
+ bool replace = true) {
+ return message.GetHeaders().SetHeader(
+ NPT_HTTP_HEADER_SERVER,
+ server,
+ replace);
+ }
+
+ static const NPT_String* GetUSN(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("USN");
+ }
+ static NPT_Result SetUSN(NPT_HttpMessage& message,
+ const char* usn) {
+ return message.GetHeaders().SetHeader("USN", usn);
+ }
+
+ static const NPT_String* GetCallbacks(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("CALLBACK");
+ }
+ static NPT_Result SetCallbacks(NPT_HttpMessage& message, const char* callbacks) {
+ return message.GetHeaders().SetHeader("CALLBACK", callbacks);
+ }
+
+ static const NPT_String* GetSID(const NPT_HttpMessage& message) {
+ return message.GetHeaders().GetHeaderValue("SID");
+ }
+ static NPT_Result SetSID(NPT_HttpMessage& message,
+ const char* sid) {
+ return message.GetHeaders().SetHeader("SID", sid);
+ }
+
+ static NPT_Result GetLeaseTime(const NPT_HttpMessage& message, NPT_TimeInterval& lease) {
+ const NPT_String* cc =
+ message.GetHeaders().GetHeaderValue("Cache-Control");
+ NPT_CHECK_POINTER(cc);
+ return ExtractLeaseTime(*cc, lease);
+ }
+ static NPT_Result SetLeaseTime(NPT_HttpMessage& message, const NPT_TimeInterval& lease) {
+ return message.GetHeaders().SetHeader("Cache-Control",
+ "max-age="+NPT_String::FromInteger(lease.ToSeconds()));
+ }
+
+ static NPT_Result GetBootId(const NPT_HttpMessage& message, NPT_UInt32& bootId) {
+ bootId = 0;
+ const NPT_String* bid = message.GetHeaders().GetHeaderValue("BOOTID.UPNP.ORG");
+ NPT_CHECK_POINTER(bid);
+ return NPT_ParseInteger32(*bid, bootId, false);
+ }
+ static NPT_Result SetBootId(NPT_HttpMessage& message, const NPT_UInt32& bootId) {
+ return message.GetHeaders().SetHeader("BOOTID.UPNP.ORG",
+ NPT_String::FromInteger(bootId));
+ }
+
+ static NPT_Result GetNextBootId(const NPT_HttpMessage& message, NPT_UInt32& nextBootId) {
+ nextBootId = 0;
+ const NPT_String* nbid = message.GetHeaders().GetHeaderValue("NEXTBOOTID.UPNP.ORG");
+ NPT_CHECK_POINTER(nbid);
+ return NPT_ParseInteger32(*nbid, nextBootId, false);
+ }
+ static NPT_Result SetNextBootId(NPT_HttpMessage& message, const NPT_UInt32& nextBootId) {
+ return message.GetHeaders().SetHeader("NEXTBOOTID.UPNP.ORG",
+ NPT_String::FromInteger(nextBootId));
+ }
+
+ static NPT_Result GetConfigId(const NPT_HttpMessage& message, NPT_UInt32& configId) {
+ configId = 0;
+ const NPT_String* cid = message.GetHeaders().GetHeaderValue("CONFIGID.UPNP.ORG");
+ NPT_CHECK_POINTER(cid);
+ return NPT_ParseInteger32(*cid, configId, false);
+ }
+ static NPT_Result SetConfigId(NPT_HttpMessage& message, const NPT_UInt32& configId) {
+ return message.GetHeaders().SetHeader("CONFIGID.UPNP.ORG", NPT_String::FromInteger(configId));
+ }
+
+ static NPT_Result GetTimeOut(const NPT_HttpMessage& message, NPT_Int32& seconds) {
+ seconds = 0;
+ const NPT_String* timeout =
+ message.GetHeaders().GetHeaderValue("TIMEOUT");
+ NPT_CHECK_POINTER(timeout);
+ return ExtractTimeOut(*timeout, seconds);
+ }
+ static NPT_Result SetTimeOut(NPT_HttpMessage& message, const NPT_Int32 seconds) {
+ if (seconds >= 0) {
+ return message.GetHeaders().SetHeader("TIMEOUT", "Second-"+NPT_String::FromInteger(seconds));
+ } else {
+ return message.GetHeaders().SetHeader("TIMEOUT", "Second-infinite");
+ }
+ }
+
+ static NPT_Result SetDate(NPT_HttpMessage& message) {
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ NPT_DateTime date(now);
+
+ return message.GetHeaders().SetHeader("Date", date.ToString(NPT_DateTime::FORMAT_RFC_1123));
+ }
+
+ static NPT_Result GetIfModifiedSince(const NPT_HttpMessage& message, NPT_DateTime& date) {
+ const NPT_String* value = message.GetHeaders().GetHeaderValue("If-Modified-Since");
+ if (!value) return NPT_FAILURE;
+
+ // Try RFC 1123, RFC 1036, then ANSI
+ if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1123)))
+ return NPT_SUCCESS;
+
+ if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1036)))
+ return NPT_SUCCESS;
+
+ return date.FromString(*value, NPT_DateTime::FORMAT_ANSI);
+ }
+ static NPT_Result SetIfModifiedSince(NPT_HttpMessage& message, const NPT_DateTime& date) {
+ return message.GetHeaders().SetHeader("If-Modified-Since",
+ date.ToString(NPT_DateTime::FORMAT_RFC_1123));
+ }
+
+ static NPT_Result GetMX(const NPT_HttpMessage& message, NPT_UInt32& value) {
+ value = 0;
+ const NPT_String* mx =
+ message.GetHeaders().GetHeaderValue("MX");
+ NPT_CHECK_POINTER(mx);
+ return NPT_ParseInteger32(*mx, value, false); // no relax to be UPnP compliant
+ }
+ static NPT_Result SetMX(NPT_HttpMessage& message, const NPT_UInt32 mx) {
+ return message.GetHeaders().SetHeader("MX",
+ NPT_String::FromInteger(mx));
+ }
+
+ static NPT_Result GetSeq(const NPT_HttpMessage& message, NPT_UInt32& value) {
+ value = 0;
+ const NPT_String* seq =
+ message.GetHeaders().GetHeaderValue("SEQ");
+ NPT_CHECK_POINTER(seq);
+ return NPT_ParseInteger32(*seq, value);
+ }
+ static NPT_Result SetSeq(NPT_HttpMessage& message, const NPT_UInt32 seq) {
+ return message.GetHeaders().SetHeader("SEQ",
+ NPT_String::FromInteger(seq));
+ }
+
+ static const char* GenerateUUID(int count, NPT_String& uuid) {
+ uuid = "";
+ for (int i=0;i<(count<100?count:100);i++) {
+ int random = NPT_System::GetRandomInteger();
+ uuid += (char)((random % 25) + 66);
+ }
+ return uuid;
+ }
+
+ static const char* GenerateSerialNumber(NPT_String& sn, int count = 40) {
+ sn = "{";
+ for (int i=0;i<count;i++) {
+ char nibble = (char)(NPT_System::GetRandomInteger() % 16);
+ sn += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
+ }
+ sn += "}";
+ return sn;
+ }
+
+ static const char* GenerateGUID(NPT_String& guid) {
+ guid = "";
+ for (int i=0;i<32;i++) {
+ char nibble = (char)(NPT_System::GetRandomInteger() % 16);
+ guid += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
+ if (i == 7 || i == 11 || i == 15 || i == 19) {
+ guid += '-';
+ }
+ }
+ return guid;
+ }
+
+ static NPT_Result ExtractLeaseTime(const NPT_String& cache_control, NPT_TimeInterval& lease) {
+ NPT_Int32 value;
+ if (cache_control.StartsWith("max-age=", true) &&
+ NPT_SUCCEEDED(NPT_ParseInteger32(cache_control.GetChars()+8, value))) {
+ lease.SetSeconds(value);
+ return NPT_SUCCESS;
+ }
+ return NPT_FAILURE;
+ }
+
+ static NPT_Result ExtractTimeOut(const char* timeout, NPT_Int32& len) {
+ NPT_String temp = timeout;
+ if (temp.CompareN("Second-", 7, true)) {
+ return NPT_ERROR_INVALID_FORMAT;
+ }
+
+ if (temp.Compare("Second-infinite", true) == 0) {
+ len = NPT_TIMEOUT_INFINITE;
+ return NPT_SUCCESS;
+ }
+ return temp.SubString(7).ToInteger(len);
+ }
+
+ static NPT_Result GetIPAddresses(NPT_List<NPT_IpAddress>& ips, bool with_localhost = false) {
+ NPT_List<NPT_NetworkInterface*> if_list;
+ NPT_CHECK(GetNetworkInterfaces(if_list, with_localhost));
+
+ NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
+ while (iface) {
+ NPT_IpAddress ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress();
+ if (ip.ToString().Compare("0.0.0.0") &&
+ (with_localhost || ip.ToString().Compare("127.0.0.1"))) {
+ ips.Add(ip);
+ }
+ ++iface;
+ }
+
+ if (with_localhost && !ips.Find(NPT_IpAddressFinder(NPT_IpAddress(127, 0, 0, 1)))) {
+ NPT_IpAddress localhost;
+ localhost.Parse("127.0.0.1");
+ ips.Add(localhost);
+ }
+
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
+ bool with_localhost = false) {
+ NPT_CHECK(_GetNetworkInterfaces(if_list, with_localhost, false));
+
+ // if no valid interfaces or if requested, add localhost interface
+ if (if_list.GetItemCount() == 0) {
+ NPT_CHECK(_GetNetworkInterfaces(if_list, true, true));
+ }
+ return NPT_SUCCESS;
+ }
+
+ static NPT_Result GetMACAddresses(NPT_List<NPT_String>& addresses) {
+ NPT_List<NPT_NetworkInterface*> if_list;
+ NPT_CHECK(GetNetworkInterfaces(if_list));
+
+ NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
+ while (iface) {
+ NPT_String ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress().ToString();
+ if (ip.Compare("0.0.0.0") && ip.Compare("127.0.0.1")) {
+ addresses.Add((*iface)->GetMacAddress().ToString());
+ }
+ ++iface;
+ }
+
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+ return NPT_SUCCESS;
+ }
+
+
+ static bool IsLocalNetworkAddress(const NPT_IpAddress& address) {
+ if (address.ToString() == "127.0.0.1") return true;
+
+ NPT_List<NPT_NetworkInterface*> if_list;
+ NPT_NetworkInterface::GetNetworkInterfaces(if_list);
+
+ NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
+ while (iface) {
+ if((*iface)->IsAddressInNetwork(address)) return true;
+ ++iface;
+ }
+
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+ return false;
+ }
+
+private:
+
+ static NPT_Result _GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
+ bool include_localhost = false,
+ bool only_localhost = false) {
+ NPT_List<NPT_NetworkInterface*> _if_list;
+ NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(_if_list));
+
+ NPT_NetworkInterface* iface;
+ while (NPT_SUCCEEDED(_if_list.PopHead(iface))) {
+ // only interested in non PTP & multicast capable interfaces
+ if ((iface->GetAddresses().GetItemCount() == 0) ||
+ !(iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) ||
+ (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT)) {
+ delete iface;
+ continue;
+ }
+
+ NPT_String ip = iface->GetAddresses().GetFirstItem()->GetPrimaryAddress().ToString();
+
+ if (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
+ if (include_localhost || only_localhost) {
+ if_list.Add(iface);
+ continue;
+ }
+ } else if (ip.Compare("0.0.0.0") && !only_localhost) {
+ if_list.Add(iface);
+ continue;
+ }
+
+ delete iface;
+ }
+
+ // cleanup any remaining items in list if we breaked early
+ _if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+ return NPT_SUCCESS;
+ }
+};
+
+#endif // _PLT_UTILITIES_H_
+
+
+
+
+
+
+
+
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.cpp
new file mode 100644
index 0000000..ccac60d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.cpp
@@ -0,0 +1,348 @@
+/*****************************************************************
+|
+| Platinum - AV Media Connect Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "Platinum.h"
+#include "PltMediaConnect.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.devices.mediaconnect")
+
+/*----------------------------------------------------------------------
+| forward references
++---------------------------------------------------------------------*/
+extern NPT_UInt8 X_MS_MediaReceiverRegistrarSCPD[];
+extern NPT_UInt8 MS_ContentDirectorySCPD[];
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::PLT_MediaConnect
++---------------------------------------------------------------------*/
+PLT_MediaConnect::PLT_MediaConnect(const char* friendly_name,
+ bool add_hostname /* = true */,
+ const char* udn /* = NULL */,
+ NPT_UInt16 port /* = 0 */,
+ bool port_rebind /* = false */) :
+ PLT_MediaServer(friendly_name, false, udn, port, port_rebind),
+ m_AddHostname(add_hostname)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::~PLT_MediaConnect
++---------------------------------------------------------------------*/
+PLT_MediaConnect::~PLT_MediaConnect()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::SetupServices()
+{
+ NPT_Reference<PLT_Service> service(new PLT_Service(
+ this,
+ "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
+ "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar",
+ "X_MS_MediaReceiverRegistrar"));
+
+ NPT_CHECK_FATAL(service->SetSCPDXML((const char*) X_MS_MediaReceiverRegistrarSCPD));
+ NPT_CHECK_FATAL(AddService(service.AsPointer()));
+
+ service->SetStateVariable("AuthorizationGrantedUpdateID", "1");
+ service->SetStateVariable("AuthorizationDeniedUpdateID", "1");
+ service->SetStateVariable("ValidationSucceededUpdateID", "0");
+ service->SetStateVariable("ValidationRevokedUpdateID", "0");
+
+ service.Detach();
+ return PLT_MediaServer::SetupServices();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::ProcessGetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::ProcessGetDescription(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ // lock to make sure another request is not modifying the device while we are already
+ NPT_AutoLock lock(m_Lock);
+
+ NPT_Result res = NPT_SUCCESS;
+ NPT_String oldModelName = m_ModelName;
+ NPT_String oldModelNumber = m_ModelNumber;
+ NPT_String oldModelURL = m_ModelURL;
+ NPT_String oldManufacturerURL = m_ManufacturerURL;
+ NPT_String oldDlnaDoc = m_DlnaDoc;
+ NPT_String oldDlnaCap = m_DlnaCap;
+ NPT_String oldAggregationFlags = m_AggregationFlags;
+ NPT_String oldFriendlyName = m_FriendlyName;
+
+ NPT_String hostname;
+ NPT_System::GetMachineName(hostname);
+
+ PLT_DeviceSignature signature = PLT_HttpHelper::GetDeviceSignature(request);
+
+ if (signature == PLT_DEVICE_XBOX_360 || signature == PLT_DEVICE_XBOX_ONE /*|| signature == PLT_SONOS*/) {
+ // XBox needs to see something behind a ':' to even show it
+ if (m_AddHostname && hostname.GetLength() > 0) {
+ m_FriendlyName += ": " + hostname;
+ } else if (m_FriendlyName.Find(":") == -1) {
+ m_FriendlyName += ": 1";
+ }
+ }
+ else if (m_AddHostname && hostname.GetLength() > 0) {
+ m_FriendlyName += " (" + hostname + ")";
+ }
+
+ // change some things based on device signature from request
+ if (signature == PLT_DEVICE_XBOX_360 || signature == PLT_DEVICE_XBOX_ONE || signature == PLT_DEVICE_WMP /*|| signature == PLT_SONOS*/) {
+ m_ModelName = "Windows Media Player Sharing";
+ m_ModelNumber = (signature == PLT_DEVICE_SONOS)?"3.0":"12.0";
+ m_ModelURL = "http://www.microsoft.com/";//"http://go.microsoft.com/fwlink/?LinkId=105926";
+ m_Manufacturer = (signature == PLT_DEVICE_SONOS)?"Microsoft":"Microsoft Corporation";
+ m_ManufacturerURL = "http://www.microsoft.com/";
+ m_DlnaDoc = (signature == PLT_DEVICE_SONOS)?"DMS-1.00":"DMS-1.50";
+ m_DlnaCap = "";
+ m_AggregationFlags = "";
+
+ //PLT_UPnPMessageHelper::GenerateGUID(m_SerialNumber);
+ // TODO: http://msdn.microsoft.com/en-us/library/ff362657(PROT.10).aspx
+ // TODO: <serialNumber>GUID</serialNumber>
+
+ } else if (signature == PLT_DEVICE_SONOS) {
+ m_ModelName = "Rhapsody";
+ m_ModelNumber = "3.0";
+ } else if (signature == PLT_DEVICE_PS3) {
+ m_DlnaDoc = "DMS-1.50";
+ m_DlnaCap = "";
+ m_AggregationFlags = "10";
+ }
+
+ // return description with modified params
+ res = PLT_MediaServer::ProcessGetDescription(request, context, response);
+
+ // reset to old values now
+ m_FriendlyName = oldFriendlyName;
+ m_ModelName = oldModelName;
+ m_ModelNumber = oldModelNumber;
+ m_ModelURL = oldModelURL;
+ m_ManufacturerURL = oldManufacturerURL;
+ m_DlnaDoc = oldDlnaDoc;
+ m_DlnaCap = oldDlnaCap;
+ m_AggregationFlags = oldAggregationFlags;
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::ProcessGetSCPD
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::ProcessGetSCPD(PLT_Service* service,
+ NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ PLT_DeviceSignature signature = PLT_HttpHelper::GetDeviceSignature(request);
+
+ // Override SCPD response by providing an SCPD without a Search action
+ // to all devices except XBox or WMP which need it
+ if (service->GetServiceType() == "urn:schemas-upnp-org:service:ContentDirectory:1" &&
+ signature != PLT_DEVICE_XBOX_360 &&
+ signature != PLT_DEVICE_XBOX_ONE &&
+ signature != PLT_DEVICE_WMP &&
+ signature != PLT_DEVICE_SONOS) {
+ NPT_HttpEntity* entity;
+ PLT_HttpHelper::SetBody(response, (const char*) MS_ContentDirectorySCPD, &entity);
+ entity->SetContentType("text/xml; charset=\"utf-8\"");
+ return NPT_SUCCESS;
+ }
+
+ return PLT_MediaServer::ProcessGetSCPD(service, request, context, response);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnAction(PLT_ActionReference& action,
+
+ const PLT_HttpRequestContext& context)
+{
+ /* parse the action name */
+ NPT_String name = action->GetActionDesc().GetName();
+
+ /* handle X_MS_MediaReceiverRegistrar actions here */
+ if (name.Compare("IsAuthorized") == 0) {
+ return OnIsAuthorized(action);
+ }
+ if (name.Compare("RegisterDevice") == 0) {
+ return OnRegisterDevice(action);
+ }
+ if (name.Compare("IsValidated") == 0) {
+ return OnIsValidated(action);
+ }
+
+ return PLT_MediaServer::OnAction(action, context);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::OnIsAuthorized
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnIsAuthorized(PLT_ActionReference& action)
+{
+ NPT_CHECK_WARNING(action->SetArgumentValue("Result", "1"));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::OnRegisterDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnRegisterDevice(PLT_ActionReference& action)
+{
+ NPT_String reqMsgBase64;
+ NPT_CHECK_WARNING(action->GetArgumentValue("RegistrationReqMsg", reqMsgBase64));
+
+ NPT_String respMsgBase64;
+ NPT_CHECK_WARNING(action->SetArgumentValue("RegistrationRespMsg", respMsgBase64));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::OnIsValidated
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::OnIsValidated(PLT_ActionReference& action)
+{
+ NPT_CHECK_WARNING(action->SetArgumentValue("Result", "1"));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect::GetMappedObjectId
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaConnect::GetMappedObjectId(const char* object_id, NPT_String& mapped_object_id)
+{
+ if (!object_id) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // Reroute XBox 360 and WMP requests to our route
+ if (NPT_StringsEqual(object_id, "15")) {
+ mapped_object_id = "0/Videos"; // Videos
+ } else if (NPT_StringsEqual(object_id, "16")) {
+ mapped_object_id = "0/Photos"; // Photos
+ } else {
+ mapped_object_id = object_id;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaConnectDelegate::GetFilePath
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaConnectDelegate::GetFilePath(const char* object_id, NPT_String& filepath)
+{
+ if (!object_id) return NPT_ERROR_INVALID_PARAMETERS;
+
+ // Reroute XBox 360 and WMP requests to our route
+ if (NPT_StringsEqual(object_id, "15")) {
+ return PLT_FileMediaServerDelegate::GetFilePath("", filepath); // Videos
+ } else if (NPT_StringsEqual(object_id, "16")) {
+ return PLT_FileMediaServerDelegate::GetFilePath("", filepath); // Photos
+ } else if (NPT_StringsEqual(object_id, "13") || NPT_StringsEqual(object_id, "4")) {
+ return PLT_FileMediaServerDelegate::GetFilePath("", filepath); // Music
+ }
+
+ return PLT_FileMediaServerDelegate::GetFilePath(object_id, filepath);;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaConnectDelegate::OnSearchContainer
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaConnectDelegate::OnSearchContainer(PLT_ActionReference& action,
+ const char* object_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ /* parse search criteria */
+
+ /* TODO: HACK TO PASS DLNA */
+ if (search_criteria && NPT_StringsEqual(search_criteria, "Unknownfieldname")) {
+ /* error */
+ NPT_LOG_WARNING_1("Unsupported or invalid search criteria %s", search_criteria);
+ action->SetError(708, "Unsupported or invalid search criteria");
+ return NPT_FAILURE;
+ }
+
+ /* locate the file from the object ID */
+ NPT_String dir;
+ if (NPT_FAILED(GetFilePath(object_id, dir))) {
+ /* error */
+ NPT_LOG_WARNING("ObjectID not found.");
+ action->SetError(710, "No Such Container.");
+ return NPT_FAILURE;
+ }
+
+ /* retrieve the item type */
+ NPT_FileInfo info;
+ NPT_Result res = NPT_File::GetInfo(dir, &info);
+ if (NPT_FAILED(res) || (info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY)) {
+ /* error */
+ NPT_LOG_WARNING("No such container");
+ action->SetError(710, "No such container");
+ return NPT_FAILURE;
+ }
+
+ /* hack for now to return something back to XBox 360 */
+ return OnBrowseDirectChildren(action,
+ object_id,
+ filter,
+ starting_index,
+ requested_count,
+ sort_criteria,
+ context);
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.h b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.h
new file mode 100644
index 0000000..b628d9b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltMediaConnect.h
@@ -0,0 +1,110 @@
+/*****************************************************************
+|
+| Platinum - AV Media Connect Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_CONNECT_H_
+#define _PLT_MEDIA_CONNECT_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltFileMediaServer.h"
+
+/*----------------------------------------------------------------------
+| PLT_MediaConnect
++---------------------------------------------------------------------*/
+class PLT_MediaConnect : public PLT_MediaServer
+{
+public:
+ // class methods
+ static NPT_Result GetMappedObjectId(const char* object_id,
+ NPT_String& mapped_object_id);
+
+ // constructor
+ PLT_MediaConnect(const char* friendly_name,
+ bool add_hostname = true,
+ const char* udn = NULL,
+ NPT_UInt16 port = 0,
+ bool port_rebind = false);
+
+protected:
+ ~PLT_MediaConnect() override;
+
+ // PLT_DeviceHost methods
+ NPT_Result SetupServices() override;
+ NPT_Result OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context) override;
+ NPT_Result ProcessGetDescription(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+ NPT_Result ProcessGetSCPD(PLT_Service* service,
+ NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ // X_MS_MediaReceiverRegistrar
+ virtual NPT_Result OnIsAuthorized(PLT_ActionReference& action);
+ virtual NPT_Result OnRegisterDevice(PLT_ActionReference& action);
+ virtual NPT_Result OnIsValidated(PLT_ActionReference& action);
+
+protected:
+ NPT_Mutex m_Lock;
+ bool m_AddHostname;
+};
+
+/*----------------------------------------------------------------------
+ | PLT_FileMediaConnectDelegate class
+ +---------------------------------------------------------------------*/
+class PLT_FileMediaConnectDelegate : public PLT_FileMediaServerDelegate
+{
+public:
+ // constructor & destructor
+ PLT_FileMediaConnectDelegate(const char* url_root, const char* file_root) :
+ PLT_FileMediaServerDelegate(url_root, file_root) {}
+ ~PLT_FileMediaConnectDelegate() override {}
+
+ // PLT_FileMediaServerDelegate methods
+ NPT_Result GetFilePath(const char* object_id, NPT_String& filepath) override;
+ NPT_Result OnSearchContainer(PLT_ActionReference& action,
+ const char* object_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context) override;
+};
+
+#endif /* _PLT_MEDIA_CONNECT_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.cpp
new file mode 100644
index 0000000..dd54bc8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.cpp
@@ -0,0 +1,214 @@
+/*****************************************************************
+|
+| Platinum - XBox 360
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltXbox360.h"
+#include "PltService.h"
+#include "PltUtilities.h"
+#include "PltSsdp.h"
+
+/*----------------------------------------------------------------------
+| externals
++---------------------------------------------------------------------*/
+extern NPT_UInt8 Platinum_48x48_png[4681];
+
+/*----------------------------------------------------------------------
+| PLT_Xbox360::PLT_Xbox360
++---------------------------------------------------------------------*/
+PLT_Xbox360::PLT_Xbox360(const char* uuid /* = NULL */,
+ unsigned int port /* = 0 */,
+ bool port_rebind /* = false */) :
+ PLT_MediaRenderer("Xbox 360", false, uuid, port, port_rebind)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Xbox360::~PLT_Xbox360
++---------------------------------------------------------------------*/
+PLT_Xbox360::~PLT_Xbox360()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Xbox360::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Xbox360::SetupServices()
+{
+ NPT_CHECK(PLT_MediaRenderer::SetupServices());
+
+ m_ModelDescription = "Xbox 360";
+ m_ModelName = "Xbox 360";
+ m_ModelURL = "http://www.xbox.com";
+ m_Manufacturer = "Microsoft Corporation";
+ m_ManufacturerURL = "http://www.microsoft.com";
+
+ NPT_Array<PLT_Service*>::Iterator service;
+
+ if (NPT_SUCCEEDED(NPT_ContainerFind(
+ m_Services,
+ PLT_ServiceTypeFinder("urn:schemas-upnp-org:service:RenderingControl:1"),
+ service))) {
+ InitServiceURLs(*service, "RenderingControl");
+ }
+
+ if (NPT_SUCCEEDED(NPT_ContainerFind(
+ m_Services,
+ PLT_ServiceTypeFinder("urn:schemas-upnp-org:service:ConnectionManager:1"),
+ service))) {
+ InitServiceURLs(*service, "ConnectionManager");
+ }
+
+ // remove AVTransport
+ if (NPT_SUCCEEDED(NPT_ContainerFind(
+ m_Services,
+ PLT_ServiceTypeFinder("urn:schemas-upnp-org:service:AVTransport:1"),
+ service))) {
+ m_Services.Erase(service);
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Service::InitServiceURLs
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Xbox360::InitServiceURLs(PLT_Service* service, const char* service_name)
+{
+ service->SetSCPDURL("/Content/" + NPT_String(service_name));
+ service->SetControlURL("/Control/" + NPT_String(service_name));
+ service->SetEventSubURL("/Event/" + NPT_String(service_name));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Xbox360::GetDescription
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Xbox360::GetDescription(NPT_XmlElementNode* root, NPT_XmlElementNode** device_out)
+{
+ // if no device out passed, pass one
+ NPT_XmlElementNode* device_out_local;
+ if (!device_out) device_out = &device_out_local;
+
+ NPT_CHECK(PLT_MediaRenderer::GetDescription(root, device_out));
+
+ // add extra stuff
+ root->SetNamespaceUri("ms", " urn:microsoft-com:wmc-1-0");
+ root->SetNamespaceUri("microsoft", "urn-schemas-microsoft-com:WMPNSS-1-0");
+
+ if (*device_out) {
+ (*device_out)->SetAttribute("ms", "X_MS_SupportsWMDRM", "true");
+ NPT_XmlElementNode* device_caps = new NPT_XmlElementNode("microsoft", "X_DeviceCaps");
+ device_caps->AddText("4754");
+ (*device_out)->AddChild(device_caps);
+
+ NPT_XmlElementNode* handshake = new NPT_XmlElementNode("microsoft", "HandshakeFlags");
+ handshake->AddText("1");
+ (*device_out)->AddChild(handshake);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Xbox360::SetupIcons
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Xbox360::SetupIcons()
+{
+ AddIcon(
+ PLT_DeviceIcon("image/png", 48, 48, 32, "/xbox360.png"),
+ Platinum_48x48_png, sizeof(Platinum_48x48_png), false);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::Announce
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Xbox360::Announce(PLT_DeviceData* device,
+ NPT_HttpRequest& req,
+ NPT_UdpSocket& socket,
+ PLT_SsdpAnnounceType type)
+{
+ AnnouncePresence(socket, "");
+
+ return PLT_MediaRenderer::Announce(device, req, socket, type);
+}
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHost::AnnouncePresence
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Xbox360::AnnouncePresence(NPT_UdpSocket& socket,
+ const char* serial_number)
+{
+ NPT_COMPILER_UNUSED(serial_number);
+
+ NPT_HttpRequest req(
+ NPT_HttpUrl("239.255.255.250", 1900, "*"),
+ "NOTIFY",
+ NPT_HTTP_PROTOCOL_1_1);
+ PLT_HttpHelper::SetHost(req, "239.255.255.250:1900");
+
+ NPT_Result res = NPT_SUCCESS;
+ // get location URL based on ip address of interface
+ PLT_UPnPMessageHelper::SetNTS(req, "ssdp:alive");
+ PLT_UPnPMessageHelper::SetLeaseTime(req, NPT_TimeInterval(4.));
+ PLT_UPnPMessageHelper::SetServer(req, "dashboard/1.0 UpnP/1.0 xbox/2.0", true);
+ req.GetHeaders().SetHeader("AL",
+ "<urn:schemas-microsoft-com:nhed:attributes?type=X02&firmwarever=8955.0&udn=uuid:10000000-0000-0000-0200-00125A8FEFAC>");
+ PLT_UPnPMessageHelper::SetLocation(req, "*");
+
+ // target address
+ NPT_IpAddress ip;
+ if (NPT_FAILED(res = ip.ResolveName(req.GetUrl().GetHost()))) {
+ return res;
+ }
+ NPT_SocketAddress addr(ip, req.GetUrl().GetPort());
+
+ PLT_SsdpSender::SendSsdp(req,
+ "uuid:00000000-0000-0000-0200-00125A8FEFAC::urn:schemas-microsoft-com:nhed:presence:1",
+ "urn:schemas-microsoft-com:nhed:presence:1",
+ socket,
+ true,
+ &addr);
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.h b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.h
new file mode 100644
index 0000000..346ce57
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/PltXbox360.h
@@ -0,0 +1,73 @@
+/*****************************************************************
+|
+| Platinum - XBox 360
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_XBOX360_H_
+#define _PLT_XBOX360_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMediaRenderer.h"
+
+class PLT_Xbox360 : public PLT_MediaRenderer
+{
+public:
+ PLT_Xbox360(const char* uuid = NULL,
+ unsigned int port = 0,
+ bool port_rebind = false);
+
+protected:
+ // PLT_DeviceHost methods
+ NPT_Result SetupServices() override;
+ NPT_Result SetupIcons() override;
+ virtual NPT_Result InitServiceURLs(PLT_Service* service, const char* service_name);
+
+ virtual NPT_Result Announce(PLT_DeviceData* device,
+ NPT_HttpRequest& request,
+ NPT_UdpSocket& socket,
+ PLT_SsdpAnnounceType type);
+
+ // PLT_DeviceData methods
+ NPT_Result GetDescription(NPT_String& desc) override { return PLT_MediaRenderer::GetDescription(desc); }
+ NPT_Result GetDescription(NPT_XmlElementNode* parent,
+ NPT_XmlElementNode** device = NULL) override;
+
+protected:
+ ~PLT_Xbox360() override;
+
+ virtual NPT_Result AnnouncePresence(NPT_UdpSocket& socket,
+ const char* serial_number);
+};
+
+#endif /* _PLT_XBOX360_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.cpp
new file mode 100644
index 0000000..e05504b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.cpp
@@ -0,0 +1,176 @@
+/*****************************************************************
+|
+| Platinum - MediaConnect SCPD
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 X_MS_MediaReceiverRegistrarSCPD[2589] =
+{
+ 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
+ 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A,
+ 0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x27, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x2D, 0x31, 0x2D, 0x30, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A,
+ 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E,
+ 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x73,
+ 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E,
+ 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C,
+ 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65,
+ 0x71, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59,
+ 0x50, 0x45, 0x5F, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x71, 0x4D, 0x73,
+ 0x67, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69,
+ 0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F,
+ 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F,
+ 0x6E, 0x52, 0x65, 0x73, 0x70, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x73, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x65, 0x76,
+ 0x69, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+ 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64,
+ 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
+ 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20,
+ 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65,
+ 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x6E, 0x74, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73,
+ 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x71, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x62, 0x69, 0x6E,
+ 0x2E, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E,
+ 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x67, 0x69, 0x73,
+ 0x74, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x73, 0x70, 0x4D, 0x73, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x62, 0x69, 0x6E, 0x2E,
+ 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64,
+ 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x47, 0x72, 0x61,
+ 0x6E, 0x74, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79,
+ 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x75, 0x74, 0x68, 0x6F,
+ 0x72, 0x69, 0x7A, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65, 0x6E, 0x69, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+ 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E,
+ 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x75, 0x63, 0x63, 0x65,
+ 0x65, 0x64, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79,
+ 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x56, 0x61, 0x6C, 0x69, 0x64,
+ 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x52, 0x65, 0x76, 0x6F, 0x6B, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x3C,
+ 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.xml b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.xml
new file mode 100644
index 0000000..aa90cb0
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/X_MS_MediaReceiverRegistrarSCPD.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns='urn:schemas-upnp-org:service-1-0'>
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>IsAuthorized</name>
+ <argumentList>
+ <argument>
+ <name>DeviceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_DeviceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Result</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>RegisterDevice</name>
+ <argumentList>
+ <argument>
+ <name>RegistrationReqMsg</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_RegistrationReqMsg</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RegistrationRespMsg</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_RegistrationRespMsg</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>IsValidated</name>
+ <argumentList>
+ <argument>
+ <name>DeviceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_DeviceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Result</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_DeviceID</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Result</name>
+ <dataType>int</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_RegistrationReqMsg</name>
+ <dataType>bin.base64</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_RegistrationRespMsg</name>
+ <dataType>bin.base64</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>AuthorizationGrantedUpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>AuthorizationDeniedUpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>ValidationSucceededUpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>ValidationRevokedUpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ </serviceStateTable>
+</scpd> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaConnect/process_scpds.sh b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/process_scpds.sh
new file mode 100644
index 0000000..50e446b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaConnect/process_scpds.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -x
+
+# abort on any errors
+set -e
+
+# ContentDirectory
+../../../Targets/x86-unknown-cygwin/Debug/TextToHeader.exe -v X_MS_MediaReceiverRegistrarSCPD -h MediaConnect X_MS_MediaReceiverRegistrarSCPD.xml X_MS_MediaReceiverRegistrarSCPD.cpp
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.cpp
new file mode 100644
index 0000000..4803a33
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.cpp
@@ -0,0 +1,996 @@
+/*****************************************************************
+|
+| Platinum - AVTransport SCPD
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 RDR_AVTransportSCPD[] =
+{
+ 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
+ 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
+ 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 0x65,
+ 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+ 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F,
+ 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E,
+ 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56,
+ 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69,
+ 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72,
+ 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74,
+ 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59,
+ 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43,
+ 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69,
+ 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E,
+ 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F,
+ 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x50, 0x6C, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6B, 0x53,
+ 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x50, 0x6F,
+ 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D,
+ 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x51,
+ 0x75, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x50, 0x6F,
+ 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x51, 0x75, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x4D,
+ 0x6F, 0x64, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49,
+ 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E,
+ 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x4E, 0x72, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65,
+ 0x72, 0x4F, 0x66, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74,
+ 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74,
+ 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72,
+ 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72,
+ 0x65, 0x6E, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44,
+ 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x55,
+ 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C,
+ 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73,
+ 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E,
+ 0x65, 0x78, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D,
+ 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50,
+ 0x6C, 0x61, 0x79, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79,
+ 0x62, 0x61, 0x63, 0x6B, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x4D, 0x65, 0x64, 0x69, 0x75,
+ 0x6D, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67,
+ 0x65, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x57,
+ 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x63,
+ 0x6F, 0x72, 0x64, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47,
+ 0x65, 0x74, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73,
+ 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54,
+ 0x72, 0x61, 0x63, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75,
+ 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72,
+ 0x61, 0x63, 0x6B, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x63, 0x6B,
+ 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65,
+ 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x4D,
+ 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54,
+ 0x72, 0x61, 0x63, 0x6B, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E,
+ 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x52, 0x65, 0x6C, 0x54, 0x69, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74,
+ 0x69, 0x76, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x54, 0x69, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x41, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x43, 0x6F, 0x75, 0x6E,
+ 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6F, 0x75, 0x6E,
+ 0x74, 0x65, 0x72, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x62,
+ 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65,
+ 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49,
+ 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C,
+ 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65,
+ 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C,
+ 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x53, 0x70,
+ 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74,
+ 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x50,
+ 0x6C, 0x61, 0x79, 0x53, 0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x53,
+ 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41,
+ 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F,
+ 0x64, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x51, 0x75, 0x61,
+ 0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65,
+ 0x6E, 0x74, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x51, 0x75, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C,
+ 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65,
+ 0x78, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E,
+ 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F,
+ 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x61, 0x75, 0x73, 0x65, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61,
+ 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69,
+ 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50,
+ 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C,
+ 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49,
+ 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E,
+ 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x53, 0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69,
+ 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74,
+ 0x50, 0x6C, 0x61, 0x79, 0x53, 0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6F, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65,
+ 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49,
+ 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x65, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69,
+ 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61,
+ 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x6E, 0x69,
+ 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x65,
+ 0x65, 0x6B, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x61,
+ 0x72, 0x67, 0x65, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E,
+ 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+ 0x5F, 0x53, 0x65, 0x65, 0x6B, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69,
+ 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73,
+ 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41,
+ 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x55,
+ 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55,
+ 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E,
+ 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x56,
+ 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53,
+ 0x65, 0x74, 0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74,
+ 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59,
+ 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4E, 0x65,
+ 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44,
+ 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C,
+ 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73,
+ 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x50, 0x6C, 0x61,
+ 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+ 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x77, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64,
+ 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F,
+ 0x64, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x53, 0x74, 0x6F, 0x70, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+ 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69,
+ 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22,
+ 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C,
+ 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x52, 0x4D, 0x41, 0x4C,
+ 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x5F, 0x4F, 0x4E, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54,
+ 0x5F, 0x41, 0x4C, 0x4C, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x48, 0x55, 0x46, 0x46, 0x4C, 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77,
+ 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x48, 0x55, 0x46, 0x46,
+ 0x4C, 0x45, 0x5F, 0x4E, 0x4F, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E,
+ 0x4F, 0x52, 0x4D, 0x41, 0x4C, 0x3C, 0x2F, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63,
+ 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x54, 0x5F, 0x49,
+ 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C,
+ 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73,
+ 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4C, 0x61, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6E,
+ 0x67, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74,
+ 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x50, 0x6F, 0x73, 0x69, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E,
+ 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x55, 0x52, 0x49, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22,
+ 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D,
+ 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x51, 0x75, 0x61, 0x6C, 0x69, 0x74,
+ 0x79, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x54, 0x5F, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C,
+ 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69,
+ 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22,
+ 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D,
+ 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x41, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x50, 0x6F, 0x73, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D,
+ 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x52, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x65, 0x72, 0x50, 0x6F, 0x73, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D,
+ 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65,
+ 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22,
+ 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73,
+ 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77,
+ 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C,
+ 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x50, 0x41, 0x55,
+ 0x53, 0x45, 0x44, 0x5F, 0x50, 0x4C, 0x41, 0x59, 0x42, 0x41, 0x43, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x50, 0x4C, 0x41, 0x59, 0x49, 0x4E,
+ 0x47, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C,
+ 0x75, 0x65, 0x3E, 0x54, 0x52, 0x41, 0x4E, 0x53, 0x49, 0x54, 0x49, 0x4F, 0x4E, 0x49, 0x4E, 0x47, 0x3C, 0x2F, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F,
+ 0x5F, 0x4D, 0x45, 0x44, 0x49, 0x41, 0x5F, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4E, 0x54, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F,
+ 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65,
+ 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74,
+ 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x55, 0x52, 0x49, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 0x69,
+ 0x62, 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x51, 0x75, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x4D, 0x6F, 0x64, 0x65,
+ 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x20, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x4E, 0x4F, 0x54, 0x5F, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61,
+ 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F,
+ 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75,
+ 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34,
+ 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75,
+ 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x36, 0x35, 0x35, 0x33, 0x35,
+ 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E,
+ 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x50, 0x6F, 0x73, 0x69,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65,
+ 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x78, 0x74, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74,
+ 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74,
+ 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20,
+ 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6B,
+ 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+ 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61,
+ 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x4E, 0x45, 0x3C, 0x2F, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x55, 0x4E,
+ 0x4B, 0x4E, 0x4F, 0x57, 0x4E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x44, 0x41, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x48, 0x44, 0x44, 0x3C, 0x2F, 0x61,
+ 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E,
+ 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45,
+ 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70,
+ 0x6F, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73,
+ 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x4D, 0x65, 0x64,
+ 0x69, 0x75, 0x6D, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x54, 0x5F, 0x49, 0x4D, 0x50,
+ 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C,
+ 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77,
+ 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E,
+ 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x50, 0x6C, 0x61,
+ 0x79, 0x62, 0x61, 0x63, 0x6B, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E, 0x4F, 0x4E, 0x45,
+ 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x4E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x43, 0x44, 0x2D, 0x44, 0x41, 0x3C, 0x2F, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x48, 0x44,
+ 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C,
+ 0x75, 0x65, 0x3E, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C,
+ 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73,
+ 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F,
+ 0x72, 0x74, 0x55, 0x52, 0x49, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72,
+ 0x4F, 0x66, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E,
+ 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x36, 0x35, 0x35, 0x33, 0x35, 0x3C, 0x2F,
+ 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47,
+ 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x65, 0x65, 0x6B, 0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x52, 0x45, 0x4C, 0x5F, 0x54, 0x49, 0x4D,
+ 0x45, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C,
+ 0x75, 0x65, 0x3E, 0x54, 0x52, 0x41, 0x43, 0x4B, 0x5F, 0x4E, 0x52, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20,
+ 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59,
+ 0x50, 0x45, 0x5F, 0x53, 0x65, 0x65, 0x6B, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x6F, 0x73, 0x73, 0x69, 0x62,
+ 0x6C, 0x65, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x4D, 0x65, 0x64, 0x69, 0x61,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77,
+ 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4E,
+ 0x4F, 0x54, 0x5F, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F,
+ 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73,
+ 0x70, 0x6F, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73,
+ 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F,
+ 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4F, 0x4B, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x5F, 0x4F,
+ 0x43, 0x43, 0x55, 0x52, 0x52, 0x45, 0x44, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64,
+ 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x50, 0x6C, 0x61,
+ 0x79, 0x53, 0x70, 0x65, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C,
+ 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x31, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+ 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x3C, 0x2F,
+ 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.xml b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.xml
new file mode 100644
index 0000000..f9ee988
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPD.xml
@@ -0,0 +1,515 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>GetCurrentTransportActions</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Actions</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTransportActions</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetDeviceCapabilities</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PlayMedia</name>
+ <direction>out</direction>
+ <relatedStateVariable>PossiblePlaybackStorageMedia</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecMedia</name>
+ <direction>out</direction>
+ <relatedStateVariable>PossibleRecordStorageMedia</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecQualityModes</name>
+ <direction>out</direction>
+ <relatedStateVariable>PossibleRecordQualityModes</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetMediaInfo</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NrTracks</name>
+ <direction>out</direction>
+ <relatedStateVariable>NumberOfTracks</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>MediaDuration</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentMediaDuration</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURI</name>
+ <direction>out</direction>
+ <relatedStateVariable>AVTransportURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURIMetaData</name>
+ <direction>out</direction>
+ <relatedStateVariable>AVTransportURIMetaData</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NextURI</name>
+ <direction>out</direction>
+ <relatedStateVariable>NextAVTransportURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NextURIMetaData</name>
+ <direction>out</direction>
+ <relatedStateVariable>NextAVTransportURIMetaData</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PlayMedium</name>
+ <direction>out</direction>
+ <relatedStateVariable>PlaybackStorageMedium</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecordMedium</name>
+ <direction>out</direction>
+ <relatedStateVariable>RecordStorageMedium</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>WriteStatus</name>
+ <direction>out</direction>
+ <relatedStateVariable>RecordMediumWriteStatus</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetPositionInfo</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Track</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrack</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TrackDuration</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrackDuration</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TrackMetaData</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrackMetaData</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TrackURI</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrackURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RelTime</name>
+ <direction>out</direction>
+ <relatedStateVariable>RelativeTimePosition</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>AbsTime</name>
+ <direction>out</direction>
+ <relatedStateVariable>AbsoluteTimePosition</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RelCount</name>
+ <direction>out</direction>
+ <relatedStateVariable>RelativeCounterPosition</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>AbsCount</name>
+ <direction>out</direction>
+ <relatedStateVariable>AbsoluteCounterPosition</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetTransportInfo</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentTransportState</name>
+ <direction>out</direction>
+ <relatedStateVariable>TransportState</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentTransportStatus</name>
+ <direction>out</direction>
+ <relatedStateVariable>TransportStatus</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentSpeed</name>
+ <direction>out</direction>
+ <relatedStateVariable>TransportPlaySpeed</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetTransportSettings</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PlayMode</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentPlayMode</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecQualityMode</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentRecordQualityMode</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Next</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Pause</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Play</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Speed</name>
+ <direction>in</direction>
+ <relatedStateVariable>TransportPlaySpeed</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Previous</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Seek</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Unit</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SeekMode</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Target</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SeekTarget</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetAVTransportURI</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURI</name>
+ <direction>in</direction>
+ <relatedStateVariable>AVTransportURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURIMetaData</name>
+ <direction>in</direction>
+ <relatedStateVariable>AVTransportURIMetaData</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetNextAVTransportURI</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NextURI</name>
+ <direction>in</direction>
+ <relatedStateVariable>NextAVTransportURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NextURIMetaData</name>
+ <direction>in</direction>
+ <relatedStateVariable>NextAVTransportURIMetaData</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetPlayMode</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NewPlayMode</name>
+ <direction>in</direction>
+ <relatedStateVariable>CurrentPlayMode</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Stop</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="no">
+ <name>CurrentPlayMode</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NORMAL</allowedValue>
+ <allowedValue>REPEAT_ONE</allowedValue>
+ <allowedValue>REPEAT_ALL</allowedValue>
+ <allowedValue>SHUFFLE</allowedValue>
+ <allowedValue>SHUFFLE_NOREPEAT</allowedValue>
+ </allowedValueList>
+ <defaultValue>NORMAL</defaultValue>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RecordStorageMedium</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>LastChange</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RelativeTimePosition</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrackURI</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrackDuration</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentRecordQualityMode</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentMediaDuration</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AbsoluteCounterPosition</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RelativeCounterPosition</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_InstanceID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AVTransportURI</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>TransportState</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>STOPPED</allowedValue>
+ <allowedValue>PAUSED_PLAYBACK</allowedValue>
+ <allowedValue>PLAYING</allowedValue>
+ <allowedValue>TRANSITIONING</allowedValue>
+ <allowedValue>NO_MEDIA_PRESENT</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrackMetaData</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>NextAVTransportURI</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PossibleRecordQualityModes</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrack</name>
+ <dataType>ui4</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>65535</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AbsoluteTimePosition</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>NextAVTransportURIMetaData</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PlaybackStorageMedium</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NONE</allowedValue>
+ <allowedValue>UNKNOWN</allowedValue>
+ <allowedValue>CD-DA</allowedValue>
+ <allowedValue>HDD</allowedValue>
+ <allowedValue>NETWORK</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTransportActions</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RecordMediumWriteStatus</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PossiblePlaybackStorageMedia</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NONE</allowedValue>
+ <allowedValue>UNKNOWN</allowedValue>
+ <allowedValue>CD-DA</allowedValue>
+ <allowedValue>HDD</allowedValue>
+ <allowedValue>NETWORK</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AVTransportURIMetaData</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>NumberOfTracks</name>
+ <dataType>ui4</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>65535</maximum>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_SeekMode</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>REL_TIME</allowedValue>
+ <allowedValue>TRACK_NR</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_SeekTarget</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PossibleRecordStorageMedia</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>TransportStatus</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>OK</allowedValue>
+ <allowedValue>ERROR_OCCURRED</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>TransportPlaySpeed</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>1</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ </serviceStateTable>
+</scpd> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPDFull.xml b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPDFull.xml
new file mode 100644
index 0000000..72de6b0
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/AVTransportSCPDFull.xml
@@ -0,0 +1,561 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>GetCurrentTransportActions</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Actions</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTransportActions</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetDeviceCapabilities</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PlayMedia</name>
+ <direction>out</direction>
+ <relatedStateVariable>PossiblePlaybackStorageMedia</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecMedia</name>
+ <direction>out</direction>
+ <relatedStateVariable>PossibleRecordStorageMedia</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecQualityModes</name>
+ <direction>out</direction>
+ <relatedStateVariable>PossibleRecordQualityModes</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetMediaInfo</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NrTracks</name>
+ <direction>out</direction>
+ <relatedStateVariable>NumberOfTracks</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>MediaDuration</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentMediaDuration</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURI</name>
+ <direction>out</direction>
+ <relatedStateVariable>AVTransportURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURIMetaData</name>
+ <direction>out</direction>
+ <relatedStateVariable>AVTransportURIMetaData</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NextURI</name>
+ <direction>out</direction>
+ <relatedStateVariable>NextAVTransportURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NextURIMetaData</name>
+ <direction>out</direction>
+ <relatedStateVariable>NextAVTransportURIMetaData</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PlayMedium</name>
+ <direction>out</direction>
+ <relatedStateVariable>PlaybackStorageMedium</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecordMedium</name>
+ <direction>out</direction>
+ <relatedStateVariable>RecordStorageMedium</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>WriteStatus</name>
+ <direction>out</direction>
+ <relatedStateVariable>RecordMediumWriteStatus</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetPositionInfo</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Track</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrack</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TrackDuration</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrackDuration</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TrackMetaData</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrackMetaData</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TrackURI</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentTrackURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RelTime</name>
+ <direction>out</direction>
+ <relatedStateVariable>RelativeTimePosition</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>AbsTime</name>
+ <direction>out</direction>
+ <relatedStateVariable>AbsoluteTimePosition</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RelCount</name>
+ <direction>out</direction>
+ <relatedStateVariable>RelativeCounterPosition</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>AbsCount</name>
+ <direction>out</direction>
+ <relatedStateVariable>AbsoluteCounterPosition</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetTransportInfo</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentTransportState</name>
+ <direction>out</direction>
+ <relatedStateVariable>TransportState</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentTransportStatus</name>
+ <direction>out</direction>
+ <relatedStateVariable>TransportStatus</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentSpeed</name>
+ <direction>out</direction>
+ <relatedStateVariable>TransportPlaySpeed</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetTransportSettings</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PlayMode</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentPlayMode</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RecQualityMode</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentRecordQualityMode</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Next</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Pause</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Play</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Speed</name>
+ <direction>in</direction>
+ <relatedStateVariable>TransportPlaySpeed</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Previous</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Seek</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Unit</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SeekMode</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Target</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SeekTarget</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetAVTransportURI</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURI</name>
+ <direction>in</direction>
+ <relatedStateVariable>AVTransportURI</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentURIMetaData</name>
+ <direction>in</direction>
+ <relatedStateVariable>AVTransportURIMetaData</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetPlayMode</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NewPlayMode</name>
+ <direction>in</direction>
+ <relatedStateVariable>CurrentPlayMode</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Stop</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="no">
+ <name>CurrentPlayMode</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>NORMAL</allowedValue>
+ <allowedValue>REPEAT_ALL</allowedValue>
+ <allowedValue>INTRO</allowedValue>
+ </allowedValueList>
+ <defaultValue>NORMAL</defaultValue>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RecordStorageMedium</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>UNKNOWN</allowedValue>
+ <allowedValue>DV</allowedValue>
+ <allowedValue>MINI-DV</allowedValue>
+ <allowedValue>VHS</allowedValue>
+ <allowedValue>W-VHS</allowedValue>
+ <allowedValue>S-VHS</allowedValue>
+ <allowedValue>D-VHS</allowedValue>
+ <allowedValue>VHSC</allowedValue>
+ <allowedValue>VIDEO8</allowedValue>
+ <allowedValue>HI8</allowedValue>
+ <allowedValue>CD-ROM</allowedValue>
+ <allowedValue>CD-DA</allowedValue>
+ <allowedValue>CD-R</allowedValue>
+ <allowedValue>CD-RW</allowedValue>
+ <allowedValue>VIDEO-CD</allowedValue>
+ <allowedValue>SACD</allowedValue>
+ <allowedValue>MD-AUDIO</allowedValue>
+ <allowedValue>MD-PICTURE</allowedValue>
+ <allowedValue>DVD-ROM</allowedValue>
+ <allowedValue>DVD-VIDEO</allowedValue>
+ <allowedValue>DVD-R</allowedValue>
+ <allowedValue>DVD+RW</allowedValue>
+ <allowedValue>DVD-RW</allowedValue>
+ <allowedValue>DVD-RAM</allowedValue>
+ <allowedValue>DVD-AUDIO</allowedValue>
+ <allowedValue>DAT</allowedValue>
+ <allowedValue>LD</allowedValue>
+ <allowedValue>HDD</allowedValue>
+ <allowedValue>MICRO-MV</allowedValue>
+ <allowedValue>NETWORK</allowedValue>
+ <allowedValue>NONE</allowedValue>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ <allowedValue> vendor-defined </allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>LastChange</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RelativeTimePosition</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrackURI</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrackDuration</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentRecordQualityMode</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>0:EP</allowedValue>
+ <allowedValue>1:LP</allowedValue>
+ <allowedValue>2:SP</allowedValue>
+ <allowedValue>0:BASIC</allowedValue>
+ <allowedValue>1:MEDIUM</allowedValue>
+ <allowedValue>2:HIGH</allowedValue>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ <allowedValue> vendor-defined </allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentMediaDuration</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AbsoluteCounterPosition</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RelativeCounterPosition</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_InstanceID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AVTransportURI</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>TransportState</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>STOPPED</allowedValue>
+ <allowedValue>PAUSED_PLAYBACK</allowedValue>
+ <allowedValue>PAUSED_RECORDING</allowedValue>
+ <allowedValue>PLAYING</allowedValue>
+ <allowedValue>RECORDING</allowedValue>
+ <allowedValue>TRANSITIONING</allowedValue>
+ <allowedValue>NO_MEDIA_PRESENT</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrackMetaData</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>NextAVTransportURI</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PossibleRecordQualityModes</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTrack</name>
+ <dataType>ui4</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>4294967295</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AbsoluteTimePosition</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>NextAVTransportURIMetaData</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PlaybackStorageMedium</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>UNKNOWN</allowedValue>
+ <allowedValue>DV</allowedValue>
+ <allowedValue>MINI-DV</allowedValue>
+ <allowedValue>VHS</allowedValue>
+ <allowedValue>W-VHS</allowedValue>
+ <allowedValue>S-VHS</allowedValue>
+ <allowedValue>D-VHS</allowedValue>
+ <allowedValue>VHSC</allowedValue>
+ <allowedValue>VIDEO8</allowedValue>
+ <allowedValue>HI8</allowedValue>
+ <allowedValue>CD-ROM</allowedValue>
+ <allowedValue>CD-DA</allowedValue>
+ <allowedValue>CD-R</allowedValue>
+ <allowedValue>CD-RW</allowedValue>
+ <allowedValue>VIDEO-CD</allowedValue>
+ <allowedValue>SACD</allowedValue>
+ <allowedValue>MD-AUDIO</allowedValue>
+ <allowedValue>MD-PICTURE</allowedValue>
+ <allowedValue>DVD-ROM</allowedValue>
+ <allowedValue>DVD-VIDEO</allowedValue>
+ <allowedValue>DVD-R</allowedValue>
+ <allowedValue>DVD+RW</allowedValue>
+ <allowedValue>DVD-RW</allowedValue>
+ <allowedValue>DVD-RAM</allowedValue>
+ <allowedValue>DVD-AUDIO</allowedValue>
+ <allowedValue>DAT</allowedValue>
+ <allowedValue>LD</allowedValue>
+ <allowedValue>HDD</allowedValue>
+ <allowedValue>MICRO-MV</allowedValue>
+ <allowedValue>NETWORK</allowedValue>
+ <allowedValue>NONE</allowedValue>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ <allowedValue> vendor-defined </allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>CurrentTransportActions</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RecordMediumWriteStatus</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>WRITABLE</allowedValue>
+ <allowedValue>PROTECTED</allowedValue>
+ <allowedValue>NOT_WRITABLE</allowedValue>
+ <allowedValue>UNKNOWN</allowedValue>
+ <allowedValue>NOT_IMPLEMENTED</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PossiblePlaybackStorageMedia</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>AVTransportURIMetaData</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>NumberOfTracks</name>
+ <dataType>ui4</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>4294967295</maximum>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_SeekMode</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>ABS_TIME</allowedValue>
+ <allowedValue>REL_TIME</allowedValue>
+ <allowedValue>ABS_COUNT</allowedValue>
+ <allowedValue>REL_COUNT</allowedValue>
+ <allowedValue>TRACK_NR</allowedValue>
+ <allowedValue>CHANNEL_FREQ</allowedValue>
+ <allowedValue>TAPE-INDEX</allowedValue>
+ <allowedValue>FRAME</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_SeekTarget</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PossibleRecordStorageMedia</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>TransportStatus</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>OK</allowedValue>
+ <allowedValue>ERROR_OCCURRED</allowedValue>
+ <allowedValue> vendor-defined </allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>TransportPlaySpeed</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>1</allowedValue>
+ <allowedValue> vendor-defined </allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ </serviceStateTable>
+</scpd> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp
new file mode 100644
index 0000000..87aabf3
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.cpp
@@ -0,0 +1,1392 @@
+/*****************************************************************
+|
+| Platinum - AV Media Controller (Media Renderer Control Point)
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaController.h"
+#include "PltDidl.h"
+#include "PltDeviceData.h"
+#include "PltUtilities.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.renderer.controller")
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::PLT_MediaController
++---------------------------------------------------------------------*/
+PLT_MediaController::PLT_MediaController(PLT_CtrlPointReference& ctrl_point,
+ PLT_MediaControllerDelegate* delegate /* = NULL */) :
+ m_CtrlPoint(ctrl_point),
+ m_Delegate(delegate)
+{
+ m_CtrlPoint->AddListener(this);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::~PLT_MediaController
++---------------------------------------------------------------------*/
+PLT_MediaController::~PLT_MediaController()
+{
+ m_CtrlPoint->RemoveListener(this);
+}
+
+/*----------------------------------------------------------------------
+| 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;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnDeviceRemoved
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnDeviceRemoved(PLT_DeviceDataReference& device)
+{
+ if (!device->GetType().StartsWith("urn:schemas-upnp-org:device:MediaRenderer"))
+ return NPT_FAILURE;
+
+ {
+ NPT_AutoLock lock(m_MediaRenderers);
+
+ // 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_MediaRenderers, 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_MediaRenderers.Remove(device);
+ }
+
+ if (m_Delegate) {
+ m_Delegate->OnMRRemoved(device);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::FindRenderer
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::FindRenderer(const char* uuid, PLT_DeviceDataReference& device)
+{
+ NPT_AutoLock lock(m_MediaRenderers);
+
+ 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);
+ return NPT_FAILURE;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetProtocolInfoSink
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetProtocolInfoSink(const NPT_String& device_uuid,
+ NPT_List<NPT_String>& sinks)
+{
+ PLT_DeviceDataReference renderer;
+ NPT_CHECK_WARNING(FindRenderer(device_uuid, renderer));
+
+ // look for ConnectionManager service
+ PLT_Service* serviceCMR;
+ NPT_CHECK_SEVERE(renderer->FindServiceByType("urn:schemas-upnp-org:service:ConnectionManager:*",
+ serviceCMR));
+
+ NPT_String value;
+ NPT_CHECK_SEVERE(serviceCMR->GetStateVariableValue("SinkProtocolInfo",
+ value));
+
+ sinks = value.Split(",");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetTransportState
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetTransportState(const NPT_String& device_uuid,
+ NPT_String& state)
+{
+ PLT_DeviceDataReference renderer;
+ NPT_CHECK_WARNING(FindRenderer(device_uuid, renderer));
+
+ // look for AVTransport service
+ PLT_Service* serviceAVT;
+ NPT_CHECK_SEVERE(renderer->FindServiceByType("urn:schemas-upnp-org:service:AVTransport:*",
+ serviceAVT));
+
+ NPT_CHECK_SEVERE(serviceAVT->GetStateVariableValue("TransportState",
+ state));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetVolumeState
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetVolumeState(const NPT_String& device_uuid,
+ NPT_UInt32& volume)
+{
+ PLT_DeviceDataReference renderer;
+ NPT_CHECK_WARNING(FindRenderer(device_uuid, renderer));
+
+ // look for RenderingControl service
+ PLT_Service* serviceRC;
+ NPT_CHECK_SEVERE(renderer->FindServiceByType("urn:schemas-upnp-org:service:RenderingControl:*",
+ serviceRC));
+
+ NPT_String value;
+ NPT_CHECK_SEVERE(serviceRC->GetStateVariableValue("Volume",
+ value));
+
+ return value.ToInteger32(volume);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::FindMatchingProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::FindMatchingProtocolInfo(NPT_List<NPT_String>& sinks,
+ const char* protocol_info)
+{
+ PLT_ProtocolInfo protocol(protocol_info);
+ for (NPT_List<NPT_String>::Iterator iter = sinks.GetFirstItem();
+ iter;
+ iter++) {
+ PLT_ProtocolInfo sink(*iter);
+ if (sink.Match(protocol)) {
+ return NPT_SUCCESS;
+ }
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::FindBestResource
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::FindBestResource(PLT_DeviceDataReference& device,
+ PLT_MediaObject& item,
+ NPT_Cardinal& resource_index)
+{
+ if (item.m_Resources.GetItemCount() <= 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+ NPT_List<NPT_String> sinks;
+ NPT_CHECK_SEVERE(GetProtocolInfoSink(device->GetUUID(), sinks));
+
+ // look for best resource
+ for (NPT_Cardinal i=0; i< item.m_Resources.GetItemCount(); i++) {
+ if (NPT_SUCCEEDED(FindMatchingProtocolInfo(
+ sinks,
+ item.m_Resources[i].m_ProtocolInfo.ToString()))) {
+ resource_index = i;
+ return NPT_SUCCESS;
+ }
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::InvokeActionWithInstance
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::InvokeActionWithInstance(PLT_ActionReference& action,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ // Set the object id
+ NPT_CHECK_SEVERE(action->SetArgumentValue(
+ "InstanceID",
+ NPT_String::FromInteger(instance_id)));
+
+ // set the arguments on the action, this will check the argument values
+ return m_CtrlPoint->InvokeAction(action, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetCurrentTransportActions
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetCurrentTransportActions(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "GetCurrentTransportActions",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetDeviceCapabilities
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetDeviceCapabilities(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "GetDeviceCapabilities",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetMediaInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetMediaInfo(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "GetMediaInfo",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetPositionInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetPositionInfo(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "GetPositionInfo",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetTransportInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetTransportInfo(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "GetTransportInfo",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetTransportSettings
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetTransportSettings(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "GetTransportSettings",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::Next
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::Next(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "Next",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::Pause
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::Pause(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "Pause",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::Play
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::Play(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ NPT_String speed,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "Play",
+ action));
+
+ // Set the speed
+ if (NPT_FAILED(action->SetArgumentValue("Speed", speed))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::Previous
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::Previous(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "Previous",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::Seek(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ NPT_String unit,
+ NPT_String target,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "Seek",
+ action));
+
+ // Set the unit
+ if (NPT_FAILED(action->SetArgumentValue("Unit", unit))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // Set the target
+ if (NPT_FAILED(action->SetArgumentValue("Target", target))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::CanSetNextAVTransportURI
++---------------------------------------------------------------------*/
+bool
+PLT_MediaController::CanSetNextAVTransportURI(PLT_DeviceDataReference &device)
+{
+ if (device.IsNull()) return false;
+
+ PLT_ActionDesc* action_desc;
+ NPT_Result result = m_CtrlPoint->FindActionDesc(device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "SetNextAVTransportURI",
+ action_desc);
+ return (result == NPT_SUCCESS);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::SetAVTransportURI
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::SetAVTransportURI(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ const char* uri,
+ const char* metadata,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "SetAVTransportURI",
+ action));
+
+ // set the uri
+ if (NPT_FAILED(action->SetArgumentValue("CurrentURI", uri))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the uri metadata
+ if (NPT_FAILED(action->SetArgumentValue("CurrentURIMetaData", metadata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::SetNextAVTransportURI
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::SetNextAVTransportURI(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ const char* next_uri,
+ const char* next_metadata,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "SetNextAVTransportURI",
+ action));
+
+ // set the uri
+ if (NPT_FAILED(action->SetArgumentValue("NextURI", next_uri))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the uri metadata
+ if (NPT_FAILED(action->SetArgumentValue("NextURIMetaData", next_metadata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::SetPlayMode
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::SetPlayMode(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ NPT_String new_play_mode,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "SetPlayMode",
+ action));
+
+ // set the New PlayMode
+ if (NPT_FAILED(action->SetArgumentValue("NewPlayMode", new_play_mode))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::Stop(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:AVTransport:1",
+ "Stop",
+ action));
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetCurrentConnectionIDs
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetCurrentConnectionIDs(PLT_DeviceDataReference& device,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:ConnectionManager:1",
+ "GetCurrentConnectionIDs",
+ action));
+
+ // set the arguments on the action, this will check the argument values
+ if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetCurrentConnectionInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetCurrentConnectionInfo(PLT_DeviceDataReference& device,
+ NPT_UInt32 connection_id,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:ConnectionManager:1",
+ "GetCurrentConnectionInfo",
+ action));
+
+ // set the New PlayMode
+ if (NPT_FAILED(action->SetArgumentValue("ConnectionID",
+ NPT_String::FromInteger(connection_id)))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the arguments on the action, this will check the argument values
+ if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetProtocolInfo(PLT_DeviceDataReference& device,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:ConnectionManager:1",
+ "GetProtocolInfo",
+ action));
+
+ // set the arguments on the action, this will check the argument values
+ if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::SetMute
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::SetMute(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ const char* channel,
+ bool mute,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:RenderingControl:1",
+ "SetMute",
+ action));
+
+ // set the channel
+ if (NPT_FAILED(action->SetArgumentValue("Channel", channel))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the channel
+ if (NPT_FAILED(action->SetArgumentValue("DesiredMute",
+ mute?"1":"0"))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::SetVolume
++---------------------------------------------------------------------*/
+NPT_Result PLT_MediaController::SetVolume(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ const char* channel,
+ int volume,
+ void* userdata)
+{
+
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:RenderingControl:1",
+ "SetVolume",
+ action));
+
+ // set the channel
+ if (NPT_FAILED(action->SetArgumentValue("Channel", channel))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ if (NPT_FAILED(action->SetArgumentValue("DesiredVolume",
+ NPT_String::FromInteger(volume)))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetMute
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::GetMute(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ const char* channel,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:RenderingControl:1",
+ "GetMute",
+ action));
+
+ // set the channel
+ if (NPT_FAILED(action->SetArgumentValue("Channel", channel))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::GetVolume
++---------------------------------------------------------------------*/
+NPT_Result PLT_MediaController::GetVolume(PLT_DeviceDataReference& device,
+ NPT_UInt32 instance_id,
+ const char* channel,
+ void* userdata)
+{
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:RenderingControl:1",
+ "GetVolume",
+ action));
+
+ // set the channel
+ if (NPT_FAILED(action->SetArgumentValue("Channel", channel))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return InvokeActionWithInstance(action, instance_id, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnActionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnActionResponse(NPT_Result res,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ if (m_Delegate == NULL) return NPT_SUCCESS;
+
+ PLT_DeviceDataReference device;
+ NPT_String uuid = action->GetActionDesc().GetService()->GetDevice()->GetUUID();
+
+ /* extract action name */
+ NPT_String actionName = action->GetActionDesc().GetName();
+
+ /* AVTransport response ? */
+ if (actionName.Compare("GetCurrentTransportActions", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetCurrentTransportActionsResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("GetDeviceCapabilities", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetDeviceCapabilitiesResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("GetMediaInfo", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetMediaInfoResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("GetPositionInfo", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetPositionInfoResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("GetTransportInfo", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetTransportInfoResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("GetTransportSettings", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetTransportSettingsResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("Next", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnNextResult(res, device, userdata);
+ }
+ else if (actionName.Compare("Pause", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnPauseResult(res, device, userdata);
+ }
+ else if (actionName.Compare("Play", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnPlayResult(res, device, userdata);
+ }
+ else if (actionName.Compare("Previous", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnPreviousResult(res, device, userdata);
+ }
+ else if (actionName.Compare("Seek", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnSeekResult(res, device, userdata);
+ }
+ else if (actionName.Compare("SetAVTransportURI", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnSetAVTransportURIResult(res, device, userdata);
+ }
+ else if (actionName.Compare("SetNextAVTransportURI", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnSetNextAVTransportURIResult(res, device, userdata);
+ }
+ else if (actionName.Compare("SetPlayMode", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnSetPlayModeResult(res, device, userdata);
+ }
+ else if (actionName.Compare("Stop", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnStopResult(res, device, userdata);
+ }
+ else if (actionName.Compare("GetCurrentConnectionIDs", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetCurrentConnectionIDsResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("GetCurrentConnectionInfo", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetCurrentConnectionInfoResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("GetProtocolInfo", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetProtocolInfoResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("SetMute", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnSetMuteResult(res, device, userdata);
+ }
+ else if (actionName.Compare("GetMute", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetMuteResponse(res, device, action, userdata);
+ }
+ else if (actionName.Compare("SetVolume", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ m_Delegate->OnSetVolumeResult(res, device, userdata);
+ }
+ else if (actionName.Compare("GetVolume", true) == 0) {
+ if (NPT_FAILED(FindRenderer(uuid, device))) res = NPT_FAILURE;
+ return OnGetVolumeResponse(res, device, action, userdata);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetCurrentTransportActionsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentTransportActionsResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String actions;
+ PLT_StringList values;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("Actions", actions))) {
+ goto bad_action;
+ }
+
+ // parse the list of actions and return a list to listener
+ ParseCSV(actions, values);
+
+ m_Delegate->OnGetCurrentTransportActionsResult(NPT_SUCCESS, device, &values, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetCurrentTransportActionsResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetDeviceCapabilitiesResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetDeviceCapabilitiesResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+ PLT_DeviceCapabilities capabilities;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("PlayMedia", value))) {
+ goto bad_action;
+ }
+ // parse the list of medias and return a list to listener
+ ParseCSV(value, capabilities.play_media);
+
+ if (NPT_FAILED(action->GetArgumentValue("RecMedia", value))) {
+ goto bad_action;
+ }
+ // parse the list of rec and return a list to listener
+ ParseCSV(value, capabilities.rec_media);
+
+ if (NPT_FAILED(action->GetArgumentValue("RecQualityModes", value))) {
+ goto bad_action;
+ }
+ // parse the list of modes and return a list to listener
+ ParseCSV(value, capabilities.rec_quality_modes);
+
+ m_Delegate->OnGetDeviceCapabilitiesResult(NPT_SUCCESS, device, &capabilities, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetDeviceCapabilitiesResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetMediaInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetMediaInfoResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+ PLT_MediaInfo info;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("NrTracks", info.num_tracks))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("MediaDuration", value))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.media_duration))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("CurrentURI", info.cur_uri))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("CurrentURIMetaData", info.cur_metadata))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("NextURI", info.next_uri))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("NextURIMetaData", info.next_metadata))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("PlayMedium", info.play_medium))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("RecordMedium", info.rec_medium))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("WriteStatus", info.write_status))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetMediaInfoResult(NPT_SUCCESS, device, &info, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetMediaInfoResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetPositionInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetPositionInfoResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+ PLT_PositionInfo info;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("Track", info.track))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("TrackDuration", value))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.track_duration))) {
+ // some renderers return garbage sometimes
+ info.track_duration = NPT_TimeStamp(0.);
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("TrackMetaData", info.track_metadata))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("TrackURI", info.track_uri))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("RelTime", value))) {
+ goto bad_action;
+ }
+
+ // NOT_IMPLEMENTED is a valid value according to spec
+ if (value != "NOT_IMPLEMENTED" && NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.rel_time))) {
+ // some dogy renderers return garbage sometimes
+ info.rel_time = NPT_TimeStamp(-1.0f);
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("AbsTime", value))) {
+ goto bad_action;
+ }
+
+ // NOT_IMPLEMENTED is a valid value according to spec
+ if (value != "NOT_IMPLEMENTED" && NPT_FAILED(PLT_Didl::ParseTimeStamp(value, info.abs_time))) {
+ // some dogy renderers return garbage sometimes
+ info.abs_time = NPT_TimeStamp(-1.0f);
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("RelCount", info.rel_count))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("AbsCount", info.abs_count))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetPositionInfoResult(NPT_SUCCESS, device, &info, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetPositionInfoResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetTransportInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetTransportInfoResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ PLT_TransportInfo info;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("CurrentTransportState", info.cur_transport_state))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("CurrentTransportStatus", info.cur_transport_status))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("CurrentSpeed", info.cur_speed))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetTransportInfoResult(NPT_SUCCESS, device, &info, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetTransportInfoResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetTransportSettingsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetTransportSettingsResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ PLT_TransportSettings settings;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("PlayMode", settings.play_mode))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("RecQualityMode", settings.rec_quality_mode))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetTransportSettingsResult(NPT_SUCCESS, device, &settings, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetTransportSettingsResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetCurrentConnectionIDsResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentConnectionIDsResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+ PLT_StringList IDs;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("ConnectionIDs", value))) {
+ goto bad_action;
+ }
+ // parse the list of medias and return a list to listener
+ ParseCSV(value, IDs);
+
+ m_Delegate->OnGetCurrentConnectionIDsResult(NPT_SUCCESS, device, &IDs, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetCurrentConnectionIDsResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetCurrentConnectionInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetCurrentConnectionInfoResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+ PLT_ConnectionInfo info;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("RcsID", info.rcs_id))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("AVTransportID", info.avtransport_id))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("ProtocolInfo", info.protocol_info))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("PeerConnectionManager", info.peer_connection_mgr))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("PeerConnectionID", info.peer_connection_id))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("Direction", info.direction))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("Status", info.status))) {
+ goto bad_action;
+ }
+ m_Delegate->OnGetCurrentConnectionInfoResult(NPT_SUCCESS, device, &info, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetCurrentConnectionInfoResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetProtocolInfoResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetProtocolInfoResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String source_info, sink_info;
+ PLT_StringList sources, sinks;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("Source", source_info))) {
+ goto bad_action;
+ }
+ ParseCSV(source_info, sources);
+
+ if (NPT_FAILED(action->GetArgumentValue("Sink", sink_info))) {
+ goto bad_action;
+ }
+ ParseCSV(sink_info, sinks);
+
+ m_Delegate->OnGetProtocolInfoResult(NPT_SUCCESS, device, &sources, &sinks, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetProtocolInfoResult(NPT_FAILURE, device, NULL, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetMuteResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetMuteResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String channel, mute;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("Channel", channel))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("CurrentMute", mute))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetMuteResult(
+ NPT_SUCCESS,
+ device,
+ channel,
+ PLT_Service::IsTrue(mute)?true:false,
+ userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetMuteResult(NPT_FAILURE, device, "", false, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnGetVolumeResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnGetVolumeResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String channel;
+ NPT_String current_volume;
+ NPT_UInt32 volume;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("Channel", channel))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("CurrentVolume", current_volume))) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(current_volume.ToInteger(volume))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetVolumeResult(NPT_SUCCESS, device, channel, volume, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetVolumeResult(NPT_FAILURE, device, "", 0, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaController::OnEventNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaController::OnEventNotify(PLT_Service* service,
+ NPT_List<PLT_StateVariable*>* vars)
+{
+ if (!service->GetDevice()->GetType().StartsWith("urn:schemas-upnp-org:device:MediaRenderer"))
+ return NPT_FAILURE;
+
+ if (!m_Delegate) return NPT_SUCCESS;
+
+ /* make sure device associated to service is still around */
+ PLT_DeviceDataReference data;
+ NPT_CHECK_WARNING(FindRenderer(service->GetDevice()->GetUUID(), data));
+
+ m_Delegate->OnMRStateVariablesChanged(service, vars);
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.h b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.h
new file mode 100644
index 0000000..743c94f
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaController.h
@@ -0,0 +1,349 @@
+/*****************************************************************
+|
+| Platinum - AV Media Controller (Media Renderer Control Point)
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_CONTROLLER_H_
+#define _PLT_MEDIA_CONTROLLER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltCtrlPoint.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+| Defines
++---------------------------------------------------------------------*/
+typedef NPT_List<NPT_String> PLT_StringList;
+
+typedef struct {
+ PLT_StringList play_media;
+ PLT_StringList rec_media;
+ PLT_StringList rec_quality_modes;
+} PLT_DeviceCapabilities;
+
+typedef struct {
+ NPT_UInt32 num_tracks;
+ NPT_TimeStamp media_duration;
+ NPT_String cur_uri;
+ NPT_String cur_metadata;
+ NPT_String next_uri;
+ NPT_String next_metadata;
+ NPT_String play_medium;
+ NPT_String rec_medium;
+ NPT_String write_status;
+} PLT_MediaInfo;
+
+typedef struct {
+ NPT_UInt32 track;
+ NPT_TimeStamp track_duration;
+ NPT_String track_metadata;
+ NPT_String track_uri;
+ NPT_TimeStamp rel_time;
+ NPT_TimeStamp abs_time;
+ NPT_Int32 rel_count;
+ NPT_Int32 abs_count;
+} PLT_PositionInfo;
+
+typedef struct {
+ NPT_String cur_transport_state;
+ NPT_String cur_transport_status;
+ NPT_String cur_speed;
+} PLT_TransportInfo;
+
+typedef struct {
+ NPT_String play_mode;
+ NPT_String rec_quality_mode;
+} PLT_TransportSettings;
+
+typedef struct {
+ NPT_UInt32 rcs_id;
+ NPT_UInt32 avtransport_id;
+ NPT_String protocol_info;
+ NPT_String peer_connection_mgr;
+ NPT_UInt32 peer_connection_id;
+ NPT_String direction;
+ NPT_String status;
+} PLT_ConnectionInfo;
+
+/*----------------------------------------------------------------------
+| PLT_MediaControllerDelegate
++---------------------------------------------------------------------*/
+class PLT_MediaControllerDelegate
+{
+public:
+ virtual ~PLT_MediaControllerDelegate() {}
+
+ virtual bool OnMRAdded(PLT_DeviceDataReference& /* device */) { return true; }
+ virtual void OnMRRemoved(PLT_DeviceDataReference& /* device */) {}
+ virtual void OnMRStateVariablesChanged(PLT_Service* /* service */,
+ NPT_List<PLT_StateVariable*>* /* vars */) {}
+
+ // AVTransport
+ virtual void OnGetCurrentTransportActionsResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_StringList* /* actions */,
+ void* /* userdata */) {}
+
+ virtual void OnGetDeviceCapabilitiesResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_DeviceCapabilities* /* capabilities */,
+ void* /* userdata */) {}
+
+ virtual void OnGetMediaInfoResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_MediaInfo* /* info */,
+ void* /* userdata */) {}
+
+ virtual void OnGetPositionInfoResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_PositionInfo* /* info */,
+ void* /* userdata */) {}
+
+ virtual void OnGetTransportInfoResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_TransportInfo* /* info */,
+ void* /* userdata */) {}
+
+ virtual void OnGetTransportSettingsResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_TransportSettings* /* settings */,
+ void* /* userdata */) {}
+
+ virtual void OnNextResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnPauseResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnPlayResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnPreviousResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnSeekResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnSetAVTransportURIResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnSetNextAVTransportURIResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnSetPlayModeResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnStopResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ // ConnectionManager
+ virtual void OnGetCurrentConnectionIDsResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_StringList* /* ids */,
+ void* /* userdata */) {}
+
+ virtual void OnGetCurrentConnectionInfoResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_ConnectionInfo* /* info */,
+ void* /* userdata */) {}
+
+ virtual void OnGetProtocolInfoResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ PLT_StringList* /* sources */,
+ PLT_StringList* /* sinks */,
+ void* /* userdata */) {}
+
+ // RenderingControl
+ virtual void OnSetMuteResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnGetMuteResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ const char* /* channel */,
+ bool /* mute */,
+ void* /* userdata */) {}
+
+ virtual void OnSetVolumeResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ void* /* userdata */) {}
+
+ virtual void OnGetVolumeResult(
+ NPT_Result /* res */,
+ PLT_DeviceDataReference& /* device */,
+ const char* /* channel */,
+ NPT_UInt32 /* volume */,
+ void* /* userdata */) {}
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaController
++---------------------------------------------------------------------*/
+class PLT_MediaController : public PLT_CtrlPointListener
+{
+public:
+ PLT_MediaController(PLT_CtrlPointReference& ctrl_point,
+ PLT_MediaControllerDelegate* delegate = NULL);
+ ~PLT_MediaController() override;
+
+ // public methods
+ virtual void SetDelegate(PLT_MediaControllerDelegate* delegate) {
+ m_Delegate = delegate;
+ }
+
+ // PLT_CtrlPointListener methods
+ NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device) override;
+ NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device) override;
+ NPT_Result OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata) override;
+ NPT_Result OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars) override;
+
+ // AVTransport
+ NPT_Result GetCurrentTransportActions(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result GetDeviceCapabilities(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result GetMediaInfo(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result GetPositionInfo(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result GetTransportInfo(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result GetTransportSettings(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result Next(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result Pause(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result Play(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, NPT_String speed, void* userdata);
+ NPT_Result Previous(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+ NPT_Result Seek(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, NPT_String unit, NPT_String target, void* userdata);
+ bool CanSetNextAVTransportURI(PLT_DeviceDataReference& device);
+ NPT_Result SetAVTransportURI(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* uri, const char* metadata, void* userdata);
+ NPT_Result SetNextAVTransportURI(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* next_uri, const char* next_metadata, void* userdata);
+ NPT_Result SetPlayMode(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, NPT_String new_play_mode, void* userdata);
+ NPT_Result Stop(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, void* userdata);
+
+ // ConnectionManager
+ NPT_Result GetCurrentConnectionIDs(PLT_DeviceDataReference& device, void* userdata);
+ NPT_Result GetCurrentConnectionInfo(PLT_DeviceDataReference& device, NPT_UInt32 connection_id, void* userdata);
+ NPT_Result GetProtocolInfo(PLT_DeviceDataReference& device, void* userdata);
+
+ // RenderingControl
+ NPT_Result SetMute(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* channel, bool mute, void* userdata);
+ NPT_Result GetMute(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* channel, void* userdata);
+ NPT_Result SetVolume(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* channel, int volume, void* userdata);
+ NPT_Result GetVolume(PLT_DeviceDataReference& device, NPT_UInt32 instance_id, const char* channel, void* userdata);
+
+ // VariableStates
+ virtual NPT_Result GetProtocolInfoSink(const NPT_String& device_uuid, NPT_List<NPT_String>& sinks);
+ virtual NPT_Result GetTransportState(const NPT_String& device_uuid, NPT_String& state);
+ virtual NPT_Result GetVolumeState(const NPT_String& device_uuid, NPT_UInt32& volume);
+
+ // methods
+ virtual NPT_Result FindRenderer(const char* uuid, PLT_DeviceDataReference& device);
+ virtual NPT_Result FindMatchingProtocolInfo(NPT_List<NPT_String>& sinks, const char* protocol_info);
+ virtual NPT_Result FindBestResource(PLT_DeviceDataReference& device, PLT_MediaObject& item, NPT_Cardinal& resource_index);
+
+private:
+ NPT_Result InvokeActionWithInstance(PLT_ActionReference& action, NPT_UInt32 instance_id, void* userdata = NULL);
+
+ NPT_Result OnGetCurrentTransportActionsResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetDeviceCapabilitiesResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetMediaInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetPositionInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetTransportInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetTransportSettingsResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+
+ NPT_Result OnGetCurrentConnectionIDsResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetCurrentConnectionInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetProtocolInfoResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+
+ NPT_Result OnGetMuteResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+ NPT_Result OnGetVolumeResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata);
+
+public:
+ static void ParseCSV(const char* csv, PLT_StringList& values) {
+ const char* start = csv;
+ const char* p = start;
+
+ // look for the , character
+ while (*p) {
+ if (*p == ',') {
+ NPT_String val(start, (int)(p-start));
+ val.Trim(' ');
+ values.Add(val);
+ start = p + 1;
+ }
+ p++;
+ }
+
+ // last one
+ NPT_String last(start, (int)(p-start));
+ last.Trim(' ');
+ if (last.GetLength()) {
+ values.Add(last);
+ }
+ }
+
+private:
+ PLT_CtrlPointReference m_CtrlPoint;
+ PLT_MediaControllerDelegate* m_Delegate;
+ NPT_Lock<PLT_DeviceDataReferenceList> m_MediaRenderers;
+};
+
+typedef NPT_Reference<PLT_MediaController> PLT_MediaControllerReference;
+
+#endif /* _PLT_MEDIA_CONTROLLER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.cpp
new file mode 100644
index 0000000..88144f7
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.cpp
@@ -0,0 +1,516 @@
+/*****************************************************************
+|
+| Platinum - AV Media Renderer Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaRenderer.h"
+#include "PltService.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.renderer")
+
+/*----------------------------------------------------------------------
+| external references
++---------------------------------------------------------------------*/
+extern NPT_UInt8 RDR_ConnectionManagerSCPD[];
+extern NPT_UInt8 RDR_AVTransportSCPD[];
+extern NPT_UInt8 RDR_RenderingControlSCPD[];
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::PLT_MediaRenderer
++---------------------------------------------------------------------*/
+PLT_MediaRenderer::PLT_MediaRenderer(const char* friendly_name,
+ bool show_ip /* = false */,
+ const char* uuid /* = NULL */,
+ unsigned int port /* = 0 */,
+ bool port_rebind /* = false */) :
+ PLT_DeviceHost("/",
+ uuid,
+ "urn:schemas-upnp-org:device:MediaRenderer:1",
+ friendly_name,
+ show_ip,
+ port,
+ port_rebind),
+ m_Delegate(NULL)
+{
+ m_ModelDescription = "Plutinosoft AV Media Renderer Device";
+ m_ModelName = "AV Renderer Device";
+ m_ModelURL = "http://www.plutinosoft.com/platinum";
+ m_DlnaDoc = "DMR-1.50";
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::~PLT_MediaRenderer
++---------------------------------------------------------------------*/
+PLT_MediaRenderer::~PLT_MediaRenderer()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::SetupServices()
+{
+ NPT_Reference<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.AsPointer()));
+
+ 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");
+
+ service.Detach();
+ service = NULL;
+ }
+
+ {
+ /* 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.AsPointer()));
+
+ 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", "");
+
+ service.Detach();
+ service = NULL;
+ }
+
+ {
+ /* 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.AsPointer()));
+
+ 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");
+
+ service.Detach();
+ service = NULL;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ /* parse the action name */
+ NPT_String name = action->GetActionDesc().GetName();
+
+ // since all actions take an instance ID and we only support 1 instance
+ // verify that the Instance ID is 0 and return an error here now if not
+ NPT_String serviceType = action->GetActionDesc().GetService()->GetServiceType();
+ if (serviceType.Compare("urn:schemas-upnp-org:service:AVTransport:1", true) == 0) {
+ if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) {
+ action->SetError(718, "Not valid InstanceID");
+ return NPT_FAILURE;
+ }
+ }
+ serviceType = action->GetActionDesc().GetService()->GetServiceType();
+ if (serviceType.Compare("urn:schemas-upnp-org:service:RenderingControl:1", true) == 0) {
+ if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) {
+ action->SetError(702, "Not valid InstanceID");
+ return NPT_FAILURE;
+ }
+ }
+
+ /* Is it a ConnectionManager Service Action ? */
+ if (name.Compare("GetCurrentConnectionInfo", true) == 0) {
+ return OnGetCurrentConnectionInfo(action);
+ }
+
+ /* Is it a AVTransport Service Action ? */
+ if (name.Compare("Next", true) == 0) {
+ return OnNext(action);
+ }
+ if (name.Compare("Pause", true) == 0) {
+ return OnPause(action);
+ }
+ if (name.Compare("Play", true) == 0) {
+ return OnPlay(action);
+ }
+ if (name.Compare("Previous", true) == 0) {
+ return OnPrevious(action);
+ }
+ if (name.Compare("Seek", true) == 0) {
+ return OnSeek(action);
+ }
+ if (name.Compare("Stop", true) == 0) {
+ return OnStop(action);
+ }
+ if (name.Compare("SetAVTransportURI", true) == 0) {
+ return OnSetAVTransportURI(action);
+ }
+ if (name.Compare("SetNextAVTransportURI", true) == 0) {
+ return OnSetNextAVTransportURI(action);
+ }
+ if (name.Compare("SetPlayMode", true) == 0) {
+ return OnSetPlayMode(action);
+ }
+
+ /* Is it a RendererControl Service Action ? */
+ if (name.Compare("SetVolume", true) == 0) {
+ return OnSetVolume(action);
+ }
+ if (name.Compare("SetVolumeDB", true) == 0) {
+ return OnSetVolumeDB(action);
+ }
+ if (name.Compare("GetVolumeDBRange", true) == 0) {
+ return OnGetVolumeDBRange(action);
+
+ }
+ if (name.Compare("SetMute", true) == 0) {
+ return OnSetMute(action);
+ }
+
+ // other actions rely on state variables
+ NPT_CHECK_LABEL_WARNING(action->SetArgumentsOutFromStateVariable(), failure);
+ return NPT_SUCCESS;
+
+failure:
+ action->SetError(401,"No Such Action.");
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnGetCurrentConnectionInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnGetCurrentConnectionInfo(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnGetCurrentConnectionInfo(action);
+ }
+
+ if (NPT_FAILED(action->VerifyArgumentValue("ConnectionID", "0"))) {
+ action->SetError(706,"No Such Connection.");
+ return NPT_FAILURE;
+ }
+
+ if (NPT_FAILED(action->SetArgumentValue("RcsID", "0"))){
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("AVTransportID", "0"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentOutFromStateVariable("ProtocolInfo"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("PeerConnectionManager", "/"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("PeerConnectionID", "-1"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("Direction", "Input"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("Status", "Unknown"))) {
+ return NPT_FAILURE;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnNext
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnNext(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnNext(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnPause
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnPause(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnPause(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnPlay
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnPlay(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnPlay(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnPrevious
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnPrevious(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnPrevious(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnSeek
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSeek(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSeek(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnStop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnStop(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnStop(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnSetAVTransportURI
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetAVTransportURI(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSetAVTransportURI(action);
+ }
+
+ // default implementation is using state variable
+ NPT_String uri;
+ NPT_CHECK_WARNING(action->GetArgumentValue("CurrentURI", uri));
+
+ NPT_String metadata;
+ NPT_CHECK_WARNING(action->GetArgumentValue("CurrentURIMetaData", metadata));
+
+ PLT_Service* serviceAVT;
+ NPT_CHECK_WARNING(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", serviceAVT));
+
+ // update service state variables
+ serviceAVT->SetStateVariable("AVTransportURI", uri);
+ serviceAVT->SetStateVariable("AVTransportURIMetaData", metadata);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ | PLT_MediaRenderer::OnSetAVTransportURI
+ +---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetNextAVTransportURI(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSetNextAVTransportURI(action);
+ }
+
+ // default implementation is using state variable
+ NPT_String uri;
+ NPT_CHECK_WARNING(action->GetArgumentValue("NextURI", uri));
+
+ NPT_String metadata;
+ NPT_CHECK_WARNING(action->GetArgumentValue("NextURIMetaData", metadata));
+
+ PLT_Service* serviceAVT;
+ NPT_CHECK_WARNING(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", serviceAVT));
+
+ // update service state variables
+ serviceAVT->SetStateVariable("NextAVTransportURI", uri);
+ serviceAVT->SetStateVariable("NextAVTransportURIMetaData", metadata);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnSetPlayMode
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetPlayMode(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSetPlayMode(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnSetVolume
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetVolume(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSetVolume(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnSetVolumeDB
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetVolumeDB(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSetVolumeDB(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnGetVolumeDBRange
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnGetVolumeDBRange(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnGetVolumeDBRange(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer::OnSetMute
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaRenderer::OnSetMute(PLT_ActionReference& action)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSetMute(action);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.h b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.h
new file mode 100644
index 0000000..ec30a36
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/PltMediaRenderer.h
@@ -0,0 +1,119 @@
+/*****************************************************************
+|
+| Platinum - AV Media Renderer Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_MEDIA_RENDERER_H_
+#define _PLT_MEDIA_RENDERER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDeviceHost.h"
+
+/*----------------------------------------------------------------------
+| PLT_MediaRendererDelegate
++---------------------------------------------------------------------*/
+class PLT_MediaRendererDelegate
+{
+public:
+ virtual ~PLT_MediaRendererDelegate() {}
+
+ // ConnectionManager
+ virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action) = 0;
+
+ // AVTransport
+ virtual NPT_Result OnNext(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnPause(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnPlay(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnPrevious(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnSeek(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnStop(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnSetNextAVTransportURI(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action) = 0;
+
+ // RenderingControl
+ virtual NPT_Result OnSetVolume(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnSetVolumeDB(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnGetVolumeDBRange(PLT_ActionReference& action) = 0;
+ virtual NPT_Result OnSetMute(PLT_ActionReference& action) = 0;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaRenderer
++---------------------------------------------------------------------*/
+class PLT_MediaRenderer : public PLT_DeviceHost
+{
+public:
+ PLT_MediaRenderer(const char* friendly_name,
+ bool show_ip = false,
+ const char* uuid = NULL,
+ unsigned int port = 0,
+ bool port_rebind = false);
+ // methods
+ virtual void SetDelegate(PLT_MediaRendererDelegate* delegate) { m_Delegate = delegate; }
+
+ // PLT_DeviceHost methods
+ NPT_Result SetupServices() override;
+ NPT_Result OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context) override;
+
+protected:
+ ~PLT_MediaRenderer() override;
+
+ // PLT_MediaRendererInterface methods
+ // ConnectionManager
+ virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action);
+
+ // AVTransport
+ virtual NPT_Result OnNext(PLT_ActionReference& action);
+ virtual NPT_Result OnPause(PLT_ActionReference& action);
+ virtual NPT_Result OnPlay(PLT_ActionReference& action);
+ virtual NPT_Result OnPrevious(PLT_ActionReference& action);
+ virtual NPT_Result OnSeek(PLT_ActionReference& action);
+ virtual NPT_Result OnStop(PLT_ActionReference& action);
+ virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action);
+ virtual NPT_Result OnSetNextAVTransportURI(PLT_ActionReference& action);
+ virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action);
+
+ // RenderingControl
+ virtual NPT_Result OnSetVolume(PLT_ActionReference& action);
+ virtual NPT_Result OnSetVolumeDB(PLT_ActionReference &action);
+ virtual NPT_Result OnGetVolumeDBRange(PLT_ActionReference &action);
+ virtual NPT_Result OnSetMute(PLT_ActionReference& action);
+
+private:
+ PLT_MediaRendererDelegate* m_Delegate;
+};
+
+#endif /* _PLT_MEDIA_RENDERER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.cpp
new file mode 100644
index 0000000..4cc0e02
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.cpp
@@ -0,0 +1,257 @@
+/*****************************************************************
+|
+| Platinum - ConnectionManager SCPD
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 RDR_ConnectionManagerSCPD[] =
+{
+ 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
+ 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A,
+ 0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x27, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x2D, 0x31, 0x2D, 0x30, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A,
+ 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E,
+ 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65,
+ 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x6E,
+ 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E,
+ 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+ 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F,
+ 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C,
+ 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49,
+ 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+ 0x5F, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F,
+ 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x65, 0x65, 0x72,
+ 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E,
+ 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43,
+ 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F,
+ 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75,
+ 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63,
+ 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74,
+ 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x69, 0x6E,
+ 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63,
+ 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75,
+ 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49,
+ 0x44, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x65, 0x72, 0x76, 0x69,
+ 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E,
+ 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F,
+ 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F,
+ 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52,
+ 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4F, 0x4B, 0x3C,
+ 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E,
+ 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x4D, 0x69, 0x73, 0x6D, 0x61, 0x74, 0x63,
+ 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6E, 0x74, 0x42, 0x61, 0x6E, 0x64, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x3E, 0x55, 0x6E, 0x72, 0x65, 0x6C, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65,
+ 0x6C, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73,
+ 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F,
+ 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50,
+ 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F,
+ 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76,
+ 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65,
+ 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E,
+ 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x50, 0x72,
+ 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74,
+ 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x49, 0x6E, 0x70, 0x75, 0x74,
+ 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+ 0x3E, 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27,
+ 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43,
+ 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x0D, 0x0A, 0x00
+};
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.xml b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.xml
new file mode 100644
index 0000000..9545801
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RdrConnectionManagerSCPD.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns='urn:schemas-upnp-org:service-1-0'>
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>GetCurrentConnectionInfo</name>
+ <argumentList>
+ <argument>
+ <name>ConnectionID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RcsID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>AVTransportID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>ProtocolInfo</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PeerConnectionManager</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PeerConnectionID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Direction</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Status</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetProtocolInfo</name>
+ <argumentList>
+ <argument>
+ <name>Source</name>
+ <direction>out</direction>
+ <relatedStateVariable>SourceProtocolInfo</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Sink</name>
+ <direction>out</direction>
+ <relatedStateVariable>SinkProtocolInfo</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetCurrentConnectionIDs</name>
+ <argumentList>
+ <argument>
+ <name>ConnectionIDs</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentConnectionIDs</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ProtocolInfo</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ConnectionStatus</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>OK</allowedValue>
+ <allowedValue>ContentFormatMismatch</allowedValue>
+ <allowedValue>InsufficientBandwidth</allowedValue>
+ <allowedValue>UnreliableChannel</allowedValue>
+ <allowedValue>Unknown</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_AVTransportID</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_RcsID</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ConnectionID</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ConnectionManager</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='yes'>
+ <name>SourceProtocolInfo</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='yes'>
+ <name>SinkProtocolInfo</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_Direction</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>Input</allowedValue>
+ <allowedValue>Output</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents='yes'>
+ <name>CurrentConnectionIDs</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ </serviceStateTable>
+</scpd>
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.cpp
new file mode 100644
index 0000000..a01b1c9
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.cpp
@@ -0,0 +1,434 @@
+/*****************************************************************
+|
+| Platinum - RenderingControl SCPD
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 RDR_RenderingControlSCPD[7748] =
+{
+ 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
+ 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A,
+ 0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72,
+ 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E,
+ 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69,
+ 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x47, 0x65, 0x74, 0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73,
+ 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+ 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x4D, 0x75, 0x74,
+ 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C,
+ 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65,
+ 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61,
+ 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47,
+ 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D,
+ 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C,
+ 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x47, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69,
+ 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49,
+ 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41,
+ 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x56,
+ 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65,
+ 0x44, 0x42, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x52, 0x61, 0x6E,
+ 0x67, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41,
+ 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E,
+ 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C,
+ 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+ 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x4D, 0x69, 0x6E, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x4D, 0x61, 0x78, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4C, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x73,
+ 0x65, 0x74, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49,
+ 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72,
+ 0x65, 0x6E, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x4C, 0x69, 0x73, 0x74,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61,
+ 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54,
+ 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72,
+ 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x4D, 0x75, 0x74, 0x65, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E,
+ 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52,
+ 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68,
+ 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x4D,
+ 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x74, 0x61,
+ 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54,
+ 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x68, 0x61, 0x6E, 0x6E,
+ 0x65, 0x6C, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x44, 0x65, 0x73,
+ 0x69, 0x72, 0x65, 0x64, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x56, 0x6F,
+ 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20,
+ 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4C, 0x61, 0x73, 0x74, 0x43, 0x68,
+ 0x61, 0x6E, 0x67, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64,
+ 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+ 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F,
+ 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x61, 0x6C, 0x6C,
+ 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E,
+ 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x49,
+ 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73,
+ 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x32,
+ 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69,
+ 0x6D, 0x75, 0x6D, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x31, 0x30,
+ 0x30, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x31, 0x3C, 0x2F, 0x73, 0x74, 0x65, 0x70, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E,
+ 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4D, 0x75, 0x74, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E,
+ 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x46, 0x61, 0x63, 0x74,
+ 0x6F, 0x72, 0x79, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x73, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+ 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52,
+ 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x46,
+ 0x61, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x73, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F,
+ 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D,
+ 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F,
+ 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x56,
+ 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x44, 0x42, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x32, 0x3C, 0x2F, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D,
+ 0x3E, 0x2D, 0x33, 0x32, 0x37, 0x36, 0x37, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E,
+ 0x33, 0x32, 0x37, 0x36, 0x37, 0x3C, 0x2F, 0x6D, 0x61, 0x78, 0x69, 0x6D, 0x75, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+ 0x52, 0x61, 0x6E, 0x67, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x3C, 0x2F,
+ 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.xml b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.xml
new file mode 100644
index 0000000..c5e9d29
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD.xml
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>GetMute</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentMute</name>
+ <direction>out</direction>
+ <relatedStateVariable>Mute</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetVolume</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentVolume</name>
+ <direction>out</direction>
+ <relatedStateVariable>Volume</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetVolumeDB</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentVolume</name>
+ <direction>out</direction>
+ <relatedStateVariable>VolumeDB</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetVolumeDBRange</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>MinValue</name>
+ <direction>out</direction>
+ <relatedStateVariable>VolumeDB</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>MaxValue</name>
+ <direction>out</direction>
+ <relatedStateVariable>VolumeDB</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>ListPresets</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentPresetNameList</name>
+ <direction>out</direction>
+ <relatedStateVariable>PresetNameList</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SelectPreset</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PresetName</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_PresetName</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetMute</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredMute</name>
+ <direction>in</direction>
+ <relatedStateVariable>Mute</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetVolume</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredVolume</name>
+ <direction>in</direction>
+ <relatedStateVariable>Volume</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="yes">
+ <name>LastChange</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Channel</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>Master</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_InstanceID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Volume</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Mute</name>
+ <dataType>boolean</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PresetNameList</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>FactoryDefaults</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_PresetName</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>FactoryDefaults</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>VolumeDB</name>
+ <dataType>i2</dataType>
+ <allowedValueRange>
+ <minimum>-32767</minimum>
+ <maximum>32767</maximum>
+ </allowedValueRange>
+ </stateVariable>
+ </serviceStateTable>
+</scpd> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD_Full.xml b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD_Full.xml
new file mode 100644
index 0000000..59af0fd
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/RenderingControlSCPD_Full.xml
@@ -0,0 +1,749 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>GetBlueVideoBlackLevel</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentBlueVideoBlackLevel</name>
+ <direction>out</direction>
+ <relatedStateVariable>BlueVideoBlackLevel</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetBlueVideoGain</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentBlueVideoGain</name>
+ <direction>out</direction>
+ <relatedStateVariable>BlueVideoGain</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetBrightness</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentBrightness</name>
+ <direction>out</direction>
+ <relatedStateVariable>Brightness</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetColorTemperature</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentColorTemperature</name>
+ <direction>out</direction>
+ <relatedStateVariable>ColorTemperature</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetContrast</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentContrast</name>
+ <direction>out</direction>
+ <relatedStateVariable>Contrast</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetGreenVideoBlackLevel</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentGreenVideoBlackLevel</name>
+ <direction>out</direction>
+ <relatedStateVariable>GreenVideoBlackLevel</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetGreenVideoGain</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentGreenVideoGain</name>
+ <direction>out</direction>
+ <relatedStateVariable>GreenVideoGain</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetHorizontalKeystone</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentHorizontalKeystone</name>
+ <direction>out</direction>
+ <relatedStateVariable>HorizontalKeystone</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetLoudness</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentLoudness</name>
+ <direction>out</direction>
+ <relatedStateVariable>Loudness</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetMute</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentMute</name>
+ <direction>out</direction>
+ <relatedStateVariable>Mute</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetRedVideoBlackLevel</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentRedVideoBlackLevel</name>
+ <direction>out</direction>
+ <relatedStateVariable>RedVideoBlackLevel</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetRedVideoGain</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentRedVideoGain</name>
+ <direction>out</direction>
+ <relatedStateVariable>RedVideoGain</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetSharpness</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentSharpness</name>
+ <direction>out</direction>
+ <relatedStateVariable>Sharpness</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetVerticalKeystone</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentVerticalKeystone</name>
+ <direction>out</direction>
+ <relatedStateVariable>VerticalKeystone</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetVolume</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentVolume</name>
+ <direction>out</direction>
+ <relatedStateVariable>Volume</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetVolumeDB</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentVolume</name>
+ <direction>out</direction>
+ <relatedStateVariable>VolumeDB</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetVolumeDBRange</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>MinValue</name>
+ <direction>out</direction>
+ <relatedStateVariable>VolumeDB</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>MaxValue</name>
+ <direction>out</direction>
+ <relatedStateVariable>VolumeDB</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>ListPresets</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentPresetNameList</name>
+ <direction>out</direction>
+ <relatedStateVariable>PresetNameList</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SelectPreset</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PresetName</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_PresetName</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetBlueVideoBlackLevel</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredBlueVideoBlackLevel</name>
+ <direction>in</direction>
+ <relatedStateVariable>BlueVideoBlackLevel</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetBlueVideoGain</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredBlueVideoGain</name>
+ <direction>in</direction>
+ <relatedStateVariable>BlueVideoGain</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetBrightness</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredBrightness</name>
+ <direction>in</direction>
+ <relatedStateVariable>Brightness</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetColorTemperature</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredColorTemperature</name>
+ <direction>in</direction>
+ <relatedStateVariable>ColorTemperature</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetContrast</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredContrast</name>
+ <direction>in</direction>
+ <relatedStateVariable>Contrast</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetGreenVideoBlackLevel</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredGreenVideoBlackLevel</name>
+ <direction>in</direction>
+ <relatedStateVariable>GreenVideoBlackLevel</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetGreenVideoGain</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredGreenVideoGain</name>
+ <direction>in</direction>
+ <relatedStateVariable>GreenVideoGain</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetHorizontalKeystone</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredHorizontalKeystone</name>
+ <direction>in</direction>
+ <relatedStateVariable>HorizontalKeystone</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetLoudness</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredLoudness</name>
+ <direction>in</direction>
+ <relatedStateVariable>Loudness</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetMute</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredMute</name>
+ <direction>in</direction>
+ <relatedStateVariable>Mute</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetRedVideoBlackLevel</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredRedVideoBlackLevel</name>
+ <direction>in</direction>
+ <relatedStateVariable>RedVideoBlackLevel</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetRedVideoGain</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredRedVideoGain</name>
+ <direction>in</direction>
+ <relatedStateVariable>RedVideoGain</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetSharpness</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredSharpness</name>
+ <direction>in</direction>
+ <relatedStateVariable>Sharpness</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetVerticalKeystone</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredVerticalKeystone</name>
+ <direction>in</direction>
+ <relatedStateVariable>VerticalKeystone</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetVolume</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredVolume</name>
+ <direction>in</direction>
+ <relatedStateVariable>Volume</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>SetVolumeDB</name>
+ <argumentList>
+ <argument>
+ <name>InstanceID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Channel</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Channel</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>DesiredVolume</name>
+ <direction>in</direction>
+ <relatedStateVariable>VolumeDB</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="no">
+ <name>VerticalKeystone</name>
+ <dataType>i2</dataType>
+ <allowedValueRange>
+ <minimum>-32768</minimum>
+ <maximum>32767</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>LastChange</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Channel</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>Master</allowedValue>
+ <allowedValue>LF</allowedValue>
+ <allowedValue>RF</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Loudness</name>
+ <dataType>boolean</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>HorizontalKeystone</name>
+ <dataType>i2</dataType>
+ <allowedValueRange>
+ <minimum>-32768</minimum>
+ <maximum>32767</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_InstanceID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>BlueVideoBlackLevel</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RedVideoGain</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>GreenVideoBlackLevel</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Volume</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Mute</name>
+ <dataType>boolean</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Brightness</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>PresetNameList</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_PresetName</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>FactoryDefaults</allowedValue>
+ <allowedValue>InstallationDefaults</allowedValue>
+ <allowedValue>Vendor defined</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>ColorTemperature</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>65535</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>VolumeDB</name>
+ <dataType>i2</dataType>
+ <allowedValueRange>
+ <minimum>-32768</minimum>
+ <maximum>32767</maximum>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Contrast</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>GreenVideoGain</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>RedVideoBlackLevel</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>BlueVideoGain</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>Sharpness</name>
+ <dataType>ui2</dataType>
+ <allowedValueRange>
+ <minimum>0</minimum>
+ <maximum>100</maximum>
+ <step>1</step>
+ </allowedValueRange>
+ </stateVariable>
+ </serviceStateTable>
+</scpd> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/process_scpds.sh b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/process_scpds.sh
new file mode 100644
index 0000000..07d5056
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaRenderer/process_scpds.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+set -x
+
+# abort on any errors
+set -e
+
+# AVTransport
+../../../Targets/x86-unknown-cygwin/Debug/TextToHeader.exe -v RDR_AVTransportSCPD -h AVTransport AVTransportSCPD.xml AVTransportSCPD.cpp
+
+# Rendering Control
+../../../Targets/x86-unknown-cygwin/Debug/TextToHeader.exe -v RDR_RenderingControlSCPD -h RenderingControl RenderingControlSCPD.xml RenderingControlSCPD.cpp
+
+# ConnectionManager
+../../../Targets/x86-unknown-cygwin/Debug/TextToHeader.exe -v RDR_ConnectionManagerSCPD -h ConnectionManager ConnectionManagerSCPD.xml RdrConnectionManagerSCPD.cpp \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.cpp
new file mode 100644
index 0000000..973b3b1
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.cpp
@@ -0,0 +1,262 @@
+/*****************************************************************
+|
+| Platinum - ConnectionManager SCPD
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP Service SCPD for urn:schemas-upnp-org:service:ConnectionManager:1
+ */
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 MS_ConnectionManagerSCPD[4216] =
+{
+ 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
+ 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A,
+ 0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x27, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x2D, 0x31, 0x2D, 0x30, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A,
+ 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E,
+ 0x6F, 0x72, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65,
+ 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x6E,
+ 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E,
+ 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+ 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44,
+ 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F,
+ 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C,
+ 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49,
+ 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+ 0x5F, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F,
+ 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x50, 0x65, 0x65, 0x72,
+ 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E,
+ 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43,
+ 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F,
+ 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, 0x2F,
+ 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75,
+ 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C,
+ 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63,
+ 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74,
+ 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x69, 0x6E,
+ 0x6B, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63,
+ 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69,
+ 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75,
+ 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49,
+ 0x44, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73,
+ 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x65, 0x72, 0x76, 0x69,
+ 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E,
+ 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F,
+ 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20,
+ 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F,
+ 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52,
+ 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x53, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x4F, 0x4B, 0x3C,
+ 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E,
+ 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x46, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x4D, 0x69, 0x73, 0x6D, 0x61, 0x74, 0x63,
+ 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x49, 0x6E, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6E, 0x74, 0x42, 0x61, 0x6E, 0x64, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x3E, 0x55, 0x6E, 0x72, 0x65, 0x6C, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65,
+ 0x6C, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61,
+ 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65,
+ 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73,
+ 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x41, 0x56, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F,
+ 0x72, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50,
+ 0x45, 0x5F, 0x52, 0x63, 0x73, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20,
+ 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F,
+ 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76,
+ 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x6E, 0x6E, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72,
+ 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65,
+ 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E,
+ 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61,
+ 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27, 0x79, 0x65, 0x73, 0x27, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x69, 0x6E, 0x6B, 0x50, 0x72,
+ 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E,
+ 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74,
+ 0x73, 0x3D, 0x27, 0x6E, 0x6F, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x49, 0x6E, 0x70, 0x75, 0x74,
+ 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+ 0x3E, 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56,
+ 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x27,
+ 0x79, 0x65, 0x73, 0x27, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43,
+ 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x43, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x73, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x0D, 0x0A, 0x00
+};
+
+/** @} */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.xml b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.xml
new file mode 100644
index 0000000..9545801
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ConnectionManagerSCPD.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns='urn:schemas-upnp-org:service-1-0'>
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>GetCurrentConnectionInfo</name>
+ <argumentList>
+ <argument>
+ <name>ConnectionID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RcsID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>AVTransportID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>ProtocolInfo</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PeerConnectionManager</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>PeerConnectionID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Direction</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Status</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetProtocolInfo</name>
+ <argumentList>
+ <argument>
+ <name>Source</name>
+ <direction>out</direction>
+ <relatedStateVariable>SourceProtocolInfo</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Sink</name>
+ <direction>out</direction>
+ <relatedStateVariable>SinkProtocolInfo</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetCurrentConnectionIDs</name>
+ <argumentList>
+ <argument>
+ <name>ConnectionIDs</name>
+ <direction>out</direction>
+ <relatedStateVariable>CurrentConnectionIDs</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ProtocolInfo</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ConnectionStatus</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>OK</allowedValue>
+ <allowedValue>ContentFormatMismatch</allowedValue>
+ <allowedValue>InsufficientBandwidth</allowedValue>
+ <allowedValue>UnreliableChannel</allowedValue>
+ <allowedValue>Unknown</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_AVTransportID</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_RcsID</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ConnectionID</name>
+ <dataType>i4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_ConnectionManager</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='yes'>
+ <name>SourceProtocolInfo</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='yes'>
+ <name>SinkProtocolInfo</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents='no'>
+ <name>A_ARG_TYPE_Direction</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>Input</allowedValue>
+ <allowedValue>Output</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents='yes'>
+ <name>CurrentConnectionIDs</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ </serviceStateTable>
+</scpd>
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.cpp
new file mode 100644
index 0000000..03f0924
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.cpp
@@ -0,0 +1,267 @@
+/*****************************************************************
+|
+| Platinum - ContentDirectory SCPD
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 MS_ContentDirectorySCPD[4409] =
+{
+ 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
+ 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0D, 0x0A,
+ 0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69,
+ 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A,
+ 0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69,
+ 0x6E, 0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x42,
+ 0x72, 0x6F, 0x77, 0x73, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4F, 0x62,
+ 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F,
+ 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A,
+ 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F,
+ 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C,
+ 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C,
+ 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65,
+ 0x78, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6F, 0x75,
+ 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+ 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+ 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69,
+ 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54,
+ 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65,
+ 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+ 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F,
+ 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+ 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E,
+ 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x4D, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+ 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44,
+ 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+ 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61,
+ 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69,
+ 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F,
+ 0x72, 0x74, 0x43, 0x61, 0x70, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+ 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x72,
+ 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C,
+ 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F,
+ 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x49, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09,
+ 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72,
+ 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74,
+ 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61,
+ 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+ 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+ 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74,
+ 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C,
+ 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09,
+ 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x73, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76,
+ 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+ 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C,
+ 0x61, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61,
+ 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75,
+ 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64,
+ 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x4D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77,
+ 0x73, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x43, 0x68, 0x69, 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x3C, 0x2F, 0x61, 0x6C,
+ 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61,
+ 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45,
+ 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44,
+ 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54,
+ 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74,
+ 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20,
+ 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F,
+ 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E,
+ 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+ 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20,
+ 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09,
+ 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F,
+ 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A,
+ 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C,
+ 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73,
+ 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72,
+ 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69,
+ 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65,
+ 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75,
+ 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65,
+ 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+ 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20,
+ 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73,
+ 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09,
+ 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x55, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64,
+ 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+ 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A,
+ 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+ 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+ 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F,
+ 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43,
+ 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D,
+ 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
+ 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74,
+ 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F,
+ 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74,
+ 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x09, 0x09,
+ 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x09, 0x3C,
+ 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D,
+ 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x00
+};
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.xml b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.xml
new file mode 100644
index 0000000..9605f91
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorySCPD.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>Browse</name>
+ <argumentList>
+ <argument>
+ <name>ObjectID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>BrowseFlag</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_BrowseFlag</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Filter</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>StartingIndex</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RequestedCount</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>SortCriteria</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Result</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NumberReturned</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TotalMatches</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>UpdateID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetSortCapabilities</name>
+ <argumentList>
+ <argument>
+ <name>SortCaps</name>
+ <direction>out</direction>
+ <relatedStateVariable>SortCapabilities</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetSystemUpdateID</name>
+ <argumentList>
+ <argument>
+ <name>Id</name>
+ <direction>out</direction>
+ <relatedStateVariable>SystemUpdateID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetSearchCapabilities</name>
+ <argumentList>
+ <argument>
+ <name>SearchCaps</name>
+ <direction>out</direction>
+ <relatedStateVariable>SearchCapabilities</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_BrowseFlag</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>BrowseMetadata</allowedValue>
+ <allowedValue>BrowseDirectChildren</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>ContainerUpdateIDs</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>SystemUpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Count</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_SortCriteria</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>SortCapabilities</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Index</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_ObjectID</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_UpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Result</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>SearchCapabilities</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Filter</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ </serviceStateTable>
+</scpd> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.cpp
new file mode 100644
index 0000000..bc16048
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.cpp
@@ -0,0 +1,453 @@
+/*****************************************************************
+|
+| Platinum - ContentDirectory SCPD
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_UInt8 MS_ContentDirectorywSearchSCPD[8121] =
+{
+ 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x20,
+0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x3F, 0x3E, 0x0A, 0x3C,
+0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75, 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 0x65,
+0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E,
+0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E,
+0x20, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E,
+0x20, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x3C,
+0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F,
+0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x3C, 0x2F, 0x6E,
+0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73,
+0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09,
+0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69,
+0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C,
+0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44,
+0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A,
+0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+0x61, 0x6D, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E,
+0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72,
+0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61,
+0x67, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C,
+0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A,
+0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61,
+0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09,
+0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x74,
+0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A,
+0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67,
+0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x71,
+0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A,
+0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64,
+0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67,
+0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72,
+0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72,
+0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47,
+0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F,
+0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09,
+0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D,
+0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09,
+0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72,
+0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47,
+0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09,
+0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75,
+0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62,
+0x65, 0x72, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09,
+0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41,
+0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74,
+0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67,
+0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x6F, 0x74,
+0x61, 0x6C, 0x4D, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69,
+0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74,
+0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52,
+0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09,
+0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75,
+0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x70, 0x64, 0x61,
+0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69,
+0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50,
+0x45, 0x5F, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F,
+0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A,
+0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+0x47, 0x65, 0x74, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C,
+0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74,
+0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x73,
+0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C,
+0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C,
+0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x3C,
+0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74,
+0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65,
+0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E,
+0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09,
+0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x49, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64,
+0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C,
+0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x79,
+0x73, 0x74, 0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65,
+0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09,
+0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72,
+0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69,
+0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C,
+0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72,
+0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x72, 0x67,
+0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65,
+0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09,
+0x09, 0x09, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69,
+0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x72, 0x65, 0x6C, 0x61,
+0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x65, 0x61,
+0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0A,
+0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C,
+0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x61,
+0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09,
+0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x3C, 0x2F, 0x6E, 0x61,
+0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67,
+0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x65, 0x72, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D,
+0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69,
+0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72,
+0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C,
+0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F,
+0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C,
+0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x65, 0x61,
+0x72, 0x63, 0x68, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x46, 0x69, 0x6C, 0x74,
+0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C,
+0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F,
+0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x72, 0x65, 0x6C,
+0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65,
+0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56,
+0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65,
+0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43,
+0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72,
+0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65,
+0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72,
+0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65,
+0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65,
+0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0A, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65,
+0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41,
+0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72,
+0x69, 0x61, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72,
+0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+0x5F, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75,
+0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x52, 0x65,
+0x74, 0x75, 0x72, 0x6E, 0x65, 0x64, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63,
+0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C,
+0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E,
+0x61, 0x6D, 0x65, 0x3E, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x4D, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61,
+0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F,
+0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54,
+0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72,
+0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+0x5F, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74,
+0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61,
+0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74,
+0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E,
+0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4F, 0x62, 0x6A, 0x65,
+0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72,
+0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C,
+0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67,
+0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x43, 0x75, 0x72, 0x72,
+0x65, 0x6E, 0x74, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C,
+0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x54, 0x61,
+0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x4E, 0x65, 0x77, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3C, 0x2F,
+0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69, 0x6E, 0x3C,
+0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64,
+0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F,
+0x54, 0x59, 0x50, 0x45, 0x5F, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3C, 0x2F, 0x72,
+0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+0x65, 0x6E, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C,
+0x69, 0x73, 0x74, 0x3E, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0A, 0x09, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x3C, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
+0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E,
+0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45,
+0x5F, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x46, 0x6C, 0x61, 0x67, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A,
+0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C,
+0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F,
+0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61,
+0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x4D, 0x65,
+0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65,
+0x3E, 0x42, 0x72, 0x6F, 0x77, 0x73, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x43, 0x68, 0x69, 0x6C, 0x64, 0x72, 0x65,
+0x6E, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x09, 0x3C, 0x2F, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3E,
+0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A,
+0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E,
+0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E,
+0x61, 0x6D, 0x65, 0x3E, 0x43, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49,
+0x44, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54,
+0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73,
+0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09,
+0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44,
+0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70,
+0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09,
+0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C,
+0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76,
+0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E,
+0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x3C, 0x2F, 0x6E, 0x61,
+0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69,
+0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74,
+0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74,
+0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73,
+0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52,
+0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C,
+0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A,
+0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09,
+0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64,
+0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D,
+0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43,
+0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64,
+0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+0x62, 0x6C, 0x65, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F,
+0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x6F, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61,
+0x62, 0x69, 0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09,
+0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61,
+0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61,
+0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22,
+0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50,
+0x45, 0x5F, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C,
+0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65,
+0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x09, 0x09,
+0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x4F, 0x62,
+0x6A, 0x65, 0x63, 0x74, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64,
+0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09,
+0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x75, 0x69, 0x34, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x09,
+0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x52,
+0x65, 0x73, 0x75, 0x6C, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x61,
+0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54,
+0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x09,
+0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69,
+0x6C, 0x69, 0x74, 0x69, 0x65, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64,
+0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64,
+0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61,
+0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69,
+0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0A,
+0x09, 0x09, 0x09, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x41, 0x5F, 0x41, 0x52, 0x47, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F,
+0x54, 0x61, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x0A,
+0x09, 0x09, 0x09, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3C,
+0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65,
+0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x3C, 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E, 0x0A,
+0x00
+};
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.xml b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.xml
new file mode 100644
index 0000000..cba42e5
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/ContentDirectorywSearchSCPD.xml
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>Browse</name>
+ <argumentList>
+ <argument>
+ <name>ObjectID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>BrowseFlag</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_BrowseFlag</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Filter</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>StartingIndex</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RequestedCount</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>SortCriteria</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Result</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NumberReturned</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TotalMatches</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>UpdateID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetSortCapabilities</name>
+ <argumentList>
+ <argument>
+ <name>SortCaps</name>
+ <direction>out</direction>
+ <relatedStateVariable>SortCapabilities</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetSystemUpdateID</name>
+ <argumentList>
+ <argument>
+ <name>Id</name>
+ <direction>out</direction>
+ <relatedStateVariable>SystemUpdateID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetSearchCapabilities</name>
+ <argumentList>
+ <argument>
+ <name>SearchCaps</name>
+ <direction>out</direction>
+ <relatedStateVariable>SearchCapabilities</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>Search</name>
+ <argumentList>
+ <argument>
+ <name>ContainerID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>SearchCriteria</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SearchCriteria</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Filter</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>StartingIndex</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>RequestedCount</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>SortCriteria</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>Result</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NumberReturned</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>TotalMatches</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>UpdateID</name>
+ <direction>out</direction>
+ <relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>UpdateObject</name>
+ <argumentList>
+ <argument>
+ <name>ObjectID</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>CurrentTagValue</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_TagValueList</relatedStateVariable>
+ </argument>
+ <argument>
+ <name>NewTagValue</name>
+ <direction>in</direction>
+ <relatedStateVariable>A_ARG_TYPE_TagValueList</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_BrowseFlag</name>
+ <dataType>string</dataType>
+ <allowedValueList>
+ <allowedValue>BrowseMetadata</allowedValue>
+ <allowedValue>BrowseDirectChildren</allowedValue>
+ </allowedValueList>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>ContainerUpdateIDs</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>SystemUpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Count</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_SortCriteria</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_SearchCriteria</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>SortCapabilities</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Index</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_ObjectID</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_UpdateID</name>
+ <dataType>ui4</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Result</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>SearchCapabilities</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_Filter</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ <stateVariable sendEvents="no">
+ <name>A_ARG_TYPE_TagValueList</name>
+ <dataType>string</dataType>
+ </stateVariable>
+ </serviceStateTable>
+</scpd>
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp
new file mode 100644
index 0000000..37d36dd
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp
@@ -0,0 +1,406 @@
+/*****************************************************************
+|
+| Platinum - DIDL
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDidl.h"
+#include "PltUtilities.h"
+#include "PltService.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.didl")
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+const char* didl_header = "<DIDL-Lite xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\""
+ " xmlns:dc=\"http://purl.org/dc/elements/1.1/\""
+ " xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\""
+ " xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\""
+ " xmlns:sec=\"http://www.sec.co.kr/\""
+ " xmlns:xbmc=\"urn:schemas-xbmc-org:metadata-1-0/\">";
+const char* didl_footer = "</DIDL-Lite>";
+const char* didl_namespace_dc = "http://purl.org/dc/elements/1.1/";
+const char* didl_namespace_upnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
+const char* didl_namespace_dlna = "urn:schemas-dlna-org:metadata-1-0/";
+const char* didl_namespace_xbmc = "urn:schemas-xbmc-org:metadata-1-0/";
+
+/*----------------------------------------------------------------------
+| PLT_Didl::ConvertFilterToMask
++---------------------------------------------------------------------*/
+NPT_UInt64
+PLT_Didl::ConvertFilterToMask(const NPT_String& filter)
+{
+ // easy out
+ if (filter.GetLength() == 0) return PLT_FILTER_MASK_ALL;
+
+ // a filter string is a comma delimited set of fields identifying
+ // a given DIDL property (or set of properties).
+ // These fields are or start with: upnp:, @, res@, res, dc:, container@
+
+ NPT_UInt64 mask = 0;
+ const char* s = filter;
+ int i = 0;
+
+ while (s[i] != '\0') {
+ int next_comma = filter.Find(',', i);
+ int len = ((next_comma < 0)?(int)filter.GetLength():next_comma)-i;
+
+ if (NPT_String::CompareN(s+i, "*", 1) == 0) {
+ // return now, there's no point in parsing the rest
+ return PLT_FILTER_MASK_ALL;
+ }
+
+ // title is required, so we return a non empty mask
+ mask |= PLT_FILTER_MASK_TITLE;
+
+ if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_TITLE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_TITLE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_REFID, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_REFID;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CREATOR, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_CREATOR;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ARTIST, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_ARTIST;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ACTOR, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_ACTOR;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DIRECTOR, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_DIRECTOR;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_AUTHOR, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_AUTHOR;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DATE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_DATE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUM, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_ALBUM;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_GENRE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_GENRE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUMARTURI, len, true) == 0 ||
+ NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUMARTURI_DLNAPROFILEID, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_ALBUMARTURI;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DESCRIPTION, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_DESCRIPTION;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_LONGDESCRIPTION, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_LONGDESCRIPTION;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ORIGINALTRACK, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_ORIGINALTRACK;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_LASTPOSITION, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_LASTPOSITION;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_LASTPLAYBACK, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_LASTPLAYBACK;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_PLAYCOUNT, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_PLAYCOUNT;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SEARCHABLE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_SEARCHABLE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SEARCHCLASS, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_SEARCHCLASS;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_SEARCHABLE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_SEARCHABLE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CHILDCOUNT, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_CHILDCOUNT;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_CHILDCOUNT, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_CHILDCOUNT;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_PROGRAMTITLE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_PROGRAMTITLE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SERIESTITLE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_SERIESTITLE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_EPISODE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_EPISODE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RATING, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RATING;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_PUBLISHER, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_PUBLISHER;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_DURATION, len, true) == 0 ||
+ NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_DURATION_SHORT, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_DURATION;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_SIZE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_SIZE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_PROTECTION, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_PROTECTION;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_RESOLUTION, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_RESOLUTION;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_BITRATE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_BITRATE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_BITSPERSAMPLE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_BITSPERSAMPLE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_NRAUDIOCHANNELS, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_NRAUDIOCHANNELS;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_SAMPLEFREQUENCY, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_SAMPLEFREQUENCY;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_EPISODE_COUNT, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_EPISODE_COUNT;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_EPISODE_SEASON, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_EPISODE_SEASON;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_LASTPLAYERSTATE, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_LASTPLAYERSTATE;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_DATEADDED, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_DATEADDED;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_RATING, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_RATING;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_VOTES, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_VOTES;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_ARTWORK, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_ARTWORK;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_UNIQUE_IDENTIFIER, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_UNIQUE_IDENTIFIER;
+ } else if (NPT_String::CompareN(s + i, PLT_FILTER_FIELD_XBMC_COUNTRY, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_COUNTRY;
+ } else if (NPT_String::CompareN(s + i, PLT_FILTER_FIELD_XBMC_USERRATING, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_XBMC_USERRATING;
+ }
+
+ if (next_comma < 0) {
+ return mask;
+ }
+
+ i = next_comma + 1;
+ }
+
+ return mask;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Didl::AppendXmlUnEscape
++---------------------------------------------------------------------*/
+void
+PLT_Didl::AppendXmlUnEscape(NPT_String& out, const char* in)
+{
+ unsigned int i=0;
+ while (i<NPT_StringLength(in)) {
+ if (NPT_String::CompareN(in+i, "&lt;", 4) == 0) {
+ out += '<';
+ i +=4;
+ } else if (NPT_String::CompareN(in+i, "&gt;", 4) == 0) {
+ out += '>';
+ i += 4;
+ } else if (NPT_String::CompareN(in+i, "&amp;", 5) == 0) {
+ out += '&';
+ i += 5;
+ } else if (NPT_String::CompareN(in+i, "&quot;", 6) == 0) {
+ out += '"';
+ i += 6;
+ } else if (NPT_String::CompareN(in+i, "&apos;", 6) == 0) {
+ out += '\'';
+ i += 6;
+ } else {
+ out += *(in+i);
+ i++;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_Didl::AppendXmlEscape
++---------------------------------------------------------------------*/
+void
+PLT_Didl::AppendXmlEscape(NPT_String& out, const char* in)
+{
+ if (!in) return;
+
+ for (int i=0; i<(int)NPT_StringLength(in); i++) {
+ if (*(in+i) == '<') {
+ out += "&lt;";
+ } else if (*(in+i) == '>') {
+ out += "&gt;";
+ } else if (*(in+i) == '&') {
+ out += "&amp;";
+ } else if (*(in+i) == '"') {
+ out += "&quot;";
+ } else if (*(in+i) == '\'') {
+ out += "&apos;";
+ } else {
+ out += *(in+i);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_Didl::FormatTimeStamp
++---------------------------------------------------------------------*/
+NPT_String
+PLT_Didl::FormatTimeStamp(NPT_UInt32 seconds)
+{
+ NPT_String result;
+ int hours = seconds/3600;
+ if (hours == 0) {
+ result += "0:";
+ } else {
+ result += NPT_String::FromInteger(hours) + ":";
+ }
+
+ int minutes = (seconds/60)%60;
+ if (minutes == 0) {
+ result += "00:";
+ } else {
+ if (minutes < 10) {
+ result += '0';
+ }
+ result += NPT_String::FromInteger(minutes) + ":";
+ }
+
+ int secs = seconds%60;
+ if (secs == 0) {
+ result += "00";
+ } else {
+ if (secs < 10) {
+ result += '0';
+ }
+ result += NPT_String::FromInteger(secs);
+ }
+
+ result += ".000"; // needed for XBOX360 otherwise it won't play the track
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Didl::ParseTimeStamp
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Didl::ParseTimeStamp(const NPT_String& timestamp, NPT_UInt32& seconds)
+{
+ // assume a timestamp in the format HH:MM:SS.FFF
+ int separator;
+ NPT_String str = timestamp;
+ NPT_UInt32 value;
+
+ // reset output params first
+ seconds = 0;
+
+ // remove milliseconds first if any
+ if ((separator = str.ReverseFind('.')) != -1) {
+ str = str.Left(separator);
+ }
+
+ // look for next separator
+ if ((separator = str.ReverseFind(':')) == -1) return NPT_FAILURE;
+
+ // extract seconds
+ NPT_CHECK_WARNING(str.SubString(separator+1).ToInteger(value));
+ seconds = value;
+ str = str.Left(separator);
+
+ // look for next separator
+ if ((separator = str.ReverseFind(':')) == -1) return NPT_FAILURE;
+
+ // extract minutes
+ NPT_CHECK_WARNING(str.SubString(separator+1).ToInteger(value));
+ seconds += 60*value;
+ str = str.Left(separator);
+
+ // extract hours
+ NPT_CHECK_WARNING(str.ToInteger(value));
+ seconds += 3600*value;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Didl::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Didl::ToDidl(PLT_MediaObject& object, const NPT_String& filter, NPT_String& didl)
+{
+ NPT_UInt64 mask = ConvertFilterToMask(filter);
+
+ // Allocate enough space for the didl
+ didl.Reserve(2048);
+
+ return object.ToDidl(mask, didl);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Didl::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Didl::FromDidl(const char* xml, PLT_MediaObjectListReference& objects)
+{
+ NPT_String str;
+ PLT_MediaObject* object = NULL;
+ NPT_XmlNode* node = NULL;
+ NPT_XmlElementNode* didl = NULL;
+ NPT_XmlParser parser;
+
+ NPT_LOG_FINE("Parsing Didl...");
+
+ NPT_CHECK_LABEL_SEVERE(parser.Parse(xml, node), cleanup);
+ if (!node || !node->AsElementNode()) {
+ NPT_LOG_SEVERE("Invalid node type");
+ goto cleanup;
+ }
+
+ didl = node->AsElementNode();
+
+ if (didl->GetTag().Compare("DIDL-Lite", true)) {
+ NPT_LOG_SEVERE("Invalid node tag");
+ goto cleanup;
+ }
+
+ // create entry list
+ objects = new PLT_MediaObjectList();
+
+ // for each child, find out if it's a container or not
+ // and then invoke the FromDidl on it
+ for (NPT_List<NPT_XmlNode*>::Iterator children = didl->GetChildren().GetFirstItem(); children; children++) {
+ NPT_XmlElementNode* child = (*children)->AsElementNode();
+ if (!child) continue;
+
+ if (child->GetTag().Compare("Container", true) == 0) {
+ object = new PLT_MediaContainer();
+ } else if (child->GetTag().Compare("item", true) == 0) {
+ object = new PLT_MediaItem();
+ } else {
+ NPT_LOG_WARNING("Invalid node tag");
+ continue;
+ }
+
+ if (NPT_FAILED(object->FromDidl(child))) {
+ NPT_LOG_WARNING_1("Invalid didl for object: %s",
+ (const char*) PLT_XmlHelper::Serialize(*child, false));
+ continue;
+ }
+
+ objects->Add(object);
+ object = NULL; // reset to make sure it doesn't get deleted twice in case of error
+ }
+
+ delete node;
+ return NPT_SUCCESS;
+
+cleanup:
+ objects = NULL;
+ delete node;
+ delete object;
+ return NPT_FAILURE;
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h
new file mode 100644
index 0000000..b74ed0f
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h
@@ -0,0 +1,197 @@
+/*****************************************************************
+|
+| Platinum - DIDL handling
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Didl
+ */
+
+#ifndef _PLT_DIDL_H_
+#define _PLT_DIDL_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define PLT_FILTER_MASK_ALL NPT_UINT64_C(0xFFFFFFFFFFFFFFFF)
+
+#define PLT_FILTER_MASK_CREATOR NPT_UINT64_C(0x0000000000000001)
+#define PLT_FILTER_MASK_ARTIST NPT_UINT64_C(0x0000000000000002)
+#define PLT_FILTER_MASK_ALBUM NPT_UINT64_C(0x0000000000000004)
+#define PLT_FILTER_MASK_GENRE NPT_UINT64_C(0x0000000000000008)
+#define PLT_FILTER_MASK_ALBUMARTURI NPT_UINT64_C(0x0000000000000010)
+#define PLT_FILTER_MASK_DESCRIPTION NPT_UINT64_C(0x0000000000000020)
+#define PLT_FILTER_MASK_SEARCHABLE NPT_UINT64_C(0x0000000000000040)
+#define PLT_FILTER_MASK_CHILDCOUNT NPT_UINT64_C(0x0000000000000080)
+#define PLT_FILTER_MASK_ORIGINALTRACK NPT_UINT64_C(0x0000000000000100)
+#define PLT_FILTER_MASK_ACTOR NPT_UINT64_C(0x0000000000000200)
+#define PLT_FILTER_MASK_AUTHOR NPT_UINT64_C(0x0000000000000400)
+#define PLT_FILTER_MASK_DIRECTOR NPT_UINT64_C(0x0000000000000800)
+#define PLT_FILTER_MASK_DATE NPT_UINT64_C(0x0000000000001000)
+#define PLT_FILTER_MASK_PROGRAMTITLE NPT_UINT64_C(0x0000000000002000)
+#define PLT_FILTER_MASK_SERIESTITLE NPT_UINT64_C(0x0000000000004000)
+#define PLT_FILTER_MASK_EPISODE NPT_UINT64_C(0x0000000000008000)
+#define PLT_FILTER_MASK_TITLE NPT_UINT64_C(0x0000000000010000)
+
+#define PLT_FILTER_MASK_RES NPT_UINT64_C(0x0000000000020000)
+#define PLT_FILTER_MASK_RES_DURATION NPT_UINT64_C(0x0000000000040000)
+#define PLT_FILTER_MASK_RES_SIZE NPT_UINT64_C(0x0000000000080000)
+#define PLT_FILTER_MASK_RES_PROTECTION NPT_UINT64_C(0x0000000000100000)
+#define PLT_FILTER_MASK_RES_RESOLUTION NPT_UINT64_C(0x0000000000200000)
+#define PLT_FILTER_MASK_RES_BITRATE NPT_UINT64_C(0x0000000000400000)
+#define PLT_FILTER_MASK_RES_BITSPERSAMPLE NPT_UINT64_C(0x0000000000800000)
+#define PLT_FILTER_MASK_RES_NRAUDIOCHANNELS NPT_UINT64_C(0x0000000001000000)
+#define PLT_FILTER_MASK_RES_SAMPLEFREQUENCY NPT_UINT64_C(0x0000000002000000)
+
+#define PLT_FILTER_MASK_LONGDESCRIPTION NPT_UINT64_C(0x0000000004000000)
+#define PLT_FILTER_MASK_ICON NPT_UINT64_C(0x0000000008000000)
+#define PLT_FILTER_MASK_RATING NPT_UINT64_C(0x0000000010000000)
+
+#define PLT_FILTER_MASK_TOC NPT_UINT64_C(0x0000000020000000)
+#define PLT_FILTER_MASK_SEARCHCLASS NPT_UINT64_C(0x0000000040000000)
+#define PLT_FILTER_MASK_REFID NPT_UINT64_C(0x0000000080000000)
+
+#define PLT_FILTER_MASK_LASTPOSITION NPT_UINT64_C(0x0000000100000000)
+#define PLT_FILTER_MASK_LASTPLAYBACK NPT_UINT64_C(0x0000000200000000)
+#define PLT_FILTER_MASK_PLAYCOUNT NPT_UINT64_C(0x0000000400000000)
+
+#define PLT_FILTER_MASK_PUBLISHER NPT_UINT64_C(0x0000000800000000)
+
+#define PLT_FILTER_MASK_EPISODE_COUNT NPT_UINT64_C(0x0000001000000000)
+#define PLT_FILTER_MASK_EPISODE_SEASON NPT_UINT64_C(0x0000002000000000)
+
+#define PLT_FILTER_MASK_XBMC_DATEADDED NPT_UINT64_C(0x0000100000000000)
+#define PLT_FILTER_MASK_XBMC_RATING NPT_UINT64_C(0x0000200000000000)
+#define PLT_FILTER_MASK_XBMC_VOTES NPT_UINT64_C(0x0000400000000000)
+#define PLT_FILTER_MASK_XBMC_ARTWORK NPT_UINT64_C(0x0000800000000000)
+#define PLT_FILTER_MASK_XBMC_UNIQUE_IDENTIFIER NPT_UINT64_C(0x0001000000000000)
+#define PLT_FILTER_MASK_XBMC_COUNTRY NPT_UINT64_C(0x0002000000000000)
+#define PLT_FILTER_MASK_XBMC_USERRATING NPT_UINT64_C(0x0004000000000000)
+#define PLT_FILTER_MASK_XBMC_LASTPLAYERSTATE NPT_UINT64_C(0x0008000000000000)
+
+#define PLT_FILTER_FIELD_TITLE "dc:title"
+#define PLT_FILTER_FIELD_CREATOR "dc:creator"
+#define PLT_FILTER_FIELD_DATE "dc:date"
+#define PLT_FILTER_FIELD_ARTIST "upnp:artist"
+#define PLT_FILTER_FIELD_ACTOR "upnp:actor"
+#define PLT_FILTER_FIELD_AUTHOR "upnp:author"
+#define PLT_FILTER_FIELD_DIRECTOR "upnp:director"
+#define PLT_FILTER_FIELD_ALBUM "upnp:album"
+#define PLT_FILTER_FIELD_GENRE "upnp:genre"
+#define PLT_FILTER_FIELD_ALBUMARTURI "upnp:albumArtURI"
+#define PLT_FILTER_FIELD_ALBUMARTURI_DLNAPROFILEID "upnp:albumArtURI@dlna:profileID"
+#define PLT_FILTER_FIELD_DESCRIPTION "dc:description"
+#define PLT_FILTER_FIELD_LONGDESCRIPTION "upnp:longDescription"
+#define PLT_FILTER_FIELD_ICON "upnp:icon"
+#define PLT_FILTER_FIELD_RATING "upnp:rating"
+#define PLT_FILTER_FIELD_ORIGINALTRACK "upnp:originalTrackNumber"
+#define PLT_FILTER_FIELD_PROGRAMTITLE "upnp:programTitle"
+#define PLT_FILTER_FIELD_SERIESTITLE "upnp:seriesTitle"
+#define PLT_FILTER_FIELD_EPISODE "upnp:episodeNumber"
+#define PLT_FILTER_FIELD_LASTPOSITION "upnp:lastPlaybackPosition"
+#define PLT_FILTER_FIELD_LASTPLAYBACK "upnp:lastPlaybackTime"
+#define PLT_FILTER_FIELD_PLAYCOUNT "upnp:playbackCount"
+#define PLT_FILTER_FIELD_SEARCHCLASS "upnp:searchClass"
+#define PLT_FILTER_FIELD_SEARCHABLE "@searchable"
+#define PLT_FILTER_FIELD_CHILDCOUNT "@childcount"
+#define PLT_FILTER_FIELD_CONTAINER_CHILDCOUNT "container@childCount"
+#define PLT_FILTER_FIELD_CONTAINER_SEARCHABLE "container@searchable"
+#define PLT_FILTER_FIELD_REFID "@refID"
+#define PLT_FILTER_FIELD_PUBLISHER "dc:publisher"
+
+#define PLT_FILTER_FIELD_RES "res"
+#define PLT_FILTER_FIELD_RES_DURATION "res@duration"
+#define PLT_FILTER_FIELD_RES_DURATION_SHORT "@duration"
+#define PLT_FILTER_FIELD_RES_SIZE "res@size"
+#define PLT_FILTER_FIELD_RES_PROTECTION "res@protection"
+#define PLT_FILTER_FIELD_RES_RESOLUTION "res@resolution"
+#define PLT_FILTER_FIELD_RES_BITRATE "res@bitrate"
+#define PLT_FILTER_FIELD_RES_BITSPERSAMPLE "res@bitsPerSample"
+#define PLT_FILTER_FIELD_RES_NRAUDIOCHANNELS "res@nrAudioChannels"
+#define PLT_FILTER_FIELD_RES_SAMPLEFREQUENCY "res@sampleFrequency"
+
+#define PLT_FILTER_FIELD_EPISODE_COUNT "upnp:episodeCount"
+#define PLT_FILTER_FIELD_EPISODE_SEASON "upnp:episodeSeason"
+
+#define PLT_FILTER_FIELD_XBMC_LASTPLAYERSTATE "xbmc:lastPlayerState"
+#define PLT_FILTER_FIELD_XBMC_DATEADDED "xbmc:dateadded"
+#define PLT_FILTER_FIELD_XBMC_RATING "xbmc:rating"
+#define PLT_FILTER_FIELD_XBMC_VOTES "xbmc:votes"
+#define PLT_FILTER_FIELD_XBMC_ARTWORK "xbmc:artwork"
+#define PLT_FILTER_FIELD_XBMC_UNIQUE_IDENTIFIER "xbmc:uniqueidentifier"
+#define PLT_FILTER_FIELD_XBMC_COUNTRY "xbmc:country"
+#define PLT_FILTER_FIELD_XBMC_USERRATING "xbmc:userrating"
+
+extern const char* didl_header;
+extern const char* didl_footer;
+extern const char* didl_namespace_dc;
+extern const char* didl_namespace_upnp;
+extern const char* didl_namespace_dlna;
+extern const char* didl_namespace_xbmc;
+
+/*----------------------------------------------------------------------
+| PLT_Didl
++---------------------------------------------------------------------*/
+/**
+ DIDL manipulation.
+ The PLT_Didl class provides a mechanism to (de)serialize a PLT_MediaObject or
+ list of PLT_MediaObject (PLT_MediaObjectList).
+ */
+class PLT_Didl
+{
+public:
+ static NPT_Result ToDidl(PLT_MediaObject& object,
+ const NPT_String& filter,
+ NPT_String& didl);
+ static NPT_Result FromDidl(const char* didl,
+ PLT_MediaObjectListReference& objects);
+ static void AppendXmlEscape(NPT_String& out, const char* in);
+ static void AppendXmlUnEscape(NPT_String& out, const char* in);
+ static NPT_Result ParseTimeStamp(const NPT_String& timestamp, NPT_UInt32& seconds);
+ static NPT_String FormatTimeStamp(NPT_UInt32 seconds);
+ static NPT_Result ParseTimeStamp(const NPT_String& in, NPT_TimeStamp& timestamp) {
+ NPT_UInt32 seconds;
+ NPT_Result res = ParseTimeStamp(in, seconds);
+ timestamp = NPT_TimeStamp((double)seconds);
+ return res;
+ }
+
+ static NPT_UInt64 ConvertFilterToMask(const NPT_String& filter);
+};
+
+#endif /* _PLT_DIDL_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.cpp
new file mode 100644
index 0000000..421d0c2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.cpp
@@ -0,0 +1,519 @@
+/*****************************************************************
+|
+| Platinum - File Media Server Delegate
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltFileMediaServer.h"
+#include "PltMediaItem.h"
+#include "PltService.h"
+#include "PltTaskManager.h"
+#include "PltHttpServer.h"
+#include "PltDidl.h"
+#include "PltVersion.h"
+#include "PltMimeType.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.file.delegate")
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::PLT_FileMediaServerDelegate
++---------------------------------------------------------------------*/
+PLT_FileMediaServerDelegate::PLT_FileMediaServerDelegate(const char* url_root,
+ const char* file_root,
+ bool use_cache) :
+ m_UrlRoot(url_root),
+ m_FileRoot(file_root),
+ m_FilterUnknownOut(false),
+ m_UseCache(use_cache)
+{
+ /* Trim excess separators */
+ m_FileRoot.TrimRight("/\\");
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::~PLT_FileMediaServerDelegate
++---------------------------------------------------------------------*/
+PLT_FileMediaServerDelegate::~PLT_FileMediaServerDelegate()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::ProcessFileRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServerDelegate::ProcessFileRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ NPT_HttpUrlQuery query(request.GetUrl().GetQuery());
+
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, "PLT_FileMediaServerDelegate::ProcessFileRequest:", &request);
+
+ if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) {
+ response.SetStatus(500, "Internal Server Error");
+ return NPT_SUCCESS;
+ }
+
+ /* Extract file path from url */
+ NPT_String file_path;
+ NPT_CHECK_LABEL_WARNING(ExtractResourcePath(request.GetUrl(), file_path), failure);
+
+ /* Serve file */
+ NPT_CHECK_WARNING(ServeFile(request, context, response, NPT_FilePath::Create(m_FileRoot, file_path)));
+ return NPT_SUCCESS;
+
+failure:
+ response.SetStatus(404, "File Not Found");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::ServeFile
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServerDelegate::ServeFile(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ const NPT_String& file_path)
+{
+ NPT_CHECK_WARNING(PLT_HttpServer::ServeFile(request, context, response, file_path));
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::OnBrowseMetadata
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServerDelegate::OnBrowseMetadata(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(sort_criteria);
+ NPT_COMPILER_UNUSED(requested_count);
+ NPT_COMPILER_UNUSED(starting_index);
+
+ NPT_String didl;
+ PLT_MediaObjectReference item;
+
+ /* locate the file from the object ID */
+ NPT_String filepath;
+ if (NPT_FAILED(GetFilePath(object_id, filepath))) {
+ /* error */
+ NPT_LOG_WARNING("PLT_FileMediaServerDelegate::OnBrowse - ObjectID not found.");
+ action->SetError(701, "No Such Object.");
+ return NPT_FAILURE;
+ }
+
+ /* build the object didl */
+ item = BuildFromFilePath(filepath, context, true, false, (NPT_String(filter).Find("ALLIP")!=-1));
+ if (item.IsNull()) return NPT_FAILURE;
+ NPT_String tmp;
+ NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp));
+
+ /* add didl header and footer */
+ didl = didl_header + tmp + didl_footer;
+
+ NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl));
+ NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", "1"));
+ NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", "1"));
+
+ /* update ID may be wrong here, it should be the one of the container?
+ TODO: We need to keep track of the overall updateID of the CDS */
+ NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1"));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::OnBrowseDirectChildren
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServerDelegate::OnBrowseDirectChildren(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(sort_criteria);
+
+ /* locate the file from the object ID */
+ NPT_String dir;
+ NPT_FileInfo info;
+ if (NPT_FAILED(GetFilePath(object_id, dir)) || NPT_FAILED(NPT_File::GetInfo(dir, &info)) || info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY) {
+ /* error */
+ NPT_LOG_WARNING_1("ObjectID \'%s\' not found or not allowed", object_id);
+ action->SetError(701, "No such Object");
+ NPT_CHECK_WARNING(NPT_FAILURE);
+ }
+
+ /* get uuid from device via action reference */
+ NPT_String uuid = action->GetActionDesc().GetService()->GetDevice()->GetUUID();
+
+ /* Try to get list from cache if allowed */
+ NPT_Result res;
+ NPT_Reference<NPT_List<NPT_String> > entries;
+ NPT_TimeStamp cached_entries_time;
+ if (!m_UseCache || NPT_FAILED(m_DirCache.Get(uuid, dir, entries, &cached_entries_time)) || cached_entries_time < info.m_ModificationTime) {
+ /* if not found in cache or if current dir has newer modified time fetch fresh new list from source */
+ entries = new NPT_List<NPT_String>();
+ res = NPT_File::ListDir(dir, *entries);
+ if (NPT_FAILED(res)) {
+ NPT_LOG_WARNING_1("PLT_FileMediaServerDelegate::OnBrowseDirectChildren - failed to open dir %s", (const char*) dir);
+ NPT_CHECK_WARNING(res);
+ }
+
+ /* sort results according to modification date */
+ res = entries->Sort(NPT_FileDateComparator(dir));
+ if (NPT_FAILED(res)) {
+ NPT_LOG_WARNING_1("PLT_FileMediaServerDelegate::OnBrowseDirectChildren - failed to open sort dir %s", (const char*) dir);
+ NPT_CHECK_WARNING(res);
+ }
+
+ /* add new list to cache */
+ if (m_UseCache) {
+ m_DirCache.Put(uuid, dir, entries, &info.m_ModificationTime);
+ }
+ }
+
+ unsigned long cur_index = 0;
+ unsigned long num_returned = 0;
+ unsigned long total_matches = 0;
+ NPT_String didl = didl_header;
+ bool allip = (NPT_String(filter).Find("ALLIP") != -1);
+
+ PLT_MediaObjectReference item;
+ for (NPT_List<NPT_String>::Iterator it = entries->GetFirstItem();
+ it;
+ ++it) {
+ NPT_String filepath = NPT_FilePath::Create(dir, *it);
+
+ /* verify we want to process this file first */
+ if (!ProcessFile(filepath, filter)) continue;
+
+ /* build item object from file path */
+ item = BuildFromFilePath(filepath,
+ context,
+ true,
+ false,
+ allip);
+
+ /* generate didl if within range requested */
+ if (!item.IsNull()) {
+ if ((cur_index >= starting_index) &&
+ ((num_returned < requested_count) || (requested_count == 0))) {
+ NPT_String tmp;
+ NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp));
+
+ didl += tmp;
+ ++num_returned;
+ }
+ ++cur_index;
+ ++total_matches;
+ }
+ };
+
+ didl += didl_footer;
+
+ NPT_LOG_FINE_6("BrowseDirectChildren from %s returning %d-%lu/%lu objects (%lu out of %d requested)",
+ (const char*)context.GetLocalAddress().GetIpAddress().ToString(),
+ starting_index, starting_index+num_returned, total_matches, num_returned, requested_count);
+
+ NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl));
+ NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned)));
+ NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches))); // 0 means we don't know how many we have but most browsers don't like that!!
+ NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1"));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::OnSearchContainer
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServerDelegate::OnSearchContainer(PLT_ActionReference& action,
+ const char* object_id,
+ const char* search_criteria,
+ const char* /* filter */,
+ NPT_UInt32 /* starting_index */,
+ NPT_UInt32 /* requested_count */,
+ const char* /* sort_criteria */,
+ const PLT_HttpRequestContext& /* context */)
+{
+ /* parse search criteria */
+
+ /* TODO: HACK TO PASS DLNA */
+ if (search_criteria && NPT_StringsEqual(search_criteria, "Unknownfieldname")) {
+ /* error */
+ NPT_LOG_WARNING_1("Unsupported or invalid search criteria %s", search_criteria);
+ action->SetError(708, "Unsupported or invalid search criteria");
+ return NPT_FAILURE;
+ }
+
+ /* locate the file from the object ID */
+ NPT_String dir;
+ if (NPT_FAILED(GetFilePath(object_id, dir))) {
+ /* error */
+ NPT_LOG_WARNING("ObjectID not found.");
+ action->SetError(710, "No Such Container.");
+ return NPT_FAILURE;
+ }
+
+ /* retrieve the item type */
+ NPT_FileInfo info;
+ NPT_Result res = NPT_File::GetInfo(dir, &info);
+ if (NPT_FAILED(res) || (info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY)) {
+ /* error */
+ NPT_LOG_WARNING("No such container");
+ action->SetError(710, "No such container");
+ return NPT_FAILURE;
+ }
+
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::GetFilePath
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServerDelegate::GetFilePath(const char* object_id,
+ NPT_String& filepath)
+{
+ if (!object_id) return NPT_ERROR_INVALID_PARAMETERS;
+
+ filepath = m_FileRoot;
+
+ /* object id is formatted as 0/<filepath> */
+ if (NPT_StringLength(object_id) >= 1) {
+ filepath += (object_id + (object_id[0]=='0'?1:0));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::BuildSafeResourceUri
++---------------------------------------------------------------------*/
+NPT_String
+PLT_FileMediaServerDelegate::BuildSafeResourceUri(const NPT_HttpUrl& base_uri,
+ const char* host,
+ const char* file_path)
+{
+ NPT_String result;
+ NPT_HttpUrl uri = base_uri;
+
+ if (host) uri.SetHost(host);
+
+ NPT_String uri_path = uri.GetPath();
+ if (!uri_path.EndsWith("/")) uri_path += "/";
+
+ /* some controllers (like WMP) will call us with an already urldecoded version.
+ We're intentionally prepending a known urlencoded string
+ to detect it when we receive the request urlencoded or already decoded to avoid double decoding*/
+ uri_path += "%/";
+ uri_path += file_path;
+
+ /* set path */
+ uri.SetPath(uri_path);
+
+ /* 360 hack: force inclusion of port in case it's 80 */
+ return uri.ToStringWithDefaultPort(0);
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::ExtractResourcePath
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FileMediaServerDelegate::ExtractResourcePath(const NPT_HttpUrl& url,
+ NPT_String& file_path)
+{
+ /* Extract non decoded path, we need to autodetect urlencoding */
+ NPT_String uri_path = url.GetPath();
+ NPT_String url_root_encode = NPT_Uri::PercentEncode(m_UrlRoot, NPT_Uri::PathCharsToEncode);
+
+ NPT_Ordinal skip = 0;
+ if (uri_path.StartsWith(m_UrlRoot)) {
+ skip = m_UrlRoot.GetLength();
+ } else if (uri_path.StartsWith(url_root_encode)) {
+ skip = url_root_encode.GetLength();
+ } else {
+ return NPT_FAILURE;
+ }
+
+ /* account for extra slash */
+ skip += ((m_UrlRoot=="/")?0:1);
+ file_path = uri_path.SubString(skip);
+
+ /* detect if client such as WMP sent a non urlencoded url */
+ if (file_path.StartsWith("%/")) {
+ NPT_LOG_FINE("Received a urldecoded version of our url!");
+ file_path.Erase(0, 2);
+ } else {
+ /* remove our prepended string we used to detect urldecoded version */
+ if (file_path.StartsWith("%25/")) file_path.Erase(0, 4);
+
+ /* ok to urldecode */
+ file_path = NPT_Uri::PercentDecode(file_path);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::BuildResourceUri
++---------------------------------------------------------------------*/
+NPT_String
+PLT_FileMediaServerDelegate::BuildResourceUri(const NPT_HttpUrl& base_uri,
+ const char* host,
+ const char* file_path)
+{
+ return BuildSafeResourceUri(base_uri, host, file_path);
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate::BuildFromFilePath
++---------------------------------------------------------------------*/
+PLT_MediaObject*
+PLT_FileMediaServerDelegate::BuildFromFilePath(const NPT_String& filepath,
+ const PLT_HttpRequestContext& context,
+ bool with_count /* = true */,
+ bool keep_extension_in_title /* = false */,
+ bool allip /* = false */)
+{
+ NPT_String root = m_FileRoot;
+ PLT_MediaItemResource resource;
+ PLT_MediaObject* object = NULL;
+
+ NPT_LOG_FINEST_1("Building didl for file '%s'", (const char*)filepath);
+
+ /* retrieve the entry type (directory or file) */
+ NPT_FileInfo info;
+ NPT_CHECK_LABEL_FATAL(NPT_File::GetInfo(filepath, &info), failure);
+
+ if (info.m_Type == NPT_FileInfo::FILE_TYPE_REGULAR) {
+ object = new PLT_MediaItem();
+
+ /* Set the title using the filename for now */
+ object->m_Title = NPT_FilePath::BaseName(filepath, keep_extension_in_title);
+ if (object->m_Title.GetLength() == 0) goto failure;
+
+ /* make sure we return something with a valid mimetype */
+ if (m_FilterUnknownOut &&
+ NPT_StringsEqual(PLT_MimeType::GetMimeType(filepath, &context),
+ "application/octet-stream")) {
+ goto failure;
+ }
+
+ /* Set the protocol Info from the extension */
+ resource.m_ProtocolInfo = PLT_ProtocolInfo::GetProtocolInfo(filepath, true, &context);
+ if (!resource.m_ProtocolInfo.IsValid()) goto failure;
+
+ /* Set the resource file size */
+ resource.m_Size = info.m_Size;
+
+ /* format the resource URI */
+ NPT_String url = filepath.SubString(root.GetLength()+1);
+
+ // get list of ip addresses
+ NPT_List<NPT_IpAddress> ips;
+ NPT_CHECK_LABEL_SEVERE(PLT_UPnPMessageHelper::GetIPAddresses(ips), failure);
+
+ /* if we're passed an interface where we received the request from
+ move the ip to the top so that it is used for the first resource */
+ if (context.GetLocalAddress().GetIpAddress().ToString() != "0.0.0.0") {
+ ips.Remove(context.GetLocalAddress().GetIpAddress());
+ ips.Insert(ips.GetFirstItem(), context.GetLocalAddress().GetIpAddress());
+ } else if (!allip) {
+ NPT_LOG_WARNING("Couldn't determine local interface IP so we might return an unreachable IP");
+ }
+ object->m_ObjectClass.type = PLT_MediaItem::GetUPnPClass(filepath, &context);
+
+ /* add as many resources as we have interfaces s*/
+ NPT_HttpUrl base_uri("127.0.0.1", context.GetLocalAddress().GetPort(), NPT_HttpUrl::PercentEncode(m_UrlRoot, NPT_Uri::PathCharsToEncode));
+ NPT_List<NPT_IpAddress>::Iterator ip = ips.GetFirstItem();
+ while (ip) {
+ resource.m_Uri = BuildResourceUri(base_uri, ip->ToString(), url);
+ object->m_Resources.Add(resource);
+ ++ip;
+
+ /* if we only want the one resource reachable by client */
+ if (!allip) break;
+ }
+ } else {
+ object = new PLT_MediaContainer;
+
+ /* Assign a title for this container */
+ if (filepath.Compare(root, true) == 0) {
+ object->m_Title = "Root";
+ } else {
+ object->m_Title = NPT_FilePath::BaseName(filepath, keep_extension_in_title);
+ if (object->m_Title.GetLength() == 0) goto failure;
+ }
+
+ /* Get the number of children for this container */
+ NPT_LargeSize count = 0;
+ if (with_count && NPT_SUCCEEDED(NPT_File::GetSize(filepath, count))) {
+ ((PLT_MediaContainer*)object)->m_ChildrenCount = (NPT_Int32)count;
+ }
+
+ object->m_ObjectClass.type = "object.container.storageFolder";
+ }
+
+ /* is it the root? */
+ if (filepath.Compare(root, true) == 0) {
+ object->m_ParentID = "-1";
+ object->m_ObjectID = "0";
+ } else {
+ NPT_String directory = NPT_FilePath::DirName(filepath);
+ /* is the parent path the root? */
+ if (directory.GetLength() == root.GetLength()) {
+ object->m_ParentID = "0";
+ } else {
+ object->m_ParentID = "0" + filepath.SubString(root.GetLength(), directory.GetLength() - root.GetLength());
+ }
+ object->m_ObjectID = "0" + filepath.SubString(root.GetLength());
+ }
+
+ return object;
+
+failure:
+ delete object;
+ return NULL;
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.h
new file mode 100644
index 0000000..fa4b5e4
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltFileMediaServer.h
@@ -0,0 +1,151 @@
+/*****************************************************************
+|
+| Platinum - File Media Server
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Filesystem based Media Server sample implementation
+ */
+
+#ifndef _PLT_FILE_MEDIA_SERVER_H_
+#define _PLT_FILE_MEDIA_SERVER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaServer.h"
+#include "PltMediaCache.h"
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServerDelegate
++---------------------------------------------------------------------*/
+/**
+ File Media Server Delegate.
+ The PLT_FileMediaServerDelegate class is an example of a PLT_MediaServerDelegate
+ implementation for a file system backed Media Server.
+ */
+class PLT_FileMediaServerDelegate : public PLT_MediaServerDelegate
+{
+public:
+ // class methods
+ static NPT_String BuildSafeResourceUri(const NPT_HttpUrl& base_uri,
+ const char* host,
+ const char* file_path);
+ // constructor & destructor
+ PLT_FileMediaServerDelegate(const char* url_root, const char* file_root, bool use_cache = false);
+ ~PLT_FileMediaServerDelegate() override;
+
+protected:
+ // PLT_MediaServerDelegate methods
+ NPT_Result OnBrowseMetadata(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context) override;
+ NPT_Result OnBrowseDirectChildren(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context) override;
+ NPT_Result OnSearchContainer(PLT_ActionReference& action,
+ const char* object_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context) override;
+ NPT_Result ProcessFileRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ // overridable methods
+ virtual NPT_Result ExtractResourcePath(const NPT_HttpUrl& url, NPT_String& file_path);
+ virtual NPT_String BuildResourceUri(const NPT_HttpUrl& base_uri, const char* host, const char* file_path);
+ virtual NPT_Result ServeFile(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ const NPT_String& file_path);
+ virtual NPT_Result GetFilePath(const char* object_id, NPT_String& filepath);
+ virtual bool ProcessFile(const NPT_String&, const char* filter = NULL) { NPT_COMPILER_UNUSED(filter); return true;}
+ virtual PLT_MediaObject* BuildFromFilePath(const NPT_String& filepath,
+ const PLT_HttpRequestContext& context,
+ bool with_count = true,
+ bool keep_extension_in_title = false,
+ bool allip = false);
+
+protected:
+ friend class PLT_MediaItem;
+
+ NPT_String m_UrlRoot;
+ NPT_String m_FileRoot;
+ bool m_FilterUnknownOut;
+ bool m_UseCache;
+
+ PLT_MediaCache<NPT_Reference<NPT_List<NPT_String> >, NPT_TimeStamp> m_DirCache;
+};
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServer
++---------------------------------------------------------------------*/
+/**
+ File Media Server.
+ The PLT_FileMediaServer class is an example of a PLT_MediaServer implementation
+ for a file system backed Media Server.
+ */
+class PLT_FileMediaServer : public PLT_MediaServer,
+ public PLT_FileMediaServerDelegate
+{
+public: // constructor
+ PLT_FileMediaServer(const char* file_root,
+ const char* friendly_name,
+ bool show_ip = false,
+ const char* uuid = NULL,
+ NPT_UInt16 port = 0,
+ bool port_rebind = false) :
+ PLT_MediaServer(friendly_name,
+ show_ip,
+ uuid,
+ port,
+ port_rebind),
+ PLT_FileMediaServerDelegate("/", file_root) {SetDelegate(this);}
+
+protected:
+ ~PLT_FileMediaServer() override {}
+};
+
+#endif /* _PLT_FILE_MEDIA_SERVER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.cpp
new file mode 100644
index 0000000..2478441
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.cpp
@@ -0,0 +1,571 @@
+/*****************************************************************
+|
+| Platinum - AV Media Browser (Media Server Control Point)
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltMediaBrowser.h"
+#include "PltDidl.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.browser")
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::PLT_MediaBrowser
++---------------------------------------------------------------------*/
+PLT_MediaBrowser::PLT_MediaBrowser(PLT_CtrlPointReference& ctrl_point,
+ PLT_MediaBrowserDelegate* delegate /* = NULL */) :
+ m_CtrlPoint(ctrl_point),
+ m_Delegate(delegate)
+{
+ m_CtrlPoint->AddListener(this);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::~PLT_MediaBrowser
++---------------------------------------------------------------------*/
+PLT_MediaBrowser::~PLT_MediaBrowser()
+{
+ m_CtrlPoint->RemoveListener(this);
+}
+
+/*----------------------------------------------------------------------
+| 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;
+}
+
+/*----------------------------------------------------------------------
+| 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_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_MediaBrowser::Search
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::Search(PLT_DeviceDataReference& device,
+ const char* container_id,
+ const char* search_criteria,
+ NPT_UInt32 start_index,
+ NPT_UInt32 count,
+ const char* filter,
+ void* userdata)
+{
+ // verify device still in our list
+ PLT_DeviceDataReference device_data;
+ NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
+
+ // create action
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:ContentDirectory:1",
+ "Search",
+ action));
+
+ // Set the container id
+ PLT_Arguments args;
+ if (NPT_FAILED(action->SetArgumentValue("ContainerID", container_id))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Search Criteria
+ if (NPT_FAILED(action->SetArgumentValue("SearchCriteria", search_criteria))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+
+ // set the Filter
+ if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Starting Index
+ if (NPT_FAILED(action->SetArgumentValue("StartingIndex",
+ NPT_String::FromInteger(start_index)))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Requested Count
+ if (NPT_FAILED(action->SetArgumentValue("RequestedCount",
+ NPT_String::FromInteger(count)))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Requested Count
+ if (NPT_FAILED(action->SetArgumentValue("SortCriteria", ""))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // invoke the action
+ if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::Browse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::Browse(PLT_DeviceDataReference& device,
+ const char* obj_id,
+ NPT_UInt32 start_index,
+ NPT_UInt32 count,
+ bool browse_metadata,
+ const char* filter,
+ const char* sort_criteria,
+ void* userdata)
+{
+ // verify device still in our list
+ PLT_DeviceDataReference device_data;
+ NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
+
+ // create action
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:ContentDirectory:1",
+ "Browse",
+ action));
+
+ // Set the object id
+ PLT_Arguments args;
+ if (NPT_FAILED(action->SetArgumentValue("ObjectID", obj_id))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the browse_flag
+ if (NPT_FAILED(action->SetArgumentValue("BrowseFlag",
+ browse_metadata?"BrowseMetadata":"BrowseDirectChildren"))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Filter
+ if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Starting Index
+ if (NPT_FAILED(action->SetArgumentValue("StartingIndex",
+ NPT_String::FromInteger(start_index)))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Requested Count
+ if (NPT_FAILED(action->SetArgumentValue("RequestedCount",
+ NPT_String::FromInteger(count)))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // set the Requested Count
+ if (NPT_FAILED(action->SetArgumentValue("SortCriteria", sort_criteria))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // invoke the action
+ if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::GetSearchCapabilities
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::GetSearchCapabilities(PLT_DeviceDataReference& device,
+ void* userdata)
+{
+ // verify device still in our list
+ PLT_DeviceDataReference device_data;
+ NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
+
+ // create action
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:ContentDirectory:1",
+ "GetSearchCapabilities",
+ action));
+
+ // invoke the action
+ if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::GetSortCapabilities
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::GetSortCapabilities(PLT_DeviceDataReference& device,
+ void* userdata)
+{
+ // verify device still in our list
+ PLT_DeviceDataReference device_data;
+ NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
+
+ // create action
+ PLT_ActionReference action;
+ NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
+ device,
+ "urn:schemas-upnp-org:service:ContentDirectory:1",
+ "GetSortCapabilities",
+ action));
+
+ // invoke the action
+ if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::OnActionResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnActionResponse(NPT_Result res,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ // look for device in our list first
+ PLT_DeviceDataReference device;
+ NPT_String uuid = action->GetActionDesc().GetService()->GetDevice()->GetUUID();
+ if (NPT_FAILED(FindServer(uuid, device))) res = NPT_FAILURE;
+
+ NPT_String actionName = action->GetActionDesc().GetName();
+ if (actionName.Compare("Browse", true) == 0) {
+ return OnBrowseResponse(res, device, action, userdata);
+ } else if (actionName.Compare("Search", true) == 0) {
+ return OnSearchResponse(res, device, action, userdata);
+ } else if (actionName.Compare("GetSearchCapabilities", true) == 0) {
+ return OnGetSearchCapabilitiesResponse(res, device, action, userdata);
+ } else if (actionName.Compare("GetSortCapabilities", true) == 0) {
+ return OnGetSortCapabilitiesResponse(res, device, action, userdata);
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::OnBrowseResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnBrowseResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+ PLT_BrowseInfo info;
+ NPT_String unescaped;
+
+ if (!m_Delegate) return NPT_SUCCESS;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("ObjectID", info.object_id))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("UpdateID", value)) ||
+ value.GetLength() == 0 ||
+ NPT_FAILED(value.ToInteger(info.uid))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("NumberReturned", value)) ||
+ value.GetLength() == 0 ||
+ NPT_FAILED(value.ToInteger(info.nr))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("TotalMatches", value)) ||
+ value.GetLength() == 0 ||
+ NPT_FAILED(value.ToInteger(info.tm))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("Result", value)) ||
+ value.GetLength() == 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(PLT_Didl::FromDidl(value, info.items))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnBrowseResult(NPT_SUCCESS, device, &info, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnBrowseResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::OnSearchResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnSearchResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+ PLT_BrowseInfo info;
+ NPT_String unescaped;
+
+ if (!m_Delegate) return NPT_SUCCESS;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("ContainerId", info.object_id))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("UpdateID", value)) ||
+ value.GetLength() == 0 ||
+ NPT_FAILED(value.ToInteger(info.uid))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("NumberReturned", value)) ||
+ value.GetLength() == 0 ||
+ NPT_FAILED(value.ToInteger(info.nr))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("TotalMatches", value)) ||
+ value.GetLength() == 0 ||
+ NPT_FAILED(value.ToInteger(info.tm))) {
+ goto bad_action;
+ }
+ if (NPT_FAILED(action->GetArgumentValue("Result", value)) ||
+ value.GetLength() == 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(PLT_Didl::FromDidl(value, info.items))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnSearchResult(NPT_SUCCESS, device, &info, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnSearchResult(NPT_FAILURE, device, NULL, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::OnGetSearchCapabilitiesResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnGetSearchCapabilitiesResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+
+ if (!m_Delegate) return NPT_SUCCESS;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("SearchCaps", value))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetSearchCapabilitiesResult(NPT_SUCCESS, device, value, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetSearchCapabilitiesResult(NPT_FAILURE, device, value, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::OnGetSearchCapabilitiesResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnGetSortCapabilitiesResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata)
+{
+ NPT_String value;
+
+ if (!m_Delegate) return NPT_SUCCESS;
+
+ if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
+ goto bad_action;
+ }
+
+ if (NPT_FAILED(action->GetArgumentValue("SortCaps", value))) {
+ goto bad_action;
+ }
+
+ m_Delegate->OnGetSortCapabilitiesResult(NPT_SUCCESS, device, value, userdata);
+ return NPT_SUCCESS;
+
+bad_action:
+ m_Delegate->OnGetSortCapabilitiesResult(NPT_FAILURE, device, value, userdata);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser::OnEventNotify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaBrowser::OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
+{
+ if (!service->GetDevice()->GetType().StartsWith("urn:schemas-upnp-org:device:MediaServer"))
+ return NPT_FAILURE;
+
+ if (!m_Delegate) return NPT_SUCCESS;
+
+ /* make sure device associated to service is still around */
+ PLT_DeviceDataReference data;
+ NPT_CHECK_WARNING(FindServer(service->GetDevice()->GetUUID(), data));
+
+ m_Delegate->OnMSStateVariablesChanged(service, vars);
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.h
new file mode 100644
index 0000000..2484dcc
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaBrowser.h
@@ -0,0 +1,184 @@
+/*****************************************************************
+|
+| Platinum - AV Media Browser (Media Server Control Point)
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Media Controller implementation.
+ */
+
+#ifndef _PLT_MEDIA_BROWSER_H_
+#define _PLT_MEDIA_BROWSER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltCtrlPoint.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+| PLT_BrowseInfo
++---------------------------------------------------------------------*/
+/**
+ The PLT_BrowseInfo struct is used to marshall Browse or Search action
+ response results across different threads of execution.
+ */
+typedef struct {
+ NPT_String object_id;
+ PLT_MediaObjectListReference items;
+ NPT_UInt32 si;
+ NPT_UInt32 nr;
+ NPT_UInt32 tm;
+ NPT_UInt32 uid;
+} PLT_BrowseInfo;
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowserDelegate
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaBrowserDelegate class is an interface for receiving PLT_MediaBrowser
+ events or action responses.
+ */
+class PLT_MediaBrowserDelegate
+{
+public:
+ virtual ~PLT_MediaBrowserDelegate() {}
+
+ virtual bool OnMSAdded(PLT_DeviceDataReference& /* device */) { return true; }
+ virtual void OnMSRemoved(PLT_DeviceDataReference& /* device */) {}
+ virtual void OnMSStateVariablesChanged(
+ PLT_Service* /*service*/,
+ NPT_List<PLT_StateVariable*>* /*vars*/) {}
+
+ // ContentDirectory
+ virtual void OnBrowseResult(
+ NPT_Result /*res*/,
+ PLT_DeviceDataReference& /*device*/,
+ PLT_BrowseInfo* /*info*/,
+ void* /*userdata*/) {}
+
+ virtual void OnSearchResult(
+ NPT_Result /*res*/,
+ PLT_DeviceDataReference& /*device*/,
+ PLT_BrowseInfo* /*info*/,
+ void* /*userdata*/) {}
+
+ virtual void OnGetSearchCapabilitiesResult(
+ NPT_Result /*res*/,
+ PLT_DeviceDataReference& /*device*/,
+ NPT_String /*searchCapabilities*/,
+ void* /*userdata*/) {}
+
+ virtual void OnGetSortCapabilitiesResult(
+ NPT_Result /*res*/,
+ PLT_DeviceDataReference& /*device*/,
+ NPT_String /*sortCapabilities*/,
+ void* /*userdata*/) {}
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaBrowser
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaBrowser class implements a UPnP AV Media Server control point.
+ */
+class PLT_MediaBrowser : public PLT_CtrlPointListener
+{
+public:
+ PLT_MediaBrowser(PLT_CtrlPointReference& ctrl_point,
+ PLT_MediaBrowserDelegate* delegate = NULL);
+ ~PLT_MediaBrowser() override;
+
+ // ContentDirectory service
+ virtual NPT_Result Browse(PLT_DeviceDataReference& device,
+ const char* object_id,
+ NPT_UInt32 start_index,
+ NPT_UInt32 count = 30, // DLNA recommendations
+ bool browse_metadata = false,
+ const char* filter = "dc:date,upnp:genre,res,res@duration,res@size,upnp:albumArtURI,upnp:originalTrackNumber,upnp:album,upnp:artist,upnp:author", // explicitely specify res otherwise WMP won't return a URL!
+ const char* sort_criteria = "",
+ void* userdata = NULL);
+
+ virtual NPT_Result Search(PLT_DeviceDataReference& device,
+ const char* container_id,
+ const char* search_criteria,
+ NPT_UInt32 start_index,
+ NPT_UInt32 count = 30, // DLNA recommendations
+ const char* filter = "dc:date,upnp:genre,res,res@duration,res@size,upnp:albumArtURI,upnp:originalTrackNumber,upnp:album,upnp:artist,upnp:author", // explicitely specify res otherwise WMP won't return a URL!
+ void* userdata = NULL);
+
+ virtual NPT_Result GetSearchCapabilities(PLT_DeviceDataReference& device,
+ void* userdata = NULL);
+
+ virtual NPT_Result GetSortCapabilities(PLT_DeviceDataReference& device,
+ void* userdata = NULL);
+
+ // methods
+ virtual const NPT_Lock<PLT_DeviceDataReferenceList>& GetMediaServers() { return m_MediaServers; }
+ virtual NPT_Result FindServer(const char* uuid, PLT_DeviceDataReference& device);
+ virtual void SetDelegate(PLT_MediaBrowserDelegate* delegate) { m_Delegate = delegate; }
+
+protected:
+ // PLT_CtrlPointListener methods
+ NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device) override;
+ NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device) override;
+ NPT_Result OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata) override;
+ NPT_Result OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars) override;
+
+ // ContentDirectory service responses
+ virtual NPT_Result OnBrowseResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata);
+
+ virtual NPT_Result OnSearchResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata);
+
+ virtual NPT_Result OnGetSearchCapabilitiesResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata);
+
+ virtual NPT_Result OnGetSortCapabilitiesResponse(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_ActionReference& action,
+ void* userdata);
+
+protected:
+ PLT_CtrlPointReference m_CtrlPoint;
+ PLT_MediaBrowserDelegate* m_Delegate;
+ NPT_Lock<PLT_DeviceDataReferenceList> m_MediaServers;
+};
+
+#endif /* _PLT_MEDIA_BROWSER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.cpp
new file mode 100644
index 0000000..aae5d01
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.cpp
@@ -0,0 +1,37 @@
+/*****************************************************************
+|
+| Platinum - AV Media Cache
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.h
new file mode 100644
index 0000000..8e365d8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaCache.h
@@ -0,0 +1,203 @@
+/*****************************************************************
+|
+| Platinum - AV Media Cache
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ Simple Object Caching utility.
+ */
+
+#ifndef _PLT_MEDIA_CACHE_H_
+#define _PLT_MEDIA_CACHE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_MediaCache
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaCache template provides a way to hold references to object in
+ memory.
+ */
+template <typename T, typename U>
+class PLT_MediaCache
+{
+public:
+ typedef typename NPT_Map<NPT_String,T>::Entry ElementEntry;
+ typedef typename NPT_List<ElementEntry*>::Iterator ElementIterator;
+
+ PLT_MediaCache<T,U>() {}
+ virtual ~PLT_MediaCache<T,U>() {}
+
+ NPT_Result Put(const char* root, const char* key, T& value, U* tag = NULL);
+ NPT_Result Get(const char* root, const char* key, T& value, U* tag = NULL);
+ NPT_Result Clear(const char* root, const char* key);
+ NPT_Result Clear(const char* root = NULL);
+
+private:
+ // methods
+ NPT_String GenerateKey(const char* root, const char* key);
+
+private:
+ // members
+ NPT_Mutex m_Mutex;
+ NPT_Map<NPT_String, T> m_Items;
+ NPT_Map<NPT_String, U> m_Tags;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaCache::GenerateKey
++---------------------------------------------------------------------*/
+template <typename T, typename U>
+inline
+NPT_String
+PLT_MediaCache<T,U>::GenerateKey(const char* root, const char* key)
+{
+ // TODO: There could be collision
+ NPT_String result = root;
+ result += "/";
+ result += key;
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaCache::Put
++---------------------------------------------------------------------*/
+template <typename T, typename U>
+inline
+NPT_Result
+PLT_MediaCache<T,U>::Put(const char* root,
+ const char* key,
+ T& value,
+ U* tag)
+{
+ NPT_AutoLock lock(m_Mutex);
+
+ NPT_String fullkey = GenerateKey(root, key);
+ if (fullkey.GetLength() == 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+ m_Items.Erase(fullkey);
+ NPT_CHECK(m_Items.Put(fullkey, value));
+
+ if (tag) NPT_CHECK(m_Tags.Put(fullkey, *tag));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaCache::Get
++---------------------------------------------------------------------*/
+template <typename T, typename U>
+inline
+NPT_Result
+PLT_MediaCache<T,U>::Get(const char* root,
+ const char* key,
+ T& value,
+ U* tag /* = NULL */)
+{
+ NPT_AutoLock lock(m_Mutex);
+
+ NPT_String fullkey = GenerateKey(root, key);
+ if (fullkey.GetLength() == 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+ T* _value = NULL;
+ NPT_CHECK(m_Items.Get(fullkey, _value));
+
+ U* _tag;
+ if (tag) {
+ m_Tags.Get(fullkey, _tag);
+ if (_tag) *tag = *_tag;
+ }
+
+ value = *_value;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaCache::Clear
++---------------------------------------------------------------------*/
+template <typename T, typename U>
+inline
+NPT_Result
+PLT_MediaCache<T,U>::Clear(const char* root, const char* key)
+{
+ NPT_AutoLock lock(m_Mutex);
+
+ NPT_String fullkey = GenerateKey(root, key);
+ if (fullkey.GetLength() == 0) return NPT_ERROR_INVALID_PARAMETERS;
+
+ ElementIterator entries = m_Items.GetEntries().GetFirstItem();
+ ElementIterator entry;
+ while (entries) {
+ entry = entries++;
+ if ((*entry)->GetKey() == (fullkey)) {
+ m_Items.Erase(fullkey);
+ m_Tags.Erase(fullkey);
+ return NPT_SUCCESS;
+ }
+ }
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaCache::Clear
++---------------------------------------------------------------------*/
+template <typename T, typename U>
+inline
+NPT_Result
+PLT_MediaCache<T,U>::Clear(const char* root)
+{
+ NPT_AutoLock lock(m_Mutex);
+
+ if (!root || root[0]=='\0')
+ return m_Items.Clear();
+
+ NPT_String key = GenerateKey(root, "");
+ ElementIterator entries = m_Items.GetEntries().GetFirstItem();
+ ElementIterator entry;
+ while (entries) {
+ entry = entries++;
+ NPT_String entry_key = (*entry)->GetKey();
+ if (entry_key.StartsWith(key)) {
+ m_Items.Erase(entry_key);
+ m_Tags.Erase(entry_key);
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+#endif /* _PLT_MEDIA_CACHE_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp
new file mode 100644
index 0000000..fac1690
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp
@@ -0,0 +1,1128 @@
+/*****************************************************************
+|
+| Platinum - AV Media Item
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMediaItem.h"
+#include "PltMediaServer.h"
+#include "PltDidl.h"
+#include "PltUtilities.h"
+#include "PltService.h"
+#include "PltMimeType.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.item")
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+NPT_DEFINE_DYNAMIC_CAST_ANCHOR(PLT_MediaObject)
+NPT_DEFINE_DYNAMIC_CAST_ANCHOR(PLT_MediaItem)
+NPT_DEFINE_DYNAMIC_CAST_ANCHOR(PLT_MediaContainer)
+
+/*----------------------------------------------------------------------
+| PLT_PersonRoles::AddPerson
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PersonRoles::Add(const NPT_String& name, const NPT_String& role /* = "" */)
+{
+ PLT_PersonRole person;
+ person.name = name;
+ person.role = role;
+
+ return NPT_List<PLT_PersonRole>::Add(person);
+}
+
+/*----------------------------------------------------------------------
+| PLT_PersonRoles::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PersonRoles::ToDidl(NPT_String& didl, const NPT_String& tag)
+{
+ NPT_String tmp;
+ for (NPT_List<PLT_PersonRole>::Iterator it =
+ NPT_List<PLT_PersonRole>::GetFirstItem(); it; it++) {
+ // if there's an empty artist, allow it only if there's nothing else
+ if (it->name.IsEmpty() && m_ItemCount>1 && !tmp.IsEmpty()) continue;
+
+ tmp += "<upnp:" + tag;
+ if (!it->role.IsEmpty()) {
+ tmp += " role=\"";
+ PLT_Didl::AppendXmlEscape(tmp, it->role);
+ tmp += "\"";
+ }
+ tmp += ">";
+ PLT_Didl::AppendXmlEscape(tmp, it->name);
+ tmp += "</upnp:" + tag + ">";
+ }
+
+ didl += tmp;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_PersonRoles::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PersonRoles::FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes)
+{
+ for (NPT_Cardinal i=0; i<nodes.GetItemCount(); i++) {
+ PLT_PersonRole person;
+ const NPT_String* name = nodes[i]->GetText();
+ const NPT_String* role = nodes[i]->GetAttribute("role");
+ // DLNA 7.3.17
+ if (name) person.name = name->SubString(0, 1024);
+ if (role) person.role = role->SubString(0, 1024);
+ NPT_CHECK(NPT_List<PLT_PersonRole>::Add(person));
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Artworks::Add
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Artworks::Add(const NPT_String& type, const NPT_String& url)
+{
+ PLT_Artwork artwork;
+ artwork.type = type;
+ artwork.url = url;
+
+ return NPT_List<PLT_Artwork>::Add(artwork);
+}
+
+/*----------------------------------------------------------------------
+| PLT_Artworks::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Artworks::ToDidl(NPT_String& didl, const NPT_String& tag)
+{
+ NPT_String tmp;
+ for (NPT_List<PLT_Artwork>::Iterator it =
+ NPT_List<PLT_Artwork>::GetFirstItem(); it; it++) {
+ if (it->type.IsEmpty()) continue;
+
+ tmp += "<xbmc:" + tag;
+ if (!it->type.IsEmpty()) {
+ tmp += " type=\"";
+ PLT_Didl::AppendXmlEscape(tmp, it->type);
+ tmp += "\"";
+ }
+ tmp += ">";
+ PLT_Didl::AppendXmlEscape(tmp, it->url);
+ tmp += "</xbmc:" + tag + ">";
+ }
+
+ didl += tmp;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Artworks::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Artworks::FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes)
+{
+ for (NPT_Cardinal i=0; i<nodes.GetItemCount(); i++) {
+ PLT_Artwork artwork;
+ const NPT_String* url = nodes[i]->GetText();
+ const NPT_String* type = nodes[i]->GetAttribute("type");
+ if (type) artwork.type = *type;
+ if (url) artwork.url = *url;
+ NPT_CHECK(NPT_List<PLT_Artwork>::Add(artwork));
+ }
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaItemResource::PLT_MediaItemResource
++---------------------------------------------------------------------*/
+PLT_MediaItemResource::PLT_MediaItemResource()
+{
+ m_Uri = "";
+ m_ProtocolInfo = PLT_ProtocolInfo();
+ m_Duration = (NPT_UInt32)-1;
+ m_Size = (NPT_LargeSize)-1;
+ m_Protection = "";
+ m_Bitrate = (NPT_UInt32)-1;
+ m_BitsPerSample = (NPT_UInt32)-1;
+ m_SampleFrequency = (NPT_UInt32)-1;
+ m_NbAudioChannels = (NPT_UInt32)-1;
+ m_Resolution = "";
+ m_ColorDepth = (NPT_UInt32)-1;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaObject::GetUPnPClass
++---------------------------------------------------------------------*/
+const char*
+PLT_MediaObject::GetUPnPClass(const char* filename,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ const char* ret = NULL;
+ NPT_String mime_type = PLT_MimeType::GetMimeType(filename, context);
+
+ if (mime_type.StartsWith("audio")) {
+ ret = "object.item.audioItem.musicTrack";
+ } else if (mime_type.StartsWith("video")) {
+ ret = "object.item.videoItem"; //Note: 360 wants "object.item.videoItem" and not "object.item.videoItem.Movie"
+ } else if (mime_type.StartsWith("image")) {
+ ret = "object.item.imageItem.photo";
+ } else {
+ ret = "object.item";
+ }
+
+ return ret;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaObject::Reset
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaObject::Reset()
+{
+ m_ObjectClass.type = "";
+ m_ObjectClass.friendly_name = "";
+ m_ObjectID = "";
+ m_ParentID = "";
+
+ m_Title = "";
+ m_Creator = "";
+ m_Date = "";
+ m_Restricted = true;
+
+ m_People.actors.Clear();
+ m_People.artists.Clear();
+ m_People.authors.Clear();
+ m_People.directors.Clear();
+ m_People.publisher.Clear();
+
+ m_Affiliation.album = "";
+ m_Affiliation.genres.Clear();
+ m_Affiliation.playlist = "";
+
+ m_Description.description = "";
+ m_Description.long_description = "";
+ m_Description.icon_uri = "";
+ m_ExtraInfo.album_arts.Clear();
+ m_ExtraInfo.artist_discography_uri = "";
+
+ m_MiscInfo.original_track_number = 0;
+ m_MiscInfo.last_position = 0;
+ m_MiscInfo.last_time = "";
+ m_MiscInfo.play_count = -1;
+ m_MiscInfo.dvdregioncode = 0;
+ m_MiscInfo.toc = "";
+ m_MiscInfo.user_annotation = "";
+
+ m_Recorded.program_title = "";
+ m_Recorded.series_title = "";
+ m_Recorded.episode_number = 0;
+ m_Recorded.episode_count = 0;
+ m_Recorded.episode_season = 0;
+
+ m_Resources.Clear();
+
+ m_XbmcInfo.last_playerstate = "";
+ m_XbmcInfo.date_added = "";
+ m_XbmcInfo.rating = 0.0f;
+ m_XbmcInfo.votes = 0;
+ m_XbmcInfo.artwork.Clear();
+ m_XbmcInfo.unique_identifier = "";
+ m_XbmcInfo.countries.Clear();
+ m_XbmcInfo.user_rating = 0;
+
+ m_Didl = "";
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaObject::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaObject::ToDidl(const NPT_String& filter, NPT_String& didl)
+{
+ return ToDidl(PLT_Didl::ConvertFilterToMask(filter), didl);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaObject::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaObject::ToDidl(NPT_UInt64 mask, NPT_String& didl)
+{
+ // title is required
+ didl += "<dc:title>";
+ PLT_Didl::AppendXmlEscape(didl, m_Title);
+ didl += "</dc:title>";
+
+ // creator
+ if (mask & PLT_FILTER_MASK_CREATOR) {
+ didl += "<dc:creator>";
+ if (m_Creator.IsEmpty()) m_Creator = "Unknown";
+ PLT_Didl::AppendXmlEscape(didl, m_Creator);
+ didl += "</dc:creator>";
+ }
+
+ // date
+ if ((mask & PLT_FILTER_MASK_DATE) && !m_Date.IsEmpty()) {
+ didl += "<dc:date>";
+ PLT_Didl::AppendXmlEscape(didl, m_Date);
+ didl += "</dc:date>";
+ }
+
+ // artist
+ if (mask & PLT_FILTER_MASK_ARTIST) {
+ // force an empty artist just in case (not DLNA Compliant though)
+ //if (m_People.artists.GetItemCount() == 0) m_People.artists.Add("");
+ m_People.artists.ToDidl(didl, "artist");
+ }
+
+ // actor
+ if (mask & PLT_FILTER_MASK_ACTOR) {
+ m_People.actors.ToDidl(didl, "actor");
+ }
+
+ // actor
+ if (mask & PLT_FILTER_MASK_AUTHOR) {
+ m_People.authors.ToDidl(didl, "author");
+ }
+
+ // director
+ if (mask & PLT_FILTER_MASK_DIRECTOR) {
+ m_People.directors.ToDidl(didl, "director");
+ }
+
+ // publisher
+ if (mask & PLT_FILTER_MASK_PUBLISHER) {
+ // Add unknown publisher
+ if (m_People.publisher.GetItemCount() == 0)
+ m_People.publisher.Add("Unknown");
+
+ for (NPT_List<NPT_String>::Iterator it =
+ m_People.publisher.GetFirstItem(); it; ++it) {
+ didl += "<dc:publisher>";
+ PLT_Didl::AppendXmlEscape(didl, (*it));
+ didl += "</dc:publisher>";
+ }
+ }
+
+ // album
+ if ((mask & PLT_FILTER_MASK_ALBUM) && !m_Affiliation.album.IsEmpty()) {
+ didl += "<upnp:album>";
+ PLT_Didl::AppendXmlEscape(didl, m_Affiliation.album);
+ didl += "</upnp:album>";
+ }
+
+ // genre
+ if (mask & PLT_FILTER_MASK_GENRE) {
+ // Add unknown genre
+ if (m_Affiliation.genres.GetItemCount() == 0)
+ m_Affiliation.genres.Add("Unknown");
+
+ for (NPT_List<NPT_String>::Iterator it =
+ m_Affiliation.genres.GetFirstItem(); it; ++it) {
+ didl += "<upnp:genre>";
+ PLT_Didl::AppendXmlEscape(didl, (*it));
+ didl += "</upnp:genre>";
+ }
+ }
+
+ // album art URI
+ if ((mask & PLT_FILTER_MASK_ALBUMARTURI) && m_ExtraInfo.album_arts.GetItemCount()) {
+ for (NPT_List<PLT_AlbumArtInfo>::Iterator iter = m_ExtraInfo.album_arts.GetFirstItem();
+ iter;
+ iter++) {
+ didl += "<upnp:albumArtURI";
+ if (!(*iter).dlna_profile.IsEmpty()) {
+ didl += " dlna:profileID=\"";
+ PLT_Didl::AppendXmlEscape(didl, (*iter).dlna_profile);
+ didl += "\"";
+ }
+ didl += ">";
+ PLT_Didl::AppendXmlEscape(didl, (*iter).uri);
+ didl += "</upnp:albumArtURI>";
+ }
+ }
+
+ // description
+ if ((mask & PLT_FILTER_MASK_DESCRIPTION) && !m_Description.description.IsEmpty()) {
+ didl += "<dc:description>";
+ PLT_Didl::AppendXmlEscape(didl, m_Description.description);
+ didl += "</dc:description>";
+ }
+
+ // long description
+ if ((mask & PLT_FILTER_MASK_LONGDESCRIPTION) && !m_Description.long_description.IsEmpty()) {
+ didl += "<upnp:longDescription>";
+ PLT_Didl::AppendXmlEscape(didl, m_Description.long_description);
+ didl += "</upnp:longDescription>";
+ }
+
+ // icon
+ if ((mask & PLT_FILTER_MASK_ICON) && !m_Description.icon_uri.IsEmpty()) {
+ didl += "<upnp:icon>";
+ PLT_Didl::AppendXmlEscape(didl, m_Description.icon_uri);
+ didl += "</upnp:icon>";
+ }
+
+ // rating
+ if ((mask & PLT_FILTER_MASK_RATING) && !m_Description.rating.IsEmpty()) {
+ didl += "<upnp:rating>";
+ PLT_Didl::AppendXmlEscape(didl, m_Description.rating);
+ didl += "</upnp:rating>";
+ }
+
+ // original track number
+ if ((mask & PLT_FILTER_MASK_ORIGINALTRACK) && m_MiscInfo.original_track_number > 0) {
+ didl += "<upnp:originalTrackNumber>";
+ didl += NPT_String::FromInteger(m_MiscInfo.original_track_number);
+ didl += "</upnp:originalTrackNumber>";
+ }
+
+ // last playback position
+ if (mask & PLT_FILTER_MASK_LASTPOSITION && m_MiscInfo.last_position > 0) {
+ didl += "<upnp:lastPlaybackPosition>";
+ didl += NPT_String::FromInteger(m_MiscInfo.last_position);
+ didl += "</upnp:lastPlaybackPosition>";
+ }
+
+ // last playback datetime
+ if (mask & PLT_FILTER_MASK_LASTPLAYBACK && !m_MiscInfo.last_time.IsEmpty()) {
+ didl += "<upnp:lastPlaybackTime>";
+ PLT_Didl::AppendXmlEscape(didl, m_MiscInfo.last_time);
+ didl += "</upnp:lastPlaybackTime>";
+ }
+
+ // playcount
+ if (mask & PLT_FILTER_MASK_PLAYCOUNT && m_MiscInfo.play_count > -1) {
+ didl += "<upnp:playbackCount>";
+ didl += NPT_String::FromInteger(m_MiscInfo.play_count);
+ didl += "</upnp:playbackCount>";
+ }
+
+ // program title
+ if (mask & PLT_FILTER_MASK_PROGRAMTITLE && !m_Recorded.program_title.IsEmpty()) {
+ didl += "<upnp:programTitle>";
+ PLT_Didl::AppendXmlEscape(didl, m_Recorded.program_title);
+ didl += "</upnp:programTitle>";
+ }
+
+ // series title
+ if ((mask & PLT_FILTER_MASK_SERIESTITLE) && !m_Recorded.series_title.IsEmpty()) {
+ didl += "<upnp:seriesTitle>";
+ PLT_Didl::AppendXmlEscape(didl, m_Recorded.series_title);
+ didl += "</upnp:seriesTitle>";
+ }
+
+ // episode number
+ if ((mask & PLT_FILTER_MASK_EPISODE) && m_Recorded.episode_number > 0) {
+ didl += "<upnp:episodeNumber>";
+ didl += NPT_String::FromInteger(m_Recorded.episode_number);
+ didl += "</upnp:episodeNumber>";
+ }
+
+ // episode count
+ if ((mask & PLT_FILTER_MASK_EPISODE_COUNT) && m_Recorded.episode_count > 0) {
+ didl += "<upnp:episodeCount>";
+ didl += NPT_String::FromInteger(m_Recorded.episode_count);
+ didl += "</upnp:episodeCount>";
+ }
+
+ // episode count
+ if ((mask & PLT_FILTER_MASK_EPISODE_SEASON)) {
+ didl += "<upnp:episodeSeason>";
+ didl += NPT_String::FromInteger(m_Recorded.episode_season);
+ didl += "</upnp:episodeSeason>";
+ }
+
+ if ((mask & PLT_FILTER_MASK_TOC) && !m_MiscInfo.toc.IsEmpty()) {
+ didl += "<upnp:toc>";
+ PLT_Didl::AppendXmlEscape(didl, m_MiscInfo.toc);
+ didl += "</upnp:toc>";
+ }
+
+ // resource
+ if (mask & PLT_FILTER_MASK_RES) {
+ for (NPT_Cardinal i=0; i<m_Resources.GetItemCount(); i++) {
+ didl += "<res";
+
+ if ((mask & PLT_FILTER_MASK_RES_DURATION) && m_Resources[i].m_Duration != (NPT_UInt32)-1) {
+ didl += " duration=\"";
+ didl += PLT_Didl::FormatTimeStamp(m_Resources[i].m_Duration);
+ didl += "\"";
+ }
+
+ if ((mask & PLT_FILTER_MASK_RES_SIZE) && m_Resources[i].m_Size != (NPT_LargeSize)-1) {
+ didl += " size=\"";
+ didl += NPT_String::FromIntegerU(m_Resources[i].m_Size);
+ didl += "\"";
+ }
+
+ if ((mask & PLT_FILTER_MASK_RES_PROTECTION) && !m_Resources[i].m_Protection.IsEmpty()) {
+ didl += " protection=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_Protection);
+ didl += "\"";
+ }
+
+ if ((mask & PLT_FILTER_MASK_RES_RESOLUTION) && !m_Resources[i].m_Resolution.IsEmpty()) {
+ didl += " resolution=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_Resolution);
+ didl += "\"";
+ }
+
+ if ((mask & PLT_FILTER_MASK_RES_BITRATE) && m_Resources[i].m_Bitrate != (NPT_Size)-1) {
+ didl += " bitrate=\"";
+ didl += NPT_String::FromIntegerU(m_Resources[i].m_Bitrate);
+ didl += "\"";
+ }
+
+ if ((mask & PLT_FILTER_MASK_RES_BITSPERSAMPLE) && m_Resources[i].m_BitsPerSample != (NPT_Size)-1) {
+ didl += " bitsPerSample=\"";
+ didl += NPT_String::FromIntegerU(m_Resources[i].m_BitsPerSample);
+ didl += "\"";
+ }
+
+ if ((mask & PLT_FILTER_MASK_RES_SAMPLEFREQUENCY) && m_Resources[i].m_SampleFrequency != (NPT_Size)-1) {
+ didl += " sampleFrequency=\"";
+ didl += NPT_String::FromIntegerU(m_Resources[i].m_SampleFrequency);
+ didl += "\"";
+ }
+
+ if ((mask & PLT_FILTER_MASK_RES_NRAUDIOCHANNELS) && m_Resources[i].m_NbAudioChannels != (NPT_Size)-1) {
+ didl += " nrAudioChannels=\"";
+ didl += NPT_String::FromIntegerU(m_Resources[i].m_NbAudioChannels);
+ didl += "\"";
+ }
+
+ didl += " protocolInfo=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_ProtocolInfo.ToString());
+ didl += "\"";
+ /* adding custom data */
+ NPT_List<NPT_Map<NPT_String, NPT_String>::Entry*>::Iterator entry = m_Resources[i].m_CustomData.GetEntries().GetFirstItem();
+ while (entry)
+ {
+ didl += " ";
+ PLT_Didl::AppendXmlEscape(didl, (*entry)->GetKey());
+ didl += "=\"";
+ PLT_Didl::AppendXmlEscape(didl, (*entry)->GetValue());
+ didl += "\"";
+
+ entry++;
+ }
+
+ didl += ">";
+ PLT_Didl::AppendXmlEscape(didl, m_Resources[i].m_Uri);
+ didl += "</res>";
+ }
+ }
+
+ //sec resources related
+ for (NPT_Cardinal i = 0; i < m_SecResources.GetItemCount(); i++) {
+ didl += "<sec:";
+ PLT_Didl::AppendXmlEscape(didl, m_SecResources[i].name);
+
+ NPT_List<NPT_Map<NPT_String, NPT_String>::Entry*>::Iterator entry = m_SecResources[i].attributes.GetEntries().GetFirstItem();
+ while (entry)
+ {
+ didl += " sec:";
+ PLT_Didl::AppendXmlEscape(didl, (*entry)->GetKey());
+ didl += "=\"";
+ PLT_Didl::AppendXmlEscape(didl, (*entry)->GetValue());
+ didl += "\"";
+
+ entry++;
+ }
+
+ didl += ">";
+ PLT_Didl::AppendXmlEscape(didl, m_SecResources[i].value);
+
+ didl += "</sec:";
+ PLT_Didl::AppendXmlEscape(didl, m_SecResources[i].name);
+ didl += ">";
+ }
+
+ // xbmc dateadded
+ if ((mask & PLT_FILTER_MASK_XBMC_DATEADDED) && !m_XbmcInfo.date_added.IsEmpty()) {
+ didl += "<xbmc:dateadded>";
+ PLT_Didl::AppendXmlEscape(didl, m_XbmcInfo.date_added);
+ didl += "</xbmc:dateadded>";
+ }
+
+ // xbmc rating
+ if (mask & PLT_FILTER_MASK_XBMC_RATING) {
+ didl += "<xbmc:rating>";
+ didl += NPT_String::Format("%.1f", m_XbmcInfo.rating);
+ didl += "</xbmc:rating>";
+ }
+
+ // xbmc votes
+ if (mask & PLT_FILTER_MASK_XBMC_VOTES && m_XbmcInfo.votes != 0) {
+ didl += "<xbmc:votes>";
+ didl += NPT_String::Format("%i", m_XbmcInfo.votes);
+ didl += "</xbmc:votes>";
+ }
+
+ // xbmc artwork
+ if (mask & PLT_FILTER_MASK_XBMC_ARTWORK) {
+ m_XbmcInfo.artwork.ToDidl(didl, "artwork");
+ }
+
+ // xbmc unique identifier
+ if (mask & PLT_FILTER_MASK_XBMC_UNIQUE_IDENTIFIER && !m_XbmcInfo.unique_identifier.IsEmpty()) {
+ didl += "<xbmc:uniqueidentifier>";
+ PLT_Didl::AppendXmlEscape(didl, m_XbmcInfo.unique_identifier);
+ didl += "</xbmc:uniqueidentifier>";
+ }
+
+ // country
+ if (mask & PLT_FILTER_MASK_XBMC_COUNTRY) {
+ for (NPT_List<NPT_String>::Iterator it =
+ m_XbmcInfo.countries.GetFirstItem(); it; ++it) {
+ didl += "<xbmc:country>";
+ PLT_Didl::AppendXmlEscape(didl, (*it));
+ didl += "</xbmc:country>";
+ }
+ }
+
+ // user rating
+ if (mask & PLT_FILTER_MASK_XBMC_USERRATING) {
+ didl += "<xbmc:userrating>";
+ didl += NPT_String::FromInteger(m_XbmcInfo.user_rating);
+ didl += "</xbmc:userrating>";
+ }
+
+ // xbmc last playback state
+ if (mask & PLT_FILTER_MASK_XBMC_LASTPLAYERSTATE && !m_XbmcInfo.last_playerstate.IsEmpty()) {
+ didl += "<xbmc:lastPlayerState>";
+ PLT_Didl::AppendXmlEscape(didl, m_XbmcInfo.last_playerstate);
+ didl += "</xbmc:lastPlayerState>";
+ }
+
+ // class is required
+ didl += "<upnp:class";
+ if (!m_ObjectClass.friendly_name.IsEmpty()) {
+ didl += " name=\"" + m_ObjectClass.friendly_name+"\"";
+ }
+ didl += ">";
+ PLT_Didl::AppendXmlEscape(didl, m_ObjectClass.type);
+ didl += "</upnp:class>";
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaObject::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaObject::FromDidl(NPT_XmlElementNode* entry)
+{
+ NPT_String str, xml;
+ NPT_Array<NPT_XmlElementNode*> children;
+ NPT_Result res;
+
+ // check if item is restricted (is default true?)
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "restricted", str, "", 5))) {
+ m_Restricted = PLT_Service::IsTrue(str);
+ }
+
+ // read non-required elements
+ PLT_XmlHelper::GetChildText(entry, "creator", m_Creator, didl_namespace_dc, 256);
+ PLT_XmlHelper::GetChildText(entry, "date", m_Date, didl_namespace_dc, 256);
+
+ // parse date and make sure it's valid
+ NPT_String parsed_date;
+ for (int format=0; format<=NPT_DateTime::FORMAT_RFC_1036; format++) {
+ NPT_DateTime date;
+ if (NPT_SUCCEEDED(date.FromString(m_Date, (NPT_DateTime::Format)format))) {
+ parsed_date = date.ToString((NPT_DateTime::Format)format);
+ break;
+ }
+ }
+ m_Date = parsed_date;
+
+ res = PLT_XmlHelper::GetAttribute(entry, "id", m_ObjectID);
+ NPT_CHECK_SEVERE(res);
+
+ res = PLT_XmlHelper::GetAttribute(entry, "parentID", m_ParentID);
+ NPT_CHECK_SEVERE(res);
+
+ PLT_XmlHelper::GetAttribute(entry, "refID", m_ReferenceID);
+
+ res = PLT_XmlHelper::GetChildText(entry, "title", m_Title, didl_namespace_dc);
+ NPT_CHECK_SEVERE(res);
+
+ res = PLT_XmlHelper::GetChildText(entry, "class", m_ObjectClass.type, didl_namespace_upnp);
+ NPT_CHECK_SEVERE(res);
+
+ // DLNA 7.3.17.3 max bytes for dc:title and upnp:class is 256 bytes
+ m_Title = m_Title.SubString(0, 256);
+ m_ObjectClass.type = m_ObjectClass.type.SubString(0, 256);
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "artist", didl_namespace_upnp);
+ m_People.artists.FromDidl(children);
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "author", didl_namespace_upnp);
+ m_People.authors.FromDidl(children);
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "actor", didl_namespace_upnp);
+ m_People.actors.FromDidl(children);
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "director", didl_namespace_upnp);
+ m_People.directors.FromDidl(children);
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "publisher", didl_namespace_dc);
+ for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) {
+ if (children[i]->GetText()) {
+ m_People.publisher.Add(*children[i]->GetText());
+ }
+ }
+
+ PLT_XmlHelper::GetChildText(entry, "album", m_Affiliation.album, didl_namespace_upnp, 256);
+ PLT_XmlHelper::GetChildText(entry, "programTitle", m_Recorded.program_title, didl_namespace_upnp);
+ PLT_XmlHelper::GetChildText(entry, "seriesTitle", m_Recorded.series_title, didl_namespace_upnp);
+ PLT_XmlHelper::GetChildText(entry, "episodeNumber", str, didl_namespace_upnp);
+ NPT_UInt32 value;
+ if (NPT_FAILED(str.ToInteger(value))) value = 0;
+ m_Recorded.episode_number = value;
+ PLT_XmlHelper::GetChildText(entry, "episodeCount", str, didl_namespace_upnp);
+ if (NPT_FAILED(str.ToInteger(value))) value = 0;
+ m_Recorded.episode_count = value;
+ PLT_XmlHelper::GetChildText(entry, "episodeSeason", str, didl_namespace_upnp);
+ if (NPT_FAILED(str.ToInteger(value))) value = -1;
+ m_Recorded.episode_season = value;
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "genre", didl_namespace_upnp);
+ for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) {
+ if (children[i]->GetText()) {
+ m_Affiliation.genres.Add(children[i]->GetText()->SubString(0, 256));
+ }
+ }
+
+ PLT_XmlHelper::GetChildText(entry, "description", m_Description.description, didl_namespace_dc);
+ PLT_XmlHelper::GetChildText(entry, "longDescription", m_Description.long_description, didl_namespace_upnp);
+ PLT_XmlHelper::GetChildText(entry, "icon", m_Description.icon_uri, didl_namespace_upnp);
+ PLT_XmlHelper::GetChildText(entry, "rating", m_Description.rating, didl_namespace_upnp);
+ PLT_XmlHelper::GetChildText(entry, "toc", m_MiscInfo.toc, didl_namespace_upnp);
+
+ // album arts
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "albumArtURI", didl_namespace_upnp);
+ for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) {
+ if (children[i]->GetText()) {
+ PLT_AlbumArtInfo info;
+ info.uri = children[i]->GetText()->SubString(0, 1024);
+ PLT_XmlHelper::GetAttribute(children[i], "profileID", info.dlna_profile, didl_namespace_dlna);
+ m_ExtraInfo.album_arts.Add(info);
+ }
+ }
+
+ PLT_XmlHelper::GetChildText(entry, "originalTrackNumber", str, didl_namespace_upnp);
+ if (NPT_FAILED(str.ToInteger(value))) value = 0;
+ m_MiscInfo.original_track_number = value;
+
+ PLT_XmlHelper::GetChildText(entry, "lastPlaybackPosition", str, didl_namespace_upnp);
+ if (NPT_FAILED(PLT_Didl::ParseTimeStamp(str, value))) {
+ // fall back to raw integer parsing
+ if (NPT_FAILED(str.ToInteger(value))) value = 0;
+ }
+ m_MiscInfo.last_position = value;
+
+ PLT_XmlHelper::GetChildText(entry, "lastPlaybackTime", m_MiscInfo.last_time, didl_namespace_upnp, 256);
+ NPT_String parsed_last_time;
+ for (int format=0; format<=NPT_DateTime::FORMAT_RFC_1036; format++) {
+ NPT_DateTime date;
+ if (NPT_SUCCEEDED(date.FromString(m_MiscInfo.last_time, (NPT_DateTime::Format)format))) {
+ parsed_last_time = date.ToString((NPT_DateTime::Format)format);
+ break;
+ }
+ }
+ m_MiscInfo.last_time = parsed_last_time;
+
+ PLT_XmlHelper::GetChildText(entry, "playbackCount", str, didl_namespace_upnp);
+ if (NPT_FAILED(str.ToInteger(value))) value = -1;
+ m_MiscInfo.play_count = value;
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "res");
+ for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) {
+ PLT_MediaItemResource resource;
+
+ // extract url
+ if (children[i]->GetText() == NULL) {
+ NPT_LOG_WARNING_1("No resource text found in: %s", (const char*)PLT_XmlHelper::Serialize(*children[i]));
+ } else {
+ resource.m_Uri = children[i]->GetText()->SubString(0, 1024);
+
+ // basic uri validation, ignoring scheme (could be rtsp)
+ NPT_HttpUrl url(resource.m_Uri, true);
+ if (!url.IsValid()) {
+ NPT_LOG_WARNING_1("Invalid resource uri: %s", (const char*)resource.m_Uri);
+ continue;
+ }
+ }
+
+ // extract protocol info
+ NPT_String protocol_info;
+ res = PLT_XmlHelper::GetAttribute(children[i], "protocolInfo", protocol_info, "", 256);
+ if (NPT_FAILED(res)) {
+ NPT_LOG_WARNING_1("No protocol info found in: %s", (const char*)PLT_XmlHelper::Serialize(*children[i]));
+ } else {
+ resource.m_ProtocolInfo = PLT_ProtocolInfo(protocol_info);
+ if (!resource.m_ProtocolInfo.IsValid()) {
+ NPT_LOG_WARNING_1("Invalid resource protocol info: %s", (const char*)protocol_info);
+ }
+ }
+
+ // extract known attributes
+ PLT_XmlHelper::GetAttribute(children[i], "protection", resource.m_Protection, "", 256);
+ PLT_XmlHelper::GetAttribute(children[i], "resolution", resource.m_Resolution, "", 256);
+
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(children[i], "size", str, "", 256))) {
+ if (NPT_FAILED(str.ToInteger64(resource.m_Size))) resource.m_Size = (NPT_Size)-1;
+ }
+
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(children[i], "duration", str, "", 256))) {
+ if (NPT_FAILED(PLT_Didl::ParseTimeStamp(str, resource.m_Duration))) {
+ // if error while converting, ignore and set to -1 to indicate we don't know the duration
+ resource.m_Duration = (NPT_UInt32)-1;
+ PLT_XmlHelper::RemoveAttribute(children[i], "duration");
+ } else {
+ // DLNA: reformat duration in case it was not compliant
+ str = PLT_Didl::FormatTimeStamp(resource.m_Duration);
+ PLT_XmlHelper::SetAttribute(children[i], "duration", str);
+ }
+ }
+ m_Resources.Add(resource);
+ }
+
+ PLT_XmlHelper::GetChildText(entry, "lastPlayerState", m_XbmcInfo.last_playerstate, didl_namespace_xbmc, 2048);
+
+ PLT_XmlHelper::GetChildText(entry, "dateadded", m_XbmcInfo.date_added, didl_namespace_xbmc, 256);
+ // parse date and make sure it's valid
+ for (int format=0; format<=NPT_DateTime::FORMAT_RFC_1036; format++) {
+ NPT_DateTime date;
+ if (NPT_SUCCEEDED(date.FromString(m_XbmcInfo.date_added, (NPT_DateTime::Format)format))) {
+ parsed_date = date.ToString((NPT_DateTime::Format)format);
+ break;
+ }
+ }
+ m_XbmcInfo.date_added = parsed_date;
+
+ PLT_XmlHelper::GetChildText(entry, "rating", str, didl_namespace_xbmc);
+ NPT_Float floatValue;
+ if (NPT_FAILED(str.ToFloat(floatValue))) floatValue = 0.0;
+ m_XbmcInfo.rating = floatValue;
+
+ PLT_XmlHelper::GetChildText(entry, "votes", str, didl_namespace_xbmc, 256);
+ NPT_Int32 intValue;
+ if (NPT_FAILED(str.ToInteger(intValue))) intValue = 0;
+ m_XbmcInfo.votes = intValue;
+
+ children.Clear();
+ PLT_XmlHelper::GetChildren(entry, children, "artwork", didl_namespace_xbmc);
+ m_XbmcInfo.artwork.FromDidl(children);
+
+ PLT_XmlHelper::GetChildText(entry, "uniqueidentifier", m_XbmcInfo.unique_identifier, didl_namespace_xbmc, 256);
+
+ // re serialize the entry didl as a we might need to pass it to a renderer
+ // we may have modified the tree to "fix" issues, so as not to break a renderer
+ // (don't write xml prefix as this didl could be part of a larger document)
+ //res = PLT_XmlHelper::Serialize(*entry, xml, false);
+ m_Didl = "";
+ res = ToDidl(PLT_FILTER_MASK_ALL, m_Didl);
+ NPT_CHECK_SEVERE(res);
+
+ m_Didl = didl_header + m_Didl + didl_footer;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaObjectList::PLT_MediaObjectList
++---------------------------------------------------------------------*/
+PLT_MediaObjectList::PLT_MediaObjectList()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaObjectList::~PLT_MediaObjectList
++---------------------------------------------------------------------*/
+PLT_MediaObjectList::~PLT_MediaObjectList()
+{
+ Apply(NPT_ObjectDeleter<PLT_MediaObject>());
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaItem::PLT_MediaItem
++---------------------------------------------------------------------*/
+PLT_MediaItem::PLT_MediaItem()
+{
+ Reset();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaItem::~PLT_MediaItem
++---------------------------------------------------------------------*/
+PLT_MediaItem::~PLT_MediaItem()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaItem::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaItem::ToDidl(const NPT_String& filter, NPT_String& didl)
+{
+ return PLT_MediaObject::ToDidl(filter, didl);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaItem::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaItem::ToDidl(NPT_UInt64 mask, NPT_String& didl)
+{
+ didl += "<item id=\"";
+
+ PLT_Didl::AppendXmlEscape(didl, m_ObjectID);
+ didl += "\" parentID=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_ParentID);
+
+ if ((mask & PLT_FILTER_MASK_REFID) && !m_ReferenceID.IsEmpty()) {
+ didl += "\" refID=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_ReferenceID);
+ }
+
+ didl += "\" restricted=\"";
+ didl += m_Restricted?"1\"":"0\"";
+
+ didl += ">";
+
+ NPT_CHECK_SEVERE(PLT_MediaObject::ToDidl(mask, didl));
+
+ /* close tag */
+ didl += "</item>";
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaItem::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaItem::FromDidl(NPT_XmlElementNode* entry)
+{
+ /* reset first */
+ Reset();
+
+ if (entry->GetTag().Compare("item", true) != 0) {
+ NPT_CHECK_SEVERE(NPT_ERROR_INTERNAL);
+ }
+
+ NPT_Result result = PLT_MediaObject::FromDidl(entry);
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainer::PLT_MediaContainer
++---------------------------------------------------------------------*/
+PLT_MediaContainer::PLT_MediaContainer()
+{
+ Reset();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainer::~PLT_MediaContainer
++---------------------------------------------------------------------*/
+PLT_MediaContainer::~PLT_MediaContainer(void)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainer::Reset
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaContainer::Reset()
+{
+ m_SearchClasses.Clear();
+ m_Searchable = false;
+ m_ChildrenCount = -1;
+ m_ContainerUpdateID = 0;
+
+ return PLT_MediaObject::Reset();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainer::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaContainer::ToDidl(const NPT_String& filter, NPT_String& didl)
+{
+ return PLT_MediaObject::ToDidl(filter, didl);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainer::ToDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaContainer::ToDidl(NPT_UInt64 mask, NPT_String& didl)
+{
+ // container id property
+ didl += "<container id=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_ObjectID);
+
+ // parent id property
+ didl += "\" parentID=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_ParentID);
+
+ // ref id
+ if ((mask & PLT_FILTER_MASK_REFID) && !m_ReferenceID.IsEmpty()) {
+ didl += "\" refID=\"";
+ PLT_Didl::AppendXmlEscape(didl, m_ReferenceID);
+ }
+
+ // restricted property
+ didl += "\" restricted=\"";
+ didl += m_Restricted?"1\"":"0\"";
+
+ // searchable property
+ if (mask & PLT_FILTER_MASK_SEARCHABLE) {
+ didl += " searchable=\"";
+ didl += m_Searchable?"1\"":"0\"";
+ }
+
+ // childcount property
+ if ((mask & PLT_FILTER_MASK_CHILDCOUNT) && m_ChildrenCount != -1) {
+ didl += " childCount=\"";
+ didl += NPT_String::FromInteger(m_ChildrenCount);
+ didl += "\"";
+ }
+
+ didl += ">";
+
+ if ((mask & PLT_FILTER_MASK_SEARCHCLASS) && m_SearchClasses.GetItemCount()) {
+ NPT_List<PLT_SearchClass>::Iterator search_class = m_SearchClasses.GetFirstItem();
+ while (search_class) {
+ didl += "<upnp:searchClass includeDerived=\"";
+ didl += (*search_class).include_derived?"1\"":"0\"";
+
+ // frienly name is any
+ if (!(*search_class).friendly_name.IsEmpty()) {
+ didl += " name=\"" + (*search_class).friendly_name + "\"";
+ }
+ didl += ">";
+ didl += (*search_class).type;
+ didl += "</upnp:searchClass>";
+
+ ++search_class;
+ }
+ }
+
+ NPT_CHECK_SEVERE(PLT_MediaObject::ToDidl(mask, didl));
+
+ /* close tag */
+ didl += "</container>";
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainer::FromDidl
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaContainer::FromDidl(NPT_XmlElementNode* entry)
+{
+ NPT_String str;
+
+ /* reset first */
+ Reset();
+
+ // check entry type
+ if (entry->GetTag().Compare("Container", true) != 0)
+ return NPT_ERROR_INTERNAL;
+
+ // check if item is searchable (is default true?)
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "searchable", str, "", 5))) {
+ m_Searchable = PLT_Service::IsTrue(str);
+ }
+
+ // look for childCount
+ if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "childCount", str, "", 256))) {
+ NPT_UInt32 count;
+ NPT_CHECK_SEVERE(str.ToInteger(count));
+ m_ChildrenCount = count;
+ }
+
+ // upnp:searchClass child elements
+ NPT_Array<NPT_XmlElementNode*> children;
+ PLT_XmlHelper::GetChildren(entry, children, "upnp:searchClass");
+
+ for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) {
+ PLT_SearchClass search_class;
+
+ // extract url
+ if (children[i]->GetText() == NULL) {
+ NPT_LOG_WARNING_1("No searchClass text found in: %s",
+ (const char*)PLT_XmlHelper::Serialize(*children[i]));
+ continue;
+ }
+
+ // DLNA 7.3.17.4
+ search_class.type = children[i]->GetText()->SubString(0, 256);
+
+ // extract optional attribute name
+ PLT_XmlHelper::GetAttribute(children[i], "name", search_class.friendly_name);
+
+ // includeDerived property
+ if (NPT_FAILED(PLT_XmlHelper::GetAttribute(children[i], "includeDerived", str))) {
+ NPT_LOG_WARNING_1("No required attribute searchClass@includeDerived found in: %s",
+ (const char*)PLT_XmlHelper::Serialize(*children[i]));
+ continue;
+ }
+
+ search_class.include_derived = PLT_Service::IsTrue(str);
+ m_SearchClasses.Add(search_class);
+ }
+
+ return PLT_MediaObject::FromDidl(entry);
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h
new file mode 100644
index 0000000..3a13967
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h
@@ -0,0 +1,348 @@
+/*****************************************************************
+|
+| Platinum - AV Media Item
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Media Object reprensentation.
+ */
+
+#ifndef _PLT_MEDIA_ITEM_H_
+#define _PLT_MEDIA_ITEM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttp.h"
+#include "PltProtocolInfo.h"
+
+/*----------------------------------------------------------------------
+| typedefs
++---------------------------------------------------------------------*/
+/**
+ The PLT_ObjectClass struct is used to assign a type to a PLT_MediaObject.
+ */
+typedef struct {
+ NPT_String type;
+ NPT_String friendly_name;
+} PLT_ObjectClass;
+
+typedef struct {
+ NPT_String type;
+ NPT_String friendly_name;
+ bool include_derived;
+} PLT_SearchClass;
+
+typedef struct {
+ NPT_String name;
+ NPT_String role;
+} PLT_PersonRole;
+
+class PLT_PersonRoles : public NPT_List<PLT_PersonRole>
+{
+public:
+ NPT_Result Add(const NPT_String& name, const NPT_String& role = "");
+ NPT_Result ToDidl(NPT_String& didl, const NPT_String& tag);
+ NPT_Result FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes);
+};
+
+typedef struct {
+ NPT_String allowed_use; // (CSV)
+ NPT_String validity_start;
+ NPT_String validity_end;
+ NPT_String remaining_time;
+ NPT_String usage_info;
+ NPT_String rights_info_uri;
+ NPT_String content_info_uri;
+} PLT_Constraint;
+
+typedef struct {
+ PLT_PersonRoles artists;
+ PLT_PersonRoles actors;
+ PLT_PersonRoles authors;
+ NPT_String producer; //TODO: can be multiple
+ PLT_PersonRoles directors;
+ NPT_List<NPT_String> publisher;
+ NPT_String contributor; // should match m_Creator (dc:creator) //TODO: can be multiple
+} PLT_PeopleInfo;
+
+typedef struct {
+ NPT_List<NPT_String> genres;
+ NPT_String album; //TODO: can be multiple
+ NPT_String playlist; // dc:title of the playlist item the content belongs too //TODO: can be multiple
+} PLT_AffiliationInfo;
+
+typedef struct {
+ NPT_String description;
+ NPT_String long_description;
+ NPT_String icon_uri;
+ NPT_String region;
+ NPT_String rating;
+ NPT_String rights; //TODO: can be multiple
+ NPT_String date;
+ NPT_String language;
+} PLT_Description;
+
+typedef struct {
+ NPT_String uri;
+ NPT_String dlna_profile;
+} PLT_AlbumArtInfo;
+
+typedef struct {
+ NPT_List<PLT_AlbumArtInfo> album_arts;
+ NPT_String artist_discography_uri;
+ NPT_String lyrics_uri;
+ NPT_List<NPT_String> relations; // dc:relation
+} PLT_ExtraInfo;
+
+typedef struct {
+ NPT_UInt32 dvdregioncode;
+ NPT_UInt32 original_track_number;
+ NPT_String toc;
+ NPT_String user_annotation; //TODO: can be multiple
+ NPT_UInt32 last_position;
+ NPT_String last_time;
+ NPT_Int32 play_count;
+} PLT_MiscInfo;
+
+typedef struct {
+ NPT_UInt64 total;
+ NPT_UInt64 used;
+ NPT_UInt64 free;
+ NPT_UInt64 max_partition;
+ NPT_UInt64 medium;
+} PLT_StorageInfo;
+
+typedef struct {
+ NPT_String program_title;
+ NPT_String series_title;
+ NPT_UInt32 episode_number;
+ NPT_UInt32 episode_count;
+ NPT_UInt32 episode_season;
+} PLT_RecordedInfo;
+
+typedef struct {
+ NPT_String type;
+ NPT_String url;
+} PLT_Artwork;
+
+class PLT_Artworks : public NPT_List<PLT_Artwork>
+{
+public:
+ NPT_Result Add(const NPT_String& type, const NPT_String& url);
+ NPT_Result ToDidl(NPT_String& didl, const NPT_String& tag);
+ NPT_Result FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes);
+};
+
+typedef struct {
+ NPT_String last_playerstate;
+ NPT_String date_added;
+ NPT_Float rating;
+ NPT_Int32 votes;
+ PLT_Artworks artwork;
+ NPT_String unique_identifier;
+ NPT_List<NPT_String> countries;
+ NPT_Int32 user_rating;
+} PLT_XbmcInfo;
+
+typedef struct {
+ NPT_String name;
+ NPT_Map<NPT_String, NPT_String> attributes;
+ NPT_String value;
+} PLT_SecResource;
+
+/*----------------------------------------------------------------------
+| PLT_MediaItemResource
++---------------------------------------------------------------------*/
+class PLT_MediaItemResource
+{
+public:
+ PLT_MediaItemResource();
+ ~PLT_MediaItemResource() {}
+
+ NPT_String m_Uri;
+ PLT_ProtocolInfo m_ProtocolInfo;
+ NPT_UInt32 m_Duration; /* seconds */
+ NPT_LargeSize m_Size;
+ NPT_String m_Protection;
+ NPT_UInt32 m_Bitrate; /* bytes/seconds */
+ NPT_UInt32 m_BitsPerSample;
+ NPT_UInt32 m_SampleFrequency;
+ NPT_UInt32 m_NbAudioChannels;
+ NPT_String m_Resolution;
+ NPT_UInt32 m_ColorDepth;
+ /* to add custom data to resource, that are not standard one, or are only
+ proper for some type of devices (UPnP)*/
+ NPT_Map<NPT_String, NPT_String> m_CustomData;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaObject
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaObject class is any data entity that can be returned by a
+ ContentDirectory Service from a browsing or searching action. This is the
+ base class from which PLT_MediaItem and PLT_MediaContainer derive.
+ */
+class PLT_MediaObject
+{
+protected:
+ NPT_IMPLEMENT_DYNAMIC_CAST(PLT_MediaObject)
+
+ PLT_MediaObject() : m_Restricted(true) {}
+
+public:
+ virtual ~PLT_MediaObject() {}
+
+ bool IsContainer() { return m_ObjectClass.type.StartsWith("object.container"); }
+
+ static const char* GetUPnPClass(const char* filename,
+ const PLT_HttpRequestContext* context = NULL);
+
+ virtual NPT_Result Reset();
+ virtual NPT_Result ToDidl(const NPT_String& filter, NPT_String& didl);
+ virtual NPT_Result ToDidl(NPT_UInt64 mask, NPT_String& didl);
+ virtual NPT_Result FromDidl(NPT_XmlElementNode* entry);
+
+public:
+ /* common properties */
+ PLT_ObjectClass m_ObjectClass;
+ NPT_String m_ObjectID;
+ NPT_String m_ParentID;
+ NPT_String m_ReferenceID;
+
+ /* metadata */
+ NPT_String m_Title;
+ NPT_String m_Creator;
+ NPT_String m_Date;
+ PLT_PeopleInfo m_People;
+ PLT_AffiliationInfo m_Affiliation;
+ PLT_Description m_Description;
+ PLT_RecordedInfo m_Recorded;
+
+ /* properties */
+ bool m_Restricted;
+
+ /* extras */
+ PLT_ExtraInfo m_ExtraInfo;
+
+ /* miscellaneous info */
+ PLT_MiscInfo m_MiscInfo;
+
+ /* resources related */
+ NPT_Array<PLT_MediaItemResource> m_Resources;
+
+ /* sec resources related */
+ NPT_Array<PLT_SecResource> m_SecResources;
+
+ /* XBMC specific */
+ PLT_XbmcInfo m_XbmcInfo;
+
+ /* original DIDL for Control Points to pass to a renderer when invoking SetAVTransportURI */
+ NPT_String m_Didl;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaItem
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaItem class represents a first-level class derived directly from
+ PLT_MediaObject. It most often represents a single piece of AV data.
+ */
+class PLT_MediaItem : public PLT_MediaObject
+{
+public:
+ NPT_IMPLEMENT_DYNAMIC_CAST_D(PLT_MediaItem, PLT_MediaObject)
+
+ PLT_MediaItem();
+ ~PLT_MediaItem() override;
+
+ // PLT_MediaObject methods
+ NPT_Result ToDidl(const NPT_String& filter, NPT_String& didl) override;
+ NPT_Result ToDidl(NPT_UInt64 mask, NPT_String& didl) override;
+ NPT_Result FromDidl(NPT_XmlElementNode* entry) override;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainer
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaContainer class represents a first-level class derived directly
+ from PLT_MediaObject. A PLT_MediaContainer represents a collection of
+ PLT_MediaObject instances.
+ */
+class PLT_MediaContainer : public PLT_MediaObject
+{
+public:
+ NPT_IMPLEMENT_DYNAMIC_CAST_D(PLT_MediaContainer, PLT_MediaObject)
+
+ PLT_MediaContainer();
+ ~PLT_MediaContainer() override;
+
+ // PLT_MediaObject methods
+ NPT_Result Reset() override;
+ NPT_Result ToDidl(const NPT_String& filter, NPT_String& didl) override;
+ NPT_Result ToDidl(NPT_UInt64 mask, NPT_String& didl) override;
+ NPT_Result FromDidl(NPT_XmlElementNode* entry) override;
+
+public:
+ NPT_List<PLT_SearchClass> m_SearchClasses;
+
+ /* properties */
+ bool m_Searchable;
+
+ /* container info related */
+ NPT_Int32 m_ChildrenCount;
+ NPT_UInt32 m_ContainerUpdateID;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaObjectList
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaObjectList class is a list of PLT_MediaObject instances.
+ */
+class PLT_MediaObjectList : public NPT_List<PLT_MediaObject*>
+{
+public:
+ PLT_MediaObjectList();
+
+protected:
+ virtual ~PLT_MediaObjectList(void);
+ friend class NPT_Reference<PLT_MediaObjectList>;
+};
+
+typedef NPT_Reference<PLT_MediaObjectList> PLT_MediaObjectListReference;
+typedef NPT_Reference<PLT_MediaObject> PLT_MediaObjectReference;
+
+#endif /* _PLT_MEDIA_ITEM_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
new file mode 100644
index 0000000..8686aa9
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp
@@ -0,0 +1,711 @@
+/*****************************************************************
+|
+| Platinum - AV Media Server Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltMediaServer.h"
+#include "PltMediaItem.h"
+#include "PltService.h"
+#include "PltTaskManager.h"
+#include "PltHttpServer.h"
+#include "PltDidl.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server")
+
+/*----------------------------------------------------------------------
+| forward references
++---------------------------------------------------------------------*/
+extern NPT_UInt8 MS_ConnectionManagerSCPD[];
+extern NPT_UInt8 MS_ContentDirectorywSearchSCPD[];
+
+const char* BrowseFlagsStr[] = {
+ "BrowseMetadata",
+ "BrowseDirectChildren"
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::PLT_MediaServer
++---------------------------------------------------------------------*/
+PLT_MediaServer::PLT_MediaServer(const char* friendly_name,
+ bool show_ip /* = false */,
+ const char* uuid /* = NULL */,
+ NPT_UInt16 port /* = 0 */,
+ bool port_rebind /* = false */) :
+ PLT_DeviceHost("/DeviceDescription.xml",
+ uuid,
+ "urn:schemas-upnp-org:device:MediaServer:1",
+ friendly_name,
+ show_ip,
+ port,
+ port_rebind),
+ m_Delegate(NULL)
+{
+ m_ModelDescription = "Plutinosoft AV Media Server Device";
+ m_ModelName = "AV Media Server Device";
+ m_ModelURL = "http://www.plutinosoft.com/platinum";
+ m_DlnaDoc = "DMS-1.50";
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::~PLT_MediaServer
++---------------------------------------------------------------------*/
+PLT_MediaServer::~PLT_MediaServer()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::SetupServices()
+{
+ NPT_Reference<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.AsPointer()));
+
+ 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.Detach();
+ service = NULL;
+ }
+
+ {
+ 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.AsPointer()));
+
+ service->SetStateVariable("CurrentConnectionIDs", "0");
+ service->SetStateVariable("SinkProtocolInfo", "");
+ service->SetStateVariable("SourceProtocolInfo", "http-get:*:*:*");
+
+ service.Detach();
+ service = NULL;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::UpdateSystemUpdateID
++---------------------------------------------------------------------*/
+void
+PLT_MediaServer::UpdateSystemUpdateID(NPT_UInt32 update)
+{
+ NPT_COMPILER_UNUSED(update);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::UpdateContainerUpdateID
++---------------------------------------------------------------------*/
+void PLT_MediaServer::UpdateContainerUpdateID(const char* id, NPT_UInt32 update)
+{
+ NPT_COMPILER_UNUSED(id);
+ NPT_COMPILER_UNUSED(update);
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ /* parse the action name */
+ NPT_String name = action->GetActionDesc().GetName();
+
+ // ContentDirectory
+ if (name.Compare("Browse", true) == 0) {
+ return OnBrowse(action, context);
+ }
+ if (name.Compare("Search", true) == 0) {
+ return OnSearch(action, context);
+ }
+ if (name.Compare("UpdateObject", true) == 0) {
+ return OnUpdate(action, context);
+ }
+ if (name.Compare("GetSystemUpdateID", true) == 0) {
+ return OnGetSystemUpdateID(action, context);
+ }
+ if (name.Compare("GetSortCapabilities", true) == 0) {
+ return OnGetSortCapabilities(action, context);
+ }
+ if (name.Compare("GetSearchCapabilities", true) == 0) {
+ return OnGetSearchCapabilities(action, context);
+ }
+
+ // ConnectionMananger
+ if (name.Compare("GetCurrentConnectionIDs", true) == 0) {
+ return OnGetCurrentConnectionIDs(action, context);
+ }
+ if (name.Compare("GetProtocolInfo", true) == 0) {
+ return OnGetProtocolInfo(action, context);
+ }
+ if (name.Compare("GetCurrentConnectionInfo", true) == 0) {
+ return OnGetCurrentConnectionInfo(action, context);
+ }
+
+ action->SetError(401,"No Such Action.");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FileMediaServer::ProcessHttpGetRequest
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::ProcessHttpGetRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ /* Try to handle file request */
+ if (m_Delegate) return m_Delegate->ProcessFileRequest(request, context, response);
+
+ return NPT_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnGetCurrentConnectionIDs
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnGetCurrentConnectionIDs(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnGetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnGetProtocolInfo(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnGetCurrentConnectionInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnGetCurrentConnectionInfo(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ if (NPT_FAILED(action->VerifyArgumentValue("ConnectionID", "0"))) {
+ action->SetError(706,"No Such Connection.");
+ return NPT_FAILURE;
+ }
+
+ if (NPT_FAILED(action->SetArgumentValue("RcsID", "-1"))){
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("AVTransportID", "-1"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("ProtocolInfo", "http-get:*:*:*"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("PeerConnectionManager", "/"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("PeerConnectionID", "-1"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("Direction", "Output"))) {
+ return NPT_FAILURE;
+ }
+ if (NPT_FAILED(action->SetArgumentValue("Status", "Unknown"))) {
+ return NPT_FAILURE;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnGetSortCapabilities
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnGetSortCapabilities(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnGetSearchCapabilities
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnGetSearchCapabilities(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnGetSystemUpdateID
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnGetSystemUpdateID(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ return action->SetArgumentsOutFromStateVariable();
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::ParseBrowseFlag
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::ParseBrowseFlag(const char* str, BrowseFlags& flag)
+{
+ if (NPT_String::Compare(str, BrowseFlagsStr[0], true) == 0) {
+ flag = BROWSEMETADATA;
+ return NPT_SUCCESS;
+ }
+ if (NPT_String::Compare(str, BrowseFlagsStr[1], true) == 0) {
+ flag = BROWSEDIRECTCHILDREN;
+ return NPT_SUCCESS;
+ }
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::ParseSort
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::ParseSort(const NPT_String& sort, NPT_List<NPT_String>& list)
+{
+ // reset output params first
+ list.Clear();
+
+ // easy out
+ if (sort.GetLength() == 0 || sort == "*") return NPT_SUCCESS;
+
+ list = sort.Split(",");
+
+ // verify each property has a namespace
+ NPT_List<NPT_String>::Iterator property = list.GetFirstItem();
+ while (property) {
+ NPT_List<NPT_String> parsed_property = (*property).Split(":");
+ if (parsed_property.GetItemCount() != 2)
+ parsed_property = (*property).Split("@");
+ if (parsed_property.GetItemCount() != 2 ||
+ (!(*property).StartsWith("-") && !(*property).StartsWith("+"))) {
+ NPT_LOG_WARNING_1("Invalid SortCriteria property %s", (*property).GetChars());
+ return NPT_FAILURE;
+ }
+ property++;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::ParseTagList
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::ParseTagList(const NPT_String& updates, NPT_Map<NPT_String,NPT_String>& tags)
+{
+ // reset output params first
+ tags.Clear();
+
+ NPT_List<NPT_String> split = updates.Split(",");
+ NPT_XmlNode* node = NULL;
+ NPT_XmlElementNode* didl_partial = NULL;
+ NPT_XmlParser parser;
+
+ // as these are single name value pairs, separated by commas we wrap in a tag
+ // to create a valid tree
+ NPT_String xml("<TagValueList>");
+ for (NPT_List<NPT_String>::Iterator entry = split.GetFirstItem(); entry; entry++) {
+ NPT_String& element = (*entry);
+ if (element.IsEmpty())
+ xml.Append("<empty>empty</empty>");
+ else
+ xml.Append(element);
+ }
+ xml.Append("</TagValueList>");
+
+ NPT_LOG_FINE("Parsing TagList...");
+ NPT_CHECK_LABEL_SEVERE(parser.Parse(xml, node), cleanup);
+ if (!node || !node->AsElementNode()) {
+ NPT_LOG_SEVERE("Invalid node type");
+ goto cleanup;
+ }
+
+ didl_partial = node->AsElementNode();
+ if (didl_partial->GetTag().Compare("TagValueList", true)) {
+ NPT_LOG_SEVERE("Invalid node tag");
+ goto cleanup;
+ }
+
+ for (NPT_List<NPT_XmlNode*>::Iterator children = didl_partial->GetChildren().GetFirstItem(); children; children++) {
+ NPT_XmlElementNode* child = (*children)->AsElementNode();
+ if (!child) continue;
+ const NPT_String *txt = child->GetText();
+ tags[child->GetTag()] = txt ? txt->GetChars() : "";
+ }
+
+ return NPT_SUCCESS;
+
+cleanup:
+ if (node) delete node;
+ return NPT_FAILURE;
+}
+
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnBrowse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnBrowse(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_Result res;
+ NPT_String object_id;
+ NPT_String browse_flag_val;
+ NPT_String filter;
+ NPT_String start;
+ NPT_String count;
+ NPT_String sort;
+ NPT_List<NPT_String> sort_list;
+
+ if (NPT_FAILED(action->GetArgumentValue("ObjectId", object_id)) ||
+ NPT_FAILED(action->GetArgumentValue("BrowseFlag", browse_flag_val)) ||
+ NPT_FAILED(action->GetArgumentValue("Filter", filter)) ||
+ NPT_FAILED(action->GetArgumentValue("StartingIndex", start)) ||
+ NPT_FAILED(action->GetArgumentValue("RequestedCount", count)) ||
+ NPT_FAILED(action->GetArgumentValue("SortCriteria", sort))) {
+ NPT_LOG_WARNING("Missing arguments");
+ action->SetError(402, "Invalid args");
+ return NPT_SUCCESS;
+ }
+
+ /* extract flag */
+ BrowseFlags flag;
+ if (NPT_FAILED(ParseBrowseFlag(browse_flag_val, flag))) {
+ /* error */
+ NPT_LOG_WARNING_1("BrowseFlag value not allowed (%s)", (const char*)browse_flag_val);
+ action->SetError(402, "Invalid args");
+ return NPT_SUCCESS;
+ }
+
+ /* convert index and counts to int */
+ NPT_UInt32 starting_index, requested_count;
+ if (NPT_FAILED(start.ToInteger(starting_index)) ||
+ NPT_FAILED(count.ToInteger(requested_count)) ||
+ PLT_Didl::ConvertFilterToMask(filter) == 0) {
+ NPT_LOG_WARNING_3("Invalid arguments (%s, %s, %s)",
+ start.GetChars(), count.GetChars(), filter.GetChars());
+ action->SetError(402, "Invalid args");
+ return NPT_FAILURE;
+ }
+
+ /* parse sort criteria for validation */
+ if (NPT_FAILED(ParseSort(sort, sort_list))) {
+ NPT_LOG_WARNING_1("Unsupported or invalid sort criteria error (%s)",
+ sort.GetChars());
+ action->SetError(709, "Unsupported or invalid sort criteria error");
+ return NPT_FAILURE;
+ }
+
+ NPT_LOG_FINE_6("Processing %s from %s with id=\"%s\", filter=\"%s\", start=%d, count=%d",
+ (const char*)browse_flag_val,
+ (const char*)context.GetRemoteAddress().GetIpAddress().ToString(),
+ (const char*)object_id,
+ (const char*)filter,
+ starting_index,
+ requested_count);
+
+ /* Invoke the browse function */
+ if (flag == BROWSEMETADATA) {
+ res = OnBrowseMetadata(
+ action,
+ object_id,
+ filter,
+ starting_index,
+ requested_count,
+ sort,
+ context);
+ } else {
+ res = OnBrowseDirectChildren(
+ action,
+ object_id,
+ filter,
+ starting_index,
+ requested_count,
+ sort,
+ context);
+ }
+
+ if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) {
+ action->SetError(800, "Internal error");
+ }
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnSearch
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnSearch(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_Result res;
+ NPT_String container_id;
+ NPT_String search;
+ NPT_String filter;
+ NPT_String start;
+ NPT_String count;
+ NPT_String sort;
+ NPT_List<NPT_String> sort_list;
+
+ if (NPT_FAILED(action->GetArgumentValue("ContainerId", container_id)) ||
+ NPT_FAILED(action->GetArgumentValue("SearchCriteria", search)) ||
+ NPT_FAILED(action->GetArgumentValue("Filter", filter)) ||
+ NPT_FAILED(action->GetArgumentValue("StartingIndex", start)) ||
+ NPT_FAILED(action->GetArgumentValue("RequestedCount", count)) ||
+ NPT_FAILED(action->GetArgumentValue("SortCriteria", sort))) {
+ NPT_LOG_WARNING("Missing arguments");
+ action->SetError(402, "Invalid args");
+ return NPT_SUCCESS;
+ }
+
+ /* convert index and counts to int */
+ NPT_UInt32 starting_index, requested_count;
+ if (NPT_FAILED(start.ToInteger(starting_index)) ||
+ NPT_FAILED(count.ToInteger(requested_count))) {
+ NPT_LOG_WARNING_2("Invalid arguments (%s, %s)",
+ start.GetChars(), count.GetChars());
+ action->SetError(402, "Invalid args");
+ return NPT_FAILURE;
+ }
+
+ /* parse sort criteria */
+ if (NPT_FAILED(ParseSort(sort, sort_list))) {
+ NPT_LOG_WARNING_1("Unsupported or invalid sort criteria error (%s)",
+ sort.GetChars());
+ action->SetError(709, "Unsupported or invalid sort criteria error");
+ return NPT_FAILURE;
+ }
+
+ NPT_LOG_INFO_5("Processing Search from %s with id=\"%s\", search=\"%s\", start=%d, count=%d",
+ (const char*)context.GetRemoteAddress().GetIpAddress().ToString(),
+ (const char*)container_id,
+ (const char*)search,
+ starting_index,
+ requested_count);
+
+ if (search.IsEmpty() || search == "*") {
+ res = OnBrowseDirectChildren(
+ action,
+ container_id,
+ filter,
+ starting_index,
+ requested_count,
+ sort,
+ context);
+ } else {
+ res = OnSearchContainer(
+ action,
+ container_id,
+ search,
+ filter,
+ starting_index,
+ requested_count,
+ sort,
+ context);
+ }
+
+ if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) {
+ action->SetError(800, "Internal error");
+ }
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnUpdate
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnUpdate(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ if (!m_Delegate)
+ return NPT_ERROR_NOT_IMPLEMENTED;
+
+ int err;
+ const char* msg = NULL;
+
+ NPT_String object_id, current_xml, new_xml;
+ NPT_Map<NPT_String,NPT_String> curr_values;
+ NPT_Map<NPT_String,NPT_String> new_values;
+
+ NPT_CHECK_LABEL(action->GetArgumentValue("ObjectID", object_id), args);
+ NPT_CHECK_LABEL(object_id.IsEmpty(),args);
+ NPT_CHECK_LABEL(action->GetArgumentValue("CurrentTagValue", current_xml), args);
+ NPT_CHECK_LABEL(action->GetArgumentValue("NewTagValue", new_xml), args);
+
+ if (NPT_FAILED(ParseTagList(current_xml, curr_values))) {
+ err = 702;
+ msg = "Invalid currentTagvalue";
+ goto failure;
+ }
+ if (NPT_FAILED(ParseTagList(new_xml, new_values))) {
+ err = 703;
+ msg = "Invalid newTagValue";
+ goto failure;
+ }
+
+ if (curr_values.GetEntryCount() != new_values.GetEntryCount()) {
+ err = 706;
+ msg = "Paramater mismatch";
+ goto failure;
+ }
+
+ return m_Delegate->OnUpdateObject(action, object_id, curr_values, new_values, context);
+
+args:
+ err = 402;
+ msg = "Invalid args";
+
+failure:
+ NPT_LOG_WARNING_1("%s", msg);
+ action->SetError(err, msg);
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnBrowseMetadata
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnBrowseMetadata(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnBrowseMetadata(action,
+ object_id,
+ filter,
+ starting_index,
+ requested_count,
+ sort_criteria,
+ context);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnBrowseDirectChildren
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnBrowseDirectChildren(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnBrowseDirectChildren(action,
+ object_id,
+ filter,
+ starting_index,
+ requested_count,
+ sort_criteria,
+ context);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer::OnSearchContainer
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MediaServer::OnSearchContainer(PLT_ActionReference& action,
+ const char* object_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ if (m_Delegate) {
+ return m_Delegate->OnSearchContainer(action,
+ object_id,
+ search_criteria,
+ filter,
+ starting_index,
+ requested_count,
+ sort_criteria,
+ context);
+ }
+ return NPT_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.h
new file mode 100644
index 0000000..d35d8d8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.h
@@ -0,0 +1,196 @@
+/*****************************************************************
+|
+| Platinum - AV Media Server Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Media Server.
+ */
+
+#ifndef _PLT_MEDIA_SERVER_H_
+#define _PLT_MEDIA_SERVER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltDeviceHost.h"
+#include "PltMediaItem.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define MAX_PATH_LENGTH 1024
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerDelegate
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaServerDelegate class is an interface for delegating the handling
+ of the required UPnP AV ContentDirectory service actions. It also handles
+ resource HTTP requests (downloading).
+ */
+class PLT_MediaServerDelegate
+{
+public:
+ PLT_MediaServerDelegate() {}
+ virtual ~PLT_MediaServerDelegate() {}
+
+ virtual NPT_Result OnBrowseMetadata(PLT_ActionReference& /*action*/,
+ const char* /*object_id*/,
+ const char* /*filter*/,
+ NPT_UInt32 /*starting_index*/,
+ NPT_UInt32 /*requested_count*/,
+ const char* /*sort_criteria*/,
+ const PLT_HttpRequestContext& /*context*/) = 0;
+ virtual NPT_Result OnBrowseDirectChildren(PLT_ActionReference& /*action*/,
+ const char* /*object_id*/,
+ const char* /*filter*/,
+ NPT_UInt32 /*starting_index*/,
+ NPT_UInt32 /*requested_count*/,
+ const char* /*sort_criteria*/,
+ const PLT_HttpRequestContext& /*context*/) = 0;
+ virtual NPT_Result OnSearchContainer(PLT_ActionReference& /*action*/,
+ const char* /*container_id*/,
+ const char* /*search_criteria*/,
+ const char* /*filter*/,
+ NPT_UInt32 /*starting_index*/,
+ NPT_UInt32 /*requested_count*/,
+ const char* /*sort_criteria*/,
+ const PLT_HttpRequestContext& /*context*/) = 0;
+ virtual NPT_Result OnUpdateObject(PLT_ActionReference& /*action*/,
+ const char* /*object_id*/,
+ NPT_Map<NPT_String,NPT_String>& /*current_vals*/,
+ NPT_Map<NPT_String,NPT_String>& /*new_vals*/,
+ const PLT_HttpRequestContext& /*context*/) = 0;
+
+ virtual NPT_Result ProcessFileRequest(NPT_HttpRequest& /*request*/,
+ const NPT_HttpRequestContext& /*context*/,
+ NPT_HttpResponse& /*response*/) = 0;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaServer
++---------------------------------------------------------------------*/
+/**
+ The PLT_MediaServer class implements the base class for a UPnP AV
+ Media Server device.
+ */
+class PLT_MediaServer : public PLT_DeviceHost
+{
+public:
+ /* BrowseFlags */
+ enum BrowseFlags {
+ BROWSEMETADATA,
+ BROWSEDIRECTCHILDREN
+ };
+
+ // class methods
+ static NPT_Result ParseBrowseFlag(const char* str, BrowseFlags& flag);
+ static NPT_Result ParseSort(const NPT_String& sort, NPT_List<NPT_String>& list);
+ static NPT_Result ParseTagList(const NPT_String& updates, NPT_Map<NPT_String,NPT_String>& tags);
+
+ // constructor
+ PLT_MediaServer(const char* friendly_name,
+ bool show_ip = false,
+ const char* uuid = NULL,
+ NPT_UInt16 port = 0,
+ bool port_rebind = false);
+
+ // methods
+ virtual void SetDelegate(PLT_MediaServerDelegate* delegate) { m_Delegate = delegate; }
+ PLT_MediaServerDelegate* GetDelegate() { return m_Delegate; }
+ virtual void UpdateSystemUpdateID(NPT_UInt32 update);
+ virtual void UpdateContainerUpdateID(const char* id, NPT_UInt32 update);
+
+protected:
+ ~PLT_MediaServer() override;
+
+ // PLT_DeviceHost methods
+ NPT_Result SetupServices() override;
+ NPT_Result OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context) override;
+ NPT_Result ProcessHttpGetRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+ // ConnectionManager
+ virtual NPT_Result OnGetCurrentConnectionIDs(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnGetProtocolInfo(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+
+ // ContentDirectory
+ virtual NPT_Result OnGetSortCapabilities(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnGetSearchCapabilities(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnGetSystemUpdateID(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnBrowse(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnSearch(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnUpdate(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+
+ // overridable methods
+ virtual NPT_Result OnBrowseMetadata(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnBrowseDirectChildren(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnSearchContainer(PLT_ActionReference& action,
+ const char* container_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context);
+
+private:
+ PLT_MediaServerDelegate* m_Delegate;
+};
+
+#endif /* _PLT_MEDIA_SERVER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
new file mode 100644
index 0000000..794b56b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.cpp
@@ -0,0 +1,578 @@
+/*****************************************************************
+|
+| Platinum - Synchronous Media Browser
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltSyncMediaBrowser.h"
+#include <algorithm>
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.syncbrowser")
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::PLT_SyncMediaBrowser
++---------------------------------------------------------------------*/
+PLT_SyncMediaBrowser::PLT_SyncMediaBrowser(PLT_CtrlPointReference& ctrlPoint,
+ bool use_cache /* = false */,
+ PLT_MediaContainerChangesListener* listener /* = NULL */) :
+ PLT_MediaBrowser(ctrlPoint),
+ m_ContainerListener(listener),
+ m_UseCache(use_cache)
+{
+ SetDelegate(this);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::~PLT_SyncMediaBrowser
++---------------------------------------------------------------------*/
+PLT_SyncMediaBrowser::~PLT_SyncMediaBrowser()
+{
+}
+
+/* Blocks forever waiting for a response from a request
+ * It is expected the request to succeed or to timeout and return an error eventually
+ */
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::WaitForResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::WaitForResponse(NPT_SharedVariable& shared_var)
+{
+ return shared_var.WaitUntilEquals(1, 30000);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::OnDeviceAdded
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::OnDeviceAdded(PLT_DeviceDataReference& device)
+{
+ NPT_String uuid = device->GetUUID();
+
+ // test if it's a media server
+ PLT_Service* service;
+ if (NPT_SUCCEEDED(device->FindServiceByType("urn:schemas-upnp-org:service:ContentDirectory:*", service))) {
+ NPT_AutoLock lock(m_MediaServers);
+ m_MediaServers.Put(uuid, device);
+ }
+
+ return PLT_MediaBrowser::OnDeviceAdded(device);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::OnDeviceRemoved
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::OnDeviceRemoved(PLT_DeviceDataReference& device)
+{
+ NPT_String uuid = device->GetUUID();
+
+ // Remove from our list of servers first if found
+ {
+ NPT_AutoLock lock(m_MediaServers);
+ m_MediaServers.Erase(uuid);
+ }
+
+ // clear cache for that device
+ if (m_UseCache) m_Cache.Clear(device.AsPointer()->GetUUID());
+
+ return PLT_MediaBrowser::OnDeviceRemoved(device);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::Find
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::Find(const char* ip, PLT_DeviceDataReference& device)
+{
+ NPT_AutoLock lock(m_MediaServers);
+ const NPT_List<PLT_DeviceMapEntry*>::Iterator it =
+ m_MediaServers.GetEntries().Find(PLT_DeviceMapFinderByIp(ip));
+ if (it) {
+ device = (*it)->GetValue();
+ return NPT_SUCCESS;
+ }
+ return NPT_FAILURE;
+}
+
+static void OnResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_BrowseInfo* info,
+ void* userdata)
+{
+ NPT_COMPILER_UNUSED(device);
+
+ if (!userdata) return;
+
+ PLT_BrowseDataReference* data = (PLT_BrowseDataReference*) userdata;
+ (*data)->res = res;
+ if (NPT_SUCCEEDED(res) && info) {
+ (*data)->info = *info;
+ }
+ (*data)->shared_var.SetValue(1);
+ delete data;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::OnBrowseResult
++---------------------------------------------------------------------*/
+void
+PLT_SyncMediaBrowser::OnBrowseResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_BrowseInfo* info,
+ void* userdata)
+{
+ OnResult(res, device, info, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::OnSearchResult
++---------------------------------------------------------------------*/
+void
+PLT_SyncMediaBrowser::OnSearchResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_BrowseInfo* info,
+ void* userdata)
+{
+ OnResult(res, device, info, userdata);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::OnGetSearchCapabilitiesResult
++---------------------------------------------------------------------*/
+void
+PLT_SyncMediaBrowser::OnGetSearchCapabilitiesResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ NPT_String searchCapabilities,
+ void* userdata)
+{
+ NPT_COMPILER_UNUSED(device);
+
+ if (!userdata) return;
+
+ PLT_CapabilitiesDataReference* data = (PLT_CapabilitiesDataReference*) userdata;
+ (*data)->res = res;
+ if (NPT_SUCCEEDED(res)) {
+ (*data)->capabilities = searchCapabilities;
+ }
+ (*data)->shared_var.SetValue(1);
+ delete data;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::OnGetSortCapabilitiesResult
++---------------------------------------------------------------------*/
+void
+PLT_SyncMediaBrowser::OnGetSortCapabilitiesResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ NPT_String sortCapabilities,
+ void* userdata)
+{
+ NPT_COMPILER_UNUSED(device);
+
+ if (!userdata) return;
+
+ PLT_CapabilitiesDataReference* data = (PLT_CapabilitiesDataReference*) userdata;
+ (*data)->res = res;
+ if (NPT_SUCCEEDED(res)) {
+ (*data)->capabilities = sortCapabilities;
+ }
+ (*data)->shared_var.SetValue(1);
+ delete data;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::OnMSStateVariablesChanged
++---------------------------------------------------------------------*/
+void
+PLT_SyncMediaBrowser::OnMSStateVariablesChanged(PLT_Service* service,
+ NPT_List<PLT_StateVariable*>* vars)
+{
+ NPT_AutoLock lock(m_MediaServers);
+
+ PLT_DeviceDataReference device;
+ const NPT_List<PLT_DeviceMapEntry*>::Iterator it =
+ m_MediaServers.GetEntries().Find(PLT_DeviceMapFinderByUUID(service->GetDevice()->GetUUID()));
+ if (!it) return; // device with this service has gone away
+
+ device = (*it)->GetValue();
+ PLT_StateVariable* var = PLT_StateVariable::Find(*vars, "ContainerUpdateIDs");
+ if (var) {
+ // variable found, parse value
+ NPT_String value = var->GetValue();
+ NPT_String item_id, update_id;
+ int index;
+
+ while (value.GetLength()) {
+ // look for container id
+ index = value.Find(',');
+ if (index < 0) break;
+ item_id = value.Left(index);
+ value = value.SubString(index+1);
+
+ // look for update id
+ if (value.GetLength()) {
+ index = value.Find(',');
+ update_id = (index<0)?value:value.Left(index);
+ value = (index < 0) ? "" : value.SubString(index + 1).GetChars();
+
+ // clear cache for that device
+ if (m_UseCache) m_Cache.Clear(device->GetUUID(), item_id);
+
+ // notify listener
+ if (m_ContainerListener) m_ContainerListener->OnContainerChanged(device, item_id, update_id);
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::BrowseSync
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::BrowseSync(PLT_BrowseDataReference& browse_data,
+ PLT_DeviceDataReference& device,
+ const char* object_id,
+ NPT_Int32 index,
+ NPT_Int32 count,
+ bool browse_metadata,
+ const char* filter,
+ const char* sort)
+{
+ NPT_Result res;
+
+ browse_data->shared_var.SetValue(0);
+ browse_data->info.si = index;
+
+ // send off the browse packet. Note that this will
+ // not block. There is a call to WaitForResponse in order
+ // to block until the response comes back.
+ res = PLT_MediaBrowser::Browse(device,
+ (const char*)object_id,
+ index,
+ count,
+ browse_metadata,
+ filter,
+ sort,
+ new PLT_BrowseDataReference(browse_data));
+ NPT_CHECK_SEVERE(res);
+
+ return WaitForResponse(browse_data->shared_var);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::SearchSync
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::SearchSync(PLT_BrowseDataReference& browse_data,
+ PLT_DeviceDataReference& device,
+ const char* container_id,
+ const char* search_criteria,
+ NPT_Int32 index,
+ NPT_Int32 count,
+ const char* filter)
+{
+ NPT_Result res;
+
+ browse_data->shared_var.SetValue(0);
+ browse_data->info.si = index;
+
+ // send off the search packet. Note that this will
+ // not block. There is a call to WaitForResponse in order
+ // to block until the response comes back.
+ res = PLT_MediaBrowser::Search(device,
+ container_id,
+ search_criteria,
+ index,
+ count,
+ filter,
+ new PLT_BrowseDataReference(browse_data));
+ NPT_CHECK_SEVERE(res);
+
+ return WaitForResponse(browse_data->shared_var);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::GetSearchCapabilitiesSync
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::GetSearchCapabilitiesSync(PLT_DeviceDataReference& device,
+ NPT_String& searchCapabilities)
+{
+ NPT_Result res;
+
+ PLT_CapabilitiesDataReference capabilities_data(new PLT_CapabilitiesData(), true);
+ capabilities_data->shared_var.SetValue(0);
+
+ // send of the GetSearchCapabilities packet. Note that this will
+ // not block. There is a call to WaitForResponse in order
+ // to block until the response comes back.
+ res = PLT_MediaBrowser::GetSearchCapabilities(device,
+ new PLT_CapabilitiesDataReference(capabilities_data));
+ NPT_CHECK_SEVERE(res);
+
+ res = WaitForResponse(capabilities_data->shared_var);
+ NPT_CHECK_LABEL_WARNING(res, done);
+
+ if (NPT_FAILED(capabilities_data->res)) {
+ res = capabilities_data->res;
+ NPT_CHECK_LABEL_WARNING(res, done);
+ }
+
+ searchCapabilities = capabilities_data->capabilities;
+
+done:
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::GetSortCapabilitiesSync
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::GetSortCapabilitiesSync(PLT_DeviceDataReference& device,
+ NPT_String& sortCapabilities)
+{
+ NPT_Result res;
+
+ PLT_CapabilitiesDataReference capabilities_data(new PLT_CapabilitiesData(), true);
+ capabilities_data->shared_var.SetValue(0);
+
+ // send of the GetSortCapabilities packet. Note that this will
+ // not block. There is a call to WaitForResponse in order
+ // to block until the response comes back.
+ res = PLT_MediaBrowser::GetSortCapabilities(device,
+ new PLT_CapabilitiesDataReference(capabilities_data));
+ NPT_CHECK_SEVERE(res);
+
+ res = WaitForResponse(capabilities_data->shared_var);
+ NPT_CHECK_LABEL_WARNING(res, done);
+
+ if (NPT_FAILED(capabilities_data->res)) {
+ res = capabilities_data->res;
+ NPT_CHECK_LABEL_WARNING(res, done);
+ }
+
+ sortCapabilities = capabilities_data->capabilities;
+
+done:
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::BrowseSync
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::BrowseSync(PLT_DeviceDataReference& device,
+ const char* object_id,
+ PLT_MediaObjectListReference& list,
+ bool metadata, /* = false */
+ NPT_Int32 start, /* = 0 */
+ NPT_Cardinal max_results /* = 0 */)
+{
+ NPT_Result res = NPT_FAILURE;
+ NPT_Int32 index = start;
+ NPT_UInt32 count = 0;
+
+ // only cache metadata or if starting from 0 and asking for maximum
+ bool cache = m_UseCache && (metadata || (start == 0 && max_results == 0));
+
+ // reset output params
+ list = NULL;
+
+ // look into cache first
+ if (cache && NPT_SUCCEEDED(m_Cache.Get(device->GetUUID(), object_id, list))) return NPT_SUCCESS;
+
+ do {
+ PLT_BrowseDataReference browse_data(new PLT_BrowseData());
+
+ // send off the browse packet. Note that this will
+ // not block. There is a call to WaitForResponse in order
+ // to block until the response comes back.
+ res = BrowseSync(
+ browse_data,
+ device,
+ (const char*)object_id,
+ index,
+ metadata?1:200, // DLNA recommendations for browsing children is no more than 30 at a time
+ metadata);
+ NPT_CHECK_LABEL_WARNING(res, done);
+
+ if (NPT_FAILED(browse_data->res)) {
+ res = browse_data->res;
+ NPT_CHECK_LABEL_WARNING(res, done);
+ }
+
+ // server returned no more, bail now
+ if (browse_data->info.nr == 0)
+ break;
+
+ if (browse_data->info.nr != browse_data->info.items->GetItemCount()) {
+ NPT_LOG_WARNING_2("Server returned unexpected number of items (%d vs %d)",
+ browse_data->info.nr, browse_data->info.items->GetItemCount());
+ }
+ count += std::max<NPT_UInt32>(browse_data->info.nr, browse_data->info.items->GetItemCount());
+
+ if (list.IsNull()) {
+ list = browse_data->info.items;
+ } else {
+ list->Add(*browse_data->info.items);
+ // clear the list items so that the data inside is not
+ // cleaned up by PLT_MediaItemList dtor since we copied
+ // each pointer into the new list.
+ browse_data->info.items->Clear();
+ }
+
+ // stop now if our list contains exactly what the server said it had.
+ // Note that the server could return 0 if it didn't know how many items were
+ // available. In this case we have to continue browsing until
+ // nothing is returned back by the server.
+ // Unless we were told to stop after reaching a certain amount to avoid
+ // length delays
+ // (some servers may return a total matches out of whack at some point too)
+ if ((browse_data->info.tm && browse_data->info.tm <= count) ||
+ (max_results && count >= max_results))
+ break;
+
+ // ask for the next chunk of entries
+ index = count;
+ } while(1);
+
+done:
+ // cache the result
+ if (cache && NPT_SUCCEEDED(res) && !list.IsNull() && list->GetItemCount()) {
+ m_Cache.Put(device->GetUUID(), object_id, list);
+ }
+
+ // clear entire cache data for device if failed, the device could be gone
+ if (NPT_FAILED(res) && cache) m_Cache.Clear(device->GetUUID());
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::SearchSync
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SyncMediaBrowser::SearchSync(PLT_DeviceDataReference& device,
+ const char* container_id,
+ const char* search_criteria,
+ PLT_MediaObjectListReference& list,
+ NPT_Int32 start, /* = 0 */
+ NPT_Cardinal max_results /* = 0 */)
+{
+ NPT_Result res = NPT_FAILURE;
+ NPT_Int32 index = start;
+ NPT_UInt32 count = 0;
+
+ // reset output params
+ list = NULL;
+
+ do {
+ PLT_BrowseDataReference browse_data(new PLT_BrowseData(), true);
+
+ // send off the search packet. Note that this will
+ // not block. There is a call to WaitForResponse in order
+ // to block until the response comes back.
+ res = SearchSync(
+ browse_data,
+ device,
+ container_id,
+ search_criteria,
+ index,
+ 200); // DLNA recommendations for browsing children is no more than 30 at a time
+
+ NPT_CHECK_LABEL_WARNING(res, done);
+
+ if (NPT_FAILED(browse_data->res)) {
+ res = browse_data->res;
+ NPT_CHECK_LABEL_WARNING(res, done);
+ }
+
+ // server returned no more, bail now
+ if (browse_data->info.nr == 0)
+ break;
+
+ if (browse_data->info.nr != browse_data->info.items->GetItemCount()) {
+ NPT_LOG_WARNING_2("Server returned unexpected number of items (%d vs %d)",
+ browse_data->info.nr, browse_data->info.items->GetItemCount());
+ }
+ count += std::max<NPT_UInt32>(browse_data->info.nr, browse_data->info.items->GetItemCount());
+
+ if (list.IsNull()) {
+ list = browse_data->info.items;
+ } else {
+ list->Add(*browse_data->info.items);
+ // clear the list items so that the data inside is not
+ // cleaned up by PLT_MediaItemList dtor since we copied
+ // each pointer into the new list.
+ browse_data->info.items->Clear();
+ }
+
+ // stop now if our list contains exactly what the server said it had.
+ // Note that the server could return 0 if it didn't know how many items were
+ // available. In this case we have to continue browsing until
+ // nothing is returned back by the server.
+ // Unless we were told to stop after reaching a certain amount to avoid
+ // length delays
+ // (some servers may return a total matches out of whack at some point too)
+ if ((browse_data->info.tm && browse_data->info.tm <= count) ||
+ (max_results && count >= max_results))
+ break;
+
+ // ask for the next chunk of entries
+ index = count;
+ } while(1);
+
+done:
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser::IsCached
++---------------------------------------------------------------------*/
+bool
+PLT_SyncMediaBrowser::IsCached(const char* uuid, const char* object_id)
+{
+ NPT_AutoLock lock(m_MediaServers);
+ const NPT_List<PLT_DeviceMapEntry*>::Iterator it =
+ m_MediaServers.GetEntries().Find(PLT_DeviceMapFinderByUUID(uuid));
+ if (!it) {
+ m_Cache.Clear(uuid);
+ return false; // device with this service has gone away
+ }
+
+ PLT_MediaObjectListReference list;
+ return NPT_SUCCEEDED(m_Cache.Get(uuid, object_id, list))?true:false;
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h
new file mode 100644
index 0000000..6da21cb
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h
@@ -0,0 +1,218 @@
+/*****************************************************************
+|
+| Platinum - Synchronous Media Browser
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/** @file
+ UPnP AV Media Controller synchronous implementation.
+ */
+
+#ifndef _PLT_SYNC_MEDIA_BROWSER_
+#define _PLT_SYNC_MEDIA_BROWSER_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltCtrlPoint.h"
+#include "PltMediaBrowser.h"
+#include "PltMediaCache.h"
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef NPT_Map<NPT_String, PLT_DeviceDataReference> PLT_DeviceMap;
+typedef NPT_Map<NPT_String, PLT_DeviceDataReference>::Entry PLT_DeviceMapEntry;
+
+typedef struct PLT_BrowseData {
+ NPT_SharedVariable shared_var;
+ NPT_Result res;
+ PLT_BrowseInfo info;
+} PLT_BrowseData;
+
+typedef NPT_Reference<PLT_BrowseData> PLT_BrowseDataReference;
+
+typedef struct PLT_CapabilitiesData {
+ NPT_SharedVariable shared_var;
+ NPT_Result res;
+ NPT_String capabilities;
+} PLT_CapabilitiesData;
+
+typedef NPT_Reference<PLT_CapabilitiesData> PLT_CapabilitiesDataReference;
+
+// explicitely specify res otherwise WMP won't return a URL!
+#define PLT_DEFAULT_FILTER "dc:date,dc:description,upnp:longDescription,upnp:genre,res,res@duration,res@size,upnp:albumArtURI,upnp:rating,upnp:lastPlaybackPosition,upnp:lastPlaybackTime,upnp:playbackCount,upnp:originalTrackNumber,upnp:episodeNumber,upnp:programTitle,upnp:seriesTitle,upnp:album,upnp:artist,upnp:author,upnp:director,dc:publisher,searchable,childCount,dc:title,dc:creator,upnp:actor,res@resolution,upnp:episodeCount,upnp:episodeSeason,xbmc:lastPlayerState,xbmc:dateadded,xbmc:rating,xbmc:votes,xbmc:artwork,xbmc:uniqueidentifier,xbmc:country,xbmc:userrating"
+
+/*----------------------------------------------------------------------
+| PLT_MediaContainerListener
++---------------------------------------------------------------------*/
+class PLT_MediaContainerChangesListener
+{
+public:
+ virtual ~PLT_MediaContainerChangesListener() {}
+ virtual void OnContainerChanged(PLT_DeviceDataReference& device,
+ const char* item_id,
+ const char* update_id) = 0;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SyncMediaBrowser
++---------------------------------------------------------------------*/
+class PLT_SyncMediaBrowser : public PLT_MediaBrowser,
+ public PLT_MediaBrowserDelegate
+{
+public:
+ PLT_SyncMediaBrowser(PLT_CtrlPointReference& ctrlPoint,
+ bool use_cache = false,
+ PLT_MediaContainerChangesListener* listener = NULL);
+ ~PLT_SyncMediaBrowser() override;
+
+ // PLT_MediaBrowser methods
+ NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device) override;
+ NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device) override;
+
+ // PLT_MediaBrowserDelegate methods
+ void OnMSStateVariablesChanged(PLT_Service* service,
+ NPT_List<PLT_StateVariable*>* vars) override;
+ void OnBrowseResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_BrowseInfo* info,
+ void* userdata) override;
+ void OnSearchResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ PLT_BrowseInfo* info,
+ void* userdata) override;
+ void OnGetSearchCapabilitiesResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ NPT_String searchCapabilities,
+ void* userdata) override;
+ void OnGetSortCapabilitiesResult(NPT_Result res,
+ PLT_DeviceDataReference& device,
+ NPT_String sortCapabilities,
+ void* userdata) override;
+
+ // methods
+ void SetContainerListener(PLT_MediaContainerChangesListener* listener) {
+ m_ContainerListener = listener;
+ }
+ NPT_Result BrowseSync(PLT_DeviceDataReference& device,
+ const char* id,
+ PLT_MediaObjectListReference& list,
+ bool metadata = false,
+ NPT_Int32 start = 0,
+ NPT_Cardinal max_results = 0); // 0 means all
+
+ NPT_Result SearchSync(PLT_DeviceDataReference& device,
+ const char* container_id,
+ const char* search_criteria,
+ PLT_MediaObjectListReference& list,
+ NPT_Int32 start = 0,
+ NPT_Cardinal max_results = 0); // 0 means all
+
+ NPT_Result GetSearchCapabilitiesSync(PLT_DeviceDataReference& device,
+ NPT_String& searchCapabilities);
+
+ NPT_Result GetSortCapabilitiesSync(PLT_DeviceDataReference& device,
+ NPT_String& sortCapabilities);
+
+ const NPT_Lock<PLT_DeviceMap>& GetMediaServersMap() const { return m_MediaServers; }
+ bool IsCached(const char* uuid, const char* object_id);
+
+protected:
+ NPT_Result BrowseSync(PLT_BrowseDataReference& browse_data,
+ PLT_DeviceDataReference& device,
+ const char* object_id,
+ NPT_Int32 index,
+ NPT_Int32 count,
+ bool browse_metadata = false,
+ const char* filter = PLT_DEFAULT_FILTER,
+ const char* sort = "");
+
+ NPT_Result SearchSync(PLT_BrowseDataReference& browse_data,
+ PLT_DeviceDataReference& device,
+ const char* container_id,
+ const char* search_criteria,
+ NPT_Int32 index,
+ NPT_Int32 count,
+ const char* filter = PLT_DEFAULT_FILTER); // explicitely specify res otherwise WMP won't return a URL!
+
+private:
+ NPT_Result Find(const char* ip, PLT_DeviceDataReference& device);
+ NPT_Result WaitForResponse(NPT_SharedVariable& shared_var);
+
+private:
+ NPT_Lock<PLT_DeviceMap> m_MediaServers;
+ PLT_MediaContainerChangesListener* m_ContainerListener;
+ bool m_UseCache;
+ PLT_MediaCache<PLT_MediaObjectListReference,NPT_String> m_Cache;
+};
+
+/*----------------------------------------------------------------------
+| PLT_DeviceMapFinderByIp
++---------------------------------------------------------------------*/
+class PLT_DeviceMapFinderByIp
+{
+public:
+ // methods
+ PLT_DeviceMapFinderByIp(const char* ip) : m_IP(ip) {}
+
+ bool operator()(const PLT_DeviceMapEntry* const& entry) const {
+ const PLT_DeviceDataReference& device = entry->GetValue();
+ return (device->GetURLBase().GetHost() == m_IP);
+ }
+
+private:
+ // members
+ NPT_String m_IP;
+};
+
+/*----------------------------------------------------------------------
+| PLT_DeviceFinderByUUID
++---------------------------------------------------------------------*/
+class PLT_DeviceMapFinderByUUID
+{
+public:
+ // methods
+ PLT_DeviceMapFinderByUUID(const char* uuid) : m_UUID(uuid) {}
+
+ bool operator()(const PLT_DeviceMapEntry* const& entry) const {
+ PLT_DeviceDataReference device = entry->GetValue();
+ return device->GetUUID() == m_UUID;
+ }
+
+private:
+ // members
+ NPT_String m_UUID;
+};
+
+#endif /* _PLT_SYNC_MEDIA_BROWSER_ */
+
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/process_scpds.sh b/lib/libUPnP/Platinum/Source/Devices/MediaServer/process_scpds.sh
new file mode 100644
index 0000000..bba4bc8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/process_scpds.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+set -x
+
+# abort on any errors
+set -e
+
+# ContentDirectory
+../../../Targets/x86-unknown-cygwin/Debug/TextToHeader.exe -v MS_ContentDirectorySCPD -h ContentDirectory ContentDirectorySCPD.xml ContentDirectorySCPD.cpp
+
+# ContentDirectory with Search
+../../../Targets/x86-unknown-cygwin/Debug/TextToHeader.exe -v MS_ContentDirectorywSearchSCPD -h ContentDirectory ContentDirectorywSearchSCPD.xml ContentDirectorywSearchSCPD.cpp
+
+# ConnectionManager
+../../../Targets/x86-unknown-cygwin/Debug/TextToHeader.exe -v MS_ConnectionManagerSCPD -h ConnectionManager ConnectionManagerSCPD.xml ConnectionManagerSCPD.cpp \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Action.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/Action.cpp
new file mode 100644
index 0000000..08a028d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Action.cpp
@@ -0,0 +1,92 @@
+/*****************************************************************
+|
+| Platinum - Managed Action
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "Action.h"
+#include "ActionDescription.h"
+#include "Service.h"
+#include "ActionArgumentDescription.h"
+#include "EnumerableNptArray.h"
+
+Platinum::Service^ Platinum::Action::ParentService::get()
+{
+ return marshal_as<Service^>(*(*m_pHandle)->GetActionDesc().GetService());
+}
+
+Platinum::ActionDescription^ Platinum::Action::Description::get()
+{
+ return marshal_as<ActionDescription^>((*m_pHandle)->GetActionDesc());
+}
+
+IEnumerable<Platinum::ActionArgumentDescription^>^ Platinum::Action::Arguments::get()
+{
+ return gcnew Enumerables::EnumerableNptArray<ActionArgumentDescription^, PLT_ArgumentDesc*>(
+ (*m_pHandle)->GetActionDesc().GetArgumentDescs()
+ );
+}
+
+Platinum::ActionArgumentDescription^ Platinum::Action::GetArgument( String^ name )
+{
+ if (String::IsNullOrEmpty(name))
+ throw gcnew ArgumentException("null or empty", "name");
+
+ marshal_context c;
+
+ PLT_ArgumentDesc* arg = (*m_pHandle)->GetActionDesc().GetArgumentDesc(c.marshal_as<const char*>(name));
+
+ if (!arg)
+ return nullptr;
+
+ return marshal_as<ActionArgumentDescription^>(*arg);
+}
+
+Int32 Platinum::Action::SetArgumentValue( String^ name, String^ value )
+{
+ if (String::IsNullOrEmpty(name))
+ throw gcnew ArgumentException("null or empty", "name");
+
+ marshal_context c;
+ return (*m_pHandle)->SetArgumentValue(c.marshal_as<const char*>(name), c.marshal_as<const char*>(value));
+}
+
+void Platinum::Action::HandleActionResponse( NeptuneException^ error, Action^ action )
+{
+ if (action->m_pHandle == m_pHandle)
+ {
+ this->ActionResponse(error);
+ }
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Action.h b/lib/libUPnP/Platinum/Source/Extras/Managed/Action.h
new file mode 100644
index 0000000..7a45f89
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Action.h
@@ -0,0 +1,159 @@
+/*****************************************************************
+|
+| Platinum - Managed Action
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+ref class ActionArgumentDescription;
+ref class ActionDescription;
+ref class Service;
+
+/*----------------------------------------------------------------------
+| Action
++---------------------------------------------------------------------*/
+public ref class Action
+{
+public:
+
+ delegate void ActionResponseDelegate(NeptuneException^ error);
+
+private:
+
+ PLT_ActionReference* m_pHandle;
+
+internal:
+
+ property PLT_ActionReference& Handle
+ {
+ PLT_ActionReference& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ property String^ Name
+ {
+ String^ get()
+ {
+ return gcnew String((*m_pHandle)->GetActionDesc().GetName());
+ }
+ }
+
+ property IEnumerable<ActionArgumentDescription^>^ Arguments
+ {
+ IEnumerable<ActionArgumentDescription^>^ get();
+ }
+
+ property Service^ ParentService
+ {
+ Service^ get();
+ }
+
+ property ActionDescription^ Description
+ {
+ ActionDescription^ get();
+ }
+
+public:
+
+ event ActionResponseDelegate^ ActionResponse;
+
+public:
+
+ ActionArgumentDescription^ GetArgument(String^ name);
+ Int32 SetArgumentValue(String^ name, String^ value);
+
+internal:
+
+ void HandleActionResponse(NeptuneException^ error, Action^ action);
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ Action^ a = (Action^)obj;
+
+ return (m_pHandle->AsPointer() == a->m_pHandle->AsPointer());
+
+ /*if (m_pHandle->AsPointer() == a->m_pHandle->AsPointer())
+ return true;
+
+ return ((*m_pHandle)->GetActionDesc() == (*a->m_pHandle)->GetActionDesc());*/
+ }
+
+internal:
+
+ Action(PLT_ActionReference& action)
+ {
+ if (action.IsNull())
+ throw gcnew ArgumentNullException("action");
+
+ m_pHandle = new PLT_ActionReference(action);
+ }
+
+public:
+
+ ~Action()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!Action();
+ }
+
+ !Action()
+ {
+ // clean-up unmanaged
+ if (m_pHandle != 0)
+ {
+ delete m_pHandle;
+
+ m_pHandle = 0;
+ }
+ }
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::Action, PLT_ActionReference); \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.cpp
new file mode 100644
index 0000000..d6db6eb
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.cpp
@@ -0,0 +1,45 @@
+/*****************************************************************
+|
+| Platinum - Managed ActionArgumentDescription
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "ActionArgumentDescription.h"
+#include "StateVariable.h"
+
+Platinum::StateVariable^ Platinum::ActionArgumentDescription::RelatedStateVariable::get()
+{
+ return marshal_as<StateVariable^>(*m_pHandle->GetRelatedStateVariable());
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.h b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.h
new file mode 100644
index 0000000..6f3fda3
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionArgumentDescription.h
@@ -0,0 +1,153 @@
+/*****************************************************************
+|
+| Platinum - Managed ActionArgumentDescription
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| ActionArgumentDirection
++---------------------------------------------------------------------*/
+public enum class ActionArgumentDirection
+{
+ In,
+ Out,
+ InOut
+};
+
+ref class StateVariable;
+
+/*----------------------------------------------------------------------
+| ActionArgumentDescription
++---------------------------------------------------------------------*/
+public ref class ActionArgumentDescription
+{
+private:
+
+ PLT_ArgumentDesc* m_pHandle;
+
+public:
+
+ property String^ Name
+ {
+ String^ get()
+ {
+ return gcnew String(m_pHandle->GetName());
+ }
+ }
+
+ property ActionArgumentDirection Direction
+ {
+ ActionArgumentDirection get()
+ {
+ return ParseArgumentDirection(m_pHandle->GetDirection());
+ }
+ }
+
+ property Boolean HasReturnValue
+ {
+ Boolean get()
+ {
+ return Boolean(m_pHandle->HasReturnValue());
+ }
+ }
+
+ property StateVariable^ RelatedStateVariable
+ {
+ StateVariable^ get();
+ }
+
+private:
+
+ static ActionArgumentDirection ParseArgumentDirection(const NPT_String& dir)
+ {
+ NPT_String s (dir);
+
+ s.MakeLowercase();
+
+ if (s == "in")
+ return ActionArgumentDirection::In;
+
+ if (s == "out")
+ return ActionArgumentDirection::Out;
+
+ if (s == "inout")
+ return ActionArgumentDirection::InOut;
+
+ if (s == "io")
+ return ActionArgumentDirection::InOut;
+
+ throw gcnew ArgumentException("unknown direction");
+ }
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((ActionArgumentDescription^)obj)->m_pHandle);
+ }
+
+internal:
+
+ ActionArgumentDescription(PLT_ArgumentDesc& devData)
+ {
+ m_pHandle = &devData;
+ }
+
+public:
+
+ ~ActionArgumentDescription()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!ActionArgumentDescription();
+ }
+
+ !ActionArgumentDescription()
+ {
+ // clean-up unmanaged
+ }
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::ActionArgumentDescription, PLT_ArgumentDesc);
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.cpp
new file mode 100644
index 0000000..de3ef5a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.cpp
@@ -0,0 +1,69 @@
+/*****************************************************************
+|
+| Platinum - Managed ActionDescription
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "ActionDescription.h"
+#include "Service.h"
+#include "ActionArgumentDescription.h"
+#include "EnumerableNptArray.h"
+
+Platinum::Service^ Platinum::ActionDescription::ParentService::get()
+{
+ return marshal_as<Service^>(*m_pHandle->GetService());
+}
+
+IEnumerable<Platinum::ActionArgumentDescription^>^ Platinum::ActionDescription::Arguments::get()
+{
+ return gcnew Enumerables::EnumerableNptArray<ActionArgumentDescription^, PLT_ArgumentDesc*>(
+ m_pHandle->GetArgumentDescs()
+ );
+}
+
+Platinum::ActionArgumentDescription^ Platinum::ActionDescription::GetArgument( String^ name )
+{
+ if (String::IsNullOrEmpty(name))
+ throw gcnew ArgumentException("null or empty", "name");
+
+ marshal_context c;
+
+ PLT_ArgumentDesc* arg = m_pHandle->GetArgumentDesc(c.marshal_as<const char*>(name));
+
+ if (!arg)
+ return nullptr;
+
+ return marshal_as<ActionArgumentDescription^>(*arg);
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.h b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.h
new file mode 100644
index 0000000..dbbe1a7
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ActionDescription.h
@@ -0,0 +1,123 @@
+/*****************************************************************
+|
+| Platinum - Managed ActionDescription
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+ref class ActionArgumentDescription;
+ref class Service;
+
+/*----------------------------------------------------------------------
+| ActionDescription
++---------------------------------------------------------------------*/
+public ref class ActionDescription
+{
+private:
+
+ PLT_ActionDesc* m_pHandle;
+
+internal:
+
+ property PLT_ActionDesc& Handle
+ {
+ PLT_ActionDesc& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ property String^ Name
+ {
+ String^ get()
+ {
+ return gcnew String(m_pHandle->GetName());
+ }
+ }
+
+ property IEnumerable<ActionArgumentDescription^>^ Arguments
+ {
+ IEnumerable<ActionArgumentDescription^>^ get();
+ }
+
+ property Service^ ParentService
+ {
+ Service^ get();
+ }
+
+public:
+
+ ActionArgumentDescription^ GetArgument(String^ name);
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((ActionDescription^)obj)->m_pHandle);
+ }
+
+internal:
+
+ ActionDescription(PLT_ActionDesc& devData)
+ {
+ m_pHandle = &devData;
+ }
+
+public:
+
+ ~ActionDescription()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!ActionDescription();
+ }
+
+ !ActionDescription()
+ {
+ }
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::ActionDescription, PLT_ActionDesc);
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Clix.h b/lib/libUPnP/Platinum/Source/Extras/Managed/Clix.h
new file mode 100644
index 0000000..2b93f60
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Clix.h
@@ -0,0 +1,202 @@
+// ------------------------------------------------------------------------------------------- //
+// clix.h
+//
+// http://www.nuclex.org/articles/5-cxx/10-marshaling-strings-in-cxx-cli
+//
+// Marshals strings between .NET and C++ using C++/CLI (Visual C++ 2005 and later only).
+// Faster and cleaner than the System::Interop method because it uses garbage collected memory.
+// Use at your own leisure. No warranties whatsoever provided.
+//
+// Original code by Markus Ewald (http://www.nuclex.org/articles/marshaling-strings-in-cxx-cli)
+// Updated version including several improvements suggested by Neil Hunt
+// ------------------------------------------------------------------------------------------- //
+#pragma once
+
+#include <string>
+#include <vcclr.h>
+
+// CLI extensions namespace
+namespace clix {
+
+ /// <summary>Encoding types for strings</summary>
+ enum Encoding {
+
+ /// <summary>ANSI encoding</summary>
+ /// <remarks>
+ /// This is the default encoding you've most likely been using all around in C++. ANSI
+ /// means 8 Bit encoding with character codes depending on the system's selected code page.
+ /// <remarks>
+ E_ANSI,
+
+ /// <summary>UTF-8 encoding</summary>
+ /// <remarks>
+ /// This is the encoding commonly used for multilingual C++ strings. All ASCII characters
+ /// (0-127) will be represented as single bytes. Be aware that UTF-8 uses more than one
+ /// byte for extended characters, so std::string::length() might not reflect the actual
+ /// length of the string in characters if it contains any non-ASCII characters.
+ /// <remarks>
+ E_UTF8,
+
+ /// <summary>UTF-16 encoding</summary>
+ /// <remarks>
+ /// This is the suggested to be used for marshaling and the native encoding of .NET
+ /// strings. It is similar to UTF-8 but uses a minimum of two bytes per character, making
+ /// the number of bytes required for a given string better predictable. Be aware, however,
+ /// that UTF-16 can still use more than two bytes for a character, so std::wstring::length()
+ /// might not reflect the actual length of the string.
+ /// </remarks>
+ E_UTF16, E_UNICODE = E_UTF16
+
+ };
+
+ // Ignore this if you're just scanning the headers for informations :-)
+ /* All this template stuff might seem like overkill, but it is well thought out and enables
+ you to use a readable and convenient call while still keeping the highest possible code
+ efficiency due to compile-time evaluation of the required conversion path.
+ */
+ namespace detail {
+
+ // Get C++ string type for specified encoding
+ template<Encoding encoding> struct StringTypeSelecter;
+ template<> struct StringTypeSelecter<E_ANSI> { typedef std::string Type; };
+ template<> struct StringTypeSelecter<E_UTF8> { typedef std::string Type; };
+ template<> struct StringTypeSelecter<E_UTF16> { typedef std::wstring Type; };
+
+ // Compile-time check whether a given type is a managed System::String
+ template<typename StringType> struct IsManagedString { enum { Result = false }; };
+ template<> struct IsManagedString<System::String ^> { enum { Result = true }; };
+
+ // Compile-time selection of two types depending on a boolean expression
+ template<bool expression> struct Select;
+ template<> struct Select<false> {
+ template<typename TrueType, typename FalseType> struct Type { typedef FalseType Result; };
+ };
+ template<> struct Select<true> {
+ template<typename TrueType, typename FalseType> struct Type { typedef TrueType Result; };
+ };
+
+ // Direction of the marshaling process
+ enum MarshalingDirection {
+ CxxFromNet,
+ NetFromCxx
+ };
+
+ // The actual marshaling code
+ template<MarshalingDirection direction> struct StringMarshaler;
+
+ // Marshals to .NET from C++ strings
+ template<> struct StringMarshaler<NetFromCxx> {
+
+ template<Encoding encoding, typename SourceType>
+ static System::String ^marshal(const SourceType &string) {
+ // Constructs a std::[w]string in case someone gave us a char * to choke on
+ return marshalCxxString<encoding, SourceType>(string);
+ }
+
+ template<Encoding encoding, typename SourceType>
+ static System::String ^marshalCxxString(
+ const typename StringTypeSelecter<encoding>::Type &cxxString
+ ) {
+ typedef typename StringTypeSelecter<encoding>::Type SourceStringType;
+ size_t byteCount = cxxString.length() * sizeof(SourceStringType::value_type);
+
+ // Copy the C++ string contents into a managed array of bytes
+ array<unsigned char> ^bytes = gcnew array<unsigned char>(byteCount);
+ { pin_ptr<unsigned char> pinnedBytes = &bytes[0];
+ memcpy(pinnedBytes, cxxString.c_str(), byteCount);
+ }
+
+ // Now let one of .NET's encoding classes do the rest
+ return decode<encoding>(bytes);
+ }
+
+ private:
+ // Converts a byte array based on the selected encoding
+ template<Encoding encoding> static System::String ^decode(array<unsigned char> ^bytes);
+ template<> static System::String ^decode<E_ANSI>(array<unsigned char> ^bytes) {
+ return System::Text::Encoding::Default->GetString(bytes);
+ }
+ template<> static System::String ^decode<E_UTF8>(array<unsigned char> ^bytes) {
+ return System::Text::Encoding::UTF8->GetString(bytes);
+ }
+ template<> static System::String ^decode<E_UTF16>(array<unsigned char> ^bytes) {
+ return System::Text::Encoding::Unicode->GetString(bytes);
+ }
+ };
+
+ // Marshals to C++ strings from .NET
+ template<> struct StringMarshaler<CxxFromNet> {
+
+ template<Encoding encoding, typename SourceType>
+ static typename detail::StringTypeSelecter<encoding>::Type marshal(
+ System::String ^string
+ ) {
+ typedef typename StringTypeSelecter<encoding>::Type StringType;
+
+ // First, we use .NET's encoding classes to convert the string into a byte array
+ array<unsigned char> ^bytes = encode<encoding>(string);
+
+ // fix crash if empty string passed
+ if (bytes->Length == 0) return StringType();
+
+ // Then we construct our native string from that byte array
+ pin_ptr<unsigned char> pinnedBytes(&bytes[0]);
+ return StringType(
+ reinterpret_cast<StringType::value_type *>(static_cast<unsigned char *>(pinnedBytes)),
+ bytes->Length / sizeof(StringType::value_type)
+ );
+ }
+
+ template<> static std::wstring marshal<E_UTF16, System::String ^>(
+ System::String ^string
+ ) {
+ // fix crash if empty string passed
+ if (string->Length == 0) return std::wstring();
+
+ // We can directly access the characters in the managed string
+ pin_ptr<const wchar_t> pinnedChars(::PtrToStringChars(string));
+ return std::wstring(pinnedChars, string->Length);
+ }
+
+ private:
+ // Converts a string based on the selected encoding
+ template<Encoding encoding> static array<unsigned char> ^encode(System::String ^string);
+ template<> static array<unsigned char> ^encode<E_ANSI>(System::String ^string) {
+ return System::Text::Encoding::Default->GetBytes(string);
+ }
+ template<> static array<unsigned char> ^encode<E_UTF8>(System::String ^string) {
+ return System::Text::Encoding::UTF8->GetBytes(string);
+ }
+ template<> static array<unsigned char> ^encode<E_UTF16>(System::String ^string) {
+ return System::Text::Encoding::Unicode->GetBytes(string);
+ }
+
+ };
+
+ } // namespace detail
+
+ // ----------------------------------------------------------------------------------------- //
+ // clix::marshalString()
+ // ----------------------------------------------------------------------------------------- //
+ /// <summary>Marshals strings between .NET managed and C++ native</summary>
+ /// <remarks>
+ /// This all-in-one function marshals native C++ strings to .NET strings and vice versa.
+ /// You have to specify an encoding to use for the conversion, which always applies to the
+ /// native C++ string as .NET always uses UTF-16 for its own strings.
+ /// </remarks>
+ /// <param name="string">String to be marshalled to the other side</param>
+ /// <returns>The marshaled representation of the string</returns>
+ template<Encoding encoding, typename SourceType>
+ typename detail::Select<detail::IsManagedString<SourceType>::Result>::Type<
+ typename detail::StringTypeSelecter<encoding>::Type,
+ System::String ^
+ >::Result marshalString(SourceType string) {
+
+ // Pass on the call to our nifty template routines
+ return detail::StringMarshaler<
+ detail::IsManagedString<SourceType>::Result ? detail::CxxFromNet : detail::NetFromCxx
+ >::marshal<encoding, SourceType>(string);
+
+ }
+
+} // namespace clix
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.cpp
new file mode 100644
index 0000000..506dbec
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.cpp
@@ -0,0 +1,115 @@
+/*****************************************************************
+|
+| Platinum - Managed ControlPoint
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "ControlPoint.h"
+#include "ControlPointEventBridge.h"
+#include "Action.h"
+#include "ActionDescription.h"
+#include "Service.h"
+
+void Platinum::ControlPoint::RegisterEvents()
+{
+ if (!m_pBridge)
+ {
+ m_pBridge = new ControlPointEventBridge(this);
+ }
+
+ Helpers::ThrowOnError((*m_pHandle)->AddListener(m_pBridge));
+}
+
+Platinum::Action^ Platinum::ControlPoint::CreateAction( ActionDescription^ desc )
+{
+ if (desc == nullptr)
+ throw gcnew ArgumentNullException("desc");
+
+ // create action
+ PLT_ActionReference r(new PLT_Action(desc->Handle));
+
+ return gcnew Action(r);
+}
+
+
+void Platinum::ControlPoint::InvokeAction(Action^ action)
+{
+ // register events
+ this->ActionResponse += gcnew ActionResponseDelegate(action, &Action::HandleActionResponse);
+
+ Helpers::ThrowOnError(
+ (*m_pHandle)->InvokeAction(action->Handle)
+ );
+}
+
+void Platinum::ControlPoint::Subscribe( Service^ srv )
+{
+ if (srv == nullptr)
+ throw gcnew ArgumentNullException("srv");
+
+ Helpers::ThrowOnError(
+ (*m_pHandle)->Subscribe(&srv->Handle, false)
+ );
+}
+
+void Platinum::ControlPoint::Unsubscribe( Service^ srv )
+{
+ if (srv == nullptr)
+ throw gcnew ArgumentNullException("srv");
+
+ Helpers::ThrowOnError(
+ (*m_pHandle)->Subscribe(&srv->Handle, true)
+ );
+}
+
+Platinum::ControlPoint::!ControlPoint()
+{
+ // clean-up unmanaged
+ if (m_pHandle != 0)
+ {
+ // remove listener first, is it necessary?
+ if (m_pBridge) (*m_pHandle)->RemoveListener(m_pBridge);
+
+ delete m_pHandle;
+
+ m_pHandle = 0;
+ }
+
+ if (m_pBridge != 0)
+ {
+ delete m_pBridge;
+
+ m_pBridge = 0;
+ }
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.h b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.h
new file mode 100644
index 0000000..0fd0bba
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPoint.h
@@ -0,0 +1,227 @@
+/*****************************************************************
+|
+| Platinum - Managed ControlPoint
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+ref class Action;
+ref class ActionDescription;
+ref class DeviceData;
+ref class Service;
+ref class StateVariable;
+class ControlPointEventBridge;
+
+/*----------------------------------------------------------------------
+| ControlPoint
++---------------------------------------------------------------------*/
+public ref class ControlPoint
+{
+public:
+
+ delegate void DeviceAddedDelegate(DeviceData^ dev);
+ delegate void DeviceRemovedDelegate(DeviceData^ dev);
+ delegate void ActionResponseDelegate(NeptuneException^ error, Action^ action);
+ delegate void EventNotifyDelegate(Service^ srv, IEnumerable<StateVariable^>^ vars);
+
+private:
+
+ PLT_CtrlPointReference* m_pHandle;
+ ControlPointEventBridge* m_pBridge;
+ List<DeviceData^>^ m_pDevices;
+
+public:
+
+ property array<DeviceData^>^ Devices
+ {
+ array<DeviceData^>^ get()
+ {
+ System::Threading::Monitor::Enter(m_pDevices);
+
+ return m_pDevices->ToArray();
+
+ System::Threading::Monitor::Exit(m_pDevices);
+ }
+ }
+
+internal:
+
+ property PLT_CtrlPointReference& Handle
+ {
+ PLT_CtrlPointReference& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ event DeviceAddedDelegate^ DeviceAdded;
+ event DeviceRemovedDelegate^ DeviceRemoved;
+ event ActionResponseDelegate^ ActionResponse;
+ event EventNotifyDelegate^ EventNotify;
+
+internal:
+
+ void OnDeviceAdded(DeviceData^ dev)
+ {
+ // add to list
+ System::Threading::Monitor::Enter(m_pDevices);
+
+ m_pDevices->Add(dev);
+
+ System::Threading::Monitor::Exit(m_pDevices);
+
+ // handle events
+ this->DeviceAdded(dev);
+ }
+
+ void OnDeviceRemoved(DeviceData^ dev)
+ {
+ // handle events
+ this->DeviceRemoved(dev);
+
+ // remove from list
+ System::Threading::Monitor::Enter(m_pDevices);
+
+ m_pDevices->Remove(dev);
+
+ System::Threading::Monitor::Exit(m_pDevices);
+ }
+
+ void OnActionResponse(NeptuneException^ error, Action^ action)
+ {
+ this->ActionResponse(error, action);
+ }
+
+ void OnEventNotify(Service^ srv, IEnumerable<StateVariable^>^ vars)
+ {
+ this->EventNotify(srv, vars);
+ }
+
+public:
+
+ Action^ CreateAction(ActionDescription^ desc);
+ void InvokeAction(Action^ action);
+
+ void Subscribe(Service^ srv);
+ void Unsubscribe(Service^ srv);
+
+private:
+
+ void RegisterEvents();
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (*m_pHandle == *((ControlPoint^)obj)->m_pHandle);
+ }
+
+internal:
+
+ ControlPoint(PLT_CtrlPointReference& ctlPoint)
+ {
+ if (ctlPoint.IsNull())
+ throw gcnew ArgumentNullException("ctlPoint");
+
+ m_pHandle = new PLT_CtrlPointReference(ctlPoint);
+
+ RegisterEvents();
+ }
+
+ ControlPoint(PLT_CtrlPoint& ctlPoint)
+ {
+ m_pHandle = new PLT_CtrlPointReference(&ctlPoint);
+
+ RegisterEvents();
+ }
+
+public:
+
+ ControlPoint(String^ autoSearcheviceType)
+ {
+ if (String::IsNullOrEmpty(autoSearcheviceType))
+ {
+ throw gcnew ArgumentException("null or empty", "autoSearcheviceType");
+ }
+
+ marshal_context c;
+
+ m_pHandle = new PLT_CtrlPointReference(
+ new PLT_CtrlPoint(c.marshal_as<const char*>(autoSearcheviceType))
+ );
+
+ m_pDevices = gcnew List<DeviceData^>();
+
+ RegisterEvents();
+ }
+
+ ControlPoint(bool autoSearch)
+ {
+ if (autoSearch)
+ {
+ m_pHandle = new PLT_CtrlPointReference(new PLT_CtrlPoint());
+ }
+ else
+ {
+ m_pHandle = new PLT_CtrlPointReference(new PLT_CtrlPoint(0));
+ }
+
+ m_pDevices = gcnew List<DeviceData^>();
+
+ RegisterEvents();
+ }
+
+ ~ControlPoint()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!ControlPoint();
+ }
+
+ !ControlPoint();
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::ControlPoint, PLT_CtrlPoint);
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.cpp
new file mode 100644
index 0000000..f229202
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.cpp
@@ -0,0 +1,88 @@
+/*****************************************************************
+|
+| Platinum - Managed ControlPointEventBridge
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "ControlPointEventBridge.h"
+#include "ControlPoint.h"
+#include "DeviceData.h"
+#include "Action.h"
+#include "Service.h"
+#include "EnumerableNptList.h"
+#include "StateVariable.h"
+
+NPT_Result Platinum::ControlPointEventBridge::OnDeviceAdded( PLT_DeviceDataReference& device )
+{
+ m_pControlPoint->OnDeviceAdded(gcnew DeviceData(device));
+
+ return NPT_SUCCESS;
+}
+
+NPT_Result Platinum::ControlPointEventBridge::OnDeviceRemoved( PLT_DeviceDataReference& device )
+{
+ m_pControlPoint->OnDeviceRemoved(gcnew DeviceData(device));
+
+ return NPT_SUCCESS;
+}
+
+NPT_Result Platinum::ControlPointEventBridge::OnActionResponse( NPT_Result res, PLT_ActionReference& action, void* userdata )
+{
+ if (NPT_FAILED(res))
+ {
+ m_pControlPoint->OnActionResponse(
+ gcnew NeptuneException(res),
+ gcnew Action(action)
+ );
+ }
+ else
+ {
+ m_pControlPoint->OnActionResponse(
+ nullptr,
+ gcnew Action(action)
+ );
+ }
+
+ return NPT_SUCCESS;
+}
+
+NPT_Result Platinum::ControlPointEventBridge::OnEventNotify( PLT_Service* service, NPT_List<PLT_StateVariable*>* vars )
+{
+ m_pControlPoint->OnEventNotify(
+ gcnew Service(*service),
+ gcnew Enumerables::EnumerableNptList<StateVariable^, PLT_StateVariable*>(*vars)
+ );
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.h b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.h
new file mode 100644
index 0000000..83a6807
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/ControlPointEventBridge.h
@@ -0,0 +1,68 @@
+/*****************************************************************
+|
+| Platinum - Managed ControlPointEventBridge
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+ref class ControlPoint;
+
+/*----------------------------------------------------------------------
+| ControlPointEventBridge
++---------------------------------------------------------------------*/
+private class ControlPointEventBridge : public PLT_CtrlPointListener
+{
+private:
+
+ gcroot<ControlPoint^> m_pControlPoint;
+
+public:
+
+ virtual NPT_Result OnDeviceAdded(PLT_DeviceDataReference& device);
+ virtual NPT_Result OnDeviceRemoved(PLT_DeviceDataReference& device);
+ virtual NPT_Result OnActionResponse(NPT_Result res, PLT_ActionReference& action, void* userdata);
+ virtual NPT_Result OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars);
+
+public:
+
+ ControlPointEventBridge(gcroot<ControlPoint^> cp)
+ {
+ m_pControlPoint = cp;
+ }
+ virtual ~ControlPointEventBridge()
+ {}
+
+};
+
+
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.cpp
new file mode 100644
index 0000000..06a6d54
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.cpp
@@ -0,0 +1,168 @@
+/*****************************************************************
+|
+| Platinum - Managed DeviceData
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "DeviceData.h"
+#include "Service.h"
+#include "EnumerableNptArray.h"
+
+IEnumerable<Platinum::Service^>^ Platinum::DeviceData::Services::get()
+{
+ return gcnew Enumerables::EnumerableNptArray<Service^, PLT_Service*>(
+ (*m_pHandle)->GetServices()
+ );
+}
+
+IEnumerable<Platinum::DeviceData^>^ Platinum::DeviceData::EmbeddedDevices::get()
+{
+ return gcnew Enumerables::EnumerableNptArrayRef<DeviceData^, PLT_DeviceDataReference>(
+ (*m_pHandle)->GetEmbeddedDevices()
+ );
+}
+
+Platinum::DeviceData^ Platinum::DeviceData::FindEmbeddedDeviceByType( String^ type )
+{
+ if (String::IsNullOrEmpty(type))
+ throw gcnew ArgumentException("null or empty", "type");
+
+ PLT_DeviceDataReference r;
+ marshal_context c;
+
+ Helpers::ThrowOnErrorButNoSuchItem((*m_pHandle)->FindEmbeddedDeviceByType(
+ c.marshal_as<const char*>(type),
+ r
+ ));
+
+ if (r.IsNull())
+ return nullptr;
+
+ return marshal_as<DeviceData^>(r);
+}
+
+Platinum::Service^ Platinum::DeviceData::FindServiceById( String^ id )
+{
+ if (String::IsNullOrEmpty(id))
+ throw gcnew ArgumentException("null or empty", "id");
+
+ PLT_Service* r = 0;
+ marshal_context c;
+
+ Helpers::ThrowOnErrorButNoSuchItem((*m_pHandle)->FindServiceById(
+ c.marshal_as<const char*>(id),
+ r
+ ));
+
+ if (!r)
+ return nullptr;
+
+ return marshal_as<Service^>(*r);
+}
+
+Platinum::Service^ Platinum::DeviceData::FindServiceByType( String^ type )
+{
+ if (String::IsNullOrEmpty(type))
+ throw gcnew ArgumentException("null or empty", "type");
+
+ PLT_Service* r = 0;
+ marshal_context c;
+
+ Helpers::ThrowOnErrorButNoSuchItem((*m_pHandle)->FindServiceByType(
+ c.marshal_as<const char*>(type),
+ r
+ ));
+
+ if (!r)
+ return nullptr;
+
+ return marshal_as<Service^>(*r);
+}
+
+Platinum::Service^ Platinum::DeviceData::FindServiceBySCPDURL( Uri^ url )
+{
+ if (url == nullptr)
+ throw gcnew ArgumentNullException("url");
+
+ PLT_Service* r = 0;
+ marshal_context c;
+
+ Helpers::ThrowOnErrorButNoSuchItem((*m_pHandle)->FindServiceBySCPDURL(
+ c.marshal_as<const char*>(url->ToString()),
+ r
+ ));
+
+ if (!r)
+ return nullptr;
+
+ return marshal_as<Service^>(*r);
+}
+
+Platinum::Service^ Platinum::DeviceData::FindServiceByControlURL( Uri^ url )
+{
+ if (url == nullptr)
+ throw gcnew ArgumentNullException("url");
+
+ PLT_Service* r = 0;
+ marshal_context c;
+
+ Helpers::ThrowOnErrorButNoSuchItem((*m_pHandle)->FindServiceByControlURL(
+ c.marshal_as<const char*>(url->ToString()),
+ r
+ ));
+
+ if (!r)
+ return nullptr;
+
+ return marshal_as<Service^>(*r);
+}
+
+Platinum::Service^ Platinum::DeviceData::FindServiceByEventSubURL( Uri^ url )
+{
+ if (url == nullptr)
+ throw gcnew ArgumentNullException("url");
+
+ PLT_Service* r = 0;
+ marshal_context c;
+
+ Helpers::ThrowOnErrorButNoSuchItem((*m_pHandle)->FindServiceByEventSubURL(
+ c.marshal_as<const char*>(url->ToString()),
+ r
+ ));
+
+ if (!r)
+ return nullptr;
+
+ return marshal_as<Service^>(*r);
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.h b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.h
new file mode 100644
index 0000000..e7e321f
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceData.h
@@ -0,0 +1,264 @@
+/*****************************************************************
+|
+| Platinum - Managed DeviceData
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| DeviceIcon
++---------------------------------------------------------------------*/
+public ref class DeviceIcon : public ManagedWrapper<PLT_DeviceIcon>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, MimeType, m_MimeType, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(Int32, Width, m_Width, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(Int32, Height, m_Height, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(Int32, Depth, m_Depth, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, UrlPath, m_UrlPath, m_pHandle);
+
+internal:
+
+ DeviceIcon(PLT_DeviceIcon& native) :
+ ManagedWrapper<PLT_DeviceIcon>(native)
+ {}
+
+public:
+ DeviceIcon() :
+ ManagedWrapper<PLT_DeviceIcon>()
+ {}
+
+ DeviceIcon(String^ mimeType, Int32 width, Int32 height, Int32 depth, String^ urlPath) :
+ ManagedWrapper<PLT_DeviceIcon>()
+ {
+ MimeType = mimeType;
+ Width = width;
+ Height = height;
+ Depth = depth;
+ UrlPath = urlPath;
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::DeviceIcon, PLT_DeviceIcon);
+
+namespace Platinum
+{
+
+ref class Service;
+
+/*----------------------------------------------------------------------
+| DeviceData
++---------------------------------------------------------------------*/
+public ref class DeviceData
+{
+protected:
+
+ PLT_DeviceDataReference* m_pHandle;
+
+public:
+
+ property String^ Description
+ {
+ String^ get()
+ {
+ NPT_String s;
+
+ Helpers::ThrowOnError((*m_pHandle)->GetDescription(s));
+
+ return gcnew String(s);
+ }
+ }
+
+ property Uri^ DescriptionUrl
+ {
+ Uri^ get()
+ {
+ return marshal_as<Uri^>((*m_pHandle)->GetDescriptionUrl());
+ }
+ }
+
+ property Uri^ UrlBase
+ {
+ Uri^ get()
+ {
+ return marshal_as<Uri^>((*m_pHandle)->GetURLBase());
+ }
+ }
+
+ property Uri^ IconUrl
+ {
+ Uri^ get()
+ {
+ return marshal_as<Uri^>((*m_pHandle)->GetIconUrl());
+ }
+ }
+
+ property TimeSpan^ LeaseTime
+ {
+ TimeSpan^ get()
+ {
+ return marshal_as<TimeSpan>((*m_pHandle)->GetLeaseTime());
+ }
+ }
+
+ property String^ UUID
+ {
+ String^ get()
+ {
+ return gcnew String((*m_pHandle)->GetUUID());
+ }
+ }
+
+ property String^ FriendlyName
+ {
+ String^ get()
+ {
+ return gcnew String((*m_pHandle)->GetFriendlyName());
+ }
+ }
+
+ property String^ TypeName
+ {
+ String^ get()
+ {
+ return gcnew String((*m_pHandle)->GetType());
+ }
+ }
+
+ property String^ ModelDescription
+ {
+ String^ get()
+ {
+ return gcnew String((*m_pHandle)->GetModelDescription());
+ }
+ }
+
+ property String^ ParentUUID
+ {
+ String^ get()
+ {
+ return gcnew String((*m_pHandle)->GetParentUUID());
+ }
+ }
+
+ property IEnumerable<Service^>^ Services
+ {
+ IEnumerable<Service^>^ get();
+ }
+
+ property IEnumerable<DeviceData^>^ EmbeddedDevices
+ {
+ IEnumerable<DeviceData^>^ get();
+ }
+
+internal:
+
+ property PLT_DeviceDataReference& Handle
+ {
+ PLT_DeviceDataReference& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ DeviceData^ FindEmbeddedDeviceByType(String^ type);
+ Service^ FindServiceById(String^ serviceId);
+ Service^ FindServiceByType(String^ type);
+ Service^ FindServiceBySCPDURL(Uri^ url);
+ Service^ FindServiceByControlURL(Uri^ url);
+ Service^ FindServiceByEventSubURL(Uri^ url);
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (*m_pHandle == *((DeviceData^)obj)->m_pHandle);
+ }
+
+internal:
+
+ DeviceData(PLT_DeviceDataReference& devData)
+ {
+ if (devData.IsNull())
+ throw gcnew ArgumentNullException("devData");
+
+ m_pHandle = new PLT_DeviceDataReference(devData);
+ }
+
+ DeviceData(PLT_DeviceData& devData)
+ {
+ m_pHandle = new PLT_DeviceDataReference(&devData);
+ }
+
+public:
+
+ ~DeviceData()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!DeviceData();
+ }
+
+ !DeviceData()
+ {
+ // clean-up unmanaged
+ if (m_pHandle != 0)
+ {
+ delete m_pHandle;
+
+ m_pHandle = 0;
+ }
+ }
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::DeviceData, PLT_DeviceData);
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::DeviceData, PLT_DeviceDataReference);
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.cpp
new file mode 100644
index 0000000..93b15f3
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.cpp
@@ -0,0 +1,38 @@
+/*****************************************************************
+|
+| Platinum - DeviceHost
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "DeviceHost.h" \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.h b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.h
new file mode 100644
index 0000000..d920e06
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/DeviceHost.h
@@ -0,0 +1,124 @@
+/*****************************************************************
+|
+| Platinum - DeviceHost
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+#include "DeviceData.h"
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| DeviceHost
++---------------------------------------------------------------------*/
+public ref class DeviceHost : public DeviceData
+{
+private:
+
+ PLT_DeviceHostReference* m_pHostHandle;
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (*m_pHandle == ((DeviceHost^)obj)->Handle);
+ }
+
+internal:
+
+ property PLT_DeviceHostReference& Host
+ {
+ PLT_DeviceHostReference& get()
+ {
+ return *m_pHostHandle;
+ }
+ }
+
+internal:
+
+ DeviceHost(PLT_DeviceHostReference& devHost) :
+ m_pHostHandle(new PLT_DeviceHostReference(devHost)),
+ DeviceData((PLT_DeviceDataReference&)*m_pHostHandle)
+ {
+ }
+
+ DeviceHost(PLT_DeviceHost& devHost) :
+ m_pHostHandle(new PLT_DeviceHostReference(&devHost)),
+ DeviceData((PLT_DeviceDataReference&)*m_pHostHandle) // we must make sure to pass our newly created ref object
+ {
+ }
+
+public:
+
+ void setLeaseTime(TimeSpan^ lease)
+ {
+ (*m_pHostHandle)->SetLeaseTime(NPT_TimeInterval((double)lease->TotalSeconds));
+ }
+
+ NPT_Result AddIcon(DeviceIcon^ icon, array<Byte>^ data)
+ {
+ pin_ptr<Byte> pinnedBuffer = &data[0];
+ return (*m_pHostHandle)->AddIcon(icon->Handle, (const void*)pinnedBuffer, data->Length, true);
+ }
+
+ ~DeviceHost()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!DeviceHost();
+ }
+
+ !DeviceHost()
+ {
+ // clean-up unmanaged
+ if (m_pHostHandle != 0)
+ {
+ delete m_pHostHandle;
+
+ m_pHostHandle = 0;
+ }
+ }
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::DeviceHost, PLT_DeviceHost);
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::DeviceHost, PLT_DeviceHostReference); \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Didl.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/Didl.cpp
new file mode 100644
index 0000000..9c8e9c2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Didl.cpp
@@ -0,0 +1,39 @@
+/*****************************************************************
+|
+| Platinum - Managed Didl
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "Didl.h"
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Didl.h b/lib/libUPnP/Platinum/Source/Extras/Managed/Didl.h
new file mode 100644
index 0000000..57b02df
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Didl.h
@@ -0,0 +1,70 @@
+/*****************************************************************
+|
+| Platinum - Managed Didl
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDidl.h"
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| Didl
++---------------------------------------------------------------------*/
+public ref class Didl
+{
+public:
+
+ static property String^ header
+ {
+ String^ get()
+ {
+ return gcnew String(didl_header);
+ }
+ }
+
+ static property String^ footer
+ {
+ String^ get()
+ {
+ return gcnew String(didl_footer);
+ }
+ }
+
+};
+
+}
+
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptArray.h b/lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptArray.h
new file mode 100644
index 0000000..7d17959
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptArray.h
@@ -0,0 +1,226 @@
+/*****************************************************************
+|
+| Platinum - Managed EnumerableNptArray
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+namespace Enumerables
+{
+
+/*----------------------------------------------------------------------
+| EnumerableNptArray
++---------------------------------------------------------------------*/
+template<typename T_DotNetType, typename T_NativeType>
+private ref class EnumerableNptArray : public IEnumerable<T_DotNetType>
+{
+private:
+
+ ref class EnumerableNptArrayIterator : public IEnumerator<T_DotNetType>
+ {
+ private:
+
+ const NPT_Array<T_NativeType>* m_pArray;
+ NPT_Ordinal m_Index;
+
+ public:
+
+ virtual property T_DotNetType Current
+ {
+ T_DotNetType get()
+ {
+ return marshal_as<T_DotNetType>(*(*m_pArray)[m_Index]);
+ }
+ }
+
+ private:
+
+ virtual property Object^ Current2
+ {
+ Object^ get() sealed = System::Collections::IEnumerator::Current::get
+ {
+ return marshal_as<T_DotNetType>(*(*m_pArray)[m_Index]); // FIXME: This is a problem when T_NativeType is not a pointer (like PLT_DeviceDataReference for example)
+ }
+ }
+
+ public:
+
+ virtual bool MoveNext()
+ {
+ if (m_Index < m_pArray->GetItemCount() - 1)
+ {
+ m_Index++;
+ }
+
+ return false;
+ }
+
+ virtual void Reset()
+ {
+ m_Index = -1;
+ }
+
+ public:
+
+ EnumerableNptArrayIterator(const NPT_Array<T_NativeType>& array)
+ {
+ m_Index = -1;
+ m_pArray = &array;
+ }
+
+ ~EnumerableNptArrayIterator()
+ {
+ }
+
+ };
+
+private:
+
+ const NPT_Array<T_NativeType>* m_pArray;
+
+public:
+
+ virtual IEnumerator<T_DotNetType>^ GetEnumerator()
+ {
+ return gcnew EnumerableNptArrayIterator(*m_pArray);
+ }
+
+private:
+
+ virtual System::Collections::IEnumerator^ GetEnumerator2() sealed = System::Collections::IEnumerable::GetEnumerator
+ {
+ return gcnew EnumerableNptArrayIterator(*m_pArray);
+ }
+
+public:
+
+ EnumerableNptArray(const NPT_Array<T_NativeType>& array)
+ {
+ m_pArray = &array;
+ }
+};
+
+/*----------------------------------------------------------------------
+| EnumerableNptArrayRef
++---------------------------------------------------------------------*/
+template<typename T_DotNetType, typename T_NativeType>
+private ref class EnumerableNptArrayRef : public IEnumerable<T_DotNetType>
+{
+private:
+
+ ref class EnumerableNptArrayRefIterator : public IEnumerator<T_DotNetType>
+ {
+ private:
+
+ const NPT_Array<T_NativeType>* m_pArray;
+ NPT_Ordinal m_Index;
+
+ public:
+
+ virtual property T_DotNetType Current
+ {
+ T_DotNetType get()
+ {
+ return marshal_as<T_DotNetType>((*m_pArray)[m_Index]);
+ }
+ }
+
+ private:
+
+ virtual property Object^ Current2
+ {
+ Object^ get() sealed = System::Collections::IEnumerator::Current::get
+ {
+ return marshal_as<T_DotNetType>((*m_pArray)[m_Index]); // FIXME: This is a problem when T_NativeType is not a pointer (like PLT_DeviceDataReference for example)
+ }
+ }
+
+ public:
+
+ virtual bool MoveNext()
+ {
+ if (m_Index < m_pArray->GetItemCount() - 1)
+ {
+ m_Index++;
+ }
+
+ return false;
+ }
+
+ virtual void Reset()
+ {
+ m_Index = -1;
+ }
+
+ public:
+
+ EnumerableNptArrayRefIterator(const NPT_Array<T_NativeType>& array)
+ {
+ m_Index = -1;
+ m_pArray = &array;
+ }
+
+ ~EnumerableNptArrayRefIterator()
+ {
+ }
+
+ };
+
+private:
+
+ const NPT_Array<T_NativeType>* m_pArray;
+
+public:
+
+ virtual IEnumerator<T_DotNetType>^ GetEnumerator()
+ {
+ return gcnew EnumerableNptArrayRefIterator(*m_pArray);
+ }
+
+private:
+
+ virtual System::Collections::IEnumerator^ GetEnumerator2() sealed = System::Collections::IEnumerable::GetEnumerator
+ {
+ return gcnew EnumerableNptArrayRefIterator(*m_pArray);
+ }
+
+public:
+
+ EnumerableNptArrayRef(const NPT_Array<T_NativeType>& array)
+ {
+ m_pArray = &array;
+ }
+};
+
+}
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptList.h b/lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptList.h
new file mode 100644
index 0000000..fea89ae
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/EnumerableNptList.h
@@ -0,0 +1,234 @@
+/*****************************************************************
+|
+| Platinum - Managed EnumerableNptList
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+namespace Enumerables
+{
+
+/*----------------------------------------------------------------------
+| EnumerableNptList
++---------------------------------------------------------------------*/
+template<typename T_DotNetType, typename T_NativeType>
+private ref class EnumerableNptList : public IEnumerable<T_DotNetType>
+{
+private:
+
+ ref class EnumerableNptListIterator : public IEnumerator<T_DotNetType>
+ {
+ private:
+
+ const NPT_List<T_NativeType>* m_pList;
+ typename NPT_List<T_NativeType>::Iterator* m_pIt;
+
+ public:
+
+ virtual property T_DotNetType Current
+ {
+ T_DotNetType get()
+ {
+ return marshal_as<T_DotNetType>(***m_pIt); // FIXME: This is a problem when T_NativeType is not a pointer (like PLT_DeviceDataReference for example)
+ }
+ }
+
+ private:
+
+ virtual property Object^ Current2
+ {
+ Object^ get() sealed = System::Collections::IEnumerator::Current::get
+ {
+ return marshal_as<T_DotNetType>(***m_pIt); // FIXME: This is a problem when T_NativeType is not a pointer (like PLT_DeviceDataReference for example)
+ }
+ }
+
+ public:
+
+ virtual bool MoveNext()
+ {
+ if (!m_pIt)
+ {
+ m_pIt = &m_pList->GetFirstItem();
+ }
+ else
+ {
+ (*m_pIt)++;
+ }
+
+ return *m_pIt;
+ }
+
+ virtual void Reset()
+ {
+ m_pIt = 0;
+ }
+
+ public:
+
+ EnumerableNptListIterator(const NPT_List<T_NativeType>& list)
+ {
+ m_pIt = 0;
+ m_pList = &list;
+ }
+
+ ~EnumerableNptListIterator()
+ {
+ }
+
+ };
+
+private:
+
+ const NPT_List<T_NativeType>* m_pList;
+
+public:
+
+ virtual IEnumerator<T_DotNetType>^ GetEnumerator()
+ {
+ return gcnew EnumerableNptListIterator(*m_pList);
+ }
+
+private:
+
+ virtual System::Collections::IEnumerator^ GetEnumerator2() sealed = System::Collections::IEnumerable::GetEnumerator
+ {
+ return gcnew EnumerableNptListIterator(*m_pList);
+ }
+
+public:
+
+ EnumerableNptList(const NPT_List<T_NativeType>& list)
+ {
+ m_pList = &list;
+ }
+};
+
+/*----------------------------------------------------------------------
+| EnumerableNptListRef
++---------------------------------------------------------------------*/
+template<typename T_DotNetType, typename T_NativeType>
+private ref class EnumerableNptListRef : public IEnumerable<T_DotNetType>
+{
+private:
+
+ ref class EnumerableNptListRefIterator : public IEnumerator<T_DotNetType>
+ {
+ private:
+
+ const NPT_List<T_NativeType>* m_pList;
+ typename NPT_List<T_NativeType>::Iterator* m_pIt;
+
+ public:
+
+ virtual property T_DotNetType Current
+ {
+ T_DotNetType get()
+ {
+ return marshal_as<T_DotNetType>(**m_pIt);
+ }
+ }
+
+ private:
+
+ virtual property Object^ Current2
+ {
+ Object^ get() sealed = System::Collections::IEnumerator::Current::get
+ {
+ return marshal_as<T_DotNetType>(**m_pIt);
+ }
+ }
+
+ public:
+
+ virtual bool MoveNext()
+ {
+ if (!m_pIt)
+ {
+ m_pIt = &m_pList->GetFirstItem();
+ }
+ else
+ {
+ (*m_pIt)++;
+ }
+
+ return *m_pIt;
+ }
+
+ virtual void Reset()
+ {
+ m_pIt = 0;
+ }
+
+ public:
+
+ EnumerableNptListRefIterator(const NPT_List<T_NativeType>& list)
+ {
+ m_pIt = 0;
+ m_pList = &list;
+ }
+
+ ~EnumerableNptListRefIterator()
+ {
+ }
+
+ };
+
+private:
+
+ const NPT_List<T_NativeType>* m_pList;
+
+public:
+
+ virtual IEnumerator<T_DotNetType>^ GetEnumerator()
+ {
+ return gcnew EnumerableNptListRefIterator(*m_pList);
+ }
+
+private:
+
+ virtual System::Collections::IEnumerator^ GetEnumerator2() sealed = System::Collections::IEnumerable::GetEnumerator
+ {
+ return gcnew EnumerableNptListRefIterator(*m_pList);
+ }
+
+public:
+
+ EnumerableNptListRef(const NPT_List<T_NativeType>& list)
+ {
+ m_pList = &list;
+ }
+};
+
+}
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.cpp
new file mode 100644
index 0000000..3dbefdf
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.cpp
@@ -0,0 +1,39 @@
+/*****************************************************************
+|
+| Platinum - Managed Helpers
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "Helpers.h"
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.h b/lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.h
new file mode 100644
index 0000000..13a9764
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Helpers.h
@@ -0,0 +1,378 @@
+/*****************************************************************
+|
+| Platinum - Managed Helpers
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "NeptuneException.h"
+#include "Clix.h"
+
+using namespace clix;
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| Helpers
++---------------------------------------------------------------------*/
+private ref class Helpers
+{
+public:
+
+ static void ThrowOnError(NPT_Result r)
+ {
+ if (NPT_FAILED(r))
+ {
+ throw gcnew NeptuneException(r);
+ }
+ }
+
+ static void ThrowOnErrorButNoSuchItem(NPT_Result r)
+ {
+ if (NPT_FAILED(r) && (r != NPT_ERROR_NO_SUCH_ITEM))
+ {
+ throw gcnew NeptuneException(r);
+ }
+ }
+
+ // this code was part of RouterControl.IO (http://routercontrol.codeplex.com)
+ // for more details see:
+ // http://www.knopflerfish.org/releases/current/docs/jars/upnp/upnp_api-2.0.0/src/org/osgi/service/upnp/UPnPStateVariable.java
+ static Type^ ParseType(const NPT_String& upnpType)
+ {
+ NPT_String s (upnpType);
+
+ s.MakeLowercase();
+
+ if (s == "string")
+ return String::typeid;
+
+ if (s == "char")
+ return Char::typeid;
+
+ if (s == "boolean")
+ return Boolean::typeid;
+
+ if (s == "ui1")
+ return Byte::typeid;
+
+ if (s == "ui2")
+ return UInt16::typeid;
+
+ if (s == "ui4")
+ return UInt32::typeid;
+
+ if (s == "i1")
+ return SByte::typeid;
+
+ if (s == "i2")
+ return Int16::typeid;
+
+ if ((s == "i4") || (s == "int"))
+ return Int32::typeid;
+
+ if ((s == "r4") || (s == "float"))
+ return Single::typeid;
+
+ if ((s == "r8") || (s == "number") || (s == "fixed.14.4"))
+ return Double::typeid;
+
+ if ((s == "date") || (s == "datetime") || (s == "datetime.tz"))
+ return DateTime::typeid;
+
+ if ((s == "time") || (s == "time.tz")) // milliseconds since midnight
+ return UInt64::typeid;
+
+ if ((s == "bin.base64") || (s == "bin.hex"))
+ return array<Byte>::typeid;
+
+ if (s == "uri")
+ return Uri::typeid;
+
+ if (s == "uuid")
+ return Guid::typeid;
+
+ throw gcnew ArgumentException("unknown type", "upnpType");
+ }
+
+ static Object^ ConvertValue(const NPT_String& targetType, const NPT_String& val)
+ {
+ return ConvertValue(ParseType(targetType), val);
+ }
+
+ static Object^ ConvertValue(Type^ targetType, const NPT_String& val)
+ {
+ String^ strVal = gcnew String(val);
+
+ if (targetType == String::typeid)
+ return strVal;
+
+ if (targetType == Char::typeid)
+ {
+ if (val.IsEmpty())
+ throw gcnew ArgumentException("character value is empty", "val");
+
+ return Char(val[0]);
+ }
+
+ if (targetType == Boolean::typeid)
+ return Convert::ToBoolean(strVal);
+
+ if (targetType == Byte::typeid)
+ return Convert::ToByte(strVal);
+
+ if (targetType == SByte::typeid)
+ return Convert::ToSByte(strVal);
+
+ if (targetType == UInt16::typeid)
+ return Convert::ToUInt16(strVal);
+
+ if (targetType == UInt32::typeid)
+ return Convert::ToUInt32(strVal);
+
+ if (targetType == UInt64::typeid)
+ return Convert::ToUInt64(strVal);
+
+ if (targetType == Int16::typeid)
+ return Convert::ToInt16(strVal);
+
+ if (targetType == Int32::typeid)
+ return Convert::ToInt32(strVal);
+
+ if (targetType == Int64::typeid)
+ return Convert::ToInt64(strVal);
+
+ if (targetType == Single::typeid)
+ return Convert::ToSingle(strVal);
+
+ if (targetType == Double::typeid)
+ return Convert::ToDouble(strVal);
+
+ if (targetType == DateTime::typeid)
+ return Convert::ToDateTime(strVal);
+
+ if (targetType == array<Byte>::typeid)
+ return Convert::FromBase64String(strVal);
+
+ if (targetType == Uri::typeid)
+ return marshal_as<Uri^>(val);
+
+ if (targetType == Guid::typeid)
+ return gcnew Guid(strVal);
+
+ throw gcnew ArgumentException("unsupported type", "targetType");
+ }
+
+};
+
+/*----------------------------------------------------------------------
+| StringConv
++---------------------------------------------------------------------*/
+struct StringConv
+{
+ gcroot<msclr::interop::marshal_context^> c;
+ //const char* szAnsi;
+ std::string szAnsi;
+
+ StringConv(System::String^ s) :
+ //c(gcnew msclr::interop::marshal_context),
+ //szAnsi(c->marshal_as<E_UTF8>(s))
+ szAnsi(marshalString<E_UTF8>(s))
+ {}
+
+ ~StringConv()
+ {}
+
+ operator const char*() const
+ {
+ //return szAnsi;
+ return szAnsi.c_str();
+ }
+};
+
+/*----------------------------------------------------------------------
+| StringConvA
++---------------------------------------------------------------------*/
+struct StringConvA
+{
+ char* szAnsi;
+
+ StringConvA(System::String^ s) :
+ szAnsi(static_cast<char*>(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(s).ToPointer()))
+ {}
+
+ ~StringConvA()
+ {
+
+ System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(szAnsi));
+ }
+
+ operator LPCSTR() const
+ {
+ return szAnsi;
+ }
+};
+
+/*----------------------------------------------------------------------
+| StringConvW
++---------------------------------------------------------------------*/
+struct StringConvW
+{
+ wchar_t* szUnicode;
+
+ StringConvW(System::String^ s) :
+ szUnicode(static_cast<wchar_t*>(System::Runtime::InteropServices::Marshal::StringToHGlobalUni(s).ToPointer()))
+ {}
+
+ ~StringConvW()
+ {
+
+ System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(szUnicode));
+ }
+
+ operator LPCWSTR() const
+ {
+ return szUnicode;
+ }
+};
+
+/*----------------------------------------------------------------------
+| ManagedWrapper
++---------------------------------------------------------------------*/
+template<typename T_NativeType>
+public ref class ManagedWrapper
+{
+protected:
+
+ T_NativeType* m_pHandle;
+ bool m_Owned;
+
+internal:
+
+ property T_NativeType& Handle
+ {
+ T_NativeType& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((ManagedWrapper^)obj)->m_pHandle);
+ }
+
+internal:
+
+ ManagedWrapper() : m_Owned(true)
+ {
+ m_pHandle = new T_NativeType();
+ }
+
+ /*ManagedWrapper(ManagedWrapper^ obj)
+ {
+ m_pHandle = new T_NativeType(obj->Handle);
+ }
+
+ ManagedWrapper(T_NativeType object_class) : m_Owned(true)
+ {
+ m_pHandle = new T_NativeType(object_class.Handle);
+ }*/
+
+ ManagedWrapper(T_NativeType& object_class) : m_Owned(false)
+ {
+ // IMPORTANT: we're keeping a reference of the native pointer
+ // so passing a reference to a local variable allocated on the stack is not OK
+ m_pHandle = &object_class;
+ }
+
+public:
+
+ ~ManagedWrapper()
+ {
+ this->!ManagedWrapper();
+ }
+
+ !ManagedWrapper()
+ {
+ if (m_pHandle != 0 && m_Owned)
+ {
+ delete m_pHandle;
+ }
+
+ m_pHandle = 0;
+ }
+};
+
+}
+
+#define PLATINUM_MANAGED_IMPLEMENT_PROPERTY(propertyType, propertyName, nativeVar, nativePtr) \
+property propertyType propertyName { \
+ propertyType get() { \
+ return (nativePtr##->##nativeVar); \
+ } \
+ void set(propertyType var) { \
+ nativePtr##->##nativeVar = (var); \
+ } \
+}
+
+#define PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(propertyType, propertyName, nativeVar, nativePtr) \
+property propertyType propertyName { \
+ propertyType get() { \
+ return marshal_as<propertyType>(nativePtr##->##nativeVar); \
+ } \
+ void set(propertyType var) { \
+ std::string s = marshalString<E_UTF8>(var); \
+ nativePtr##->##nativeVar = s.c_str(); \
+ } \
+}
+
+#define PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(propertyType, propertyName, nativeVar, nativePtr) \
+property propertyType propertyName { \
+ propertyType get() { \
+ return marshal_as<propertyType>(nativePtr##->##nativeVar); \
+ } \
+ void set(propertyType var) { \
+ nativePtr##->##nativeVar = var->Handle; \
+ } \
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Http.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/Http.cpp
new file mode 100644
index 0000000..155b307
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Http.cpp
@@ -0,0 +1,38 @@
+/*****************************************************************
+|
+| Platinum - Managed Http
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "Http.h"
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Http.h b/lib/libUPnP/Platinum/Source/Extras/Managed/Http.h
new file mode 100644
index 0000000..01059f4
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Http.h
@@ -0,0 +1,286 @@
+/*****************************************************************
+|
+| Platinum - Managed Http
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| HttpRequest
++---------------------------------------------------------------------*/
+public ref class HttpRequest
+{
+protected:
+
+ NPT_HttpRequest* m_pHandle;
+
+internal:
+
+ property NPT_HttpRequest& Handle
+ {
+ NPT_HttpRequest& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((HttpRequest^)obj)->m_pHandle);
+ }
+
+public:
+
+ // properties
+ virtual property Uri^ URI
+ {
+ Uri^ get()
+ {
+ return marshal_as<Uri^>(m_pHandle->GetUrl());
+ }
+ }
+
+internal:
+
+ // Note: Because a NPT_HttpRequest cannot do a deep copy,
+ // this only refers to the original native object
+ HttpRequest(NPT_HttpRequest& native) :
+ m_pHandle(&native)
+ {
+ }
+
+public:
+
+ ~HttpRequest()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!HttpRequest();
+ }
+
+ !HttpRequest()
+ {
+ // clean-up unmanaged
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::HttpRequest, NPT_HttpRequest);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| HttpRequest
++---------------------------------------------------------------------*/
+public ref class HttpResponse
+{
+protected:
+
+ NPT_HttpResponse* m_pHandle;
+
+internal:
+
+ property NPT_HttpResponse& Handle
+ {
+ NPT_HttpResponse& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((HttpResponse^)obj)->m_pHandle);
+ }
+
+internal:
+
+ // Note: Because a NPT_HttpResponse cannot do a deep copy,
+ // this only refers to the original native object
+ HttpResponse(NPT_HttpResponse& native) :
+ m_pHandle(&native)
+ {
+ }
+
+public:
+
+ ~HttpResponse()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!HttpResponse();
+ }
+
+ !HttpResponse()
+ {
+ // clean-up unmanaged
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::HttpResponse, NPT_HttpResponse);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| DeviceSignature
++---------------------------------------------------------------------*/
+public enum class DeviceSignature
+{
+ Unknown,
+ XBox,
+ PS3,
+ WMP
+};
+
+/*----------------------------------------------------------------------
+| HttpRequestContext
++---------------------------------------------------------------------*/
+public ref class HttpRequestContext : ManagedWrapper<PLT_HttpRequestContext>
+{
+
+public:
+
+ ref struct SocketAddress {
+ String^ ip;
+ UInt32 port;
+ };
+
+ virtual property SocketAddress^ LocalAddress
+ {
+ SocketAddress^ get()
+ {
+ SocketAddress^ local = gcnew SocketAddress;
+ local->ip = marshal_as<String^>(Handle.GetLocalAddress().GetIpAddress().ToString());
+ local->port = Handle.GetLocalAddress().GetPort();
+ return local;
+ }
+ }
+
+ virtual property SocketAddress^ RemoteAddress
+ {
+ SocketAddress^ get()
+ {
+ SocketAddress^ local = gcnew SocketAddress;
+ local->ip = marshal_as<String^>(Handle.GetRemoteAddress().GetIpAddress().ToString());
+ local->port = Handle.GetRemoteAddress().GetPort();
+ return local;
+ }
+ }
+
+ virtual property HttpRequest^ Request
+ {
+ HttpRequest^ get()
+ {
+ return marshal_as<HttpRequest^>(m_pHandle->GetRequest());
+ }
+ }
+
+ virtual property DeviceSignature Signature
+ {
+ DeviceSignature get()
+ {
+ return ParseDeviceSignature(m_pHandle->GetDeviceSignature());
+ }
+ }
+private:
+
+ static DeviceSignature ParseDeviceSignature(PLT_DeviceSignature signature)
+ {
+ switch (signature)
+ {
+ case PLT_DEVICE_XBOX:
+ return DeviceSignature::XBox;
+ case PLT_DEVICE_PS3:
+ return DeviceSignature::PS3;
+ case PLT_DEVICE_WMP:
+ return DeviceSignature::WMP;
+ default:
+ return DeviceSignature::Unknown;
+ }
+ }
+
+
+internal:
+
+ HttpRequestContext(PLT_HttpRequestContext& native) :
+ ManagedWrapper<PLT_HttpRequestContext>(native)
+ {
+ }
+
+ ~HttpRequestContext()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!HttpRequestContext();
+ }
+
+ !HttpRequestContext()
+ {
+ // clean-up unmanaged
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::HttpRequestContext, PLT_HttpRequestContext);
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.cpp
new file mode 100644
index 0000000..f31b433
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.cpp
@@ -0,0 +1,59 @@
+/*****************************************************************
+|
+| Platinum - Managed MediaConnect
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "MediaConnect.h"
+#include "PltMediaConnect.h"
+
+Platinum::MediaConnect::MediaConnect(PLT_MediaConnect* server) :
+ MediaServer((PLT_MediaServer*)server)
+{
+}
+
+Platinum::MediaConnect::MediaConnect(String^ friendlyName) :
+ MediaServer(new PLT_MediaConnect(StringConv(friendlyName)))
+{
+}
+
+Platinum::MediaConnect::MediaConnect(String^ friendlyName, String^ uuid, Int16 port) :
+ MediaServer(new PLT_MediaConnect(StringConv(friendlyName), true, StringConv(uuid), port))
+{
+}
+
+Platinum::MediaConnect::!MediaConnect()
+{
+
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.h b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.h
new file mode 100644
index 0000000..54a9ec4
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaConnect.h
@@ -0,0 +1,80 @@
+/*****************************************************************
+|
+| Platinum - Managed MediaConnect
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "MediaServer.h"
+
+class PLT_MediaConnect;
+
+namespace Platinum
+{
+
+ref class MediaServer;
+
+/*----------------------------------------------------------------------
+| MediaConnect
++---------------------------------------------------------------------*/
+public ref class MediaConnect : public MediaServer
+{
+public:
+
+private:
+
+
+public:
+
+ // properties
+
+private:
+
+public:
+
+ MediaConnect(String^ friendlyName);
+ MediaConnect(String^ friendlyName, String^ uuid, Int16 port);
+ MediaConnect(PLT_MediaConnect* server);
+
+ ~MediaConnect()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!MediaConnect();
+ }
+
+ !MediaConnect();
+};
+
+} \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.cpp
new file mode 100644
index 0000000..23b56a7
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.cpp
@@ -0,0 +1,118 @@
+/*****************************************************************
+|
+| Platinum - Managed MediaObject
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "MediaObject.h"
+#include "EnumerableNptArray.h"
+#include "EnumerableNptList.h"
+
+IEnumerable<Platinum::PersonRole^>^ Platinum::PeopleInfo::Actors::get()
+{
+ return gcnew Enumerables::EnumerableNptListRef<PersonRole^, PLT_PersonRole>(
+ m_pHandle->actors
+ );
+}
+
+IEnumerable<Platinum::PersonRole^>^ Platinum::PeopleInfo::Artists::get()
+{
+ return gcnew Enumerables::EnumerableNptListRef<PersonRole^, PLT_PersonRole>(
+ m_pHandle->artists
+ );
+}
+
+IEnumerable<Platinum::PersonRole^>^ Platinum::PeopleInfo::Authors::get()
+{
+ return gcnew Enumerables::EnumerableNptListRef<PersonRole^, PLT_PersonRole>(
+ m_pHandle->authors
+ );
+}
+
+IEnumerable<System::String^>^ Platinum::AffiliationInfo::Genres::get()
+{
+ return gcnew Enumerables::EnumerableNptListRef<String^, NPT_String>(
+ m_pHandle->genres
+ );
+}
+
+IEnumerable<System::String^>^ Platinum::ExtraInfo::Relations::get()
+{
+ return gcnew Enumerables::EnumerableNptListRef<String^, NPT_String>(
+ m_pHandle->relations
+ );
+}
+
+IEnumerable<Platinum::AlbumArtInfo^>^ Platinum::ExtraInfo::AlbumArts::get()
+{
+ return gcnew Enumerables::EnumerableNptListRef<AlbumArtInfo^, PLT_AlbumArtInfo>(
+ m_pHandle->album_arts
+ );
+}
+
+
+Platinum::ProtocolInfo^ Platinum::ProtocolInfo::GetProtocolInfo(String^ filename,
+ bool with_dlna_extension,
+ HttpRequestContext^ context)
+{
+ return marshal_as<Platinum::ProtocolInfo^>(PLT_ProtocolInfo::GetProtocolInfo(StringConv(filename),
+ with_dlna_extension,
+ (context==nullptr)?NULL:&context->Handle).ToString());
+}
+
+Platinum::ProtocolInfo^ Platinum::ProtocolInfo::GetProtocolInfoFromMimeType(String^ mime_type,
+ bool with_dlna_extension,
+ HttpRequestContext^ context)
+{
+ return marshal_as<Platinum::ProtocolInfo^>(PLT_ProtocolInfo::GetProtocolInfoFromMimeType(StringConv(mime_type),
+ with_dlna_extension,
+ (context==nullptr)?NULL:&context->Handle).ToString());
+}
+
+Platinum::MediaItem^ Platinum::MediaObject::item()
+{
+ return gcnew MediaItem(this);
+}
+
+Platinum::MediaContainer^ Platinum::MediaObject::container()
+{
+ return gcnew MediaContainer(this);
+}
+
+IEnumerable<Platinum::MediaResource^>^ Platinum::MediaObject::Resources::get()
+{
+ return gcnew Enumerables::EnumerableNptArrayRef<MediaResource^, PLT_MediaItemResource>(
+ (*m_pHandle)->m_Resources
+ );
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.h b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.h
new file mode 100644
index 0000000..11ebfce
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaObject.h
@@ -0,0 +1,735 @@
+/*****************************************************************
+|
+| Platinum - Managed ActionDescription
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMediaItem.h"
+#include "Http.h"
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| ObjectClass
++---------------------------------------------------------------------*/
+public ref class ObjectClass : public ManagedWrapper<PLT_ObjectClass>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Type, type, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, FriendlyName, friendly_name, m_pHandle);
+
+internal:
+
+ ObjectClass(PLT_ObjectClass& native) :
+ ManagedWrapper<PLT_ObjectClass>(native)
+ {}
+
+public:
+
+ ObjectClass(String^ type)
+ {
+ Type = type;
+ }
+
+ ObjectClass(String^ type, String^ friendly_name)
+ {
+ Type = type;
+ FriendlyName = friendly_name;
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::ObjectClass, PLT_ObjectClass);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| PersonRole
++---------------------------------------------------------------------*/
+public ref class PersonRole : public ManagedWrapper<PLT_PersonRole>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Name, name, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Role, role, m_pHandle);
+
+internal:
+
+ PersonRole(PLT_PersonRole& native) :
+ ManagedWrapper<PLT_PersonRole>(native)
+ {}
+
+public:
+ PersonRole(String^ name)
+ {
+ Name = name;
+ }
+
+ PersonRole(String^ name, String^ role)
+ {
+ Name = name;
+ Role = role;
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::PersonRole, PLT_PersonRole);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| PeopleInfo
++---------------------------------------------------------------------*/
+public ref class PeopleInfo : public ManagedWrapper<PLT_PeopleInfo>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Producer, producer, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Director, director, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Publisher, publisher, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Contributor, contributor, m_pHandle);
+
+ property IEnumerable<PersonRole^>^ Artists
+ {
+ IEnumerable<PersonRole^>^ get();
+ }
+
+ property IEnumerable<PersonRole^>^ Actors
+ {
+ IEnumerable<PersonRole^>^ get();
+ }
+
+ property IEnumerable<PersonRole^>^ Authors
+ {
+ IEnumerable<PersonRole^>^ get();
+ }
+
+public:
+
+ void AddArtist(PersonRole^ artist)
+ {
+ ((NPT_List<PLT_PersonRole>&)m_pHandle->artists).Add(artist->Handle);
+ }
+
+ void AddActor(PersonRole^ actor)
+ {
+ ((NPT_List<PLT_PersonRole>&)m_pHandle->actors).Add(actor->Handle);
+ }
+
+ void AddAuthors(PersonRole^ author)
+ {
+ ((NPT_List<PLT_PersonRole>&)m_pHandle->authors).Add(author->Handle);
+ }
+
+internal:
+
+ PeopleInfo(PLT_PeopleInfo& native) :
+ ManagedWrapper<PLT_PeopleInfo>(native)
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::PeopleInfo, PLT_PeopleInfo);
+
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| AffiliationInfo
++---------------------------------------------------------------------*/
+public ref class AffiliationInfo : public ManagedWrapper<PLT_AffiliationInfo>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Album, album, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Playlist, playlist, m_pHandle);
+
+ property IEnumerable<String^>^ Genres
+ {
+ IEnumerable<String^>^ get();
+ }
+
+public:
+
+ void AddGenre(String^ genre)
+ {
+ m_pHandle->genres.Add(NPT_String(StringConv(genre)));
+ }
+
+internal:
+
+ AffiliationInfo(PLT_AffiliationInfo& native) :
+ ManagedWrapper<PLT_AffiliationInfo>(native)
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::AffiliationInfo, PLT_AffiliationInfo);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| DescriptionInfo
++---------------------------------------------------------------------*/
+public ref class DescriptionInfo : public ManagedWrapper<PLT_Description>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, DescriptionText, description, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, LongDescriptionText, long_description, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, IconUri, icon_uri, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Region, region, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Rating, rating, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Date, date, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Language, language, m_pHandle);
+
+internal:
+
+ DescriptionInfo(PLT_Description& native) :
+ ManagedWrapper<PLT_Description>(native)
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::DescriptionInfo, PLT_Description);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| RecordedInfo
++---------------------------------------------------------------------*/
+public ref class RecordedInfo : public ManagedWrapper<PLT_RecordedInfo>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, ProgramTitle, program_title, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, SeriesTitle, series_title, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, EpisodeNumber, episode_number, m_pHandle);
+
+internal:
+
+ RecordedInfo(PLT_RecordedInfo& native) :
+ ManagedWrapper<PLT_RecordedInfo>(native)
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::RecordedInfo, PLT_RecordedInfo);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| AlbumArtInfo
++---------------------------------------------------------------------*/
+public ref class AlbumArtInfo : public ManagedWrapper<PLT_AlbumArtInfo>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Uri, uri, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, DlnaProfile, dlna_profile, m_pHandle);
+
+internal:
+
+ AlbumArtInfo(PLT_AlbumArtInfo& native) :
+ ManagedWrapper<PLT_AlbumArtInfo>(native)
+ {}
+
+public:
+ AlbumArtInfo(String^ uri)
+ {
+ Uri = uri;
+ }
+
+ AlbumArtInfo(String^ uri, String^ dlna_profile)
+ {
+ Uri = uri;
+ DlnaProfile = dlna_profile;
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::AlbumArtInfo, PLT_AlbumArtInfo);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| ExtraInfo
++---------------------------------------------------------------------*/
+public ref class ExtraInfo : public ManagedWrapper<PLT_ExtraInfo>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, ArtistDiscographyUri, artist_discography_uri, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, LyricsUri, lyrics_uri, m_pHandle);
+
+ property IEnumerable<String^>^ Relations
+ {
+ IEnumerable<String^>^ get();
+ }
+
+ property IEnumerable<AlbumArtInfo^>^ AlbumArts
+ {
+ IEnumerable<AlbumArtInfo^>^ get();
+ }
+
+public:
+
+ void AddGenre(String^ relation)
+ {
+ m_pHandle->relations.Add(NPT_String(StringConv(relation)));
+ }
+
+ void AddAlbumArtInfo(AlbumArtInfo^ info)
+ {
+ m_pHandle->album_arts.Add(info->Handle);
+ }
+
+
+internal:
+
+ ExtraInfo(PLT_ExtraInfo& native) :
+ ManagedWrapper<PLT_ExtraInfo>(native)
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::ExtraInfo, PLT_ExtraInfo);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| MiscInfo
++---------------------------------------------------------------------*/
+public ref class MiscInfo : public ManagedWrapper<PLT_MiscInfo>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, DvdRegionCode, dvdregioncode, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, OriginalTrackNumber, original_track_number, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Toc, toc, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, UserAnnotation, user_annotation, m_pHandle);
+
+internal:
+
+ MiscInfo(PLT_MiscInfo& native) :
+ ManagedWrapper<PLT_MiscInfo>(native)
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::MiscInfo, PLT_MiscInfo);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| ProtocolInfo
++---------------------------------------------------------------------*/
+public ref class ProtocolInfo : public ManagedWrapper<PLT_ProtocolInfo>
+{
+public:
+
+ // properties
+
+public:
+ static ProtocolInfo^ GetProtocolInfo(String^ filename)
+ {
+ return GetProtocolInfo(filename, true, nullptr);
+ }
+
+ static ProtocolInfo^ GetProtocolInfo(String^ filename,
+ bool with_dlna_extension)
+ {
+ return GetProtocolInfo(filename, with_dlna_extension, nullptr);
+ }
+
+ static ProtocolInfo^ GetProtocolInfo(String^ filename,
+ bool with_dlna_extension,
+ HttpRequestContext^ context);
+
+ static ProtocolInfo^ GetProtocolInfoFromMimeType(String^ mime_type)
+ {
+ return GetProtocolInfoFromMimeType(mime_type, true, nullptr);
+ }
+
+ static ProtocolInfo^ GetProtocolInfoFromMimeType(String^ mime_type,
+ bool with_dlna_extension)
+ {
+ return GetProtocolInfoFromMimeType(mime_type, with_dlna_extension, nullptr);
+ }
+
+ static ProtocolInfo^ GetProtocolInfoFromMimeType(String^ mime_type,
+ bool with_dlna_extension,
+ HttpRequestContext^ context);
+
+internal:
+
+ ProtocolInfo(PLT_ProtocolInfo& native) :
+ ManagedWrapper<PLT_ProtocolInfo>(native)
+ {}
+
+public:
+
+ ProtocolInfo(NPT_String& protocol_info) :
+ ManagedWrapper<PLT_ProtocolInfo>()
+ {
+ *m_pHandle = PLT_ProtocolInfo(protocol_info);
+ }
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::ProtocolInfo, PLT_ProtocolInfo);
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::ProtocolInfo, NPT_String);
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| MediaResource
++---------------------------------------------------------------------*/
+public ref class MediaResource : public ManagedWrapper<PLT_MediaItemResource>
+{
+public:
+
+ // properties
+
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, URI, m_Uri, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(ProtocolInfo^, ProtoInfo, m_ProtocolInfo, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, Duration, m_Duration, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt64, Size, m_Size, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Protection, m_Protection, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, Bitrate, m_Bitrate, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, BitsPerSample, m_BitsPerSample, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, SampleFrequency, m_SampleFrequency, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, NbAudioChannels, m_NbAudioChannels, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Resolution, m_Resolution, m_pHandle);
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, ColorDepth, m_ColorDepth, m_pHandle);
+
+internal:
+
+ MediaResource(PLT_MediaItemResource& native) :
+ ManagedWrapper<PLT_MediaItemResource>(native)
+ {}
+
+public:
+ MediaResource() :
+ ManagedWrapper<PLT_MediaItemResource>()
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::MediaResource, PLT_MediaItemResource);
+
+namespace Platinum
+{
+ref class MediaItem;
+ref class MediaContainer;
+
+/*----------------------------------------------------------------------
+| MediaObject
++---------------------------------------------------------------------*/
+public ref class MediaObject
+{
+protected:
+
+ PLT_MediaObjectReference* m_pHandle;
+
+public:
+
+ // properties
+
+ /* common properties */
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(ObjectClass^, Class, m_ObjectClass, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, ObjectID, m_ObjectID, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, ParentID, m_ParentID, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, ReferenceID, m_ReferenceID, (*m_pHandle));
+
+ /* metadata */
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Title, m_Title, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Creator, m_Creator, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_STRING_PROPERTY(String^, Date, m_Date, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(PeopleInfo^, People, m_People, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(AffiliationInfo^, Affiliation, m_Affiliation, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(DescriptionInfo^, Description, m_Description, (*m_pHandle));
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(RecordedInfo^, Recorded, m_Recorded, (*m_pHandle));
+
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(bool, Restricted, m_Restricted, (*m_pHandle));
+
+ /* extras */
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(ExtraInfo^, Extra, m_ExtraInfo, (*m_pHandle));
+
+ /* miscellaneous info */
+ PLATINUM_MANAGED_IMPLEMENT_OBJECT_PROPERTY(MiscInfo^, Miscellaneous, m_MiscInfo, (*m_pHandle));
+
+ property IEnumerable<MediaResource^>^ Resources
+ {
+ IEnumerable<MediaResource^>^ get();
+ }
+
+public:
+
+ void AddResource(MediaResource^ resource)
+ {
+ (*m_pHandle)->m_Resources.Add(resource->Handle);
+ }
+
+internal:
+
+ property PLT_MediaObjectReference& Handle
+ {
+ PLT_MediaObjectReference& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ MediaItem^ item();
+ MediaContainer^ container();
+
+ String^ ToDidl(String^ filter)
+ {
+ NPT_String didl;
+ didl.Reserve(1024);
+
+ marshal_context c;
+ NPT_String _filter(c.marshal_as<const char*>(filter));
+
+ (*m_pHandle)->ToDidl(_filter, didl);
+
+ return marshal_as<String^>(didl.GetChars());
+ }
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (*m_pHandle == *((MediaObject^)obj)->m_pHandle);
+ }
+
+internal:
+
+ MediaObject(PLT_MediaObjectReference& media)
+ {
+ if (media.IsNull())
+ throw gcnew ArgumentNullException("media");
+
+ m_pHandle = new PLT_MediaObjectReference(media);
+ }
+
+ MediaObject(PLT_MediaObject& media)
+ {
+ m_pHandle = new PLT_MediaObjectReference(&media);
+ }
+
+protected:
+
+ MediaObject(PLT_MediaObject* media)
+ {
+ if (media == NULL)
+ throw gcnew ArgumentNullException("media");
+
+ m_pHandle = new PLT_MediaObjectReference(media);
+ }
+
+public:
+
+ ~MediaObject()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!MediaObject();
+ }
+
+ !MediaObject()
+ {
+ // clean-up unmanaged
+ if (m_pHandle != 0)
+ {
+ delete m_pHandle;
+
+ m_pHandle = 0;
+ }
+ }
+
+};
+
+/*----------------------------------------------------------------------
+| MediaItem
++---------------------------------------------------------------------*/
+public ref class MediaItem : public MediaObject
+{
+internal:
+
+ MediaItem(PLT_MediaItem& media) : MediaObject(media)
+ {}
+
+public:
+
+ MediaItem() : MediaObject(new PLT_MediaItem)
+ {}
+
+ MediaItem(PLT_MediaObjectReference& media) : MediaObject(media)
+ {
+ if (media->IsContainer())
+ throw gcnew ArgumentException("object");
+ }
+
+ MediaItem(MediaObject^ media) : MediaObject(*media->Handle)
+ {
+ if (media->Handle->IsContainer())
+ throw gcnew ArgumentException("object");
+ }
+
+ ~MediaItem()
+ {
+ this->!MediaItem();
+ }
+
+ !MediaItem()
+ {}
+};
+
+/*----------------------------------------------------------------------
+| MediaContainer
++---------------------------------------------------------------------*/
+public ref class MediaContainer : public MediaObject
+{
+public:
+
+ // properties
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(bool, Searchable, m_Searchable, ((PLT_MediaContainer*)m_pHandle->AsPointer()));
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(Int32, ChildrenCount, m_ChildrenCount, ((PLT_MediaContainer*)m_pHandle->AsPointer()));
+ PLATINUM_MANAGED_IMPLEMENT_PROPERTY(UInt32, ContainerUpdateID, m_ContainerUpdateID, ((PLT_MediaContainer*)m_pHandle->AsPointer()));
+
+internal:
+
+ MediaContainer(PLT_MediaContainer& media) :
+ MediaObject(media)
+ {}
+
+public:
+ MediaContainer() :
+ MediaObject(new PLT_MediaContainer)
+ {}
+
+ MediaContainer(PLT_MediaObjectReference& media) :
+ MediaObject(media)
+ {
+ if (!media->IsContainer())
+ throw gcnew ArgumentException("object");
+ }
+
+ MediaContainer(MediaObject^ media) :
+ MediaObject(*media->Handle)
+ {
+ if (!media->Handle->IsContainer())
+ throw gcnew ArgumentException("object");
+ }
+
+ ~MediaContainer()
+ {
+ this->!MediaContainer();
+ }
+
+ !MediaContainer()
+ {}
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::MediaObject, PLT_MediaObject);
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::MediaObject, PLT_MediaObjectReference);
+
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::MediaItem, PLT_MediaItem);
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::MediaContainer, PLT_MediaContainer); \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.cpp
new file mode 100644
index 0000000..0ecf275
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.cpp
@@ -0,0 +1,121 @@
+/*****************************************************************
+|
+| Platinum - Managed MediaServer
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "PltMimeType.h"
+#include "MediaServer.h"
+#include "DeviceHost.h"
+#include "MediaServerEventBridge.h"
+
+Platinum::MediaServer::MediaServer(PLT_MediaServer* server) :
+ DeviceHost(*(server))
+{
+ RegisterEvents();
+}
+
+Platinum::MediaServer::MediaServer(String^ friendlyName) :
+ DeviceHost(*(new PLT_MediaServer(StringConv(friendlyName))))
+{
+ RegisterEvents();
+}
+
+Platinum::MediaServer::MediaServer(String^ friendlyName, String^ uuid) :
+ DeviceHost(*(new PLT_MediaServer(StringConv(friendlyName), false, StringConv(uuid))))
+{
+ RegisterEvents();
+}
+
+void Platinum::MediaServer::RegisterEvents()
+{
+ if (!m_pBridge)
+ {
+ m_pBridge = new MediaServerEventBridge(this);
+ }
+
+ PLT_MediaServer* server = (PLT_MediaServer*)(Handle.AsPointer());
+ server->SetDelegate(m_pBridge);
+}
+
+Platinum::MediaServer::!MediaServer()
+{
+
+}
+
+void Platinum::MediaServer::UpdateSystemUpdateID(Int32 update)
+{
+ PLT_MediaServer* server = (PLT_MediaServer*)(Handle.AsPointer());
+ server->UpdateSystemUpdateID(update);
+}
+
+
+void Platinum::MediaServer::UpdateContainerUpdateID(String^ id, Int32 update)
+{
+ PLT_MediaServer* server = (PLT_MediaServer*)(Handle.AsPointer());
+ server->UpdateContainerUpdateID(StringConv(id), update);
+}
+
+Int32 Platinum::MediaServer::SetResponseFilePath(HttpRequestContext^ context, HttpResponse^ response, String^ filepath)
+{
+ NPT_CHECK_WARNING(PLT_HttpServer::ServeFile(context->Request->Handle,
+ context->Handle,
+ response->Handle,
+ NPT_String(StringConv(filepath))));
+
+ /* Update content type header according to file and context */
+ NPT_HttpEntity* entity = response->Handle.GetEntity();
+ if (entity) entity->SetContentType(
+ PLT_MimeType::GetMimeType(NPT_String(StringConv(filepath)),
+ &context->Handle));
+
+ /* streaming header for DLNA */
+ response->Handle.GetHeaders().SetHeader("transferMode.dlna.org", "Streaming");
+ return NPT_SUCCESS;
+}
+
+
+Int32 Platinum::MediaServer::SetResponseData(HttpRequestContext^ context, HttpResponse^ response, array<Byte>^ data)
+{
+ NPT_HttpEntity* entity = response->Handle.GetEntity();
+ if (entity)
+ {
+ pin_ptr<Byte> pinnedBuffer = &data[0];
+ entity->SetInputStream((const void*)pinnedBuffer, data->Length);
+ }
+
+ /* interactive header for DLNA ?*/
+ response->Handle.GetHeaders().SetHeader("transferMode.dlna.org", "Interactive");
+ return NPT_SUCCESS;
+} \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.h b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.h
new file mode 100644
index 0000000..ad78319
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServer.h
@@ -0,0 +1,131 @@
+/*****************************************************************
+|
+| Platinum - Managed MediaServer
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "DeviceHost.h"
+#include "Http.h"
+
+class PLT_MediaServer;
+
+namespace Platinum
+{
+
+ref class DeviceHost;
+ref class Action;
+class MediaServerEventBridge;
+
+/*----------------------------------------------------------------------
+| MediaServer
++---------------------------------------------------------------------*/
+public ref class MediaServer : public DeviceHost
+{
+public:
+
+ delegate Int32 BrowseMetadataDelegate(Action^ action, String^ object_id, String^ filter, Int32 starting_index, Int32 requested_count, String^ sort_criteria, HttpRequestContext^ context);
+ delegate Int32 BrowseDirectChildrenDelegate(Action^ action, String^ object_id, String^ filter, Int32 starting_index, Int32 requested_count, String^ sort_criteria, HttpRequestContext^ context);
+ delegate Int32 SearchContainerDelegate(Action^ action, String^ object_id, String^ searchCriteria, String^ filter, Int32 starting_index, Int32 requested_count, String^ sort_criteria, HttpRequestContext^ context);
+ delegate Int32 ProcessFileRequestDelegate(HttpRequestContext^ context, HttpResponse^ response);
+
+private:
+
+ MediaServerEventBridge* m_pBridge;
+
+public:
+
+ // properties
+
+private:
+
+ void RegisterEvents();
+
+public:
+
+ event BrowseMetadataDelegate^ BrowseMetadata;
+ event BrowseDirectChildrenDelegate^ BrowseDirectChildren;
+ event SearchContainerDelegate^ SearchContainer;
+ event ProcessFileRequestDelegate^ ProcessFileRequest;
+
+
+internal:
+
+ Int32 OnBrowseMetadataDelegate(Action^ action, String^ object_id, String^ filter, Int32 starting_index, Int32 requested_count, String^ sort_criteria, HttpRequestContext^ context)
+ {
+ // handle events
+ return this->BrowseMetadata(action, object_id, filter, starting_index, requested_count, sort_criteria, context);
+ }
+
+ Int32 OnBrowseDirectChildrenDelegate(Action^ action, String^ object_id, String^ filter, Int32 starting_index, Int32 requested_count, String^ sort_criteria, HttpRequestContext^ context)
+ {
+ // handle events
+ return this->BrowseDirectChildren(action, object_id, filter, starting_index, requested_count, sort_criteria, context);
+ }
+
+ Int32 OnSearchContainerDelegate(Action^ action, String^ object_id, String^ searchCriteria, String^ filter, Int32 starting_index, Int32 requested_count, String^ sort_criteria, HttpRequestContext^ context)
+ {
+ // handle events
+ return this->SearchContainer(action, object_id, searchCriteria, filter, starting_index, requested_count, sort_criteria, context);
+ }
+
+ Int32 OnProcessFileRequestDelegate(HttpRequestContext^ context, HttpResponse^ response)
+ {
+ return this->ProcessFileRequest(context, response);
+ }
+
+public:
+
+ MediaServer(String^ friendlyName);
+ MediaServer(String^ friendlyName, String^ uuid);
+ MediaServer(PLT_MediaServer* server);
+
+ void UpdateSystemUpdateID(Int32 update);
+ void UpdateContainerUpdateID(String^ id, Int32 update);
+
+ ~MediaServer()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!MediaServer();
+ }
+
+ !MediaServer();
+
+
+ static Int32 SetResponseFilePath(HttpRequestContext^ context, HttpResponse^ response, String^ filepath);
+ static Int32 SetResponseData(HttpRequestContext^ context, HttpResponse^ response, array<Byte>^ data);
+};
+
+} \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.cpp
new file mode 100644
index 0000000..32da39a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.cpp
@@ -0,0 +1,103 @@
+/*****************************************************************
+|
+| Platinum - Managed MediaServerEventBridge
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "MediaServerEventBridge.h"
+#include "MediaServer.h"
+#include "Action.h"
+
+NPT_Result Platinum::MediaServerEventBridge::OnBrowseMetadata(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ return m_pMediaServer->OnBrowseMetadataDelegate(marshal_as<Action^>(action),
+ marshal_as<String^>(object_id),
+ marshal_as<String^>(filter),
+ starting_index,
+ requested_count,
+ marshal_as<String^>(sort_criteria),
+ marshal_as<HttpRequestContext^>(context));
+}
+
+NPT_Result Platinum::MediaServerEventBridge::OnBrowseDirectChildren(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+ return m_pMediaServer->OnBrowseDirectChildrenDelegate(marshal_as<Action^>(action),
+ marshal_as<String^>(object_id),
+ marshal_as<String^>(filter),
+ starting_index,
+ requested_count,
+ marshal_as<String^>(sort_criteria),
+ marshal_as<HttpRequestContext^>(context));
+}
+
+NPT_Result Platinum::MediaServerEventBridge::OnSearchContainer(PLT_ActionReference& action,
+ const char* object_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context)
+{
+
+ return m_pMediaServer->OnSearchContainerDelegate(marshal_as<Action^>(action),
+ marshal_as<String^>(object_id),
+ marshal_as<String^>(search_criteria),
+ marshal_as<String^>(filter),
+ starting_index,
+ requested_count,
+ marshal_as<String^>(sort_criteria),
+ marshal_as<HttpRequestContext^>(context));
+}
+
+NPT_Result Platinum::MediaServerEventBridge::ProcessFileRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ PLT_HttpRequestContext _context(request, context);
+ return m_pMediaServer->OnProcessFileRequestDelegate(marshal_as<HttpRequestContext^>(_context),
+ marshal_as<HttpResponse^>(response));
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.h b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.h
new file mode 100644
index 0000000..ca13044
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/MediaServerEventBridge.h
@@ -0,0 +1,97 @@
+/*****************************************************************
+|
+| Platinum - Managed MediaServerEventBridge
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#pragma once
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMediaServer.h"
+
+namespace Platinum
+{
+
+ref class MediaServer;
+
+/*----------------------------------------------------------------------
+| MediaServerEventBridge
++---------------------------------------------------------------------*/
+private class MediaServerEventBridge : public PLT_MediaServerDelegate
+{
+private:
+
+ gcroot<MediaServer^> m_pMediaServer;
+
+public:
+
+ // PLT_MediaServerDelegate methods
+ virtual NPT_Result OnBrowseMetadata(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnBrowseDirectChildren(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result OnSearchContainer(PLT_ActionReference& action,
+ const char* object_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context);
+ virtual NPT_Result ProcessFileRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response);
+
+public:
+
+ MediaServerEventBridge(gcroot<MediaServer^> server)
+ {
+ m_pMediaServer = server;
+ }
+
+ virtual ~MediaServerEventBridge()
+ {}
+
+};
+
+
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Neptun_marshal_as.h b/lib/libUPnP/Platinum/Source/Extras/Managed/Neptun_marshal_as.h
new file mode 100644
index 0000000..429be7d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Neptun_marshal_as.h
@@ -0,0 +1,104 @@
+/*****************************************************************
+|
+| Platinum - Managed Marshalling
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace msclr {
+namespace interop {
+
+// -------------------------- NPT_IpAddress -------
+
+template<>
+inline String^ marshal_as<String^, NPT_IpAddress> (const NPT_IpAddress& from)
+{
+ return gcnew String(from.ToString());
+}
+
+// -------------------------- NPT_HttpUrl -------
+
+template<>
+inline Uri^ marshal_as<Uri^, NPT_HttpUrl> (const NPT_HttpUrl& from)
+{
+ if (!from.IsValid())
+ return nullptr;
+
+ return gcnew Uri(gcnew String(from.ToString()));
+}
+
+// -------------------------- NPT_String -------
+
+template<>
+inline Uri^ marshal_as<Uri^, NPT_String> (const NPT_String& from)
+{
+ if (from.IsEmpty())
+ return nullptr;
+
+ return gcnew Uri(gcnew String(from));
+}
+
+template<>
+inline String^ marshal_as<String^, NPT_String> (const NPT_String& from)
+{
+ return gcnew String(from);
+}
+
+// -------------------------- PLT_ProtocolInfo -------
+
+template<>
+inline String^ marshal_as<String^, PLT_ProtocolInfo> (const PLT_ProtocolInfo& from)
+{
+ return gcnew String(from.ToString());
+}
+
+// -------------------------- NPT_TimeInterval -------
+
+template<>
+inline TimeSpan marshal_as<TimeSpan, NPT_TimeInterval> (const NPT_TimeInterval& from)
+{
+ return TimeSpan(from.ToSeconds() * TimeSpan::TicksPerSecond);
+}
+
+// ---------------------------------------------
+
+
+}}
+
+
+// -------------------------- generic wrapper marshal macro -------
+
+#define PLATINUM_MANAGED_MARSHAL_AS(dotNetType,nativeType) \
+ namespace msclr { namespace interop { \
+ template<> \
+ inline dotNetType^ marshal_as<dotNetType^, nativeType> (const nativeType& from) \
+ { return gcnew dotNetType(const_cast<nativeType&>(from)); } \
+ }}
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.cpp
new file mode 100644
index 0000000..aef0fee
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.cpp
@@ -0,0 +1,39 @@
+/*****************************************************************
+|
+| Platinum - Managed NeptuneException
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "NeptuneException.h"
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.h b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.h
new file mode 100644
index 0000000..04c943d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneException.h
@@ -0,0 +1,64 @@
+/*****************************************************************
+|
+| Platinum - Managed NeptuneException
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| NeptuneException
++---------------------------------------------------------------------*/
+[Serializable]
+public ref class NeptuneException : Exception
+{
+private:
+
+ int m_err;
+
+public:
+
+ property int ErrorResult
+ {
+ int get() { return m_err; }
+ }
+
+public:
+
+ NeptuneException(NPT_Result r)
+ : Exception(gcnew String(NPT_ResultText(r))), m_err(r)
+ {
+ }
+
+};
+
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.cpp
new file mode 100644
index 0000000..d69f5eb
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.cpp
@@ -0,0 +1,38 @@
+/*****************************************************************
+|
+| Platinum - Managed NeptuneLoggingBridge
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "NeptuneLoggingBridge.h"
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.h b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.h
new file mode 100644
index 0000000..920dd3d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/NeptuneLoggingBridge.h
@@ -0,0 +1,207 @@
+/*****************************************************************
+|
+| Platinum - Managed NeptuneLoggingBridge
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+using namespace log4net;
+
+namespace Platinum
+{
+
+/*----------------------------------------------------------------------
+| NeptuneLoggingBridge
++---------------------------------------------------------------------*/
+class NeptuneLoggingBridge : NPT_LogHandler
+{
+private:
+
+ NPT_Mutex m_SetLoggerNameLock;
+ gcroot<String^> m_pFormatString;
+ gcroot<ILog^> m_pLogger;
+
+public:
+
+ static void Configure()
+ {
+ static NPT_Mutex lock;
+
+ lock.Lock();
+
+ static NeptuneLoggingBridge instance;
+
+ // clear config
+ NPT_LogManager::GetDefault().Configure("plist:.level=ALL;.handlers=;platinum.level=ALL;platinum.handlers=");
+
+ // get root logger
+ NPT_Logger* rootLogger = NPT_LogManager::GetLogger("platinum");
+
+ if (rootLogger)
+ {
+ // set handler
+ rootLogger->AddHandler(&instance, false);
+ }
+
+ lock.Unlock();
+ }
+
+public:
+
+ virtual void Log(const NPT_LogRecord& record)
+ {
+ gcroot<ILog^> log = SetLoggerName(record.m_LoggerName);
+
+ switch (record.m_Level)
+ {
+ case NPT_LOG_LEVEL_FATAL:
+ if (log->IsFatalEnabled)
+ {
+ log->FatalFormat(
+ m_pFormatString,
+ marshal_as<String^>(NPT_Log::GetLogLevelName(record.m_Level)),
+ marshal_as<String^>(record.m_Message),
+ marshal_as<String^>(record.m_SourceFile),
+ UInt32(record.m_SourceLine)
+ );
+ }
+
+ break;
+
+ case NPT_LOG_LEVEL_SEVERE:
+ if (log->IsErrorEnabled)
+ {
+ log->ErrorFormat(
+ m_pFormatString,
+ marshal_as<String^>(NPT_Log::GetLogLevelName(record.m_Level)),
+ marshal_as<String^>(record.m_Message),
+ marshal_as<String^>(record.m_SourceFile),
+ UInt32(record.m_SourceLine)
+ );
+ }
+
+ break;
+
+ case NPT_LOG_LEVEL_WARNING:
+ if (log->IsWarnEnabled)
+ {
+ log->WarnFormat(
+ m_pFormatString,
+ marshal_as<String^>(NPT_Log::GetLogLevelName(record.m_Level)),
+ marshal_as<String^>(record.m_Message),
+ marshal_as<String^>(record.m_SourceFile),
+ UInt32(record.m_SourceLine)
+ );
+ }
+
+ break;
+
+ case NPT_LOG_LEVEL_INFO:
+ if (log->IsInfoEnabled)
+ {
+ log->InfoFormat(
+ m_pFormatString,
+ marshal_as<String^>(NPT_Log::GetLogLevelName(record.m_Level)),
+ marshal_as<String^>(record.m_Message),
+ marshal_as<String^>(record.m_SourceFile),
+ UInt32(record.m_SourceLine)
+ );
+ }
+
+ break;
+
+ case NPT_LOG_LEVEL_FINE:
+ case NPT_LOG_LEVEL_FINER:
+ case NPT_LOG_LEVEL_FINEST:
+ if (log->IsDebugEnabled)
+ {
+ log->DebugFormat(
+ m_pFormatString,
+ marshal_as<String^>(NPT_Log::GetLogLevelName(record.m_Level)),
+ marshal_as<String^>(record.m_Message),
+ marshal_as<String^>(record.m_SourceFile),
+ UInt32(record.m_SourceLine)
+ );
+ }
+
+ break;
+
+ default:
+ if (log->IsWarnEnabled)
+ {
+ log->WarnFormat(
+ m_pFormatString,
+ marshal_as<String^>("UNKNOWN_LOG_LEVEL"),
+ marshal_as<String^>(record.m_Message),
+ marshal_as<String^>(record.m_SourceFile),
+ UInt32(record.m_SourceLine)
+ );
+ }
+
+ break;
+ }
+ }
+
+private:
+
+ gcroot<ILog^> SetLoggerName(const char* name)
+ {
+ m_SetLoggerNameLock.Lock();
+
+ gcroot<String^> loggerName = gcnew String(name);
+ gcroot<ILog^> logger = m_pLogger;
+
+ if (logger->Logger->Name != loggerName)
+ {
+ logger = LogManager::GetLogger(loggerName);
+
+ m_pLogger = logger;
+ }
+
+ m_SetLoggerNameLock.Unlock();
+
+ return logger;
+ }
+
+public:
+
+ NeptuneLoggingBridge()
+ {
+ m_pLogger = LogManager::GetLogger(gcnew String("NeptuneLoggingBridge"));
+ m_pFormatString = gcnew String("{0}: {2}:{3}: {1}");
+ }
+
+ virtual ~NeptuneLoggingBridge()
+ {
+ }
+
+};
+
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Service.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/Service.cpp
new file mode 100644
index 0000000..5f66254
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Service.cpp
@@ -0,0 +1,97 @@
+/*****************************************************************
+|
+| Platinum - Managed Service
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "Service.h"
+#include "ActionDescription.h"
+#include "StateVariable.h"
+#include "DeviceData.h"
+#include "EnumerableNptArray.h"
+#include "EnumerableNptList.h"
+
+Platinum::DeviceData^ Platinum::Service::ParentDevice::get()
+{
+ return marshal_as<DeviceData^>(*m_pHandle->GetDevice());
+}
+
+IEnumerable<Platinum::StateVariable^>^ Platinum::Service::StateVariables::get()
+{
+ return gcnew Enumerables::EnumerableNptList<StateVariable^, PLT_StateVariable*>(
+ m_pHandle->GetStateVariables()
+ );
+}
+
+IEnumerable<Platinum::ActionDescription^>^ Platinum::Service::Actions::get()
+{
+ return gcnew Enumerables::EnumerableNptArray<ActionDescription^, PLT_ActionDesc*>(
+ m_pHandle->GetActionDescs()
+ );
+}
+
+Platinum::ActionDescription^ Platinum::Service::FindAction( String^ name )
+{
+ if (String::IsNullOrEmpty(name))
+ throw gcnew ArgumentException("null or empty", "name");
+
+ marshal_context c;
+
+ PLT_ActionDesc* d = m_pHandle->FindActionDesc(
+ c.marshal_as<const char*>(name)
+ );
+
+ if (!d)
+ return nullptr;
+
+ return marshal_as<ActionDescription^>(*d);
+}
+
+Platinum::StateVariable^ Platinum::Service::FindStateVariable( String^ name )
+{
+ if (String::IsNullOrEmpty(name))
+ throw gcnew ArgumentException("null or empty", "name");
+
+ marshal_context c;
+
+ PLT_StateVariable* d = m_pHandle->FindStateVariable(
+ c.marshal_as<const char*>(name)
+ );
+
+ if (!d)
+ return nullptr;
+
+ return marshal_as<StateVariable^>(*d);
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/Service.h b/lib/libUPnP/Platinum/Source/Extras/Managed/Service.h
new file mode 100644
index 0000000..1578f23
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/Service.h
@@ -0,0 +1,147 @@
+/*****************************************************************
+|
+| Platinum - Managed Service
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+ref class DeviceData;
+ref class ActionDescription;
+ref class StateVariable;
+
+/*----------------------------------------------------------------------
+| Service
++---------------------------------------------------------------------*/
+public ref class Service
+{
+private:
+
+ PLT_Service* m_pHandle;
+
+internal:
+
+ property PLT_Service& Handle
+ {
+ PLT_Service& get()
+ {
+ return *m_pHandle;
+ }
+ }
+
+public:
+
+ property Uri^ SCPDURL
+ {
+ Uri^ get()
+ {
+ return marshal_as<Uri^>(m_pHandle->GetSCPDURL());
+ }
+ }
+
+ property String^ ServiceID
+ {
+ String^ get()
+ {
+ return gcnew String(m_pHandle->GetServiceID());
+ }
+ }
+
+ property String^ ServiceType
+ {
+ String^ get()
+ {
+ return gcnew String(m_pHandle->GetServiceType());
+ }
+ }
+
+ property DeviceData^ ParentDevice
+ {
+ DeviceData^ get();
+ }
+
+ property IEnumerable<StateVariable^>^ StateVariables
+ {
+ IEnumerable<StateVariable^>^ get();
+ }
+
+ property IEnumerable<ActionDescription^>^ Actions
+ {
+ IEnumerable<ActionDescription^>^ get();
+ }
+
+public:
+
+ ActionDescription^ FindAction(String^ name);
+ StateVariable^ FindStateVariable(String^ name);
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((Service^)obj)->m_pHandle);
+ }
+
+internal:
+
+ Service(PLT_Service& devData)
+ {
+ m_pHandle = &devData;
+ }
+
+public:
+
+ ~Service()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!Service();
+ }
+
+ !Service()
+ {
+ // clean-up unmanaged
+ }
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::Service, PLT_Service);
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.cpp
new file mode 100644
index 0000000..9a4208c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.cpp
@@ -0,0 +1,44 @@
+/*****************************************************************
+|
+| Platinum - Managed StateVariable
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "StateVariable.h"
+#include "Service.h"
+
+Platinum::Service^ Platinum::StateVariable::ParentService::get()
+{
+ return marshal_as<Service^>(*m_pHandle->GetService());
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.h b/lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.h
new file mode 100644
index 0000000..7184a15
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/StateVariable.h
@@ -0,0 +1,165 @@
+/*****************************************************************
+|
+| Platinum - Managed StateVariable
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+ref class Service;
+
+/*----------------------------------------------------------------------
+| StateVariable
++---------------------------------------------------------------------*/
+public ref class StateVariable
+{
+private:
+
+ PLT_StateVariable* m_pHandle;
+
+public:
+
+ property String^ Name
+ {
+ String^ get()
+ {
+ return gcnew String(m_pHandle->GetName());
+ }
+ }
+
+ property Service^ ParentService
+ {
+ Service^ get();
+ }
+
+ property Type^ DataType
+ {
+ Type^ get()
+ {
+ return Helpers::ParseType(m_pHandle->GetDataType());
+ }
+ }
+
+ property String^ DataTypeString
+ {
+ String^ get()
+ {
+ return gcnew String(m_pHandle->GetDataType());
+ }
+ }
+
+ property Object^ Value
+ {
+ Object^ get()
+ {
+ return Helpers::ConvertValue(
+ m_pHandle->GetDataType(),
+ m_pHandle->GetValue()
+ );
+ }
+ }
+
+ property String^ ValueString
+ {
+ String^ get()
+ {
+ return gcnew String(m_pHandle->GetValue());
+ }
+
+ void set (String^ value)
+ {
+ if (value == nullptr)
+ throw gcnew ArgumentNullException("value");
+
+ marshal_context c;
+
+ Helpers::ThrowOnError(m_pHandle->SetValue(
+ c.marshal_as<const char*>(value)
+ ));
+ }
+ }
+
+public:
+
+ void ValidateValue(String^ value)
+ {
+ if (value == nullptr)
+ throw gcnew ArgumentNullException("value");
+
+ marshal_context c;
+
+ Helpers::ThrowOnError(m_pHandle->ValidateValue(
+ c.marshal_as<const char*>(value)
+ ));
+ }
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((StateVariable^)obj)->m_pHandle);
+ }
+
+internal:
+
+ StateVariable(PLT_StateVariable& devData)
+ {
+ m_pHandle = &devData;
+ }
+
+public:
+
+ ~StateVariable()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!StateVariable();
+ }
+
+ !StateVariable()
+ {
+ // clean-up unmanaged
+ }
+
+};
+
+}
+
+// marshal wrapper
+PLATINUM_MANAGED_MARSHAL_AS(Platinum::StateVariable, PLT_StateVariable);
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.cpp b/lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.cpp
new file mode 100644
index 0000000..d80d745
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.cpp
@@ -0,0 +1,81 @@
+/*****************************************************************
+|
+| Platinum - Managed UPnP
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "StdAfx.h"
+#include "UPnP.h"
+#include "ControlPoint.h"
+#include "DeviceHost.h"
+#include "NeptuneLoggingBridge.h"
+
+void Platinum::UPnP::AddControlPoint( ControlPoint^ cp )
+{
+ Helpers::ThrowOnError(m_pHandle->AddCtrlPoint(cp->Handle));
+}
+
+void Platinum::UPnP::RemoveControlPoint( ControlPoint^ cp )
+{
+ Helpers::ThrowOnError(m_pHandle->RemoveCtrlPoint(cp->Handle));
+}
+
+void Platinum::UPnP::AddDeviceHost( DeviceHost^ host )
+{
+ Helpers::ThrowOnError(m_pHandle->AddDevice((PLT_DeviceHostReference)host->Host));
+}
+
+void Platinum::UPnP::RemoveDeviceHost( DeviceHost^ host )
+{
+ Helpers::ThrowOnError(m_pHandle->RemoveDevice((PLT_DeviceHostReference)host->Host));
+}
+
+static Platinum::UPnP::UPnP()
+{
+ NeptuneLoggingBridge::Configure();
+}
+
+List<String^>^ Platinum::UPnP::GetIpAddresses(bool include_localhost)
+{
+ NPT_List<NPT_IpAddress> ips;
+ PLT_UPnPMessageHelper::GetIPAddresses(ips, include_localhost); // TODO: Throw on Error?
+
+ List<String^>^ _ips = gcnew List<String^>();
+ NPT_List<NPT_IpAddress>::Iterator ip = ips.GetFirstItem();
+ while (ip) {
+ _ips->Add(gcnew String((*ip).ToString()));
+ ++ip;
+ }
+
+ return _ips;
+} \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.h b/lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.h
new file mode 100644
index 0000000..4c87e8d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/UPnP.h
@@ -0,0 +1,131 @@
+/*****************************************************************
+|
+| Platinum - Managed UPnP
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+#pragma once
+
+namespace Platinum
+{
+
+ref class ControlPoint;
+ref class DeviceHost;
+class NeptuneLoggingBridge;
+
+/*----------------------------------------------------------------------
+| UPnP
++---------------------------------------------------------------------*/
+public ref class UPnP
+{
+public:
+
+ static const unsigned short DefaultPort = 1900;
+
+private:
+
+ PLT_UPnP* m_pHandle;
+
+public:
+
+ void Start()
+ {
+ Helpers::ThrowOnError(m_pHandle->Start());
+ }
+
+ void Stop()
+ {
+ if (m_pHandle) m_pHandle->Stop();
+ }
+
+ void AddControlPoint(ControlPoint^ cp);
+ void RemoveControlPoint(ControlPoint^ cp);
+
+ void AddDeviceHost(DeviceHost^ host);
+ void RemoveDeviceHost(DeviceHost^ host);
+
+ static List<String^>^ GetIpAddresses()
+ {
+ return GetIpAddresses(false);
+ }
+ static List<String^>^ GetIpAddresses(bool include_localhost);
+
+ property bool Running
+ {
+ bool get()
+ {
+ return m_pHandle->IsRunning();
+ }
+ }
+
+public:
+
+ virtual Boolean Equals(Object^ obj) override
+ {
+ if (obj == nullptr)
+ return false;
+
+ if (!this->GetType()->IsInstanceOfType(obj))
+ return false;
+
+ return (m_pHandle == ((UPnP^)obj)->m_pHandle);
+ }
+
+public:
+
+ static UPnP();
+
+ UPnP()
+ {
+ m_pHandle = new PLT_UPnP();
+ }
+
+ ~UPnP()
+ {
+ // clean-up managed
+
+ // clean-up unmanaged
+ this->!UPnP();
+ }
+
+ !UPnP()
+ {
+ // clean-up unmanaged
+ if (m_pHandle != 0)
+ {
+ delete m_pHandle;
+
+ m_pHandle = 0;
+ }
+ }
+};
+
+
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/Managed/clix.hpp b/lib/libUPnP/Platinum/Source/Extras/Managed/clix.hpp
new file mode 100644
index 0000000..bb93978
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/Managed/clix.hpp
@@ -0,0 +1,209 @@
+// ------------------------------------------------------------------------------------------- //
+// clix.h
+//
+// Marshals strings between .NET and C++ using C++/CLI (Visual C++ 2005 and later only).
+// Faster and cleaner than the System::Interop method because it uses garbage collected memory.
+// Use at your own leisure. No warranties whatsoever provided.
+//
+// Original code by Markus Ewald (http://www.nuclex.org/articles/marshaling-strings-in-cxx-cli)
+// Updated version including several improvements suggested by Neil Hunt
+//
+// Licensed under the IBM CPL (free of charge, closed source commercial use is okay)
+// ------------------------------------------------------------------------------------------- //
+#pragma once
+
+#include <string>
+#include <vcclr.h>
+
+// CLI extensions namespace
+namespace clix {
+
+ /// <summary>Encoding types for strings</summary>
+ enum Encoding {
+
+ /// <summary>ANSI encoding</summary>
+ /// <remarks>
+ /// This is the default encoding you've most likely been using all around in C++. ANSI
+ /// means 8 Bit encoding with character codes depending on the system's selected code page.
+ /// <remarks>
+ E_ANSI,
+
+ /// <summary>UTF-8 encoding</summary>
+ /// <remarks>
+ /// This is the encoding commonly used for multilingual C++ strings. All ASCII characters
+ /// (0-127) will be represented as single bytes. Be aware that UTF-8 uses more than one
+ /// byte for extended characters, so std::string::length() might not reflect the actual
+ /// length of the string in characters if it contains any non-ASCII characters.
+ /// <remarks>
+ E_UTF8,
+
+ /// <summary>UTF-16 encoding</summary>
+ /// <remarks>
+ /// This is the suggested encoding for marshaling and the native encoding of .NET strings.
+ /// It is similar to UTF-8 but uses a minimum of two bytes per character, making the number
+ /// of bytes required for a given string better predictable. Be aware, however, that UTF-16
+ /// can still use more than two bytes for a character, so std::wstring::length() might not
+ /// reflect the actual length of the string.
+ /// </remarks>
+ E_UTF16, E_UNICODE = E_UTF16
+
+ };
+
+ // Ignore this if you're just scanning the headers for informations!
+ /* All this template stuff might seem like overkill, but it is well thought out and enables
+ you to use a readable and convenient call while still keeping the highest possible code
+ efficiency due to compile-time evaluation of the required conversion path.
+ */
+ namespace detail {
+
+ // Get C++ string type for specified encoding
+ template<Encoding encoding> struct StringTypeSelector;
+ template<> struct StringTypeSelector<E_ANSI> { typedef std::string Type; };
+ template<> struct StringTypeSelector<E_UTF8> { typedef std::string Type; };
+ template<> struct StringTypeSelector<E_UTF16> { typedef std::wstring Type; };
+
+ // Compile-time selection depending on whether a string is managed
+ template<typename StringType> struct IfManaged {
+ struct Select {
+ template<typename TrueType, typename FalseType>
+ struct Either { typedef FalseType Type; };
+ };
+ enum { Result = false };
+ };
+ template<> struct IfManaged<System::String ^> {
+ struct Select {
+ template<typename TrueType, typename FalseType>
+ struct Either { typedef TrueType Type; };
+ };
+ enum { Result = true };
+ };
+
+ // Direction of the marshaling process
+ enum MarshalingDirection {
+ CxxFromNet,
+ NetFromCxx
+ };
+
+ // The actual marshaling code
+ template<MarshalingDirection direction> struct StringMarshaler;
+
+ // Marshals to .NET from C++ strings
+ template<> struct StringMarshaler<NetFromCxx> {
+
+ template<Encoding encoding, typename SourceType>
+ static System::String ^marshal(const SourceType &string) {
+ // Constructs a std::[w]string in case someone gave us a char * to choke on
+ return marshalCxxString<encoding, SourceType>(string);
+ }
+
+ template<Encoding encoding, typename SourceType>
+ static System::String ^marshalCxxString(
+ const typename StringTypeSelector<encoding>::Type &cxxString
+ ) {
+ typedef typename StringTypeSelector<encoding>::Type SourceStringType;
+ size_t byteCount = cxxString.length() * sizeof(SourceStringType::value_type);
+
+ // Empty strings would cause trouble accessing the array below
+ if(byteCount == 0) {
+ return System::String::Empty;
+ }
+
+ // Copy the C++ string contents into a managed array of bytes
+ array<unsigned char> ^bytes = gcnew array<unsigned char>(byteCount);
+ { pin_ptr<unsigned char> pinnedBytes = &bytes[0];
+ memcpy(pinnedBytes, cxxString.c_str(), byteCount);
+ }
+
+ // Now let one of .NET's encoding classes do the rest
+ return decode<encoding>(bytes);
+ }
+
+ private:
+ // Converts a byte array based on the selected encoding
+ template<Encoding encoding> static System::String ^decode(array<unsigned char> ^bytes);
+ template<> static System::String ^decode<E_ANSI>(array<unsigned char> ^bytes) {
+ return System::Text::Encoding::Default->GetString(bytes);
+ }
+ template<> static System::String ^decode<E_UTF8>(array<unsigned char> ^bytes) {
+ return System::Text::Encoding::UTF8->GetString(bytes);
+ }
+ template<> static System::String ^decode<E_UTF16>(array<unsigned char> ^bytes) {
+ return System::Text::Encoding::Unicode->GetString(bytes);
+ }
+ };
+
+ // Marshals to C++ strings from .NET
+ template<> struct StringMarshaler<CxxFromNet> {
+
+ template<Encoding encoding, typename SourceType>
+ static typename detail::StringTypeSelector<encoding>::Type marshal(
+ System::String ^string
+ ) {
+ typedef typename StringTypeSelector<encoding>::Type StringType;
+
+ // Empty strings would cause a problem when accessing the empty managed array
+ if(string->Length == 0) {
+ return StringType();
+ }
+
+ // First, we use .NET's encoding classes to convert the string into a byte array
+ array<unsigned char> ^bytes = encode<encoding>(string);
+
+ // Then we construct our native string from that byte array
+ pin_ptr<unsigned char> pinnedBytes(&bytes[0]);
+ return StringType(
+ reinterpret_cast<StringType::value_type *>(static_cast<unsigned char *>(pinnedBytes)),
+ bytes->Length / sizeof(StringType::value_type)
+ );
+ }
+
+ template<> static std::wstring marshal<E_UTF16, System::String ^>(
+ System::String ^string
+ ) {
+ // We can directly accesss the characters in the managed string
+ pin_ptr<const wchar_t> pinnedChars(::PtrToStringChars(string));
+ return std::wstring(pinnedChars, string->Length);
+ }
+
+ private:
+ // Converts a string based on the selected encoding
+ template<Encoding encoding> static array<unsigned char> ^encode(System::String ^string);
+ template<> static array<unsigned char> ^encode<E_ANSI>(System::String ^string) {
+ return System::Text::Encoding::Default->GetBytes(string);
+ }
+ template<> static array<unsigned char> ^encode<E_UTF8>(System::String ^string) {
+ return System::Text::Encoding::UTF8->GetBytes(string);
+ }
+ template<> static array<unsigned char> ^encode<E_UTF16>(System::String ^string) {
+ return System::Text::Encoding::Unicode->GetBytes(string);
+ }
+
+ };
+
+ } // namespace detail
+
+ // ----------------------------------------------------------------------------------------- //
+ // clix::marshalString()
+ // ----------------------------------------------------------------------------------------- //
+ /// <summary>Marshals strings between .NET managed and C++ native</summary>
+ /// <remarks>
+ /// This all-in-one function marshals native C++ strings to .NET strings and vice versa.
+ /// You have to specify an encoding to use for the conversion, which always applies to the
+ /// native C++ string as .NET always uses UTF-16 for its own strings.
+ /// </remarks>
+ /// <param name="string">String to be marshalled to the other side</param>
+ /// <returns>The marshaled representation of the string</returns>
+ template<Encoding encoding, typename SourceType>
+ typename detail::IfManaged<SourceType>::Select::Either<
+ typename detail::StringTypeSelector<encoding>::Type,
+ System::String ^
+ >::Type marshalString(SourceType string) {
+
+ // Pass on the call to our nifty template routines
+ return detail::StringMarshaler<
+ detail::IfManaged<SourceType>::Result ? detail::CxxFromNet : detail::NetFromCxx
+ >::marshal<encoding, SourceType>(string);
+
+ }
+
+} // namespace clix
diff --git a/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.h b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.h
new file mode 100644
index 0000000..bbc6743
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.h
@@ -0,0 +1,84 @@
+//
+// PltMediaServerObject.h
+// Platinum
+//
+// Created by Sylvain on 9/14/10.
+// Copyright 2010 Plutinosoft LLC. All rights reserved.
+//
+
+#import "Neptune.h"
+
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#include <UIKit/UIKit.h>
+#else
+#import <Cocoa/Cocoa.h>
+#endif
+
+#import "PltUPnPObject.h"
+
+// define
+#if !defined(_PLATINUM_H_)
+typedef class PLT_HttpRequestContext PLT_HttpRequestContext;
+typedef class NPT_HttpResponse NPT_HttpResponse;
+#endif
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerObject
++---------------------------------------------------------------------*/
+@interface PLT_MediaServerObject : PLT_DeviceHostObject
+@property (nonatomic, assign) id delegate;
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerBrowseCapsule
++---------------------------------------------------------------------*/
+@interface PLT_MediaServerBrowseCapsule : PLT_ActionObject {
+ NSString* objectId;
+ NPT_UInt32 start;
+ NPT_UInt32 count;
+ NSString* filter;
+ NSString* sort;
+ PLT_HttpRequestContext* context;
+}
+
+- (id)initWithAction:(PLT_Action*)action objectId:(const char*)objectId filter:(const char*)filter start:(NPT_UInt32)start count:(NPT_UInt32)count sort:(const char*)sort context:(PLT_HttpRequestContext*)context;
+
+@property (readonly, copy) NSString* objectId;
+@property (readonly) NPT_UInt32 start;
+@property (readonly) NPT_UInt32 count;
+@property (readonly, copy) NSString* filter;
+@property (readonly, copy) NSString* sort;
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerSearchCapsule
++---------------------------------------------------------------------*/
+@interface PLT_MediaServerSearchCapsule : PLT_MediaServerBrowseCapsule {
+ NSString* search;
+}
+
+- (id)initWithAction:(PLT_Action*)action objectId:(const char*)objectId search:(const char*)search filter:(const char*)filter start:(NPT_UInt32)start count:(NPT_UInt32)count sort:(const char*)sort context:(PLT_HttpRequestContext*)context;
+
+@property (readonly, copy) NSString* search;
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerFileRequestCapsule
++---------------------------------------------------------------------*/
+@interface PLT_MediaServerFileRequestCapsule : NSObject {
+ NPT_HttpResponse* response;
+ PLT_HttpRequestContext* context;
+}
+
+- (id)initWithResponse:(NPT_HttpResponse*)response context:(PLT_HttpRequestContext*)context;
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerDelegateObject
++---------------------------------------------------------------------*/
+@protocol PLT_MediaServerDelegateObject
+- (NPT_Result)onBrowseMetadata:(PLT_MediaServerBrowseCapsule*)info;
+- (NPT_Result)onBrowseDirectChildren:(PLT_MediaServerBrowseCapsule*)info;
+- (NPT_Result)onSearchContainer:(PLT_MediaServerSearchCapsule*)info;
+- (NPT_Result)onFileRequest:(PLT_MediaServerFileRequestCapsule*)info;
+@end
diff --git a/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.mm b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.mm
new file mode 100644
index 0000000..0900819
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltMediaServerObject.mm
@@ -0,0 +1,198 @@
+//
+// PltMediaServerObject.mm
+// Platinum
+//
+// Created by Sylvain on 9/14/10.
+// Copyright 2010 Plutinosoft LLC. All rights reserved.
+//
+
+#import "Platinum.h"
+#import "PltMediaServerObject.h"
+#import "PltMediaConnect.h"
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerDelegate_Wrapper
++---------------------------------------------------------------------*/
+class PLT_MediaServerDelegate_Wrapper : public PLT_MediaServerDelegate {
+public:
+ PLT_MediaServerDelegate_Wrapper(PLT_MediaServerObject* target) : m_Target(target) {}
+
+ NPT_Result OnBrowseMetadata(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context) {
+ if (![m_Target.delegate respondsToSelector:@selector(onBrowseMetadata:)])
+ return NPT_FAILURE;
+
+ PLT_MediaServerBrowseCapsule* capsule =
+ [[PLT_MediaServerBrowseCapsule alloc] initWithAction:action.AsPointer()
+ objectId:object_id
+ filter:filter
+ start:starting_index
+ count:requested_count
+ sort:sort_criteria
+ context:(PLT_HttpRequestContext*)&context];
+ NPT_Result result = [m_Target.delegate onBrowseMetadata:capsule];
+
+ return result;
+ }
+
+ NPT_Result OnBrowseDirectChildren(PLT_ActionReference& action,
+ const char* object_id,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context) {
+ if (![m_Target.delegate respondsToSelector:@selector(onBrowseDirectChildren:)])
+ return NPT_FAILURE;
+
+ PLT_MediaServerBrowseCapsule* capsule =
+ [[PLT_MediaServerBrowseCapsule alloc] initWithAction:action.AsPointer()
+ objectId:object_id
+ filter:filter
+ start:starting_index
+ count:requested_count
+ sort:sort_criteria
+ context:(PLT_HttpRequestContext*)&context];
+ NPT_Result result = [m_Target.delegate onBrowseDirectChildren:capsule];
+
+ return result;
+ }
+
+ NPT_Result OnSearchContainer(PLT_ActionReference& action,
+ const char* container_id,
+ const char* search_criteria,
+ const char* filter,
+ NPT_UInt32 starting_index,
+ NPT_UInt32 requested_count,
+ const char* sort_criteria,
+ const PLT_HttpRequestContext& context) {
+ if (![m_Target.delegate respondsToSelector:@selector(onSearchContainer:)])
+ return NPT_FAILURE;
+
+ PLT_MediaServerSearchCapsule* capsule =
+ [[PLT_MediaServerSearchCapsule alloc] initWithAction:action.AsPointer()
+ objectId:container_id
+ search:search_criteria
+ filter:filter
+ start:starting_index
+ count:requested_count
+ sort:sort_criteria
+ context:(PLT_HttpRequestContext*)&context];
+ NPT_Result result = [m_Target.delegate onSearchContainer:capsule];
+
+ return result;
+ }
+
+ NPT_Result ProcessFileRequest(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) {
+ PLT_HttpRequestContext _context(request, context);
+ PLT_MediaServerFileRequestCapsule* capsule =
+ [[PLT_MediaServerFileRequestCapsule alloc] initWithResponse:&response
+ context:&_context];
+ NPT_Result result = [m_Target.delegate onFileRequest:capsule];
+
+ return result;
+ }
+
+private:
+ PLT_MediaServerObject* m_Target;
+};
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerBrowseCapsule
++---------------------------------------------------------------------*/
+@implementation PLT_MediaServerBrowseCapsule
+
+@synthesize objectId, filter, start, count, sort;
+
+- (id)initWithAction:(PLT_Action*)action objectId:(const char*)_id filter:(const char*)_filter start:(NPT_UInt32)_start count:(NPT_UInt32)_count sort:(const char*)_sort context:(PLT_HttpRequestContext*)_context
+{
+ if ((self = [super initWithAction:action])) {
+ objectId = [[NSString alloc] initWithCString:_id encoding:NSUTF8StringEncoding];
+ filter = [[NSString alloc] initWithCString:(_filter==NULL)?"":_filter
+ encoding:NSUTF8StringEncoding];
+ sort = [[NSString alloc] initWithCString:(_sort==NULL)?"":_sort
+ encoding:NSUTF8StringEncoding];
+ start = _start;
+ count = _count;
+ context = _context;
+ }
+ return self;
+}
+
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerSearchCapsule
++---------------------------------------------------------------------*/
+@implementation PLT_MediaServerSearchCapsule
+
+@synthesize search;
+
+- (id)initWithAction:(PLT_Action*)action objectId:(const char*)_id search:(const char*)_search filter:(const char*)_filter start:(NPT_UInt32)_start count:(NPT_UInt32)_count sort:(const char*)_sort context:(PLT_HttpRequestContext*)_context
+{
+ if ((self = [super initWithAction:action
+ objectId:_id
+ filter:_filter
+ start:_start
+ count:_count
+ sort:_sort
+ context:_context])) {
+ search = [[NSString alloc] initWithCString:_search encoding:NSUTF8StringEncoding];
+ }
+ return self;
+}
+
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerFileRequestCapsule
++---------------------------------------------------------------------*/
+@implementation PLT_MediaServerFileRequestCapsule
+
+- (id)initWithResponse:(NPT_HttpResponse*)_response context:(PLT_HttpRequestContext*)_context
+{
+ if ((self = [super init])) {
+ response = _response;
+ context = _context;
+ }
+ return self;
+}
+
+@end
+
+/*----------------------------------------------------------------------
+| PLT_MediaServerObject
++---------------------------------------------------------------------*/
+@interface PLT_MediaServerObject () {
+ PLT_MediaServerDelegate_Wrapper *_wrapper;
+}
+@end
+
+@implementation PLT_MediaServerObject
+
+- (id)init
+{
+ if ((self = [super init])) {
+ PLT_MediaConnect* server = new PLT_MediaConnect("Test");
+ PLT_DeviceHostReference _device(server);
+ [self setDevice:&_device];
+
+ _wrapper = new PLT_MediaServerDelegate_Wrapper(self);
+ server->SetDelegate(_wrapper);
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ delete _wrapper;
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.h b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.h
new file mode 100644
index 0000000..4c9b8ed
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.h
@@ -0,0 +1,61 @@
+//
+// PltUPnPObject.h
+// Platinum
+//
+// Created by Sylvain on 9/14/10.
+// Copyright 2010 Plutinosoft LLC. All rights reserved.
+//
+
+#import "Neptune.h"
+
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#include <UIKit/UIKit.h>
+#else
+#import <Cocoa/Cocoa.h>
+#endif
+
+
+#if !defined(_PLATINUM_H_)
+typedef struct PLT_UPnP PLT_UPnP;
+typedef struct PLT_Action PLT_Action;
+typedef struct PLT_DeviceHostReference PLT_DeviceHostReference;
+#endif
+
+/*----------------------------------------------------------------------
+| PLT_ActionObject
++---------------------------------------------------------------------*/
+@interface PLT_ActionObject : NSObject {
+@private
+ PLT_Action* action;
+}
+
+- (id)initWithAction:(PLT_Action *)_action;
+- (NPT_Result)setValue:(NSString*)value forArgument:(NSString*)argument;
+- (NPT_Result)setErrorCode:(unsigned int)code withDescription:(NSString*)description;
+@end
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHostObject
++---------------------------------------------------------------------*/
+@interface PLT_DeviceHostObject : NSObject {
+@private
+ PLT_DeviceHostReference* device;
+}
+
+- (void)setDevice:(PLT_DeviceHostReference*)_device;
+- (PLT_DeviceHostReference&)getDevice;
+@end
+
+/*----------------------------------------------------------------------
+| PLT_UPnPObject
++---------------------------------------------------------------------*/
+@interface PLT_UPnPObject : NSObject
+
+- (NPT_Result)start;
+- (NPT_Result)stop;
+- (bool)isRunning;
+
+- (NPT_Result)addDevice:(PLT_DeviceHostObject*)device;
+- (NPT_Result)removeDevice:(PLT_DeviceHostObject*)device;
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.mm b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.mm
new file mode 100644
index 0000000..d49f1f5
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/ObjectiveC/PltUPnPObject.mm
@@ -0,0 +1,118 @@
+//
+// PltUPnPObject.mm
+// Platinum
+//
+// Created by Sylvain on 9/14/10.
+// Copyright 2010 Plutinosoft LLC. All rights reserved.
+//
+
+#import "Platinum.h"
+#import "PltUPnPObject.h"
+
+/*----------------------------------------------------------------------
+| PLT_ActionObject
++---------------------------------------------------------------------*/
+@implementation PLT_ActionObject
+
+- (id)initWithAction:(PLT_Action *)_action
+{
+ if ((self = [super init])) {
+ action = _action;
+ }
+ return self;
+}
+
+- (NPT_Result)setValue:(NSString *)value forArgument:(NSString *)argument
+{
+ return action->SetArgumentValue([argument UTF8String], [value UTF8String]);
+}
+
+- (NPT_Result)setErrorCode:(unsigned int)code withDescription:(NSString*)description
+{
+ return action->SetError(code, [description UTF8String]);
+}
+
+@end
+
+/*----------------------------------------------------------------------
+| PLT_DeviceHostObject
++---------------------------------------------------------------------*/
+@implementation PLT_DeviceHostObject
+
+- (id)init
+{
+ return [super init];
+}
+
+- (void)setDevice:(PLT_DeviceHostReference*)_device
+{
+ delete device;
+ device = new PLT_DeviceHostReference(*_device);
+}
+
+- (void)dealloc
+{
+ delete device;
+}
+
+- (PLT_DeviceHostReference&)getDevice
+{
+ return *device;
+}
+
+@end
+
+/*----------------------------------------------------------------------
+| PLT_UPnPObject
++---------------------------------------------------------------------*/
+
+@interface PLT_UPnPObject () {
+ PLT_UPnP *_upnp;
+ NSMutableArray *_devices;
+}
+@end
+
+@implementation PLT_UPnPObject
+
+- (id)init
+{
+ if ((self = [super init])) {
+ _upnp = new PLT_UPnP();
+ _devices = [NSMutableArray array];
+ }
+ return self;
+}
+
+-(void) dealloc
+{
+ delete _upnp;
+}
+
+- (NPT_Result)start
+{
+ return _upnp->Start();
+}
+
+- (NPT_Result)stop
+{
+ return _upnp->Stop();
+}
+
+- (bool)isRunning
+{
+ return _upnp->IsRunning();
+}
+
+- (NPT_Result)addDevice:(PLT_DeviceHostObject*)device
+{
+ [_devices addObject:device];
+ return _upnp->AddDevice([device getDevice]);
+}
+
+- (NPT_Result)removeDevice:(PLT_DeviceHostObject*)device
+{
+ [_devices removeObject:device];
+ return _upnp->RemoveDevice([device getDevice]);
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltDownloader.cpp b/lib/libUPnP/Platinum/Source/Extras/PltDownloader.cpp
new file mode 100644
index 0000000..a910370
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltDownloader.cpp
@@ -0,0 +1,132 @@
+/*****************************************************************
+|
+| Platinum - Downloader
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDownloader.h"
+#include "PltTaskManager.h"
+#include "Neptune.h"
+
+
+NPT_SET_LOCAL_LOGGER("platinum.extra.downloader")
+
+/*----------------------------------------------------------------------
+| PLT_Downloader::PLT_Downloader
++---------------------------------------------------------------------*/
+PLT_Downloader::PLT_Downloader(NPT_HttpUrl& url,
+ NPT_OutputStreamReference& output) :
+ PLT_HttpClientSocketTask(new NPT_HttpRequest(url,
+ "GET",
+ NPT_HTTP_PROTOCOL_1_1)),
+ m_URL(url),
+ m_Output(output),
+ m_State(PLT_DOWNLOADER_IDLE)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Downloader::~PLT_Downloader
++---------------------------------------------------------------------*/
+PLT_Downloader::~PLT_Downloader()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Downloader::DoRun
++---------------------------------------------------------------------*/
+void
+PLT_Downloader::DoRun()
+{
+ m_State = PLT_DOWNLOADER_STARTED;
+ return PLT_HttpClientSocketTask::DoRun();
+}
+
+/*----------------------------------------------------------------------
+| PLT_Downloader::DoAbort
++---------------------------------------------------------------------*/
+void
+PLT_Downloader::DoAbort()
+{
+ PLT_HttpClientSocketTask::DoAbort();
+ m_State = PLT_DOWNLOADER_IDLE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Downloader::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Downloader::ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(request);
+ NPT_COMPILER_UNUSED(context);
+
+ if (NPT_FAILED(res)) {
+ NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars());
+ m_State = PLT_DOWNLOADER_ERROR;
+ return res;
+ }
+
+ m_State = PLT_DOWNLOADER_DOWNLOADING;
+
+ NPT_HttpEntity* entity;
+ NPT_InputStreamReference body;
+ if (!response ||
+ !(entity = response->GetEntity()) ||
+ NPT_FAILED(entity->GetInputStream(body)) ||
+ body.IsNull()) {
+ m_State = PLT_DOWNLOADER_ERROR;
+ NPT_LOG_WARNING_2("No body %d for %s", res, m_URL.ToString().GetChars());
+ return NPT_FAILURE;
+ }
+
+ // Read body (no content length means until socket is closed)
+ res = NPT_StreamToStreamCopy(*body.AsPointer(),
+ *m_Output.AsPointer(),
+ 0,
+ entity->GetContentLength());
+
+ if (NPT_FAILED(res)) {
+ NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars());
+ m_State = PLT_DOWNLOADER_ERROR;
+ return res;
+ }
+
+ NPT_LOG_INFO_1("Finished downloading %s", m_URL.ToString().GetChars());
+ m_State = PLT_DOWNLOADER_SUCCESS;
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltDownloader.h b/lib/libUPnP/Platinum/Source/Extras/PltDownloader.h
new file mode 100644
index 0000000..15d9279
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltDownloader.h
@@ -0,0 +1,89 @@
+/*****************************************************************
+|
+| Platinum - Downloader
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_DOWNLOADER_H_
+#define _PLT_DOWNLOADER_H_
+
+/*----------------------------------------------------------------------
+| Includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpClientTask.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_Downloader;
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+typedef enum {
+ PLT_DOWNLOADER_IDLE,
+ PLT_DOWNLOADER_STARTED,
+ PLT_DOWNLOADER_DOWNLOADING,
+ PLT_DOWNLOADER_ERROR,
+ PLT_DOWNLOADER_SUCCESS
+} Plt_DowloaderState;
+
+/*----------------------------------------------------------------------
+| PLT_Downloader class
++---------------------------------------------------------------------*/
+class PLT_Downloader : public PLT_HttpClientSocketTask
+{
+public:
+ PLT_Downloader(NPT_HttpUrl& url,
+ NPT_OutputStreamReference& output);
+ ~PLT_Downloader() override;
+
+ Plt_DowloaderState GetState() { return m_State; }
+
+ // PLT_HttpClientTask method
+ NPT_Result ProcessResponse(NPT_Result res,
+ const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response) override;
+
+protected:
+ void DoRun() override;
+ void DoAbort() override;
+
+private:
+ // members
+ NPT_HttpUrl m_URL;
+ NPT_OutputStreamReference m_Output;
+ Plt_DowloaderState m_State;
+};
+
+#endif /* _PLT_DOWNLOADER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.cpp b/lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.cpp
new file mode 100644
index 0000000..5c4232d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.cpp
@@ -0,0 +1,129 @@
+/*****************************************************************
+|
+| Platinum - Frame Buffer
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltFrameBuffer.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.framebuffer")
+
+/*----------------------------------------------------------------------
+| PLT_FrameBuffer::PLT_FrameBuffer
++---------------------------------------------------------------------*/
+PLT_FrameBuffer::PLT_FrameBuffer(const char* mime_type) :
+ m_MimeType(mime_type),
+ m_Aborted(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameBuffer::~PLT_FrameBuffer
++---------------------------------------------------------------------*/
+PLT_FrameBuffer::~PLT_FrameBuffer()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameBuffer::Reset
++---------------------------------------------------------------------*/
+void
+PLT_FrameBuffer::Reset()
+{
+ NPT_AutoLock lock(m_FrameLock);
+
+ // mark that we're planning to receive more frames
+ m_Aborted = false;
+
+ // reset to 0 for new readers to
+ m_FrameIndex.SetValue(0);
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameBuffer::Abort
++---------------------------------------------------------------------*/
+void
+PLT_FrameBuffer::Abort()
+{
+ NPT_AutoLock lock(m_FrameLock);
+
+ // mark that we're not planning to receive more frames
+ m_Aborted = true;
+
+ // increment to unlock readers
+ m_FrameIndex.SetValue(m_FrameIndex.GetValue()+1);
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameBuffer::SetNextFrame
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameBuffer::SetNextFrame(const NPT_Byte* data, NPT_Size size)
+{
+ NPT_AutoLock lock(m_FrameLock);
+
+ m_Frame.SetData(data, size);
+ m_FrameIndex.SetValue(m_FrameIndex.GetValue()+1);
+
+ NPT_LOG_INFO_1("Set frame %d", m_FrameIndex.GetValue());
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameBuffer::GetNextFrame
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameBuffer::GetNextFrame(NPT_UInt32& last_frame_index,
+ NPT_DataBuffer& buffer,
+ NPT_Timeout timeout)
+{
+ NPT_CHECK_WARNING(m_FrameIndex.WaitWhileEquals(last_frame_index, timeout));
+
+ {
+ NPT_AutoLock lock(m_FrameLock);
+
+ // if we're aborted or we reseted, disconnect
+ if (m_Aborted || last_frame_index > (NPT_UInt32)m_FrameIndex.GetValue())
+ return NPT_ERROR_EOS;
+
+ buffer.SetData(m_Frame.GetData(), m_Frame.GetDataSize());
+
+ // update current frame index
+ last_frame_index = m_FrameIndex.GetValue();
+ NPT_LOG_INFO_1("Retrieved frame %d", last_frame_index);
+ }
+
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.h b/lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.h
new file mode 100644
index 0000000..aa270df
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltFrameBuffer.h
@@ -0,0 +1,76 @@
+/*****************************************************************
+|
+| Platinum - Frame Buffer
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_FRAME_BUFFER_H_
+#define _PLT_FRAME_BUFFER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_FrameBuffer
++---------------------------------------------------------------------*/
+class PLT_FrameBuffer
+{
+ public:
+ // constructor & destructor
+ PLT_FrameBuffer(const char* mime_type);
+ virtual ~PLT_FrameBuffer();
+
+ void Reset();
+ void Abort();
+ void AddReader() { m_Readers.Increment(); }
+ void RemoveReader() { m_Readers.Decrement(); }
+ int GetNbReaders() { return m_Readers.GetValue(); }
+ const char* GetMimeType() { return m_MimeType; }
+
+ // data buffer handling methods
+ virtual NPT_Result SetNextFrame(const NPT_Byte* buffer, NPT_Size bufferSize);
+ virtual NPT_Result GetNextFrame(NPT_UInt32& last_frame_index,
+ NPT_DataBuffer& buffer,
+ NPT_Timeout timeout = NPT_TIMEOUT_INFINITE);
+
+ protected:
+ // members
+ NPT_String m_MimeType;
+ bool m_Aborted;
+ NPT_SharedVariable m_FrameIndex;
+ NPT_DataBuffer m_Frame;
+ NPT_Mutex m_FrameLock;
+ NPT_AtomicVariable m_Readers;
+};
+
+#endif // _PLT_FRAME_BUFFER_H_
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltFrameServer.cpp b/lib/libUPnP/Platinum/Source/Extras/PltFrameServer.cpp
new file mode 100644
index 0000000..d01d414
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltFrameServer.cpp
@@ -0,0 +1,236 @@
+/*****************************************************************
+|
+| Platinum - Frame Server
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltFrameStream.h"
+#include "PltFrameServer.h"
+#include "PltUtilities.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.frame")
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define BOUNDARY "BOUNDARYGOAWAY"
+
+/*----------------------------------------------------------------------
+| PLT_SocketPolicyServer
++---------------------------------------------------------------------*/
+class PLT_SocketPolicyServer : public NPT_Thread
+{
+public:
+ PLT_SocketPolicyServer(const char* policy,
+ NPT_IpPort port = 0,
+ const char* authorized_ports = "5900") :
+ m_Socket(NPT_SOCKET_FLAG_CANCELLABLE),
+ m_Policy(policy),
+ m_Port(port),
+ m_AuthorizedPorts(authorized_ports),
+ m_Aborted(false) {}
+
+ ~PLT_SocketPolicyServer() {
+ Stop();
+ }
+
+ NPT_Result Start() {
+ NPT_Result result = NPT_FAILURE;
+
+ // bind
+ // randomly try a port for our http server
+ int retries = 100;
+ do {
+ int random = NPT_System::GetRandomInteger();
+ NPT_IpPort port = (unsigned short)(50000 + (random % 15000));
+
+ result = m_Socket.Bind(
+ NPT_SocketAddress(NPT_IpAddress::Any, m_Port?m_Port:port),
+ false);
+
+ if (NPT_SUCCEEDED(result) || m_Port)
+ break;
+ } while (--retries > 0);
+
+ if (NPT_FAILED(result) || retries == 0) return NPT_FAILURE;
+
+ // remember that we're bound
+ NPT_SocketInfo info;
+ m_Socket.GetInfo(info);
+ m_Port = info.local_address.GetPort();
+
+ return NPT_Thread::Start();
+ }
+
+ NPT_Result Stop() {
+ m_Aborted = true;
+ m_Socket.Cancel();
+
+ return Wait();
+ }
+
+ 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);
+ }
+
+ NPT_TcpServerSocket m_Socket;
+ NPT_String m_Policy;
+ NPT_IpPort m_Port;
+ NPT_String m_AuthorizedPorts;
+ bool m_Aborted;
+};
+
+/*----------------------------------------------------------------------
+| PLT_HttpStreamRequestHandler::SetupResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_HttpStreamRequestHandler::SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response)
+{
+ PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, "PLT_HttpStreamRequestHandler::SetupResponse:", &request);
+
+ if (request.GetMethod().Compare("GET") &&
+ request.GetMethod().Compare("HEAD")) {
+ return NPT_FAILURE;
+ }
+
+ NPT_Reference<PLT_FrameBuffer> buffer;
+ if (!m_StreamValidator.OnNewRequestAccept(request, context, response, buffer)) {
+ return NPT_ERROR_NO_SUCH_ITEM;
+ }
+
+ response.SetProtocol(NPT_HTTP_PROTOCOL_1_0);
+ response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONNECTION, "close");
+ response.GetHeaders().SetHeader("Cache-Control", "no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0");
+ response.GetHeaders().SetHeader("Pragma", "no-cache");
+ response.GetHeaders().SetHeader("Expires", "Tue, 4 Jan 2000 02:43:05 GMT");
+
+ // HEAD request has no entity or if status code is not 2xx
+ if (!request.GetMethod().Compare("HEAD") || response.GetStatusCode()/100 != 2)
+ return NPT_SUCCESS;
+
+ NPT_HttpEntity* entity = response.GetEntity();
+ NPT_CHECK_POINTER_FATAL(entity);
+ entity->SetContentType("multipart/x-mixed-replace;boundary=" BOUNDARY);
+
+ NPT_InputStreamReference body(new PLT_InputFrameStream(buffer, BOUNDARY));
+ entity->SetInputStream(body, false);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameServer::PLT_FrameServer
++---------------------------------------------------------------------*/
+PLT_FrameServer::PLT_FrameServer(const char* resource_name,
+ PLT_StreamValidator& stream_validator,
+ NPT_IpAddress address,
+ NPT_UInt16 port,
+ bool policy_server_enabled) :
+ PLT_HttpServer(address, port, false),
+ m_PolicyServer(NULL),
+ m_StreamValidator(stream_validator),
+ m_PolicyServerEnabled(policy_server_enabled)
+{
+ NPT_String resource(resource_name);
+ resource.Trim("/\\");
+ AddRequestHandler(
+ new PLT_HttpStreamRequestHandler(stream_validator),
+ "/" + resource,
+ true,
+ true);
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameServer::~PLT_FrameServer
++---------------------------------------------------------------------*/
+PLT_FrameServer::~PLT_FrameServer()
+{
+ delete m_PolicyServer;
+}
+
+/*----------------------------------------------------------------------
+| PLT_FrameServer::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_FrameServer::Start()
+{
+ // start main server so we can get the listening port
+ NPT_CHECK_SEVERE(PLT_HttpServer::Start());
+
+ // start the xml socket policy server for flash
+ if (m_PolicyServerEnabled) {
+ m_PolicyServer = new PLT_SocketPolicyServer(
+ "",
+ 8989,
+ "5900,"+NPT_String::FromInteger(GetPort()));
+ NPT_CHECK_SEVERE(m_PolicyServer->Start());
+ }
+
+ return NPT_SUCCESS;
+}
+
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltFrameServer.h b/lib/libUPnP/Platinum/Source/Extras/PltFrameServer.h
new file mode 100644
index 0000000..e5c1192
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltFrameServer.h
@@ -0,0 +1,103 @@
+/*****************************************************************
+|
+| Platinum - Frame Server
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_FRAME_SERVER_H_
+#define _PLT_FRAME_SERVER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltHttpServer.h"
+#include "PltFrameBuffer.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_SocketPolicyServer;
+
+/*----------------------------------------------------------------------
+| PLT_StreamValidator class
++---------------------------------------------------------------------*/
+class PLT_StreamValidator
+{
+public:
+ virtual ~PLT_StreamValidator() {}
+ virtual bool OnNewRequestAccept(const NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response,
+ NPT_Reference<PLT_FrameBuffer>& buffer) = 0;
+};
+
+/*----------------------------------------------------------------------
+| PLT_HttpStreamRequestHandler
++---------------------------------------------------------------------*/
+class PLT_HttpStreamRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+ // constructor
+ PLT_HttpStreamRequestHandler(PLT_StreamValidator& stream_validator) :
+ m_StreamValidator(stream_validator) {}
+
+ // NPT_HttpRequestHandler methods
+ NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) override;
+
+private:
+ PLT_StreamValidator& m_StreamValidator;
+};
+
+/*----------------------------------------------------------------------
+| PLT_FrameServer class
++---------------------------------------------------------------------*/
+class PLT_FrameServer : public PLT_HttpServer
+{
+public:
+ PLT_FrameServer(const char* resource_name,
+ PLT_StreamValidator& stream_validator,
+ NPT_IpAddress address = NPT_IpAddress::Any,
+ NPT_UInt16 port = 0,
+ bool policy_server_enabled = false);
+ ~PLT_FrameServer() override;
+
+ NPT_Result Start() override;
+
+protected:
+ PLT_SocketPolicyServer* m_PolicyServer;
+ PLT_StreamValidator& m_StreamValidator;
+ bool m_PolicyServerEnabled;
+};
+
+#endif /* _PLT_FRAME_SERVER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltFrameStream.cpp b/lib/libUPnP/Platinum/Source/Extras/PltFrameStream.cpp
new file mode 100644
index 0000000..2b3b3e1
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltFrameStream.cpp
@@ -0,0 +1,128 @@
+/*****************************************************************
+|
+| Platinum - Frame Stream
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltFrameStream.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.framestream")
+
+/*----------------------------------------------------------------------
+| PLT_InputFrameStream::PLT_InputFrameStream
++---------------------------------------------------------------------*/
+PLT_InputFrameStream::PLT_InputFrameStream(NPT_Reference<PLT_FrameBuffer>& frame_buffer,
+ const char* boundary) :
+ m_FrameBuffer(frame_buffer),
+ m_LastFrameIndex(0),
+ m_Boundary(boundary),
+ m_Eos(false)
+{
+ m_FrameBuffer->AddReader();
+}
+
+/*----------------------------------------------------------------------
+| PLT_InputFrameStream::~PLT_InputFrameStream
++---------------------------------------------------------------------*/
+PLT_InputFrameStream::~PLT_InputFrameStream()
+{
+ m_FrameBuffer->RemoveReader();
+}
+
+/*----------------------------------------------------------------------
+| PLT_InputFrameStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_InputFrameStream::GetAvailable(NPT_LargeSize& available)
+{
+ NPT_CHECK_WARNING(m_Part.GetAvailable(available));
+
+ if (available == 0 && !m_Eos) {
+ NPT_CHECK_WARNING(FillBuffer());
+ NPT_CHECK_WARNING(m_Part.GetAvailable(available));
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_InputFrameStream::FillBuffer
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_InputFrameStream::FillBuffer()
+{
+ // reset memorystream
+ m_Part.SetDataSize(0);
+
+ // fetch next frame
+ NPT_DataBuffer frame;
+ NPT_Result result = m_FrameBuffer->GetNextFrame(m_LastFrameIndex, frame);
+
+ // error (EOS) or empty frame means we're done
+ if (NPT_FAILED(result) || frame.GetDataSize() == 0) {
+ m_Part.WriteLine("--" + m_Boundary + "--");
+ m_Eos = true;
+ return NPT_SUCCESS;
+ }
+
+ m_Part.WriteLine("--" + m_Boundary);
+ m_Part.WriteLine("Content-Type: " + NPT_String(m_FrameBuffer->GetMimeType()));
+ m_Part.WriteLine("Content-Length: "+NPT_String::FromInteger(frame.GetDataSize()));
+ m_Part.WriteLine("");
+ m_Part.Write(frame.GetData(), frame.GetDataSize());
+ m_Part.WriteLine("");
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_InputFrameStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_InputFrameStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read /*= 0*/)
+{
+
+ if (bytes_read) *bytes_read = 0;
+
+ if (bytes_to_read == 0) {
+ return NPT_SUCCESS;
+ }
+
+ // make sure we have data
+ NPT_LargeSize available;
+ NPT_CHECK_WARNING(GetAvailable(available));
+
+ return m_Part.Read(buffer, bytes_to_read, bytes_read);
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltFrameStream.h b/lib/libUPnP/Platinum/Source/Extras/PltFrameStream.h
new file mode 100644
index 0000000..6d6deb8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltFrameStream.h
@@ -0,0 +1,79 @@
+/*****************************************************************
+|
+| Platinum - Frame Stream
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_FRAMESTREAM_H_
+#define _PLT_FRAMESTREAM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltFrameBuffer.h"
+
+/*----------------------------------------------------------------------
+| PLT_InputFrameStream
++---------------------------------------------------------------------*/
+class PLT_InputFrameStream : public NPT_InputStream
+{
+public:
+ // methods
+ PLT_InputFrameStream(NPT_Reference<PLT_FrameBuffer>& frame_buffer,
+ const char* boundary);
+ ~PLT_InputFrameStream() override;
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = 0) override;
+
+ NPT_Result Seek(NPT_Position offset) override { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+ NPT_Result Skip(NPT_Size offset) override { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+ NPT_Result Tell(NPT_Position& offset) override { NPT_COMPILER_UNUSED(offset); return NPT_FAILURE; }
+ NPT_Result GetSize(NPT_LargeSize& size) override { NPT_COMPILER_UNUSED(size); return NPT_FAILURE; }
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+
+private:
+ NPT_Result FillBuffer();
+
+protected:
+ NPT_Reference<PLT_FrameBuffer> m_FrameBuffer;
+ NPT_MemoryStream m_Part;
+ NPT_UInt32 m_LastFrameIndex;
+ NPT_String m_Boundary;
+ bool m_Eos;
+};
+
+typedef NPT_Reference<PLT_InputFrameStream> PLT_InputFrameStreamReference;
+
+#endif /* _PLT_FRAMESTREAM_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltLeaks.cpp b/lib/libUPnP/Platinum/Source/Extras/PltLeaks.cpp
new file mode 100644
index 0000000..91b1b99
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltLeaks.cpp
@@ -0,0 +1,99 @@
+/*****************************************************************
+|
+| Platinum - Leaks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltLeaks.h"
+
+#if defined(WIN32)
+#include <crtdbg.h>
+#include <stdio.h>
+#include "string.h"
+
+/*----------------------------------------------------------------------
+| PLT_Leak_AllocHook
++---------------------------------------------------------------------*/
+int PLT_Leak_AllocHook(int alloc_type,
+ void* user_data,
+ size_t size,
+ int block_type,
+ long request_number,
+ const unsigned char* filename,
+ int line_number)
+{
+ (void)alloc_type;
+ (void)user_data;
+ (void)size;
+ (void)block_type;
+ (void)request_number;
+ (void)line_number;
+ (void)filename;
+ /*
+ * if (request_number == 34556)
+ * return 2;
+ *
+ */
+ return 1;
+}
+
+/*----------------------------------------------------------------------
+| PLT_Leak_Enable
++---------------------------------------------------------------------*/
+void
+PLT_Leak_Enable(void)
+{
+#if defined(_DEBUG)
+ /*
+ * If you want VC to dump file name and line number of leaking resource
+ * use #define _CRTDBG_MAP_ALLOC in suspected file (project)
+ * and #include "crtdbg.h" in suspected file
+ */
+_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF |
+ _CRTDBG_CHECK_ALWAYS_DF |
+ _CRTDBG_LEAK_CHECK_DF);
+
+_CrtSetAllocHook(PLT_Leak_AllocHook );
+
+#endif
+}
+#else
+/*----------------------------------------------------------------------
+| PLT_Leak_Enable
++---------------------------------------------------------------------*/
+void
+PLT_Leak_Enable(void)
+{
+}
+#endif
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltLeaks.h b/lib/libUPnP/Platinum/Source/Extras/PltLeaks.h
new file mode 100644
index 0000000..73d1e3a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltLeaks.h
@@ -0,0 +1,51 @@
+/*****************************************************************
+|
+| Platinum - Leaks
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_LEAKS_H_
+#define _PLT_LEAKS_H_
+
+/*----------------------------------------------------------------------
+| functions
++---------------------------------------------------------------------*/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void PLT_Leak_Enable(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _PLT_LEAKS_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.cpp b/lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.cpp
new file mode 100644
index 0000000..b7d0312
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.cpp
@@ -0,0 +1,90 @@
+/*****************************************************************
+|
+| Platinum - Metadata Handler
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltMetadataHandler.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.metadata.handler")
+
+/*----------------------------------------------------------------------
+| PLT_MetadataHandler::Load
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MetadataHandler::Load(const char* filename)
+{
+ NPT_File file(filename);
+ NPT_Result res = file.Open(NPT_FILE_OPEN_MODE_READ);
+ if (res != NPT_SUCCESS) {
+ NPT_LOG_SEVERE_2("error %d opening : %s\n", res, filename);
+ } else {
+ NPT_InputStreamReference stream;
+ res = file.GetInputStream(stream);
+ if (NPT_FAILED(res)) {
+ NPT_LOG_SEVERE_2("error %d getting input stream: %s\n", res, filename);
+ }
+ res = Load(*stream);
+ if (NPT_FAILED(res)) {
+ NPT_LOG_SEVERE_2("error %d reading header: %s\n", res, filename);
+ }
+ }
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_MetadataHandler::Save
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_MetadataHandler::Save(const char* filename)
+{
+ NPT_File file(filename);
+ NPT_Result res = file.Open(NPT_FILE_OPEN_MODE_WRITE);
+ if (res != NPT_SUCCESS) {
+ NPT_LOG_SEVERE_2("error %d opening : %s\n", res, filename);
+ } else {
+ NPT_OutputStreamReference stream;
+ res = file.GetOutputStream(stream);
+ if (NPT_FAILED(res)) {
+ NPT_LOG_SEVERE_2("error %d getting output stream: %s\n", res, filename);
+ }
+ res = Save(*stream);
+ if (NPT_FAILED(res)) {
+ NPT_LOG_SEVERE_2("error %d writing header: %s\n", res, filename);
+ }
+ }
+
+ return res;
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.h b/lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.h
new file mode 100644
index 0000000..d1709bd
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltMetadataHandler.h
@@ -0,0 +1,91 @@
+/*****************************************************************
+|
+| Platinum - Metadata Handler
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_METADATA_HANDLER_H_
+#define _PLT_METADATA_HANDLER_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_MetadataHandler class
++---------------------------------------------------------------------*/
+class PLT_MetadataHandler
+{
+public:
+ virtual ~PLT_MetadataHandler() {}
+
+ // metadata overridables
+ virtual bool HandleExtension(const char* extension) = 0;
+ virtual NPT_Result Load(NPT_InputStream& stream,
+ NPT_TimeInterval sleeptime = NPT_TimeInterval(.01),
+ NPT_TimeInterval timeout = NPT_TimeInterval(30.)) = 0;
+ virtual NPT_Result Save(NPT_OutputStream& stream,
+ NPT_TimeInterval sleeptime = NPT_TimeInterval(.01),
+ NPT_TimeInterval timeout = NPT_TimeInterval(30.)) = 0;
+
+ virtual const char* GetLicenseData(NPT_String& licenseData) = 0;
+ virtual NPT_Result GetCoverArtData(char*& caData, int& len) = 0;
+ virtual const char* GetContentID(NPT_String& value) = 0;
+ virtual const char* GetTitle(NPT_String& value) = 0;
+ virtual const char* GetDescription(NPT_String& value) = 0;
+ virtual NPT_Result GetDuration(NPT_UInt32& seconds) = 0;
+ virtual const char* GetProtection(NPT_String& protection) = 0;
+ virtual NPT_Result GetYear(NPT_Size& year) = 0;
+
+ // helper functions
+ virtual NPT_Result Load(const char* filename);
+ virtual NPT_Result Save(const char* filename);
+};
+
+/*----------------------------------------------------------------------
+| PLT_MetadataHandlerFinder
++---------------------------------------------------------------------*/
+class PLT_MetadataHandlerFinder
+{
+public:
+ // methods
+ PLT_MetadataHandlerFinder(const char* extension) : m_Extension(extension) {}
+ bool operator()(PLT_MetadataHandler* const & handler) const {
+ return handler->HandleExtension(m_Extension) ? true : false;
+ }
+
+private:
+ // members
+ NPT_String m_Extension;
+};
+
+#endif /* _PLT_METADATA_HANDLER_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.cpp b/lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.cpp
new file mode 100644
index 0000000..92eb355
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.cpp
@@ -0,0 +1,255 @@
+/*****************************************************************
+|
+| Platinum - Ring Buffer Stream
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltRingBufferStream.h"
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| defines
++---------------------------------------------------------------------*/
+#ifdef max
+#undef max
+#endif
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+
+#ifdef min
+#undef min
+#endif
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream::PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::PLT_RingBufferStream(NPT_Size buffer_size,
+ bool blocking /* = true */) :
+ m_TotalBytesRead(0),
+ m_TotalBytesWritten(0),
+ m_Blocking(blocking),
+ m_Eos(false),
+ m_Aborted(false)
+{
+ m_RingBuffer = new NPT_RingBuffer(buffer_size);
+}
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream::PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::PLT_RingBufferStream(NPT_RingBufferReference& buffer,
+ bool blocking /* = true */) :
+ m_RingBuffer(buffer),
+ m_TotalBytesRead(0),
+ m_TotalBytesWritten(0),
+ m_Blocking(blocking),
+ m_Eos(false),
+ m_Aborted(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream::~PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::~PLT_RingBufferStream()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_RingBufferStream::Read(void* buffer,
+ NPT_Size max_bytes_to_read,
+ NPT_Size* _bytes_read /*= NULL*/)
+{
+ NPT_Size bytes_to_read;
+ NPT_Size bytes_read = 0;
+
+ // reset output param first
+ if (_bytes_read) *_bytes_read = 0;
+
+ // wait for data
+ do {
+ {
+ NPT_AutoLock autoLock(m_Lock);
+
+ if (m_Aborted) {
+ return NPT_ERROR_INTERRUPTED;
+ }
+
+ // check for data
+ if (m_RingBuffer->GetAvailable())
+ break;
+
+ if (m_Eos) {
+ return NPT_ERROR_EOS;
+ } else if (!m_Blocking) {
+ return NPT_ERROR_WOULD_BLOCK;
+ }
+ }
+
+ // sleep and try again
+ NPT_System::Sleep(NPT_TimeInterval(.1));
+ } while (1);
+
+ {
+ NPT_AutoLock autoLock(m_Lock);
+
+ // try twice in case available data was not contiguous
+ for (int i=0; i<2; i++) {
+ bytes_to_read = min(max_bytes_to_read - bytes_read, m_RingBuffer->GetContiguousAvailable());
+
+ // break if nothing to read the second time
+ if (bytes_to_read == 0) break;
+
+ // read into buffer and advance
+ NPT_CHECK(m_RingBuffer->Read((unsigned char*)buffer+bytes_read, bytes_to_read));
+
+ // keep track of the total bytes we have read so far
+ m_TotalBytesRead += bytes_to_read;
+ bytes_read += bytes_to_read;
+
+ if (_bytes_read) *_bytes_read += bytes_to_read;
+ }
+ }
+
+ // we have read some chars, so return success
+ // even if we have read less than asked
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_RingBufferStream::Write(const void* buffer,
+ NPT_Size max_bytes_to_write,
+ NPT_Size* _bytes_written /*= NULL*/)
+{
+ NPT_Size bytes_to_write;
+ NPT_Size bytes_written = 0;
+
+ // reset output param first
+ if (_bytes_written) *_bytes_written = 0;
+
+ // wait for space
+ do {
+ {
+ NPT_AutoLock autoLock(m_Lock);
+
+ if (m_Aborted) {
+ return NPT_ERROR_INTERRUPTED;
+ }
+
+ // return immediately if we are told we're finished
+ if (m_Eos) {
+ return NPT_ERROR_EOS;
+ }
+
+ if (m_RingBuffer->GetSpace())
+ break;
+
+ if (!m_Blocking) {
+ return NPT_ERROR_WOULD_BLOCK;
+ }
+ }
+
+ // sleep and try again
+ NPT_System::Sleep(NPT_TimeInterval(.1));
+ } while (1);
+
+ {
+ NPT_AutoLock autoLock(m_Lock);
+
+ // try twice in case available space was not contiguous
+ for (int i=0; i<2; i++) {
+ bytes_to_write = min(max_bytes_to_write - bytes_written, m_RingBuffer->GetContiguousSpace());
+
+ // break if no space to write the second time
+ if (bytes_to_write == 0) break;
+
+ // write into buffer
+ NPT_CHECK(m_RingBuffer->Write((unsigned char*)buffer+bytes_written, bytes_to_write));
+
+ m_TotalBytesWritten += bytes_to_write;
+ bytes_written += bytes_to_write;
+
+ if (_bytes_written) *_bytes_written += bytes_to_write;
+ }
+ }
+
+ // we have written some chars, so return success
+ // even if we have written less than provided
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_RingBufferStream::Flush()
+{
+ NPT_AutoLock autoLock(m_Lock);
+
+ m_RingBuffer->Flush();
+ m_TotalBytesRead = 0;
+ m_TotalBytesWritten = 0;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream::SetEOS
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_RingBufferStream::SetEOS()
+{
+ NPT_AutoLock autoLock(m_Lock);
+
+ m_Eos = true;
+ return NPT_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+ | PLT_RingBufferStream::Abort
+ +---------------------------------------------------------------------*/
+NPT_Result
+PLT_RingBufferStream::Abort()
+{
+ NPT_AutoLock autoLock(m_Lock);
+
+ m_Aborted = true;
+ return NPT_SUCCESS;
+}
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.h b/lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.h
new file mode 100644
index 0000000..bd56b8a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltRingBufferStream.h
@@ -0,0 +1,119 @@
+/*****************************************************************
+|
+| Platinum - Ring buffer stream
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_RING_BUFFER_STREAM_H_
+#define _PLT_RING_BUFFER_STREAM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_RingBufferStream class
++---------------------------------------------------------------------*/
+class PLT_RingBufferStream : public NPT_DelegatingInputStream,
+ public NPT_DelegatingOutputStream
+{
+public:
+ PLT_RingBufferStream(NPT_Size buffer_size = 4096, bool blocking = true);
+ PLT_RingBufferStream(NPT_RingBufferReference& buffer, bool blocking = true);
+ ~PLT_RingBufferStream() override;
+
+ // methods
+ bool IsAborted() { return m_Aborted; }
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read = NULL) override;
+ NPT_Result GetSize(NPT_LargeSize& size) override {
+ NPT_COMPILER_UNUSED(size);
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+ NPT_Result GetSpace(NPT_LargeSize& space) {
+ NPT_AutoLock autoLock(m_Lock);
+ space = m_RingBuffer->GetSpace();
+ return NPT_SUCCESS;
+ }
+ NPT_Result GetAvailable(NPT_LargeSize& available) override {
+ NPT_AutoLock autoLock(m_Lock);
+ available = m_RingBuffer->GetAvailable();
+ return NPT_SUCCESS;
+ }
+
+ // NPT_OutputStream methods
+ NPT_Result Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written = NULL) override;
+ NPT_Result Flush() override;
+ NPT_Result SetEOS();
+ NPT_Result Abort();
+
+protected:
+ // NPT_DelegatingInputStream methods
+ NPT_Result InputSeek(NPT_Position offset) override {
+ NPT_COMPILER_UNUSED(offset);
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+ NPT_Result InputTell(NPT_Position& offset) override {
+ NPT_AutoLock autoLock(m_Lock);
+ offset = m_TotalBytesRead;
+ return NPT_SUCCESS;
+ }
+
+ // NPT_DelegatingOutputStream methods
+ NPT_Result OutputSeek(NPT_Position offset) override {
+ NPT_COMPILER_UNUSED(offset);
+ return NPT_ERROR_NOT_SUPPORTED;
+ }
+ NPT_Result OutputTell(NPT_Position& offset) override {
+ NPT_AutoLock autoLock(m_Lock);
+ offset = m_TotalBytesWritten;
+ return NPT_SUCCESS;
+ }
+
+private:
+ NPT_RingBufferReference m_RingBuffer;
+ NPT_Offset m_TotalBytesRead;
+ NPT_Offset m_TotalBytesWritten;
+ NPT_Mutex m_Lock;
+ bool m_Blocking;
+ bool m_Eos;
+ bool m_Aborted;
+};
+
+typedef NPT_Reference<PLT_RingBufferStream> PLT_RingBufferStreamReference;
+
+#endif // _PLT_RING_BUFFER_STREAM_H_
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltStreamPump.cpp b/lib/libUPnP/Platinum/Source/Extras/PltStreamPump.cpp
new file mode 100644
index 0000000..80d1614
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltStreamPump.cpp
@@ -0,0 +1,227 @@
+/*****************************************************************
+|
+| Platinum - Stream Pump
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltStreamPump.h"
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_StreamPump::PLT_StreamPump
++---------------------------------------------------------------------*/
+PLT_StreamPump::PLT_StreamPump(NPT_Size size) :
+ m_TotalBytesRead(0),
+ m_TotalBytesWritten(0)
+{
+ m_RingBuffer = new NPT_RingBuffer(size);
+}
+
+/*----------------------------------------------------------------------
+| PLT_StreamPump::~PLT_StreamPump
++---------------------------------------------------------------------*/
+PLT_StreamPump::~PLT_StreamPump()
+{
+ delete m_RingBuffer;
+}
+/*----------------------------------------------------------------------+
+| PLT_StreamPump::PushData
++----------------------------------------------------------------------*/
+NPT_Result
+PLT_StreamPump::PushData(NPT_OutputStream& output,
+ NPT_Size& bytes_written)
+{
+ NPT_Result res = NPT_ERROR_WOULD_BLOCK;
+ NPT_Size count = 0;
+ NPT_Size bytes_available = m_RingBuffer->GetContiguousAvailable();
+
+ bytes_written = 0;
+
+ if (bytes_available) {
+ res = output.Write(m_RingBuffer->GetReadPointer(), bytes_available, &count);
+ m_RingBuffer->MoveOut(count);
+ bytes_written += count;
+
+ // check if we wrapped around
+ bytes_available = m_RingBuffer->GetContiguousAvailable();
+ if (NPT_SUCCEEDED(res) && bytes_available) {
+ res = output.Write(m_RingBuffer->GetReadPointer(), bytes_available, &count);
+ m_RingBuffer->MoveOut(count);
+ bytes_written += count;
+ }
+ }
+
+ m_TotalBytesWritten += bytes_written;
+
+ return res;
+}
+
+/*----------------------------------------------------------------------+
+| PLT_StreamPump::PullData
++----------------------------------------------------------------------*/
+NPT_Result
+PLT_StreamPump::PullData(NPT_InputStream& input,
+ NPT_Size max_bytes_to_read)
+{
+ NPT_Result res = NPT_ERROR_WOULD_BLOCK;
+ NPT_Size byte_space = m_RingBuffer->GetContiguousSpace();
+
+ // check that there is space left
+ // make sure we don't read more than our contiguous space
+ NPT_Size nb_to_read = (max_bytes_to_read<byte_space)?max_bytes_to_read:byte_space;
+ if (nb_to_read > 0) {
+ NPT_Size count;
+ res = input.Read(m_RingBuffer->GetWritePointer(), nb_to_read, &count);
+ m_RingBuffer->MoveIn(count);
+ max_bytes_to_read -= count;
+ m_TotalBytesRead += count;
+
+ byte_space = m_RingBuffer->GetContiguousSpace();
+ nb_to_read = (max_bytes_to_read<byte_space)?max_bytes_to_read:byte_space;
+ // if we filled our contiguous space, and we wrapped, check if there is more to read
+ if (NPT_SUCCEEDED(res) && (nb_to_read > 0)) {
+ res = input.Read(m_RingBuffer->GetWritePointer(), nb_to_read, &count);
+ m_RingBuffer->MoveIn(count);
+ m_TotalBytesRead += count;
+ }
+ }
+
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_PipeInputStreamPump::PLT_PipeInputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeInputStreamPump::PLT_PipeInputStreamPump(NPT_OutputStreamReference& output,
+ NPT_Size size) :
+ PLT_StreamPump(size),
+ m_Output(output),
+ m_LastRes(NPT_SUCCESS)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_PipeInputStreamPump::~PLT_PipeInputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeInputStreamPump::~PLT_PipeInputStreamPump()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_PipeInputStreamPump::Receive
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PipeInputStreamPump::Receive(NPT_InputStream& input,
+ NPT_Size max_bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ NPT_Size count;
+ NPT_Result res;
+
+ if ((m_LastRes == NPT_SUCCESS) || (m_LastRes == NPT_ERROR_WOULD_BLOCK)) {
+ // look at what we have buffered already from out input
+ // and if have less than what was asked, read more
+ NPT_Size available = m_RingBuffer->GetAvailable();
+ if (available < max_bytes_to_read) {
+ m_LastRes = PullData(input, max_bytes_to_read-available);
+ }
+ } else if (!m_RingBuffer->GetAvailable()) {
+ // if the buffer is now empty, return the input last error
+ return m_LastRes;
+ }
+
+ // write as much as we can on the output stream
+ res = PushData(*m_Output, count);
+
+ if (bytes_read) *bytes_read = count;
+ return res;
+}
+
+
+/*----------------------------------------------------------------------
+| PLT_PipeOutputStreamPump::PLT_PipeOutputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeOutputStreamPump::PLT_PipeOutputStreamPump(NPT_InputStreamReference& input,
+ NPT_Size size /* 65535 */,
+ NPT_Size max_bytes_to_read /* = 0 */) :
+ PLT_StreamPump(size),
+ m_Input(input),
+ m_MaxBytesToRead(max_bytes_to_read),
+ m_LastRes(NPT_SUCCESS)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_PipeOutputStreamPump::~PLT_PipeOutputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeOutputStreamPump::~PLT_PipeOutputStreamPump()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_PipeOutputStreamPump::Transmit
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_PipeOutputStreamPump::Transmit(NPT_OutputStream& output)
+{
+ NPT_Size count;
+ NPT_Result res;
+
+ if ((m_LastRes == NPT_SUCCESS) || (m_LastRes == NPT_ERROR_WOULD_BLOCK)) {
+ // fill the entire space by default
+ NPT_Size max_space = m_RingBuffer->GetSpace();
+ if (max_space) {
+ NPT_Size max_to_read = max_space;
+ if (m_MaxBytesToRead != 0) {
+ // if a total maximum amount was set, make sure we don't read more
+ max_to_read = ((m_MaxBytesToRead - m_TotalBytesRead) < max_space) ? (m_MaxBytesToRead - m_TotalBytesRead) : max_space;
+ }
+
+ // any data to read
+ if (max_to_read) {
+ m_LastRes = PullData(*m_Input, max_to_read);
+ } else {
+ m_LastRes = NPT_ERROR_EOS;
+ }
+ }
+ } else if (!m_RingBuffer->GetAvailable()) {
+ // if the buffer is now empty, return the input last error
+ return m_LastRes;
+ }
+
+ // write as much as we can on the output stream
+ res = PushData(output, count);
+ return res;
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Extras/PltStreamPump.h b/lib/libUPnP/Platinum/Source/Extras/PltStreamPump.h
new file mode 100644
index 0000000..f8fa719
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Extras/PltStreamPump.h
@@ -0,0 +1,131 @@
+/*****************************************************************
+|
+| Platinum - Stream Pump
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_STREAM_PUMP_H_
+#define _PLT_STREAM_PUMP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+| PLT_PipeInputStream
++---------------------------------------------------------------------*/
+class PLT_PipeInputStream
+{
+public:
+ // constructor and destructor
+ virtual ~PLT_PipeInputStream() {};
+
+ // methods
+ virtual NPT_Result Receive(NPT_InputStream& stream, NPT_Size max_bytes_to_read, NPT_Size* bytes_read = 0) = 0;
+};
+
+typedef NPT_Reference<PLT_PipeInputStream> PLT_PipeInputStreamReference;
+
+/*----------------------------------------------------------------------
+| PLT_PipeOutputStream
++---------------------------------------------------------------------*/
+class PLT_PipeOutputStream
+{
+public:
+ // constructor and destructor
+ virtual ~PLT_PipeOutputStream() {};
+
+ // methods
+ virtual NPT_Result Transmit(NPT_OutputStream& stream) = 0;
+};
+
+typedef NPT_Reference<PLT_PipeOutputStream> PLT_PipeOutputStreamReference;
+
+/*----------------------------------------------------------------------
+| PLT_StreamPump class
++---------------------------------------------------------------------*/
+class PLT_StreamPump
+{
+public:
+ virtual ~PLT_StreamPump();
+
+protected:
+ // methods
+ PLT_StreamPump(NPT_Size size = 65535);
+ NPT_Result PullData(NPT_InputStream& input, NPT_Size max_bytes_to_read);
+ NPT_Result PushData(NPT_OutputStream& output, NPT_Size& bytes_written);
+
+ // members
+ NPT_RingBuffer* m_RingBuffer;
+ NPT_Offset m_TotalBytesRead;
+ NPT_Offset m_TotalBytesWritten;
+};
+
+/*----------------------------------------------------------------------
+| PLT_PipeInputStreamPump class
++---------------------------------------------------------------------*/
+class PLT_PipeInputStreamPump : public PLT_StreamPump,
+ public PLT_PipeInputStream
+{
+public:
+ PLT_PipeInputStreamPump(NPT_OutputStreamReference& output, NPT_Size size = 65535);
+ ~PLT_PipeInputStreamPump() override;
+
+ NPT_Result Receive(NPT_InputStream& input, NPT_Size max_bytes_to_read, NPT_Size* bytes_read) override;
+
+protected:
+ NPT_OutputStreamReference m_Output;
+ NPT_Result m_LastRes;
+};
+
+/*----------------------------------------------------------------------
+| PLT_PipeInputStreamPump class
++---------------------------------------------------------------------*/
+class PLT_PipeOutputStreamPump : public PLT_StreamPump,
+ public PLT_PipeOutputStream
+{
+public:
+ PLT_PipeOutputStreamPump(NPT_InputStreamReference& input,
+ NPT_Size size = 65535,
+ NPT_Size max_bytes_to_read = 0);
+ ~PLT_PipeOutputStreamPump() override;
+
+ NPT_Result Transmit(NPT_OutputStream& output) override;
+
+protected:
+ NPT_InputStreamReference m_Input;
+ NPT_Size m_MaxBytesToRead;
+ NPT_Result m_LastRes;
+};
+
+
+#endif // _PLT_STREAM_PUMP_H_
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/AndroidManifest.xml b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/AndroidManifest.xml
new file mode 100644
index 0000000..a30a0a9
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.plutinosoft.platinum"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name">
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Android.mk b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Android.mk
new file mode 100644
index 0000000..e39fe62
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Android.mk
@@ -0,0 +1,52 @@
+LOCAL_PATH := $(call my-dir)
+
+PLT_ROOT := $(LOCAL_PATH)/../../../../../..
+PLT_SRC_ROOT := $(PLT_ROOT)/Source
+
+ifeq ($(NDK_DEBUG),1)
+PLT_PREBUILT_PATH := ../../../../../../Build/Targets/arm-android-linux/Debug
+else
+PLT_PREBUILT_PATH := ../../../../../../Build/Targets/arm-android-linux/Release
+endif
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := Platinum
+LOCAL_SRC_FILES := $(PLT_PREBUILT_PATH)/libPlatinum.a
+LOCAL_EXPORT_C_INCLUDES += $(PLT_SRC_ROOT)/Platinum
+LOCAL_EXPORT_C_INCLUDES += $(PLT_SRC_ROOT)/Core
+LOCAL_EXPORT_C_INCLUDES += $(PLT_SRC_ROOT)/Devices/MediaConnect
+LOCAL_EXPORT_C_INCLUDES += $(PLT_SRC_ROOT)/Devices/MediaServer
+LOCAL_EXPORT_C_INCLUDES += $(PLT_SRC_ROOT)/Devices/MediaRenderer
+LOCAL_EXPORT_C_INCLUDES += $(PLT_SRC_ROOT)/Extras
+LOCAL_C_INCLUDES += $(PLT_ROOT)/../Neptune/Source/Core
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := Neptune
+LOCAL_SRC_FILES := $(PLT_PREBUILT_PATH)/libNeptune.a
+LOCAL_EXPORT_C_INCLUDES += $(PLT_ROOT)/../Neptune/Source/Core
+include $(PREBUILT_STATIC_LIBRARY)
+
+ifneq ($(NPT_CONFIG_NO_SSL),1)
+include $(CLEAR_VARS)
+LOCAL_MODULE := axTLS
+LOCAL_SRC_FILES := $(PLT_PREBUILT_PATH)/libaxTLS.a
+include $(PREBUILT_STATIC_LIBRARY)
+endif
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := platinum-jni
+LOCAL_SRC_FILES := platinum-jni.cpp
+LOCAL_LDLIBS += -llog
+LOCAL_LDLIBS += -landroid
+
+LOCAL_CFLAGS += -DNPT_CONFIG_ENABLE_LOGGING
+
+LOCAL_STATIC_LIBRARIES := Platinum
+LOCAL_STATIC_LIBRARIES += Neptune
+
+ifneq ($(NPT_CONFIG_NO_SSL),1)
+LOCAL_STATIC_LIBRARIES += axTLS
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Application.mk b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Application.mk
new file mode 100644
index 0000000..d0a1e39
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := armeabi armeabi-v7a \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.cpp b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.cpp
new file mode 100644
index 0000000..eb5209a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.cpp
@@ -0,0 +1,81 @@
+/*****************************************************************
+|
+| Android JNI Interface
+|
+| (c) 2002-2012 Plutinosoft LLC
+| Author: Sylvain Rebaud (sylvain@plutinosoft.com)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include <assert.h>
+#include <jni.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "platinum-jni.h"
+#include "Platinum.h"
+
+#include <android/log.h>
+
+/*----------------------------------------------------------------------
+| logging
++---------------------------------------------------------------------*/
+NPT_SET_LOCAL_LOGGER("platinum.android.jni")
+
+/*----------------------------------------------------------------------
+| functions
++---------------------------------------------------------------------*/
+__attribute__((constructor)) static void onDlOpen(void)
+{
+}
+
+/*----------------------------------------------------------------------
+| JNI_OnLoad
++---------------------------------------------------------------------*/
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ NPT_LogManager::GetDefault().Configure("plist:.level=FINE;.handlers=ConsoleHandler;.ConsoleHandler.outputs=2;.ConsoleHandler.colors=false;.ConsoleHandler.filter=59");
+ return JNI_VERSION_1_4;
+}
+
+/*
+ * Class: com_plutinosoft_platinum_UPnP
+ * Method: _init
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_plutinosoft_platinum_UPnP__1init(JNIEnv *env, jclass)
+{
+ NPT_LOG_INFO("init");
+ PLT_UPnP* self = new PLT_UPnP();
+ return (jlong)self;
+}
+
+/*
+ * Class: com_plutinosoft_platinum_UPnP
+ * Method: _start
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_plutinosoft_platinum_UPnP__1start(JNIEnv *, jclass, jlong _self)
+{
+ NPT_LOG_INFO("start");
+ PLT_UPnP* self = (PLT_UPnP*)_self;
+
+ return self->Start();
+}
+
+/*
+ * Class: com_plutinosoft_platinum_UPnP
+ * Method: _stop
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_plutinosoft_platinum_UPnP__1stop(JNIEnv *, jclass, jlong _self)
+{
+ NPT_LOG_INFO("stop");
+ PLT_UPnP* self = (PLT_UPnP*)_self;
+
+ return self->Stop();
+}
+
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.h b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.h
new file mode 100644
index 0000000..ed96e1a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/platinum-jni.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_plutinosoft_platinum_UPnP */
+
+#ifndef _Included_com_plutinosoft_platinum_UPnP
+#define _Included_com_plutinosoft_platinum_UPnP
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_plutinosoft_platinum_UPnP
+ * Method: _init
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_plutinosoft_platinum_UPnP__1init
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_plutinosoft_platinum_UPnP
+ * Method: _start
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_plutinosoft_platinum_UPnP__1start
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_plutinosoft_platinum_UPnP
+ * Method: _stop
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_plutinosoft_platinum_UPnP__1stop
+ (JNIEnv *, jclass, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/update-header.sh b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/update-header.sh
new file mode 100644
index 0000000..4fd611d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/jni/update-header.sh
@@ -0,0 +1 @@
+javah -o platinum-jni.h -classpath ../bin/platinum.jar com.plutinosoft.platinum.UPnP
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/proguard-project.txt b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/project.properties b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/project.properties
new file mode 100644
index 0000000..03d0617
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/project.properties
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-10
+android.library=true
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-hdpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-ldpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-mdpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-xhdpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/layout/main.xml b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/layout/main.xml
new file mode 100644
index 0000000..bc12cd8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/layout/main.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/values/strings.xml b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/values/strings.xml
new file mode 100644
index 0000000..09d80ad
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="hello">Hello World!</string>
+ <string name="app_name">Platinum</string>
+
+</resources> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/src/com/plutinosoft/platinum/UPnP.java b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/src/com/plutinosoft/platinum/UPnP.java
new file mode 100644
index 0000000..fc285fe
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/module/platinum/src/com/plutinosoft/platinum/UPnP.java
@@ -0,0 +1,25 @@
+package com.plutinosoft.platinum;
+
+public class UPnP {
+ public UPnP() {
+ cSelf = _init();
+ }
+
+ public int start() {
+ return _start(cSelf);
+ }
+
+ public int stop() {
+ return _stop(cSelf);
+ }
+
+ // C glue
+ private static native long _init();
+ private static native int _start(long self);
+ private static native int _stop(long self);
+ private final long cSelf;
+
+ static {
+ System.loadLibrary("platinum-jni");
+ }
+}
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/AndroidManifest.xml b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/AndroidManifest.xml
new file mode 100644
index 0000000..af402dc
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.plutinosoft.platinum.sample"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".PlatinumUPnPActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/proguard-project.txt b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/project.properties b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/project.properties
new file mode 100644
index 0000000..69631c2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/project.properties
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-10
+android.library.reference.1=../../module/platinum
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-hdpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-ldpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-mdpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-xhdpi/ic_launcher.png b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/layout/main.xml b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/layout/main.xml
new file mode 100644
index 0000000..046546d
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/layout/main.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <Button
+ android:id="@+id/startStopButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:onClick="onStartStopButtonClicked"
+ android:text="Start" />
+
+ </RelativeLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/values/strings.xml b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/values/strings.xml
new file mode 100644
index 0000000..973f71e
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="hello">Hello World, PlatinumUPnPActivity!</string>
+ <string name="app_name">PlatinumUPnP</string>
+
+</resources> \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/src/com/plutinosoft/platinum/sample/PlatinumUPnPActivity.java b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/src/com/plutinosoft/platinum/sample/PlatinumUPnPActivity.java
new file mode 100644
index 0000000..baa3c5c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platform/Android/samples/sample-upnp/src/com/plutinosoft/platinum/sample/PlatinumUPnPActivity.java
@@ -0,0 +1,44 @@
+package com.plutinosoft.platinum.sample;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import com.plutinosoft.platinum.UPnP;
+
+public class PlatinumUPnPActivity extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ startStopButton = (Button)findViewById(R.id.startStopButton);
+ startStopButton.setEnabled(true);
+
+ upnp = new UPnP();
+ }
+
+ public void onStartStopButtonClicked(View button) {
+ if (isRunning) {
+ upnp.stop();
+ isRunning = false;
+ startStopButton.setText("Start`");
+ } else {
+ int result = upnp.start();
+ Log.d(TAG, "upnp.Start returned: " + result);
+ if (result == 0) {
+ isRunning = true;
+ startStopButton.setText("Stop");
+ }
+ }
+ }
+
+ private final String TAG = PlatinumUPnPActivity.this.getClass().getName();
+ private UPnP upnp;
+ private boolean isRunning;
+
+ private Button startStopButton;
+} \ No newline at end of file
diff --git a/lib/libUPnP/Platinum/Source/Platinum/Platinum.h b/lib/libUPnP/Platinum/Source/Platinum/Platinum.h
new file mode 100644
index 0000000..970cb8b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platinum/Platinum.h
@@ -0,0 +1,111 @@
+/*****************************************************************
+|
+| Platinum - Top Level Include
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+ ****************************************************************/
+/** @file
+ Master Header file included by Platinum client applications.
+
+ Client Applications should only need to include this file, as it
+ includes all the more specific include files required to use the API
+ */
+
+/**
+@mainpage Platinum UPnP SDK
+
+@section intro Introduction
+
+The Platinum SDK contains all the software components necessary to
+build and use the Platinum UPnP Framework. This includes
+the Platinum framework and the Neptune C++ runtime
+library.
+
+@section architecture Architecture
+
+The Platinum framework consists of a core framework that implements the UPnP
+core specifications including GENA, SOAP and SSDP. Building on top of that, the
+Platinum framework provides the foundation for UPnP AV Media Server and
+Media Renderer compliant implementations.
+
+The Platinum framework leverages the Neptune C++ runtime library which offers an
+elegant platform abstraction layer for multithreading, file system and
+network operations. Additionally, it provides support for XML parsing, string and time
+manipulation, template based linked-lists, stacks and arrays, and a configurable
+cross-platform logging system.
+
+*/
+
+#ifndef _PLATINUM_H_
+#define _PLATINUM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltCtrlPoint.h"
+#include "PltDeviceData.h"
+#include "PltHttpServer.h"
+#include "PltVersion.h"
+
+#include "PltMimeType.h"
+#include "PltProtocolInfo.h"
+#include "PltAction.h"
+#include "PltArgument.h"
+#include "PltConstants.h"
+#include "PltCtrlPointTask.h"
+#include "PltDatagramStream.h"
+#include "PltDeviceHost.h"
+#include "PltEvent.h"
+#include "PltHttp.h"
+#include "PltHttpClientTask.h"
+#include "PltHttpServer.h"
+#include "PltHttpServerTask.h"
+#include "PltService.h"
+#include "PltSsdp.h"
+#include "PltStateVariable.h"
+#include "PltTaskManager.h"
+#include "PltThreadTask.h"
+#include "PltUtilities.h"
+
+#include "PltMediaServer.h"
+#include "PltMediaBrowser.h"
+#include "PltMediaRenderer.h"
+#include "PltMediaController.h"
+#include "PltDidl.h"
+#include "PltFileMediaServer.h"
+#include "PltMediaCache.h"
+#include "PltMediaItem.h"
+#include "PltSyncMediaBrowser.h"
+
+#include "PltXbox360.h"
+#include "PltMediaConnect.h"
+
+#endif /* _PLATINUM_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Platinum/PltVersion.h b/lib/libUPnP/Platinum/Source/Platinum/PltVersion.h
new file mode 100644
index 0000000..5101009
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Platinum/PltVersion.h
@@ -0,0 +1,44 @@
+/*****************************************************************
+|
+| Platinum - Version Info
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_VERSION_H_
+#define _PLT_VERSION_H_
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+#define PLT_PLATINUM_SDK_VERSION 0x00010513
+#define PLT_PLATINUM_SDK_VERSION_STRING "1.0.5.13"
+
+#endif // _PLT_VERSION_H_
diff --git a/lib/libUPnP/Platinum/Source/Tests/FileMediaServer/FileMediaServerTest.cpp b/lib/libUPnP/Platinum/Source/Tests/FileMediaServer/FileMediaServerTest.cpp
new file mode 100644
index 0000000..0d1223b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/FileMediaServer/FileMediaServerTest.cpp
@@ -0,0 +1,159 @@
+/*****************************************************************
+|
+| Platinum - Test UPnP A/V MediaServer
+|
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltFileMediaServer.h"
+
+#include <stdlib.h>
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.file.test")
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+struct Options {
+ const char* path;
+ const char* friendly_name;
+ const char* guid;
+ NPT_UInt32 port;
+} Options;
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit()
+{
+ fprintf(stderr, "usage: FileMediaServerTest [-f <friendly_name>] [-p <port>] [-g <guid>] <path>\n");
+ fprintf(stderr, "-f : optional upnp device friendly name\n");
+ fprintf(stderr, "-p : optional http port\n");
+ fprintf(stderr, "<path> : local path to serve\n");
+ exit(1);
+}
+
+/*----------------------------------------------------------------------
+| ParseCommandLine
++---------------------------------------------------------------------*/
+static void
+ParseCommandLine(char** args)
+{
+ const char* arg;
+
+ /* default values */
+ Options.path = NULL;
+ Options.friendly_name = NULL;
+ Options.guid = NULL;
+ Options.port = 0;
+
+ while ((arg = *args++)) {
+ if (!strcmp(arg, "-f")) {
+ Options.friendly_name = *args++;
+ } else if (!strcmp(arg, "-g")) {
+ Options.guid = *args++;
+ } else if (!strcmp(arg, "-p")) {
+ if (NPT_FAILED(NPT_ParseInteger32(*args++, Options.port))) {
+ fprintf(stderr, "ERROR: invalid argument\n");
+ PrintUsageAndExit();
+ }
+ } else if (Options.path == NULL) {
+ Options.path = arg;
+ } else {
+ fprintf(stderr, "ERROR: too many arguments\n");
+ PrintUsageAndExit();
+ }
+ }
+
+ /* check args */
+ if (Options.path == NULL) {
+ fprintf(stderr, "ERROR: path missing\n");
+ PrintUsageAndExit();
+ }
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int /* argc */, char** argv)
+{
+ // setup Neptune logging
+ NPT_LogManager::GetDefault().Configure("plist:.level=FINE;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=56");
+
+ /* parse command line */
+ ParseCommandLine(argv+1);
+
+ /* for faster DLNA faster testing */
+ PLT_Constants::GetInstance().SetDefaultDeviceLease(NPT_TimeInterval(60.));
+
+ PLT_UPnP upnp;
+ PLT_DeviceHostReference device(
+ new PLT_FileMediaServer(
+ Options.path,
+ Options.friendly_name?Options.friendly_name:"Platinum UPnP Media Server",
+ false,
+ Options.guid, // NULL for random ID
+ (NPT_UInt16)Options.port)
+ );
+
+ NPT_List<NPT_IpAddress> list;
+ NPT_CHECK_SEVERE(PLT_UPnPMessageHelper::GetIPAddresses(list));
+ NPT_String ip = list.GetFirstItem()->ToString();
+
+ device->m_ModelDescription = "Platinum File Media Server";
+ device->m_ModelURL = "http://www.plutinosoft.com/";
+ device->m_ModelNumber = "1.0";
+ device->m_ModelName = "Platinum File Media Server";
+ device->m_Manufacturer = "Plutinosoft";
+ device->m_ManufacturerURL = "http://www.plutinosoft.com/";
+
+ upnp.AddDevice(device);
+ NPT_String uuid = device->GetUUID();
+
+ NPT_CHECK_SEVERE(upnp.Start());
+ NPT_LOG_INFO("Press 'q' to quit.");
+
+ char buf[256];
+ while (gets(buf)) {
+ if (*buf == 'q')
+ break;
+ }
+
+ upnp.Stop();
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp b/lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp
new file mode 100644
index 0000000..00b1f52
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp
@@ -0,0 +1,526 @@
+/*****************************************************************
+|
+| Platinum - HTTP tests
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltTaskManager.h"
+#include "PltHttpServer.h"
+#include "PltDownloader.h"
+#include "PltRingBufferStream.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+NPT_SET_LOCAL_LOGGER("platinum.core.http.test")
+
+//#define TEST1
+//#define TEST2
+//#define TEST3
+//#define TEST4
+#define TEST5
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+struct Options {
+ NPT_UInt32 port;
+ NPT_String path;
+} Options;
+
+/*----------------------------------------------------------------------
+| PLT_HttpCustomRequestHandler
++---------------------------------------------------------------------*/
+class PLT_HttpCustomRequestHandler : public NPT_HttpRequestHandler
+{
+public:
+ // constructors
+ PLT_HttpCustomRequestHandler(NPT_InputStreamReference& body,
+ const char* mime_type,
+ bool update_content_length = false) :
+ m_Body(body),
+ m_MimeType(mime_type),
+ m_UpdateContentLength(update_content_length) {}
+
+ // NPT_HttpRequetsHandler methods
+ virtual NPT_Result SetupResponse(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse& response) {
+ NPT_COMPILER_UNUSED(request);
+ NPT_COMPILER_UNUSED(context);
+
+ NPT_HttpEntity* entity = response.GetEntity();
+ if (entity == NULL) return NPT_ERROR_INVALID_STATE;
+
+ entity->SetContentType(m_MimeType);
+ entity->SetInputStream(m_Body, m_UpdateContentLength);
+
+ return NPT_SUCCESS;
+ }
+
+private:
+ NPT_InputStreamReference m_Body;
+ NPT_String m_MimeType;
+ bool m_UpdateContentLength;
+};
+
+
+#ifdef TEST1
+/*----------------------------------------------------------------------
+| Test1
++---------------------------------------------------------------------*/
+static bool
+Test1(PLT_TaskManager* task_manager, NPT_HttpUrl 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(.1f));
+ break;
+ }
+ };
+
+ return false;
+}
+#endif
+
+#ifdef TEST2
+/*----------------------------------------------------------------------
+| 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(.1f));
+ break;
+ }
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| Test2
++---------------------------------------------------------------------*/
+static bool
+Test2(PLT_TaskManager* task_manager, NPT_HttpUrl 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(.1f));
+ break;
+ }
+ };
+
+ return false;
+}
+#endif
+
+
+#ifdef TEST3
+class RingBufferWriterTask : public PLT_ThreadTask
+{
+public:
+ RingBufferWriterTask(PLT_RingBufferStreamReference& ringbuffer_stream)
+ : m_RingBufferStream(ringbuffer_stream) {}
+
+ // PLT_ThreadTask methods
+ virtual void DoRun() {
+ char buffer[32768];
+ m_RingBufferStream->WriteFully(buffer, 32768);
+
+ /* mark as done */
+ m_RingBufferStream->SetEOS();
+ }
+
+private:
+ PLT_RingBufferStreamReference m_RingBufferStream;
+};
+
+/*----------------------------------------------------------------------
+| 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;
+}
+#endif
+
+#ifdef TEST4
+class ClientStuckTask : public PLT_ThreadTask
+{
+public:
+ ClientStuckTask(NPT_HttpUrl& url, NPT_HttpClient& client)
+ : m_Url(url), m_Client(client) {}
+
+ // PLT_ThreadTask methods
+ virtual void DoRun() {
+ NPT_HttpRequest request(m_Url, NPT_HTTP_METHOD_GET);
+ NPT_HttpResponse* response = NULL;
+ m_Client.SendRequest(request, response);
+ }
+
+ virtual void DoAbort() {
+ m_Client.Abort();
+ }
+
+private:
+ NPT_HttpUrl m_Url;
+ NPT_HttpClient& m_Client;
+ bool m_Aborted;
+};
+/*----------------------------------------------------------------------
+| Test4
++---------------------------------------------------------------------*/
+static bool
+Test4(PLT_TaskManager* task_manager, NPT_HttpUrl url, NPT_TimeInterval wait_before_kill)
+{
+ NPT_LOG_INFO("########### TEST 4 ######################");
+
+ NPT_HttpClient client;
+
+ /* start task to asynchronously fetch url */
+ ClientStuckTask* task = new ClientStuckTask(url, client);
+ task_manager->StartTask(task, NULL, false);
+
+ /* wait a bit and abort client */
+ NPT_System::Sleep(wait_before_kill);
+
+ task->Kill();
+ return true;
+}
+#endif
+
+#ifdef TEST5
+/*----------------------------------------------------------------------
+| Test5
++---------------------------------------------------------------------*/
+static bool
+Test5(NPT_HttpUrl url)
+{
+ NPT_LOG_INFO("########### TEST 5 ######################");
+
+ NPT_HttpClient client;
+
+ // first request
+ NPT_HttpRequest request(url, NPT_HTTP_METHOD_POST, NPT_HTTP_PROTOCOL_1_1);
+ NPT_HttpEntity* request_entity = new NPT_HttpEntity();
+ request_entity->SetInputStream("Testing");
+ request.SetEntity(request_entity);
+
+ NPT_HttpResponse* response = NULL;
+ client.SendRequest(request, response);
+ NPT_HttpEntity* entity = NULL;
+ if (response && (entity = response->GetEntity())) {
+ NPT_DataBuffer buffer;
+ if (NPT_FAILED(entity->Load(buffer))) return false;
+ }
+
+ // try again
+ delete response;
+ response = NULL;
+ request_entity = new NPT_HttpEntity();
+ request_entity->SetInputStream("Testing2");
+ request.SetEntity(request_entity);
+ client.SendRequest(request, response);
+ entity = NULL;
+ if (response && (entity = response->GetEntity())) {
+ NPT_DataBuffer buffer;
+ if (NPT_FAILED(entity->Load(buffer))) return false;
+ }
+
+ return true;
+}
+#endif
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit(char** args)
+{
+ fprintf(stderr, "usage: %s [-p <port>] [-f <filepath>]\n", args[0]);
+ fprintf(stderr, "-p : optional server port\n");
+ fprintf(stderr, "-f : optional local filepath to serve\n");
+ exit(1);
+}
+
+/*----------------------------------------------------------------------
+| ParseCommandLine
++---------------------------------------------------------------------*/
+static void
+ParseCommandLine(char** args)
+{
+ const char* arg;
+ char** tmp = args+1;
+
+ /* default values */
+ Options.port = 0;
+ Options.path = "";
+
+ while ((arg = *tmp++)) {
+ if (Options.port == 0 && !strcmp(arg, "-p")) {
+ NPT_UInt32 port;
+ if (NPT_FAILED(NPT_ParseInteger32(*tmp++, port, false))) {
+ fprintf(stderr, "ERROR: invalid port\n");
+ exit(1);
+ }
+ Options.port = port;
+ } else if (Options.path.IsEmpty() && !strcmp(arg, "-f")) {
+ Options.path = *tmp++;
+ } else {
+ fprintf(stderr, "ERROR: too many arguments\n");
+ PrintUsageAndExit(args);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int argc, char** argv)
+{
+ NPT_COMPILER_UNUSED(argc);
+
+ NPT_HttpRequestHandler* handler;
+ NPT_Reference<NPT_DataBuffer> buffer;
+ bool result;
+
+ /* parse command line */
+ ParseCommandLine(argv);
+
+ /* create http server */
+ PLT_HttpServer http_server(Options.port?Options.port:8089);
+ NPT_String 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_FileInfo info;
+ NPT_CHECK_SEVERE(NPT_File::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 garbage data */
+ buffer = new NPT_DataBuffer(32768);
+ buffer->SetDataSize(32768);
+
+ /* add static handler */
+ handler = new NPT_HttpStaticRequestHandler(buffer->GetData(),
+ buffer->GetDataSize(),
+ "application/octet-stream");
+ http_server.AddRequestHandler(handler, "/test");
+
+ /* build url */
+ url = "/test";
+ }
+
+ /* add custom handler */
+ PLT_RingBufferStreamReference ringbuffer_stream(new PLT_RingBufferStream());
+ NPT_InputStreamReference stream(ringbuffer_stream);
+ NPT_HttpRequestHandler* custom_handler = new PLT_HttpCustomRequestHandler(stream, "text/xml");
+ http_server.AddRequestHandler(custom_handler, "/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.f));
+
+ /* execute tests */
+ NPT_Size size;
+ NPT_COMPILER_UNUSED(size);
+
+#ifdef TEST1
+ result = Test1(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), url), size);
+ if (!result) return -1;
+#endif
+
+#ifdef TEST2
+ result = Test2(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), url), size);
+ if (!result) return -1;
+#endif
+
+#ifdef TEST3
+ result = Test3(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), ringbuffer_stream, size);
+ if (!result) return -1;
+#endif
+
+#ifdef TEST4
+ result = Test4(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), NPT_TimeInterval(.1f));
+ if (!result) return -1;
+
+ result = Test4(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), NPT_TimeInterval(1.f));
+ if (!result) return -1;
+
+ result = Test4(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), NPT_TimeInterval(2.f));
+ if (!result) return -1;
+#endif
+
+#ifdef TEST5
+ result = Test5(NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/test"));
+ if (!result) return -1;
+#endif
+
+ NPT_System::Sleep(NPT_TimeInterval(1.f));
+
+ // abort server tasks that are waiting on ring buffer stream
+ ringbuffer_stream->Abort();
+
+ http_server.Stop();
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tests/LightSample/LightSampleTest.cpp b/lib/libUPnP/Platinum/Source/Tests/LightSample/LightSampleTest.cpp
new file mode 100644
index 0000000..d9f35a0
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/LightSample/LightSampleTest.cpp
@@ -0,0 +1,76 @@
+/*****************************************************************
+|
+| Platinum - Test Light Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltLightSample.h"
+
+#define TEST_EMBEDDED_DEVICE 1
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int /* argc */, char** /* argv */)
+{
+ // setup Neptune logging
+ NPT_LogManager::GetDefault().Configure("plist:.level=FINE;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=42");
+
+ PLT_UPnP upnp;
+
+ PLT_DeviceHostReference device(new PLT_LightSampleDevice("Platinum Light Bulb"));
+
+#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
+
+ upnp.AddDevice(device);
+ upnp.Start();
+
+ char buf[256];
+ while (gets(buf)) {
+ if (*buf == 'q')
+ break;
+ }
+
+ upnp.Stop();
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.cpp b/lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.cpp
new file mode 100644
index 0000000..f31ffe1
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.cpp
@@ -0,0 +1,171 @@
+/*****************************************************************
+|
+| Platinum - Light Sample Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "Platinum.h"
+#include "PltLightSample.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.test.lightsample")
+
+/*----------------------------------------------------------------------
+| forward references
++---------------------------------------------------------------------*/
+extern NPT_UInt8 SCPDXML[];
+
+/*----------------------------------------------------------------------
+| PLT_LightSampleDevice::PLT_LightSampleDevice
++---------------------------------------------------------------------*/
+PLT_LightSampleDevice::PLT_LightSampleDevice(const char* FriendlyName, const char* UUID) :
+ PLT_DeviceHost("/", UUID, "urn:schemas-upnp-org:device:SwitchPower:1", FriendlyName)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_LightSampleDevice::~PLT_LightSampleDevice
++---------------------------------------------------------------------*/
+PLT_LightSampleDevice::~PLT_LightSampleDevice()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_LightSampleDevice::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_LightSampleDevice::SetupServices()
+{
+ NPT_Result res;
+ PLT_Service* service = new PLT_Service(
+ this,
+ "urn:schemas-upnp-org:service:SwitchPower:1",
+ "urn:upnp-org:serviceId:SwitchPower.001",
+ "SwitchPower");
+ NPT_CHECK_LABEL_FATAL(res = service->SetSCPDXML((const char*)SCPDXML), failure);
+ NPT_CHECK_LABEL_FATAL(res = AddService(service), failure);
+
+ service->SetStateVariable("Status", "True");
+
+ return NPT_SUCCESS;
+
+failure:
+ delete service;
+ return res;
+}
+
+/*----------------------------------------------------------------------
+| PLT_LightSampleDevice::OnAction
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_LightSampleDevice::OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ /* parse the action name */
+ NPT_String name = action->GetActionDesc().GetName();
+ if (name.Compare("SetTarget") == 0) {
+ NPT_String value;
+ action->GetArgumentValue("newTargetValue", value);
+
+ PLT_StateVariable* variable = action->GetActionDesc().GetService()->FindStateVariable("Status");
+ if (NPT_FAILED(variable->SetValue(value))) {
+ action->SetError(402, "Invalid Args");
+ return NPT_FAILURE;
+ }
+ return NPT_SUCCESS;
+ } else if (name.Compare("GetStatus") == 0) {
+ PLT_StateVariable* variable = action->GetActionDesc().GetService()->FindStateVariable("Status");
+ if (variable) {
+ action->SetArgumentValue("ResultStatus", variable->GetValue());
+ return NPT_SUCCESS;
+ }
+ }
+
+ action->SetError(501, "Action Failed");
+ return NPT_FAILURE;
+}
+
+NPT_UInt8 SCPDXML[957] =
+{
+ 0x20, 0x20, 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30,
+ 0x22, 0x20, 0x65, 0x6E, 0x63, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x3D, 0x22, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x22, 0x20, 0x3F,
+ 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x73, 0x63, 0x70, 0x64, 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x75,
+ 0x72, 0x6E, 0x3A, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x73, 0x2D, 0x75, 0x70, 0x6E, 0x70, 0x2D, 0x6F, 0x72, 0x67, 0x3A,
+ 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x31, 0x2D, 0x30, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x73, 0x70,
+ 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x6D, 0x61, 0x6A, 0x6F, 0x72,
+ 0x3E, 0x31, 0x3C, 0x2F, 0x6D, 0x61, 0x6A, 0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x6D, 0x69, 0x6E, 0x6F,
+ 0x72, 0x3E, 0x30, 0x3C, 0x2F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x70,
+ 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E,
+ 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69,
+ 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C,
+ 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F,
+ 0x6E, 0x3E, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A,
+ 0x20, 0x20, 0x3C, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6C, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F,
+ 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20,
+ 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A,
+ 0x20, 0x20, 0x3C, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D,
+ 0x65, 0x3E, 0x6E, 0x65, 0x77, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3C, 0x2F, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x69,
+ 0x6E, 0x3C, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x72,
+ 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E,
+ 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3C, 0x2F, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75,
+ 0x6D, 0x65, 0x6E, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x72, 0x67, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x4C,
+ 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x3C, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4C, 0x69, 0x73, 0x74, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
+ 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64,
+ 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x6E, 0x61,
+ 0x6D, 0x65, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20,
+ 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x3C, 0x2F,
+ 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x3D,
+ 0x22, 0x6E, 0x6F, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x54, 0x61, 0x72, 0x67, 0x65,
+ 0x74, 0x3C, 0x2F, 0x6E, 0x61, 0x6D, 0x65, 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79,
+ 0x70, 0x65, 0x3E, 0x62, 0x6F, 0x6F, 0x6C, 0x65, 0x61, 0x6E, 0x3C, 0x2F, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65,
+ 0x3E, 0x20, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6C,
+ 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x54, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x2F, 0x73, 0x63, 0x70, 0x64, 0x3E
+};
diff --git a/lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.h b/lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.h
new file mode 100644
index 0000000..a23e8ff
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/LightSample/PltLightSample.h
@@ -0,0 +1,59 @@
+/*****************************************************************
+|
+| Platinum - Light Sample Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_LIGHT_SAMPLE_H_
+#define _PLT_LIGHT_SAMPLE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDeviceHost.h"
+
+/*----------------------------------------------------------------------
+| PLT_LightSampleDevice class
++---------------------------------------------------------------------*/
+class PLT_LightSampleDevice : public PLT_DeviceHost
+{
+public:
+ PLT_LightSampleDevice(const char* FriendlyName,
+ const char* UUID = "");
+ virtual ~PLT_LightSampleDevice();
+
+ // PLT_DeviceHost methods
+ virtual NPT_Result SetupServices();
+ virtual NPT_Result OnAction(PLT_ActionReference& action,
+ const PLT_HttpRequestContext& context);
+};
+
+#endif /* _PLT_LIGHT_SAMPLE_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaRenderer/MediaRendererTest.cpp b/lib/libUPnP/Platinum/Source/Tests/MediaRenderer/MediaRendererTest.cpp
new file mode 100644
index 0000000..54d9d24
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaRenderer/MediaRendererTest.cpp
@@ -0,0 +1,121 @@
+/*****************************************************************
+|
+| Platinum - Test UPnP A/V MediaRenderer
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltMediaRenderer.h"
+
+#include <stdlib.h>
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+struct Options {
+ const char* friendly_name;
+} Options;
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit(char** args)
+{
+ fprintf(stderr, "usage: %s [-f <friendly_name>]\n", args[0]);
+ fprintf(stderr, "-f : optional upnp server friendly name\n");
+ fprintf(stderr, "<path> : local path to serve\n");
+ exit(1);
+}
+
+/*----------------------------------------------------------------------
+| ParseCommandLine
++---------------------------------------------------------------------*/
+static void
+ParseCommandLine(char** args)
+{
+ const char* arg;
+ char** tmp = args+1;
+
+ /* default values */
+ Options.friendly_name = NULL;
+
+ while ((arg = *tmp++)) {
+ if (!strcmp(arg, "-f")) {
+ Options.friendly_name = *tmp++;
+ } else {
+ fprintf(stderr, "ERROR: too many arguments\n");
+ PrintUsageAndExit(args);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int /* argc */, char** argv)
+{
+ PLT_UPnP upnp;
+
+ /* parse command line */
+ ParseCommandLine(argv);
+
+ PLT_DeviceHostReference device(
+ new PLT_MediaRenderer(Options.friendly_name?Options.friendly_name:"Platinum Media Renderer",
+ false,
+ "e6572b54-f3c7-2d91-2fb5-b757f2537e21"));
+ upnp.AddDevice(device);
+ bool added = true;
+
+ upnp.Start();
+
+ char buf[256];
+ while (gets(buf)) {
+ if (*buf == 'q')
+ break;
+
+ if (*buf == 's') {
+ if (added) {
+ upnp.RemoveDevice(device);
+ } else {
+ upnp.AddDevice(device);
+ }
+ added = !added;
+ }
+ }
+
+ upnp.Stop();
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/InfoPlist.strings b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..b92732c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/InfoPlist.strings
@@ -0,0 +1 @@
+/* Localized versions of Info.plist keys */
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/MainMenu.xib b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/MainMenu.xib
new file mode 100644
index 0000000..8d4fb5c
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/English.lproj/MainMenu.xib
@@ -0,0 +1,3224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">10F569</string>
+ <string key="IBDocument.InterfaceBuilderVersion">788</string>
+ <string key="IBDocument.AppKitVersion">1038.29</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="NS.object.0">788</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="2"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="53522055">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="493647166">
+ <object class="NSMutableString" key="NSClassName">
+ <characters key="NS.bytes">NSApplication</characters>
+ </object>
+ </object>
+ <object class="NSCustomObject" id="909243075">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="547858435">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSWindowTemplate" id="483958638">
+ <int key="NSWindowStyleMask">15</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{6, 593}, {480, 360}}</string>
+ <int key="NSWTFlags">1886912512</int>
+ <string key="NSWindowTitle">MediaServerCocoaTest</string>
+ <string key="NSWindowClass">NSWindow</string>
+ <object class="NSMutableString" key="NSViewClass">
+ <characters key="NS.bytes">View</characters>
+ </object>
+ <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
+ <string key="NSWindowContentMinSize">{213, 107}</string>
+ <object class="NSView" key="NSWindowView" id="823886803">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSButton" id="544612128">
+ <reference key="NSNextResponder" ref="823886803"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{19, 312}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="823886803"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="879879405">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">Start</string>
+ <object class="NSFont" key="NSSupport" id="293448079">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">13</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <reference key="NSControlView" ref="544612128"/>
+ <int key="NSButtonFlags">-927579905</int>
+ <int key="NSButtonFlags2">1</int>
+ <reference key="NSAlternateImage" ref="293448079"/>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{480, 360}</string>
+ <reference key="NSSuperview"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+ <string key="NSMinSize">{213, 129}</string>
+ <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
+ </object>
+ <object class="NSMenu" id="1055885701">
+ <string key="NSTitle">MainMenu</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="376192112">
+ <reference key="NSMenu" ref="1055885701"/>
+ <string key="NSTitle">MediaServerCocoaTest</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <object class="NSCustomResource" key="NSOnImage" id="893455832">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuCheckmark</string>
+ </object>
+ <object class="NSCustomResource" key="NSMixedImage" id="424226900">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuMixedState</string>
+ </object>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="123765298">
+ <string key="NSTitle">MediaServerCocoaTest</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="743093781">
+ <reference key="NSMenu" ref="123765298"/>
+ <string key="NSTitle">About MediaServerCocoaTest</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="791044830">
+ <reference key="NSMenu" ref="123765298"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="124073989">
+ <reference key="NSMenu" ref="123765298"/>
+ <string key="NSTitle">Preferences…</string>
+ <string key="NSKeyEquiv">,</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="621602699">
+ <reference key="NSMenu" ref="123765298"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="515282677">
+ <reference key="NSMenu" ref="123765298"/>
+ <string key="NSTitle">Services</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="939189088">
+ <object class="NSMutableString" key="NSTitle">
+ <characters key="NS.bytes">Services</characters>
+ </object>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <string key="NSName">_NSServicesMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="931166327">
+ <reference key="NSMenu" ref="123765298"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="780549861">
+ <reference key="NSMenu" ref="123765298"/>
+ <string key="NSTitle">Hide MediaServerCocoaTest</string>
+ <string key="NSKeyEquiv">h</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="514007154">
+ <reference key="NSMenu" ref="123765298"/>
+ <string key="NSTitle">Hide Others</string>
+ <string key="NSKeyEquiv">h</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="163840636">
+ <reference key="NSMenu" ref="123765298"/>
+ <string key="NSTitle">Show All</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="901869444">
+ <reference key="NSMenu" ref="123765298"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="349823970">
+ <reference key="NSMenu" ref="123765298"/>
+ <string key="NSTitle">Quit MediaServerCocoaTest</string>
+ <string key="NSKeyEquiv">q</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ <string key="NSName">_NSAppleMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="842783111">
+ <reference key="NSMenu" ref="1055885701"/>
+ <string key="NSTitle">File</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="960517776">
+ <object class="NSMutableString" key="NSTitle">
+ <characters key="NS.bytes">File</characters>
+ </object>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="1005751409">
+ <reference key="NSMenu" ref="960517776"/>
+ <string key="NSTitle">Save</string>
+ <string key="NSKeyEquiv">s</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="402151840">
+ <reference key="NSMenu" ref="960517776"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="620705007">
+ <reference key="NSMenu" ref="960517776"/>
+ <string key="NSTitle">Page Setup…</string>
+ <string key="NSKeyEquiv">P</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="51940822">
+ <reference key="NSMenu" ref="960517776"/>
+ <string key="NSTitle">Print…</string>
+ <string key="NSKeyEquiv">p</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="545718297">
+ <reference key="NSMenu" ref="1055885701"/>
+ <string key="NSTitle">Edit</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="1022019938">
+ <string key="NSTitle">Edit</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="307109690">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Undo</string>
+ <string key="NSKeyEquiv">z</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="744402274">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Redo</string>
+ <string key="NSKeyEquiv">Z</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="831119715">
+ <reference key="NSMenu" ref="1022019938"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="70873500">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Cut</string>
+ <string key="NSKeyEquiv">x</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="808304593">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Copy</string>
+ <string key="NSKeyEquiv">c</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="597871667">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Paste</string>
+ <string key="NSKeyEquiv">v</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="324532357">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Paste and Match Style</string>
+ <string key="NSKeyEquiv">V</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="618358412">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Delete</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="883438165">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Select All</string>
+ <string key="NSKeyEquiv">a</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="473717252">
+ <reference key="NSMenu" ref="1022019938"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="69846141">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Find</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="216314426">
+ <string key="NSTitle">Find</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="914446540">
+ <reference key="NSMenu" ref="216314426"/>
+ <string key="NSTitle">Find…</string>
+ <string key="NSKeyEquiv">f</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">1</int>
+ </object>
+ <object class="NSMenuItem" id="160366792">
+ <reference key="NSMenu" ref="216314426"/>
+ <string key="NSTitle">Find Next</string>
+ <string key="NSKeyEquiv">g</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">2</int>
+ </object>
+ <object class="NSMenuItem" id="248661547">
+ <reference key="NSMenu" ref="216314426"/>
+ <string key="NSTitle">Find Previous</string>
+ <string key="NSKeyEquiv">G</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">3</int>
+ </object>
+ <object class="NSMenuItem" id="30033296">
+ <reference key="NSMenu" ref="216314426"/>
+ <string key="NSTitle">Use Selection for Find</string>
+ <string key="NSKeyEquiv">e</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">7</int>
+ </object>
+ <object class="NSMenuItem" id="827334636">
+ <reference key="NSMenu" ref="216314426"/>
+ <string key="NSTitle">Jump to Selection</string>
+ <string key="NSKeyEquiv">j</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="365048869">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Spelling and Grammar</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="666968844">
+ <string key="NSTitle">Spelling</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="356339891">
+ <reference key="NSMenu" ref="666968844"/>
+ <string key="NSTitle">Show Spelling and Grammar</string>
+ <string key="NSKeyEquiv">:</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="416352713">
+ <reference key="NSMenu" ref="666968844"/>
+ <string key="NSTitle">Check Document Now</string>
+ <string key="NSKeyEquiv">;</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="47615281">
+ <reference key="NSMenu" ref="666968844"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="252035059">
+ <reference key="NSMenu" ref="666968844"/>
+ <string key="NSTitle">Check Spelling While Typing</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="286376998">
+ <reference key="NSMenu" ref="666968844"/>
+ <string key="NSTitle">Check Grammar With Spelling</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="81755183">
+ <reference key="NSMenu" ref="666968844"/>
+ <string key="NSTitle">Correct Spelling Automatically</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="958645126">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Substitutions</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="218631249">
+ <string key="NSTitle">Substitutions</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="64764928">
+ <reference key="NSMenu" ref="218631249"/>
+ <string key="NSTitle">Show Substitutions</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="136936362">
+ <reference key="NSMenu" ref="218631249"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="607672977">
+ <reference key="NSMenu" ref="218631249"/>
+ <string key="NSTitle">Smart Copy/Paste</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="484928874">
+ <reference key="NSMenu" ref="218631249"/>
+ <string key="NSTitle">Smart Quotes</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="693070189">
+ <reference key="NSMenu" ref="218631249"/>
+ <string key="NSTitle">Smart Dashes</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="1059551809">
+ <reference key="NSMenu" ref="218631249"/>
+ <string key="NSTitle">Smart Links</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="416554597">
+ <reference key="NSMenu" ref="218631249"/>
+ <string key="NSTitle">Text Replacement</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="814247416">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Transformations</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="562140037">
+ <string key="NSTitle">Transformations</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="698135111">
+ <reference key="NSMenu" ref="562140037"/>
+ <string key="NSTitle">Make Upper Case</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="899181471">
+ <reference key="NSMenu" ref="562140037"/>
+ <string key="NSTitle">Make Lower Case</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="582459168">
+ <reference key="NSMenu" ref="562140037"/>
+ <string key="NSTitle">Capitalize</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="1058116061">
+ <reference key="NSMenu" ref="1022019938"/>
+ <string key="NSTitle">Speech</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="792127484">
+ <string key="NSTitle">Speech</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="318734362">
+ <reference key="NSMenu" ref="792127484"/>
+ <string key="NSTitle">Start Speaking</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="612849471">
+ <reference key="NSMenu" ref="792127484"/>
+ <string key="NSTitle">Stop Speaking</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="259022320">
+ <reference key="NSMenu" ref="1055885701"/>
+ <string key="NSTitle">Format</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="708542952">
+ <string key="NSTitle">Format</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="1044121641">
+ <reference key="NSMenu" ref="708542952"/>
+ <string key="NSTitle">Font</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="16789759">
+ <string key="NSTitle">Font</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="486510693">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Show Fonts</string>
+ <string key="NSKeyEquiv">t</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="322671057">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Bold</string>
+ <string key="NSKeyEquiv">b</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">2</int>
+ </object>
+ <object class="NSMenuItem" id="294925675">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Italic</string>
+ <string key="NSKeyEquiv">i</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">1</int>
+ </object>
+ <object class="NSMenuItem" id="386587767">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Underline</string>
+ <string key="NSKeyEquiv">u</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="530490813">
+ <reference key="NSMenu" ref="16789759"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="791073707">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Bigger</string>
+ <string key="NSKeyEquiv">+</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">3</int>
+ </object>
+ <object class="NSMenuItem" id="820131188">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Smaller</string>
+ <string key="NSKeyEquiv">-</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <int key="NSTag">4</int>
+ </object>
+ <object class="NSMenuItem" id="593643800">
+ <reference key="NSMenu" ref="16789759"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="17067790">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Kern</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="277000559">
+ <string key="NSTitle">Kern</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="53041874">
+ <reference key="NSMenu" ref="277000559"/>
+ <string key="NSTitle">Use Default</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="665619559">
+ <reference key="NSMenu" ref="277000559"/>
+ <string key="NSTitle">Use None</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="807093337">
+ <reference key="NSMenu" ref="277000559"/>
+ <string key="NSTitle">Tighten</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="81316040">
+ <reference key="NSMenu" ref="277000559"/>
+ <string key="NSTitle">Loosen</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="654563803">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Ligature</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="164619877">
+ <string key="NSTitle">Ligature</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="291130592">
+ <reference key="NSMenu" ref="164619877"/>
+ <string key="NSTitle">Use Default</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="557989785">
+ <reference key="NSMenu" ref="164619877"/>
+ <string key="NSTitle">Use None</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="8023761">
+ <reference key="NSMenu" ref="164619877"/>
+ <string key="NSTitle">Use All</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="35184653">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Baseline</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="1040787833">
+ <string key="NSTitle">Baseline</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="299485767">
+ <reference key="NSMenu" ref="1040787833"/>
+ <string key="NSTitle">Use Default</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="362581379">
+ <reference key="NSMenu" ref="1040787833"/>
+ <string key="NSTitle">Superscript</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="368049810">
+ <reference key="NSMenu" ref="1040787833"/>
+ <string key="NSTitle">Subscript</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="650703522">
+ <reference key="NSMenu" ref="1040787833"/>
+ <string key="NSTitle">Raise</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="470064337">
+ <reference key="NSMenu" ref="1040787833"/>
+ <string key="NSTitle">Lower</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="638669489">
+ <reference key="NSMenu" ref="16789759"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="169445129">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Show Colors</string>
+ <string key="NSKeyEquiv">C</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="511988305">
+ <reference key="NSMenu" ref="16789759"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="637704817">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Copy Style</string>
+ <string key="NSKeyEquiv">c</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="684848834">
+ <reference key="NSMenu" ref="16789759"/>
+ <string key="NSTitle">Paste Style</string>
+ <string key="NSKeyEquiv">v</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ <string key="NSName">_NSFontMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="446410933">
+ <reference key="NSMenu" ref="708542952"/>
+ <string key="NSTitle">Text</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="640850853">
+ <string key="NSTitle">Text</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="775088230">
+ <reference key="NSMenu" ref="640850853"/>
+ <string key="NSTitle">Align Left</string>
+ <string key="NSKeyEquiv">{</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="20804296">
+ <reference key="NSMenu" ref="640850853"/>
+ <string key="NSTitle">Center</string>
+ <string key="NSKeyEquiv">|</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="489997371">
+ <reference key="NSMenu" ref="640850853"/>
+ <string key="NSTitle">Justify</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="766941912">
+ <reference key="NSMenu" ref="640850853"/>
+ <string key="NSTitle">Align Right</string>
+ <string key="NSKeyEquiv">}</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="831789293">
+ <reference key="NSMenu" ref="640850853"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="473944779">
+ <reference key="NSMenu" ref="640850853"/>
+ <string key="NSTitle">Show Ruler</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="405928732">
+ <reference key="NSMenu" ref="640850853"/>
+ <string key="NSTitle">Copy Ruler</string>
+ <string key="NSKeyEquiv">c</string>
+ <int key="NSKeyEquivModMask">1310720</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="784305476">
+ <reference key="NSMenu" ref="640850853"/>
+ <string key="NSTitle">Paste Ruler</string>
+ <string key="NSKeyEquiv">v</string>
+ <int key="NSKeyEquivModMask">1310720</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="147235865">
+ <reference key="NSMenu" ref="1055885701"/>
+ <string key="NSTitle">View</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="877676881">
+ <string key="NSTitle">View</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="653321099">
+ <reference key="NSMenu" ref="877676881"/>
+ <string key="NSTitle">Show Toolbar</string>
+ <string key="NSKeyEquiv">t</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="854660346">
+ <reference key="NSMenu" ref="877676881"/>
+ <string key="NSTitle">Customize Toolbar…</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="560112995">
+ <reference key="NSMenu" ref="1055885701"/>
+ <string key="NSTitle">Window</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="747245393">
+ <object class="NSMutableString" key="NSTitle">
+ <characters key="NS.bytes">Window</characters>
+ </object>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="814052996">
+ <reference key="NSMenu" ref="747245393"/>
+ <string key="NSTitle">Minimize</string>
+ <string key="NSKeyEquiv">m</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="319459889">
+ <reference key="NSMenu" ref="747245393"/>
+ <string key="NSTitle">Zoom</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="1042829312">
+ <reference key="NSMenu" ref="747245393"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ <object class="NSMenuItem" id="1057689233">
+ <reference key="NSMenu" ref="747245393"/>
+ <string key="NSTitle">Bring All to Front</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ <string key="NSName">_NSWindowsMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="713319646">
+ <reference key="NSMenu" ref="1055885701"/>
+ <string key="NSTitle">Help</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="508081226">
+ <string key="NSTitle">Help</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="954120217">
+ <reference key="NSMenu" ref="508081226"/>
+ <string key="NSTitle">MediaServerCocoaTest Help</string>
+ <string key="NSKeyEquiv">?</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="893455832"/>
+ <reference key="NSMixedImage" ref="424226900"/>
+ </object>
+ </object>
+ <string key="NSName">_NSHelpMenu</string>
+ </object>
+ </object>
+ </object>
+ <string key="NSName">_NSMainMenu</string>
+ </object>
+ <object class="NSCustomObject" id="612578685">
+ <string key="NSClassName">MediaServerCocoaTest_AppDelegate</string>
+ </object>
+ <object class="NSCustomObject" id="39582327">
+ <string key="NSClassName">NSFontManager</string>
+ </object>
+ <object class="NSCustomObject" id="770142414">
+ <string key="NSClassName">MediaServerCocoaTestController</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">print:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="51940822"/>
+ </object>
+ <int key="connectionID">86</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">runPageLayout:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="620705007"/>
+ </object>
+ <int key="connectionID">87</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">terminate:</string>
+ <reference key="source" ref="493647166"/>
+ <reference key="destination" ref="349823970"/>
+ </object>
+ <int key="connectionID">139</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontStandardAboutPanel:</string>
+ <reference key="source" ref="493647166"/>
+ <reference key="destination" ref="743093781"/>
+ </object>
+ <int key="connectionID">142</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">hideOtherApplications:</string>
+ <reference key="source" ref="493647166"/>
+ <reference key="destination" ref="514007154"/>
+ </object>
+ <int key="connectionID">146</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">hide:</string>
+ <reference key="source" ref="493647166"/>
+ <reference key="destination" ref="780549861"/>
+ </object>
+ <int key="connectionID">152</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">unhideAllApplications:</string>
+ <reference key="source" ref="493647166"/>
+ <reference key="destination" ref="163840636"/>
+ </object>
+ <int key="connectionID">153</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="493647166"/>
+ <reference key="destination" ref="612578685"/>
+ </object>
+ <int key="connectionID">206</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="483958638"/>
+ <reference key="destination" ref="612578685"/>
+ </object>
+ <int key="connectionID">207</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="612578685"/>
+ <reference key="destination" ref="483958638"/>
+ </object>
+ <int key="connectionID">208</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">saveAction:</string>
+ <reference key="source" ref="612578685"/>
+ <reference key="destination" ref="1005751409"/>
+ </object>
+ <int key="connectionID">211</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performMiniaturize:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="814052996"/>
+ </object>
+ <int key="connectionID">247</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performZoom:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="319459889"/>
+ </object>
+ <int key="connectionID">248</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">arrangeInFront:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="1057689233"/>
+ </object>
+ <int key="connectionID">249</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleToolbarShown:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="653321099"/>
+ </object>
+ <int key="connectionID">342</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">runToolbarCustomizationPalette:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="854660346"/>
+ </object>
+ <int key="connectionID">343</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">addFontTrait:</string>
+ <reference key="source" ref="39582327"/>
+ <reference key="destination" ref="322671057"/>
+ </object>
+ <int key="connectionID">393</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">addFontTrait:</string>
+ <reference key="source" ref="39582327"/>
+ <reference key="destination" ref="294925675"/>
+ </object>
+ <int key="connectionID">394</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">modifyFont:</string>
+ <reference key="source" ref="39582327"/>
+ <reference key="destination" ref="820131188"/>
+ </object>
+ <int key="connectionID">395</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontFontPanel:</string>
+ <reference key="source" ref="39582327"/>
+ <reference key="destination" ref="486510693"/>
+ </object>
+ <int key="connectionID">396</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">modifyFont:</string>
+ <reference key="source" ref="39582327"/>
+ <reference key="destination" ref="791073707"/>
+ </object>
+ <int key="connectionID">397</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">raiseBaseline:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="650703522"/>
+ </object>
+ <int key="connectionID">398</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">lowerBaseline:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="470064337"/>
+ </object>
+ <int key="connectionID">399</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">copyFont:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="637704817"/>
+ </object>
+ <int key="connectionID">400</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">subscript:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="368049810"/>
+ </object>
+ <int key="connectionID">401</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">superscript:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="362581379"/>
+ </object>
+ <int key="connectionID">402</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">tightenKerning:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="807093337"/>
+ </object>
+ <int key="connectionID">403</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">underline:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="386587767"/>
+ </object>
+ <int key="connectionID">404</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontColorPanel:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="169445129"/>
+ </object>
+ <int key="connectionID">405</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">useAllLigatures:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="8023761"/>
+ </object>
+ <int key="connectionID">406</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">loosenKerning:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="81316040"/>
+ </object>
+ <int key="connectionID">407</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">pasteFont:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="684848834"/>
+ </object>
+ <int key="connectionID">408</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">unscript:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="299485767"/>
+ </object>
+ <int key="connectionID">409</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">useStandardKerning:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="53041874"/>
+ </object>
+ <int key="connectionID">410</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">useStandardLigatures:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="291130592"/>
+ </object>
+ <int key="connectionID">411</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">turnOffLigatures:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="557989785"/>
+ </object>
+ <int key="connectionID">412</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">turnOffKerning:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="665619559"/>
+ </object>
+ <int key="connectionID">413</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignLeft:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="775088230"/>
+ </object>
+ <int key="connectionID">414</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignJustified:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="489997371"/>
+ </object>
+ <int key="connectionID">415</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">copyRuler:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="405928732"/>
+ </object>
+ <int key="connectionID">416</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignCenter:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="20804296"/>
+ </object>
+ <int key="connectionID">417</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleRuler:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="473944779"/>
+ </object>
+ <int key="connectionID">418</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignRight:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="766941912"/>
+ </object>
+ <int key="connectionID">419</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">pasteRuler:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="784305476"/>
+ </object>
+ <int key="connectionID">420</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">capitalizeWord:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="582459168"/>
+ </object>
+ <int key="connectionID">489</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">cut:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="70873500"/>
+ </object>
+ <int key="connectionID">490</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">paste:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="597871667"/>
+ </object>
+ <int key="connectionID">491</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleSmartInsertDelete:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="607672977"/>
+ </object>
+ <int key="connectionID">492</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleAutomaticQuoteSubstitution:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="484928874"/>
+ </object>
+ <int key="connectionID">493</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">redo:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="744402274"/>
+ </object>
+ <int key="connectionID">494</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleAutomaticDashSubstitution:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="693070189"/>
+ </object>
+ <int key="connectionID">495</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleContinuousSpellChecking:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="252035059"/>
+ </object>
+ <int key="connectionID">496</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">undo:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="307109690"/>
+ </object>
+ <int key="connectionID">497</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleGrammarChecking:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="286376998"/>
+ </object>
+ <int key="connectionID">498</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">startSpeaking:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="318734362"/>
+ </object>
+ <int key="connectionID">499</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">showGuessPanel:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="356339891"/>
+ </object>
+ <int key="connectionID">500</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">checkSpelling:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="416352713"/>
+ </object>
+ <int key="connectionID">501</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">pasteAsPlainText:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="324532357"/>
+ </object>
+ <int key="connectionID">502</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">copy:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="808304593"/>
+ </object>
+ <int key="connectionID">503</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">delete:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="618358412"/>
+ </object>
+ <int key="connectionID">504</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">lowercaseWord:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="899181471"/>
+ </object>
+ <int key="connectionID">505</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">selectAll:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="883438165"/>
+ </object>
+ <int key="connectionID">506</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">stopSpeaking:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="612849471"/>
+ </object>
+ <int key="connectionID">507</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontSubstitutionsPanel:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="64764928"/>
+ </object>
+ <int key="connectionID">508</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleAutomaticTextReplacement:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="416554597"/>
+ </object>
+ <int key="connectionID">509</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleAutomaticLinkDetection:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="1059551809"/>
+ </object>
+ <int key="connectionID">510</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleAutomaticSpellingCorrection:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="81755183"/>
+ </object>
+ <int key="connectionID">511</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">uppercaseWord:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="698135111"/>
+ </object>
+ <int key="connectionID">512</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performFindPanelAction:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="160366792"/>
+ </object>
+ <int key="connectionID">513</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performFindPanelAction:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="30033296"/>
+ </object>
+ <int key="connectionID">514</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performFindPanelAction:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="914446540"/>
+ </object>
+ <int key="connectionID">515</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">centerSelectionInVisibleArea:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="827334636"/>
+ </object>
+ <int key="connectionID">516</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performFindPanelAction:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="248661547"/>
+ </object>
+ <int key="connectionID">517</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">showHelp:</string>
+ <reference key="source" ref="909243075"/>
+ <reference key="destination" ref="954120217"/>
+ </object>
+ <int key="connectionID">521</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="770142414"/>
+ <reference key="destination" ref="483958638"/>
+ </object>
+ <int key="connectionID">524</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">mainButton</string>
+ <reference key="source" ref="770142414"/>
+ <reference key="destination" ref="544612128"/>
+ </object>
+ <int key="connectionID">527</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="53522055"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="493647166"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="909243075"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="547858435"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">21</int>
+ <reference key="object" ref="483958638"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="823886803"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Window</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="823886803"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="544612128"/>
+ </object>
+ <reference key="parent" ref="483958638"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">29</int>
+ <reference key="object" ref="1055885701"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="376192112"/>
+ <reference ref="842783111"/>
+ <reference ref="560112995"/>
+ <reference ref="147235865"/>
+ <reference ref="259022320"/>
+ <reference ref="545718297"/>
+ <reference ref="713319646"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">MainMenu</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">56</int>
+ <reference key="object" ref="376192112"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="123765298"/>
+ </object>
+ <reference key="parent" ref="1055885701"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">57</int>
+ <reference key="object" ref="123765298"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="743093781"/>
+ <reference ref="124073989"/>
+ <reference ref="515282677"/>
+ <reference ref="780549861"/>
+ <reference ref="349823970"/>
+ <reference ref="621602699"/>
+ <reference ref="931166327"/>
+ <reference ref="514007154"/>
+ <reference ref="901869444"/>
+ <reference ref="163840636"/>
+ <reference ref="791044830"/>
+ </object>
+ <reference key="parent" ref="376192112"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">58</int>
+ <reference key="object" ref="743093781"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">129</int>
+ <reference key="object" ref="124073989"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">131</int>
+ <reference key="object" ref="515282677"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="939189088"/>
+ </object>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">130</int>
+ <reference key="object" ref="939189088"/>
+ <reference key="parent" ref="515282677"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">134</int>
+ <reference key="object" ref="780549861"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">136</int>
+ <reference key="object" ref="349823970"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">143</int>
+ <reference key="object" ref="621602699"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">144</int>
+ <reference key="object" ref="931166327"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">145</int>
+ <reference key="object" ref="514007154"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">149</int>
+ <reference key="object" ref="901869444"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">150</int>
+ <reference key="object" ref="163840636"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">196</int>
+ <reference key="object" ref="791044830"/>
+ <reference key="parent" ref="123765298"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">83</int>
+ <reference key="object" ref="842783111"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="960517776"/>
+ </object>
+ <reference key="parent" ref="1055885701"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">81</int>
+ <reference key="object" ref="960517776"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="402151840"/>
+ <reference ref="1005751409"/>
+ <reference ref="620705007"/>
+ <reference ref="51940822"/>
+ </object>
+ <reference key="parent" ref="842783111"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">74</int>
+ <reference key="object" ref="402151840"/>
+ <reference key="parent" ref="960517776"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">75</int>
+ <reference key="object" ref="1005751409"/>
+ <reference key="parent" ref="960517776"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">77</int>
+ <reference key="object" ref="620705007"/>
+ <reference key="parent" ref="960517776"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">78</int>
+ <reference key="object" ref="51940822"/>
+ <reference key="parent" ref="960517776"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">241</int>
+ <reference key="object" ref="560112995"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="747245393"/>
+ </object>
+ <reference key="parent" ref="1055885701"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">242</int>
+ <reference key="object" ref="747245393"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1042829312"/>
+ <reference ref="319459889"/>
+ <reference ref="1057689233"/>
+ <reference ref="814052996"/>
+ </object>
+ <reference key="parent" ref="560112995"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">243</int>
+ <reference key="object" ref="1042829312"/>
+ <reference key="parent" ref="747245393"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">244</int>
+ <reference key="object" ref="319459889"/>
+ <reference key="parent" ref="747245393"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">245</int>
+ <reference key="object" ref="1057689233"/>
+ <reference key="parent" ref="747245393"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">246</int>
+ <reference key="object" ref="814052996"/>
+ <reference key="parent" ref="747245393"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">338</int>
+ <reference key="object" ref="147235865"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="877676881"/>
+ </object>
+ <reference key="parent" ref="1055885701"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">339</int>
+ <reference key="object" ref="877676881"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="854660346"/>
+ <reference ref="653321099"/>
+ </object>
+ <reference key="parent" ref="147235865"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">340</int>
+ <reference key="object" ref="854660346"/>
+ <reference key="parent" ref="877676881"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">341</int>
+ <reference key="object" ref="653321099"/>
+ <reference key="parent" ref="877676881"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">205</int>
+ <reference key="object" ref="612578685"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">MediaServerCocoaTest_AppDelegate</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">347</int>
+ <reference key="object" ref="259022320"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="708542952"/>
+ </object>
+ <reference key="parent" ref="1055885701"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">348</int>
+ <reference key="object" ref="708542952"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1044121641"/>
+ <reference ref="446410933"/>
+ </object>
+ <reference key="parent" ref="259022320"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">349</int>
+ <reference key="object" ref="1044121641"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="16789759"/>
+ </object>
+ <reference key="parent" ref="708542952"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">350</int>
+ <reference key="object" ref="446410933"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="640850853"/>
+ </object>
+ <reference key="parent" ref="708542952"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">351</int>
+ <reference key="object" ref="640850853"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="775088230"/>
+ <reference ref="20804296"/>
+ <reference ref="489997371"/>
+ <reference ref="766941912"/>
+ <reference ref="831789293"/>
+ <reference ref="473944779"/>
+ <reference ref="405928732"/>
+ <reference ref="784305476"/>
+ </object>
+ <reference key="parent" ref="446410933"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">352</int>
+ <reference key="object" ref="775088230"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">353</int>
+ <reference key="object" ref="20804296"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">354</int>
+ <reference key="object" ref="489997371"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">355</int>
+ <reference key="object" ref="766941912"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">356</int>
+ <reference key="object" ref="831789293"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">357</int>
+ <reference key="object" ref="473944779"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">358</int>
+ <reference key="object" ref="405928732"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">359</int>
+ <reference key="object" ref="784305476"/>
+ <reference key="parent" ref="640850853"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">360</int>
+ <reference key="object" ref="16789759"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="486510693"/>
+ <reference ref="322671057"/>
+ <reference ref="294925675"/>
+ <reference ref="386587767"/>
+ <reference ref="530490813"/>
+ <reference ref="791073707"/>
+ <reference ref="820131188"/>
+ <reference ref="593643800"/>
+ <reference ref="17067790"/>
+ <reference ref="654563803"/>
+ <reference ref="35184653"/>
+ <reference ref="638669489"/>
+ <reference ref="169445129"/>
+ <reference ref="511988305"/>
+ <reference ref="637704817"/>
+ <reference ref="684848834"/>
+ </object>
+ <reference key="parent" ref="1044121641"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">361</int>
+ <reference key="object" ref="486510693"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">362</int>
+ <reference key="object" ref="322671057"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">363</int>
+ <reference key="object" ref="294925675"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">364</int>
+ <reference key="object" ref="386587767"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">365</int>
+ <reference key="object" ref="530490813"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">366</int>
+ <reference key="object" ref="791073707"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">367</int>
+ <reference key="object" ref="820131188"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">368</int>
+ <reference key="object" ref="593643800"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">369</int>
+ <reference key="object" ref="17067790"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="277000559"/>
+ </object>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">370</int>
+ <reference key="object" ref="654563803"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="164619877"/>
+ </object>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">371</int>
+ <reference key="object" ref="35184653"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1040787833"/>
+ </object>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">372</int>
+ <reference key="object" ref="638669489"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">373</int>
+ <reference key="object" ref="169445129"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">374</int>
+ <reference key="object" ref="511988305"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">375</int>
+ <reference key="object" ref="637704817"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">376</int>
+ <reference key="object" ref="684848834"/>
+ <reference key="parent" ref="16789759"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">377</int>
+ <reference key="object" ref="1040787833"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="299485767"/>
+ <reference ref="362581379"/>
+ <reference ref="368049810"/>
+ <reference ref="650703522"/>
+ <reference ref="470064337"/>
+ </object>
+ <reference key="parent" ref="35184653"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">378</int>
+ <reference key="object" ref="299485767"/>
+ <reference key="parent" ref="1040787833"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">379</int>
+ <reference key="object" ref="362581379"/>
+ <reference key="parent" ref="1040787833"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">380</int>
+ <reference key="object" ref="368049810"/>
+ <reference key="parent" ref="1040787833"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">381</int>
+ <reference key="object" ref="650703522"/>
+ <reference key="parent" ref="1040787833"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">382</int>
+ <reference key="object" ref="470064337"/>
+ <reference key="parent" ref="1040787833"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">383</int>
+ <reference key="object" ref="164619877"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="291130592"/>
+ <reference ref="557989785"/>
+ <reference ref="8023761"/>
+ </object>
+ <reference key="parent" ref="654563803"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">384</int>
+ <reference key="object" ref="291130592"/>
+ <reference key="parent" ref="164619877"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">385</int>
+ <reference key="object" ref="557989785"/>
+ <reference key="parent" ref="164619877"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">386</int>
+ <reference key="object" ref="8023761"/>
+ <reference key="parent" ref="164619877"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">387</int>
+ <reference key="object" ref="277000559"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="53041874"/>
+ <reference ref="665619559"/>
+ <reference ref="807093337"/>
+ <reference ref="81316040"/>
+ </object>
+ <reference key="parent" ref="17067790"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">388</int>
+ <reference key="object" ref="53041874"/>
+ <reference key="parent" ref="277000559"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">389</int>
+ <reference key="object" ref="665619559"/>
+ <reference key="parent" ref="277000559"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">390</int>
+ <reference key="object" ref="807093337"/>
+ <reference key="parent" ref="277000559"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">391</int>
+ <reference key="object" ref="81316040"/>
+ <reference key="parent" ref="277000559"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">392</int>
+ <reference key="object" ref="39582327"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">444</int>
+ <reference key="object" ref="545718297"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1022019938"/>
+ </object>
+ <reference key="parent" ref="1055885701"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">445</int>
+ <reference key="object" ref="1022019938"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="307109690"/>
+ <reference ref="744402274"/>
+ <reference ref="831119715"/>
+ <reference ref="70873500"/>
+ <reference ref="808304593"/>
+ <reference ref="597871667"/>
+ <reference ref="324532357"/>
+ <reference ref="618358412"/>
+ <reference ref="883438165"/>
+ <reference ref="473717252"/>
+ <reference ref="69846141"/>
+ <reference ref="365048869"/>
+ <reference ref="958645126"/>
+ <reference ref="814247416"/>
+ <reference ref="1058116061"/>
+ </object>
+ <reference key="parent" ref="545718297"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">446</int>
+ <reference key="object" ref="307109690"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">447</int>
+ <reference key="object" ref="744402274"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">448</int>
+ <reference key="object" ref="831119715"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">449</int>
+ <reference key="object" ref="70873500"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">450</int>
+ <reference key="object" ref="808304593"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">451</int>
+ <reference key="object" ref="597871667"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">452</int>
+ <reference key="object" ref="324532357"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">453</int>
+ <reference key="object" ref="618358412"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">454</int>
+ <reference key="object" ref="883438165"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">455</int>
+ <reference key="object" ref="473717252"/>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">456</int>
+ <reference key="object" ref="69846141"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="216314426"/>
+ </object>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">457</int>
+ <reference key="object" ref="365048869"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="666968844"/>
+ </object>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">458</int>
+ <reference key="object" ref="958645126"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="218631249"/>
+ </object>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">459</int>
+ <reference key="object" ref="814247416"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="562140037"/>
+ </object>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">460</int>
+ <reference key="object" ref="1058116061"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="792127484"/>
+ </object>
+ <reference key="parent" ref="1022019938"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">461</int>
+ <reference key="object" ref="792127484"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="318734362"/>
+ <reference ref="612849471"/>
+ </object>
+ <reference key="parent" ref="1058116061"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">462</int>
+ <reference key="object" ref="318734362"/>
+ <reference key="parent" ref="792127484"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">463</int>
+ <reference key="object" ref="612849471"/>
+ <reference key="parent" ref="792127484"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">464</int>
+ <reference key="object" ref="562140037"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="698135111"/>
+ <reference ref="899181471"/>
+ <reference ref="582459168"/>
+ </object>
+ <reference key="parent" ref="814247416"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">465</int>
+ <reference key="object" ref="698135111"/>
+ <reference key="parent" ref="562140037"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">466</int>
+ <reference key="object" ref="899181471"/>
+ <reference key="parent" ref="562140037"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">467</int>
+ <reference key="object" ref="582459168"/>
+ <reference key="parent" ref="562140037"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">468</int>
+ <reference key="object" ref="218631249"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="64764928"/>
+ <reference ref="136936362"/>
+ <reference ref="607672977"/>
+ <reference ref="484928874"/>
+ <reference ref="693070189"/>
+ <reference ref="1059551809"/>
+ <reference ref="416554597"/>
+ </object>
+ <reference key="parent" ref="958645126"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">469</int>
+ <reference key="object" ref="64764928"/>
+ <reference key="parent" ref="218631249"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">470</int>
+ <reference key="object" ref="136936362"/>
+ <reference key="parent" ref="218631249"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">471</int>
+ <reference key="object" ref="607672977"/>
+ <reference key="parent" ref="218631249"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">472</int>
+ <reference key="object" ref="484928874"/>
+ <reference key="parent" ref="218631249"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">473</int>
+ <reference key="object" ref="693070189"/>
+ <reference key="parent" ref="218631249"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">474</int>
+ <reference key="object" ref="1059551809"/>
+ <reference key="parent" ref="218631249"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">475</int>
+ <reference key="object" ref="416554597"/>
+ <reference key="parent" ref="218631249"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">476</int>
+ <reference key="object" ref="666968844"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="356339891"/>
+ <reference ref="416352713"/>
+ <reference ref="47615281"/>
+ <reference ref="252035059"/>
+ <reference ref="286376998"/>
+ <reference ref="81755183"/>
+ </object>
+ <reference key="parent" ref="365048869"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">477</int>
+ <reference key="object" ref="356339891"/>
+ <reference key="parent" ref="666968844"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">478</int>
+ <reference key="object" ref="416352713"/>
+ <reference key="parent" ref="666968844"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">479</int>
+ <reference key="object" ref="47615281"/>
+ <reference key="parent" ref="666968844"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">480</int>
+ <reference key="object" ref="252035059"/>
+ <reference key="parent" ref="666968844"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">481</int>
+ <reference key="object" ref="286376998"/>
+ <reference key="parent" ref="666968844"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">482</int>
+ <reference key="object" ref="81755183"/>
+ <reference key="parent" ref="666968844"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">483</int>
+ <reference key="object" ref="216314426"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="914446540"/>
+ <reference ref="160366792"/>
+ <reference ref="248661547"/>
+ <reference ref="30033296"/>
+ <reference ref="827334636"/>
+ </object>
+ <reference key="parent" ref="69846141"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">484</int>
+ <reference key="object" ref="914446540"/>
+ <reference key="parent" ref="216314426"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">485</int>
+ <reference key="object" ref="160366792"/>
+ <reference key="parent" ref="216314426"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">486</int>
+ <reference key="object" ref="248661547"/>
+ <reference key="parent" ref="216314426"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">487</int>
+ <reference key="object" ref="30033296"/>
+ <reference key="parent" ref="216314426"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">488</int>
+ <reference key="object" ref="827334636"/>
+ <reference key="parent" ref="216314426"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">518</int>
+ <reference key="object" ref="713319646"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="508081226"/>
+ </object>
+ <reference key="parent" ref="1055885701"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">519</int>
+ <reference key="object" ref="508081226"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="954120217"/>
+ </object>
+ <reference key="parent" ref="713319646"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">520</int>
+ <reference key="object" ref="954120217"/>
+ <reference key="parent" ref="508081226"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">523</int>
+ <reference key="object" ref="770142414"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">MediaServerCocoaTestController</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">525</int>
+ <reference key="object" ref="544612128"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="879879405"/>
+ </object>
+ <reference key="parent" ref="823886803"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">526</int>
+ <reference key="object" ref="879879405"/>
+ <reference key="parent" ref="544612128"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-3.IBPluginDependency</string>
+ <string>-3.ImportedFromIB2</string>
+ <string>129.IBPluginDependency</string>
+ <string>129.ImportedFromIB2</string>
+ <string>130.IBEditorWindowLastContentRect</string>
+ <string>130.IBPluginDependency</string>
+ <string>130.ImportedFromIB2</string>
+ <string>131.IBPluginDependency</string>
+ <string>131.ImportedFromIB2</string>
+ <string>134.IBPluginDependency</string>
+ <string>134.ImportedFromIB2</string>
+ <string>136.IBPluginDependency</string>
+ <string>136.ImportedFromIB2</string>
+ <string>143.IBPluginDependency</string>
+ <string>143.ImportedFromIB2</string>
+ <string>144.IBPluginDependency</string>
+ <string>144.ImportedFromIB2</string>
+ <string>145.IBPluginDependency</string>
+ <string>145.ImportedFromIB2</string>
+ <string>149.IBPluginDependency</string>
+ <string>149.ImportedFromIB2</string>
+ <string>150.IBPluginDependency</string>
+ <string>150.ImportedFromIB2</string>
+ <string>196.IBPluginDependency</string>
+ <string>196.ImportedFromIB2</string>
+ <string>2.IBPluginDependency</string>
+ <string>2.ImportedFromIB2</string>
+ <string>205.ImportedFromIB2</string>
+ <string>21.IBEditorWindowLastContentRect</string>
+ <string>21.IBPluginDependency</string>
+ <string>21.IBWindowTemplateEditedContentRect</string>
+ <string>21.ImportedFromIB2</string>
+ <string>21.NSWindowTemplate.visibleAtLaunch</string>
+ <string>21.windowTemplate.hasMinSize</string>
+ <string>21.windowTemplate.minSize</string>
+ <string>241.IBPluginDependency</string>
+ <string>241.ImportedFromIB2</string>
+ <string>242.IBEditorWindowLastContentRect</string>
+ <string>242.IBPluginDependency</string>
+ <string>242.ImportedFromIB2</string>
+ <string>243.IBPluginDependency</string>
+ <string>243.ImportedFromIB2</string>
+ <string>244.IBPluginDependency</string>
+ <string>244.ImportedFromIB2</string>
+ <string>245.IBPluginDependency</string>
+ <string>245.ImportedFromIB2</string>
+ <string>246.IBPluginDependency</string>
+ <string>246.ImportedFromIB2</string>
+ <string>29.IBEditorWindowLastContentRect</string>
+ <string>29.IBPluginDependency</string>
+ <string>29.ImportedFromIB2</string>
+ <string>338.IBPluginDependency</string>
+ <string>338.ImportedFromIB2</string>
+ <string>339.IBEditorWindowLastContentRect</string>
+ <string>339.IBPluginDependency</string>
+ <string>339.ImportedFromIB2</string>
+ <string>340.IBPluginDependency</string>
+ <string>340.ImportedFromIB2</string>
+ <string>341.IBPluginDependency</string>
+ <string>341.ImportedFromIB2</string>
+ <string>347.IBPluginDependency</string>
+ <string>348.IBEditorWindowLastContentRect</string>
+ <string>348.IBPluginDependency</string>
+ <string>349.IBPluginDependency</string>
+ <string>350.IBPluginDependency</string>
+ <string>351.IBPluginDependency</string>
+ <string>352.IBPluginDependency</string>
+ <string>353.IBPluginDependency</string>
+ <string>354.IBPluginDependency</string>
+ <string>355.IBPluginDependency</string>
+ <string>356.IBPluginDependency</string>
+ <string>357.IBPluginDependency</string>
+ <string>358.IBPluginDependency</string>
+ <string>359.IBPluginDependency</string>
+ <string>360.IBPluginDependency</string>
+ <string>361.IBPluginDependency</string>
+ <string>362.IBPluginDependency</string>
+ <string>363.IBPluginDependency</string>
+ <string>364.IBPluginDependency</string>
+ <string>365.IBPluginDependency</string>
+ <string>366.IBPluginDependency</string>
+ <string>367.IBPluginDependency</string>
+ <string>368.IBPluginDependency</string>
+ <string>369.IBPluginDependency</string>
+ <string>370.IBPluginDependency</string>
+ <string>371.IBPluginDependency</string>
+ <string>372.IBPluginDependency</string>
+ <string>373.IBPluginDependency</string>
+ <string>374.IBPluginDependency</string>
+ <string>375.IBPluginDependency</string>
+ <string>376.IBPluginDependency</string>
+ <string>377.IBPluginDependency</string>
+ <string>378.IBPluginDependency</string>
+ <string>379.IBPluginDependency</string>
+ <string>380.IBPluginDependency</string>
+ <string>381.IBPluginDependency</string>
+ <string>382.IBPluginDependency</string>
+ <string>383.IBPluginDependency</string>
+ <string>384.IBPluginDependency</string>
+ <string>385.IBPluginDependency</string>
+ <string>386.IBPluginDependency</string>
+ <string>387.IBPluginDependency</string>
+ <string>388.IBPluginDependency</string>
+ <string>389.IBPluginDependency</string>
+ <string>390.IBPluginDependency</string>
+ <string>391.IBPluginDependency</string>
+ <string>444.IBPluginDependency</string>
+ <string>445.IBEditorWindowLastContentRect</string>
+ <string>445.IBPluginDependency</string>
+ <string>446.IBPluginDependency</string>
+ <string>447.IBPluginDependency</string>
+ <string>448.IBPluginDependency</string>
+ <string>449.IBPluginDependency</string>
+ <string>450.IBPluginDependency</string>
+ <string>451.IBPluginDependency</string>
+ <string>452.IBPluginDependency</string>
+ <string>453.IBPluginDependency</string>
+ <string>454.IBPluginDependency</string>
+ <string>455.IBPluginDependency</string>
+ <string>456.IBPluginDependency</string>
+ <string>457.IBPluginDependency</string>
+ <string>458.IBPluginDependency</string>
+ <string>459.IBPluginDependency</string>
+ <string>460.IBPluginDependency</string>
+ <string>461.IBPluginDependency</string>
+ <string>462.IBPluginDependency</string>
+ <string>463.IBPluginDependency</string>
+ <string>464.IBEditorWindowLastContentRect</string>
+ <string>464.IBPluginDependency</string>
+ <string>465.IBPluginDependency</string>
+ <string>466.IBPluginDependency</string>
+ <string>467.IBPluginDependency</string>
+ <string>468.IBPluginDependency</string>
+ <string>469.IBPluginDependency</string>
+ <string>470.IBPluginDependency</string>
+ <string>471.IBPluginDependency</string>
+ <string>472.IBPluginDependency</string>
+ <string>473.IBPluginDependency</string>
+ <string>474.IBPluginDependency</string>
+ <string>475.IBPluginDependency</string>
+ <string>476.IBPluginDependency</string>
+ <string>477.IBPluginDependency</string>
+ <string>478.IBPluginDependency</string>
+ <string>479.IBPluginDependency</string>
+ <string>480.IBPluginDependency</string>
+ <string>481.IBPluginDependency</string>
+ <string>482.IBPluginDependency</string>
+ <string>483.IBPluginDependency</string>
+ <string>484.IBPluginDependency</string>
+ <string>485.IBPluginDependency</string>
+ <string>486.IBPluginDependency</string>
+ <string>487.IBPluginDependency</string>
+ <string>488.IBPluginDependency</string>
+ <string>518.IBPluginDependency</string>
+ <string>519.IBEditorWindowLastContentRect</string>
+ <string>519.IBPluginDependency</string>
+ <string>520.IBPluginDependency</string>
+ <string>523.IBPluginDependency</string>
+ <string>525.IBPluginDependency</string>
+ <string>526.IBPluginDependency</string>
+ <string>56.IBPluginDependency</string>
+ <string>56.ImportedFromIB2</string>
+ <string>57.IBEditorWindowLastContentRect</string>
+ <string>57.IBPluginDependency</string>
+ <string>57.ImportedFromIB2</string>
+ <string>58.IBPluginDependency</string>
+ <string>58.ImportedFromIB2</string>
+ <string>74.IBPluginDependency</string>
+ <string>74.ImportedFromIB2</string>
+ <string>75.IBPluginDependency</string>
+ <string>75.ImportedFromIB2</string>
+ <string>77.IBPluginDependency</string>
+ <string>77.ImportedFromIB2</string>
+ <string>78.IBPluginDependency</string>
+ <string>78.ImportedFromIB2</string>
+ <string>81.IBEditorWindowLastContentRect</string>
+ <string>81.IBPluginDependency</string>
+ <string>81.ImportedFromIB2</string>
+ <string>83.IBPluginDependency</string>
+ <string>83.ImportedFromIB2</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>{{370, 880}, {64, 6}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <integer value="1"/>
+ <string>{{319, 476}, {480, 360}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{319, 476}, {480, 360}}</string>
+ <integer value="1"/>
+ <integer value="1"/>
+ <integer value="1"/>
+ <string>{213, 107}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>{{610, 1023}, {194, 73}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>{{380, 810}, {528, 20}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>{{410, 921}, {234, 43}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{494, 1053}, {83, 43}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{450, 813}, {254, 283}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{783, 793}, {170, 63}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{681, 1073}, {250, 23}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>{{85, 781}, {245, 183}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>{{408, 1023}, {176, 73}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1"/>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">527</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">MediaServerCocoaTestController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>mainButton</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSButton</string>
+ <string>NSWindow</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>mainButton</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">mainButton</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">window</string>
+ <string key="candidateClassName">NSWindow</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../../../Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">MediaServerCocoaTest_AppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="actions">
+ <string key="NS.key.0">saveAction:</string>
+ <string key="NS.object.0">id</string>
+ </object>
+ <object class="NSMutableDictionary" key="actionInfosByName">
+ <string key="NS.key.0">saveAction:</string>
+ <object class="IBActionInfo" key="NS.object.0">
+ <string key="name">saveAction:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">window</string>
+ <string key="NS.object.0">NSWindow</string>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <string key="NS.key.0">window</string>
+ <object class="IBToOneOutletInfo" key="NS.object.0">
+ <string key="name">window</string>
+ <string key="candidateClassName">NSWindow</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../../../Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">MediaServerCocoaTest_AppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBUserSource</string>
+ <string key="minorKey"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+ <integer value="1050" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../../../../Build/Targets/universal-apple-macosx/Platinum.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSMenuCheckmark</string>
+ <string>NSMenuMixedState</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>{9, 8}</string>
+ <string>{7, 2}</string>
+ </object>
+ </object>
+ </data>
+</archive>
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest-Info.plist b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest-Info.plist
new file mode 100644
index 0000000..883d858
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest-Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.h b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.h
new file mode 100644
index 0000000..2de7c10
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.h
@@ -0,0 +1,20 @@
+//
+// MediaServerCocoaTestController.h
+// Platinum
+//
+// Created by Sylvain on 9/14/10.
+// Copyright 2010 Plutinosoft LLC. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <Platinum/PltUPnPObject.h>
+#import <Platinum/PltMediaServerObject.h>
+
+@interface MediaServerCocoaTestController : NSObject <PLT_MediaServerDelegateObject> {
+ IBOutlet NSWindow* window;
+ IBOutlet NSButton* mainButton;
+
+ PLT_UPnPObject* upnp;
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.mm b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.mm
new file mode 100644
index 0000000..d7b9a29
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTestController.mm
@@ -0,0 +1,64 @@
+//
+// MediaServerCocoaTestController.mm
+// Platinum
+//
+// Created by Sylvain on 9/14/10.
+// Copyright 2010 Plutinosoft LLC. All rights reserved.
+//
+
+#import "MediaServerCocoaTestController.h"
+#import <Neptune/Neptune.h>
+
+
+@implementation MediaServerCocoaTestController
+
++ (void)initialize {
+ NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.outputs=1;.ConsoleHandler.filter=61");
+}
+
+- (void)awakeFromNib {
+ upnp = [[PLT_UPnPObject alloc] init];
+
+ // create server and add ourselves as the delegate
+ PLT_MediaServerObject* server = [[PLT_MediaServerObject alloc] init];
+ [server setDelegate:self];
+ [upnp addDevice:server];
+
+ [mainButton setTarget:self];
+ [mainButton setTitle:@"Start"];
+ [mainButton setAction:@selector(performUPnPStarStop:)];
+}
+
+- (void)performUPnPStarStop:(id)sender {
+ if ([upnp isRunning]) {
+ [upnp stop];
+ [mainButton setTitle:@"Start"];
+ } else {
+ [upnp start];
+ [mainButton setTitle:@"Stop"];
+ }
+}
+
+#pragma mark - PLT_MediaServerDelegateObject
+
+- (NPT_Result)onBrowseMetadata:(PLT_MediaServerBrowseCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+- (NPT_Result)onBrowseDirectChildren:(PLT_MediaServerBrowseCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+- (NPT_Result)onSearchContainer:(PLT_MediaServerSearchCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+- (NPT_Result)onFileRequest:(PLT_MediaServerFileRequestCapsule*)info
+{
+ return NPT_FAILURE;
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.h b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.h
new file mode 100644
index 0000000..07ca005
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.h
@@ -0,0 +1,28 @@
+//
+// MediaServerCocoaTest_AppDelegate.h
+// MediaServerCocoaTest
+//
+// Created by Sylvain on 9/14/10.
+// Copyright Plutinosoft LLC 2010 . All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface MediaServerCocoaTest_AppDelegate : NSObject
+{
+ NSWindow *window;
+
+ NSPersistentStoreCoordinator *persistentStoreCoordinator;
+ NSManagedObjectModel *managedObjectModel;
+ NSManagedObjectContext *managedObjectContext;
+}
+
+@property (nonatomic, retain) IBOutlet NSWindow *window;
+
+@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
+@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
+@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
+
+- (IBAction)saveAction:sender;
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.m b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.m
new file mode 100644
index 0000000..e8120ba
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.m
@@ -0,0 +1,212 @@
+//
+// MediaServerCocoaTest_AppDelegate.m
+// MediaServerCocoaTest
+//
+// Created by Sylvain on 9/14/10.
+// Copyright Plutinosoft LLC 2010 . All rights reserved.
+//
+
+#import "MediaServerCocoaTest_AppDelegate.h"
+
+@implementation MediaServerCocoaTest_AppDelegate
+
+@synthesize window;
+
+/**
+ Returns the support directory for the application, used to store the Core Data
+ store file. This code uses a directory named "MediaServerCocoaTest" for
+ the content, either in the NSApplicationSupportDirectory location or (if the
+ former cannot be found), the system's temporary directory.
+ */
+
+- (NSString *)applicationSupportDirectory {
+
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
+ return [basePath stringByAppendingPathComponent:@"MediaServerCocoaTest"];
+}
+
+
+/**
+ Creates, retains, and returns the managed object model for the application
+ by merging all of the models found in the application bundle.
+ */
+
+- (NSManagedObjectModel *)managedObjectModel {
+
+ if (managedObjectModel) return managedObjectModel;
+
+ managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
+ return managedObjectModel;
+}
+
+
+/**
+ Returns the persistent store coordinator for the application. This
+ implementation will create and return a coordinator, having added the
+ store for the application to it. (The directory for the store is created,
+ if necessary.)
+ */
+
+- (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
+
+ if (persistentStoreCoordinator) return persistentStoreCoordinator;
+
+ NSManagedObjectModel *mom = [self managedObjectModel];
+ if (!mom) {
+ NSAssert(NO, @"Managed object model is nil");
+ NSLog(@"%@:%s No model to generate a store from", [self class], _cmd);
+ return nil;
+ }
+
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ NSString *applicationSupportDirectory = [self applicationSupportDirectory];
+ NSError *error = nil;
+
+ if ( ![fileManager fileExistsAtPath:applicationSupportDirectory isDirectory:NULL] ) {
+ if (![fileManager createDirectoryAtPath:applicationSupportDirectory withIntermediateDirectories:NO attributes:nil error:&error]) {
+ NSAssert(NO, ([NSString stringWithFormat:@"Failed to create App Support directory %@ : %@", applicationSupportDirectory,error]));
+ NSLog(@"Error creating application support directory at %@ : %@",applicationSupportDirectory,error);
+ return nil;
+ }
+ }
+
+ NSURL *url = [NSURL fileURLWithPath: [applicationSupportDirectory stringByAppendingPathComponent: @"storedata"]];
+ persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: mom];
+ if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType
+ configuration:nil
+ URL:url
+ options:nil
+ error:&error]){
+ [[NSApplication sharedApplication] presentError:error];
+ [persistentStoreCoordinator release], persistentStoreCoordinator = nil;
+ return nil;
+ }
+
+ return persistentStoreCoordinator;
+}
+
+/**
+ Returns the managed object context for the application (which is already
+ bound to the persistent store coordinator for the application.)
+ */
+
+- (NSManagedObjectContext *) managedObjectContext {
+
+ if (managedObjectContext) return managedObjectContext;
+
+ NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
+ if (!coordinator) {
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+ [dict setValue:@"Failed to initialize the store" forKey:NSLocalizedDescriptionKey];
+ [dict setValue:@"There was an error building up the data file." forKey:NSLocalizedFailureReasonErrorKey];
+ NSError *error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
+ [[NSApplication sharedApplication] presentError:error];
+ return nil;
+ }
+ managedObjectContext = [[NSManagedObjectContext alloc] init];
+ [managedObjectContext setPersistentStoreCoordinator: coordinator];
+
+ return managedObjectContext;
+}
+
+/**
+ Returns the NSUndoManager for the application. In this case, the manager
+ returned is that of the managed object context for the application.
+ */
+
+- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
+ return [[self managedObjectContext] undoManager];
+}
+
+
+/**
+ Performs the save action for the application, which is to send the save:
+ message to the application's managed object context. Any encountered errors
+ are presented to the user.
+ */
+
+- (IBAction) saveAction:(id)sender {
+
+ NSError *error = nil;
+
+ if (![[self managedObjectContext] commitEditing]) {
+ NSLog(@"%@:%s unable to commit editing before saving", [self class], _cmd);
+ }
+
+ if (![[self managedObjectContext] save:&error]) {
+ [[NSApplication sharedApplication] presentError:error];
+ }
+}
+
+
+/**
+ Implementation of the applicationShouldTerminate: method, used here to
+ handle the saving of changes in the application managed object context
+ before the application terminates.
+ */
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
+
+ if (!managedObjectContext) return NSTerminateNow;
+
+ if (![managedObjectContext commitEditing]) {
+ NSLog(@"%@:%s unable to commit editing to terminate", [self class], _cmd);
+ return NSTerminateCancel;
+ }
+
+ if (![managedObjectContext hasChanges]) return NSTerminateNow;
+
+ NSError *error = nil;
+ if (![managedObjectContext save:&error]) {
+
+ // This error handling simply presents error information in a panel with an
+ // "Ok" button, which does not include any attempt at error recovery (meaning,
+ // attempting to fix the error.) As a result, this implementation will
+ // present the information to the user and then follow up with a panel asking
+ // if the user wishes to "Quit Anyway", without saving the changes.
+
+ // Typically, this process should be altered to include application-specific
+ // recovery steps.
+
+ BOOL result = [sender presentError:error];
+ if (result) return NSTerminateCancel;
+
+ NSString *question = NSLocalizedString(@"Could not save changes while quitting. Quit anyway?", @"Quit without saves error question message");
+ NSString *info = NSLocalizedString(@"Quitting now will lose any changes you have made since the last successful save", @"Quit without saves error question info");
+ NSString *quitButton = NSLocalizedString(@"Quit anyway", @"Quit anyway button title");
+ NSString *cancelButton = NSLocalizedString(@"Cancel", @"Cancel button title");
+ NSAlert *alert = [[NSAlert alloc] init];
+ [alert setMessageText:question];
+ [alert setInformativeText:info];
+ [alert addButtonWithTitle:quitButton];
+ [alert addButtonWithTitle:cancelButton];
+
+ NSInteger answer = [alert runModal];
+ [alert release];
+ alert = nil;
+
+ if (answer == NSAlertAlternateReturn) return NSTerminateCancel;
+
+ }
+
+ return NSTerminateNow;
+}
+
+
+/**
+ Implementation of dealloc, to release the retained variables.
+ */
+
+- (void)dealloc {
+
+ [window release];
+ [managedObjectContext release];
+ [persistentStoreCoordinator release];
+ [managedObjectModel release];
+
+ [super dealloc];
+}
+
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.mm b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.mm
new file mode 100644
index 0000000..c6fb49a
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_AppDelegate.mm
@@ -0,0 +1,195 @@
+//
+// MediaServerCocoaTest_AppDelegate.m
+// MediaServerCocoaTest
+//
+// Created by Sylvain on 9/14/10.
+// Copyright Plutinosoft LLC 2010 . All rights reserved.
+//
+
+#import "MediaServerCocoaTest_AppDelegate.h"
+
+@implementation MediaServerCocoaTest_AppDelegate
+
+@synthesize window;
+
+/**
+ Returns the support directory for the application, used to store the Core Data
+ store file. This code uses a directory named "MediaServerCocoaTest" for
+ the content, either in the NSApplicationSupportDirectory location or (if the
+ former cannot be found), the system's temporary directory.
+ */
+
+- (NSString *)applicationSupportDirectory {
+
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
+ return [basePath stringByAppendingPathComponent:@"MediaServerCocoaTest"];
+}
+
+
+/**
+ Creates, retains, and returns the managed object model for the application
+ by merging all of the models found in the application bundle.
+ */
+
+- (NSManagedObjectModel *)managedObjectModel {
+
+ if (managedObjectModel) return managedObjectModel;
+
+ managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
+ return managedObjectModel;
+}
+
+
+/**
+ Returns the persistent store coordinator for the application. This
+ implementation will create and return a coordinator, having added the
+ store for the application to it. (The directory for the store is created,
+ if necessary.)
+ */
+
+- (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
+
+ if (persistentStoreCoordinator) return persistentStoreCoordinator;
+
+ NSManagedObjectModel *mom = [self managedObjectModel];
+ if (!mom) {
+ NSAssert(NO, @"Managed object model is nil");
+ //NSLog(@"%@:%s No model to generate a store from", [self class], _cmd);
+ return nil;
+ }
+
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ NSString *applicationSupportDirectory = [self applicationSupportDirectory];
+ NSError *error = nil;
+
+ if ( ![fileManager fileExistsAtPath:applicationSupportDirectory isDirectory:NULL] ) {
+ if (![fileManager createDirectoryAtPath:applicationSupportDirectory withIntermediateDirectories:NO attributes:nil error:&error]) {
+ NSAssert(NO, ([NSString stringWithFormat:@"Failed to create App Support directory %@ : %@", applicationSupportDirectory,error]));
+ NSLog(@"Error creating application support directory at %@ : %@",applicationSupportDirectory,error);
+ return nil;
+ }
+ }
+
+ NSURL *url = [NSURL fileURLWithPath: [applicationSupportDirectory stringByAppendingPathComponent: @"storedata"]];
+ persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: mom];
+ if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType
+ configuration:nil
+ URL:url
+ options:nil
+ error:&error]){
+ [[NSApplication sharedApplication] presentError:error];
+ persistentStoreCoordinator = nil;
+ return nil;
+ }
+
+ return persistentStoreCoordinator;
+}
+
+/**
+ Returns the managed object context for the application (which is already
+ bound to the persistent store coordinator for the application.)
+ */
+
+- (NSManagedObjectContext *) managedObjectContext {
+
+ if (managedObjectContext) return managedObjectContext;
+
+ NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
+ if (!coordinator) {
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+ [dict setValue:@"Failed to initialize the store" forKey:NSLocalizedDescriptionKey];
+ [dict setValue:@"There was an error building up the data file." forKey:NSLocalizedFailureReasonErrorKey];
+ NSError *error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
+ [[NSApplication sharedApplication] presentError:error];
+ return nil;
+ }
+ managedObjectContext = [[NSManagedObjectContext alloc] init];
+ [managedObjectContext setPersistentStoreCoordinator: coordinator];
+
+ return managedObjectContext;
+}
+
+/**
+ Returns the NSUndoManager for the application. In this case, the manager
+ returned is that of the managed object context for the application.
+ */
+
+- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
+ return [[self managedObjectContext] undoManager];
+}
+
+
+/**
+ Performs the save action for the application, which is to send the save:
+ message to the application's managed object context. Any encountered errors
+ are presented to the user.
+ */
+
+- (IBAction) saveAction:(id)sender {
+
+ NSError *error = nil;
+
+ if (![[self managedObjectContext] commitEditing]) {
+ //NSLog(@"%@:%s unable to commit editing before saving", [self class], _cmd);
+ }
+
+ if (![[self managedObjectContext] save:&error]) {
+ [[NSApplication sharedApplication] presentError:error];
+ }
+}
+
+
+/**
+ Implementation of the applicationShouldTerminate: method, used here to
+ handle the saving of changes in the application managed object context
+ before the application terminates.
+ */
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
+
+ if (!managedObjectContext) return NSTerminateNow;
+
+ if (![managedObjectContext commitEditing]) {
+ //NSLog(@"%@:%s unable to commit editing to terminate", [self class], _cmd);
+ return NSTerminateCancel;
+ }
+
+ if (![managedObjectContext hasChanges]) return NSTerminateNow;
+
+ NSError *error = nil;
+ if (![managedObjectContext save:&error]) {
+
+ // This error handling simply presents error information in a panel with an
+ // "Ok" button, which does not include any attempt at error recovery (meaning,
+ // attempting to fix the error.) As a result, this implementation will
+ // present the information to the user and then follow up with a panel asking
+ // if the user wishes to "Quit Anyway", without saving the changes.
+
+ // Typically, this process should be altered to include application-specific
+ // recovery steps.
+
+ BOOL result = [sender presentError:error];
+ if (result) return NSTerminateCancel;
+
+ NSString *question = NSLocalizedString(@"Could not save changes while quitting. Quit anyway?", @"Quit without saves error question message");
+ NSString *info = NSLocalizedString(@"Quitting now will lose any changes you have made since the last successful save", @"Quit without saves error question info");
+ NSString *quitButton = NSLocalizedString(@"Quit anyway", @"Quit anyway button title");
+ NSString *cancelButton = NSLocalizedString(@"Cancel", @"Cancel button title");
+ NSAlert *alert = [[NSAlert alloc] init];
+ [alert setMessageText:question];
+ [alert setInformativeText:info];
+ [alert addButtonWithTitle:quitButton];
+ [alert addButtonWithTitle:cancelButton];
+
+ NSInteger answer = [alert runModal];
+ alert = nil;
+
+ if (answer == NSAlertAlternateReturn) return NSTerminateCancel;
+
+ }
+
+ return NSTerminateNow;
+}
+
+@end
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/elements b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/elements
new file mode 100644
index 0000000..2209062
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/elements
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/layout b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/layout
new file mode 100644
index 0000000..85196a8
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_DataModel.xcdatamodel/layout
Binary files differ
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_Prefix.pch b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_Prefix.pch
new file mode 100644
index 0000000..23e1c62
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/MediaServerCocoaTest_Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'MediaServerCocoaTest' target in the 'MediaServerCocoaTest' project
+//
+
+#ifdef __OBJC__
+ #import <Cocoa/Cocoa.h>
+#endif
diff --git a/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/main.mm b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/main.mm
new file mode 100644
index 0000000..87077c6
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/MediaServerCocoaTest/main.mm
@@ -0,0 +1,14 @@
+//
+// main.m
+// MediaServerCocoaTest
+//
+// Created by Sylvain on 9/14/10.
+// Copyright Plutinosoft LLC 2010. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
diff --git a/lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.cpp b/lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.cpp
new file mode 100644
index 0000000..0d32ec2
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.cpp
@@ -0,0 +1,111 @@
+/*****************************************************************
+|
+| Platinum - Simple Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "Platinum.h"
+#include "PltSimple.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.test.simple")
+
+/*----------------------------------------------------------------------
+| forward references
++---------------------------------------------------------------------*/
+extern const char* SCPDXML_SIMPLE;
+
+/*----------------------------------------------------------------------
+| PLT_Simple::PLT_Simple
++---------------------------------------------------------------------*/
+PLT_Simple::PLT_Simple(const char* FriendlyName, const char* UUID) :
+ PLT_DeviceHost("/", UUID, "urn:schemas-upnp-org:device:Simple:1", FriendlyName)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Simple::~PLT_Simple
++---------------------------------------------------------------------*/
+PLT_Simple::~PLT_Simple()
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_Simple::SetupServices
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_Simple::SetupServices()
+{
+ NPT_Result res;
+ PLT_Service* service = new PLT_Service(
+ this,
+ "urn:schemas-upnp-org:service:Test:1",
+ "urn:upnp-org:serviceId:Test.001",
+ "Test");
+
+ NPT_CHECK_LABEL_FATAL(res = service->SetSCPDXML((const char*)SCPDXML_SIMPLE), failure);
+ NPT_CHECK_LABEL_FATAL(res = AddService(service), failure);
+
+ service->SetStateVariable("Status", "True");
+
+ return NPT_SUCCESS;
+
+failure:
+ delete service;
+ return res;
+}
+
+const char* SCPDXML_SIMPLE =
+ "<?xml version=\"1.0\" ?>"
+ " <scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">"
+ " <specVersion>"
+ " <major>1</major>"
+ " <minor>0</minor>"
+ " </specVersion>"
+ " <serviceStateTable>"
+ " <stateVariable sendEvents=\"yes\">"
+ " <name>LastChange</name>"
+ " <dataType>string</dataType>"
+ " <defaultValue></defaultValue>"
+ " </stateVariable>"
+ " <stateVariable sendEvents=\"yes\">"
+ " <name>PresetNameList</name>"
+ " <dataType>string</dataType>"
+ " <defaultValue></defaultValue>"
+ " </stateVariable>"
+ " </serviceStateTable>"
+ " <intel_nmpr:X_INTEL_NMPR xmlns:intel_nmpr=\"udn:schemas-intel-com:device-1-0\">2.1</intel_nmpr:X_INTEL_NMPR>"
+ " <dlna:X_DLNADOC xmlns:dlna=\"udn:schemas-dlna-org:device-1-0\">DMP 1.00</dlna:X_DLNADOC>"
+ " </scpd>";
+
diff --git a/lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.h b/lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.h
new file mode 100644
index 0000000..487e760
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/Simple/PltSimple.h
@@ -0,0 +1,56 @@
+/*****************************************************************
+|
+| Platinum -Simple Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_SIMPLE_H_
+#define _PLT_SIMPLE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltDeviceHost.h"
+
+/*----------------------------------------------------------------------
+| PLT_Simple class
++---------------------------------------------------------------------*/
+class PLT_Simple : public PLT_DeviceHost
+{
+public:
+ PLT_Simple(const char* FriendlyName, const char* UUID = "");
+ virtual ~PLT_Simple();
+
+ // PLT_DeviceHost methods
+ virtual NPT_Result SetupServices();
+};
+
+#endif /* _PLT_SIMPLE_H_ */
diff --git a/lib/libUPnP/Platinum/Source/Tests/Simple/SimpleTest.cpp b/lib/libUPnP/Platinum/Source/Tests/Simple/SimpleTest.cpp
new file mode 100644
index 0000000..6596227
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/Simple/SimpleTest.cpp
@@ -0,0 +1,63 @@
+/*****************************************************************
+|
+| Platinum - Test Light Device
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltUPnP.h"
+#include "PltSimple.h"
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int /* argc */, char** /* argv */)
+{
+ PLT_UPnP upnp;
+
+ PLT_DeviceHostReference device(new PLT_Simple("Platinum Test"));
+
+ upnp.AddDevice(device);
+ upnp.Start();
+
+ char buf[256];
+ while (gets(buf)) {
+ if (*buf == 'q')
+ break;
+ }
+
+ upnp.Stop();
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tests/Ssdp/SsdpTest1.cpp b/lib/libUPnP/Platinum/Source/Tests/Ssdp/SsdpTest1.cpp
new file mode 100644
index 0000000..1e1f6aa
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/Ssdp/SsdpTest1.cpp
@@ -0,0 +1,66 @@
+/*****************************************************************
+|
+| Platinum - SSDP Test Program 1
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "Platinum.h"
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int, char**)
+{
+ // setup Neptune logging
+ NPT_LogManager::GetDefault().Configure("plist:.level=FINE;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=42");
+
+ PLT_UPnP upnp;
+ PLT_CtrlPointReference ctrl_point(new PLT_CtrlPoint());
+ upnp.AddCtrlPoint(ctrl_point);
+
+ if (NPT_FAILED(upnp.Start()))
+ return 1;
+
+ char buf[256];
+ while (gets(buf)) {
+ if (*buf == 'q')
+ break;
+ }
+
+ upnp.Stop();
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tests/Time/TimeTest1.cpp b/lib/libUPnP/Platinum/Source/Tests/Time/TimeTest1.cpp
new file mode 100644
index 0000000..6d62708
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tests/Time/TimeTest1.cpp
@@ -0,0 +1,189 @@
+/*****************************************************************
+|
+| Platinum - Time Test
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <stdio.h>
+#include "Neptune.h"
+#include "Platinum.h"
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#define SHOULD_SUCCEED(r) \
+ do { \
+ if (NPT_FAILED(r)) { \
+ fprintf(stderr, "FAILED: line %d\n", __LINE__); \
+ NPT_ASSERT(0); \
+ } \
+ } while(0)
+
+#define SHOULD_FAIL(r) \
+ do { \
+ if (NPT_SUCCEEDED(r)) { \
+ fprintf(stderr, "should have failed line %d (%d)\n", \
+ __LINE__, r); \
+ NPT_ASSERT(0); \
+ } \
+ } while(0)
+
+#define SHOULD_EQUAL_I(a, b) \
+ do { \
+ if ((a) != (b)) { \
+ fprintf(stderr, "got %d expected %d line %d\n", \
+ (int)a, (int)b, __LINE__); \
+ NPT_ASSERT(0); \
+ } \
+ } while(0)
+
+#define SHOULD_EQUAL_F(a, b) \
+ do { \
+ if ((a) != (b)) { \
+ fprintf(stderr, "got %f, expected %f line %d\n", \
+ (float)a, (float)b, __LINE__); \
+ NPT_ASSERT(0); \
+ } \
+ } while(0)
+
+#define SHOULD_EQUAL_S(a, b) \
+ do { \
+ if (!NPT_StringsEqual(a,b)) { \
+ fprintf(stderr, "got %s, expected %s line %d\n", \
+ a, b, __LINE__); \
+ NPT_ASSERT(0); \
+ } \
+ } while(0)
+
+/*----------------------------------------------------------------------
+| TestSuiteGetTime
++---------------------------------------------------------------------*/
+static void
+TestSuiteGetTime()
+{
+ NPT_TimeStamp now, now2;
+ NPT_DateTime today;
+
+ /* get utc time */
+ SHOULD_SUCCEED(NPT_System::GetCurrentTimeStamp(now));
+
+ /* convert utc time to date */
+ SHOULD_SUCCEED(today.FromTimeStamp(now));
+
+ /* convert local time back to utc */
+ SHOULD_SUCCEED(today.ToTimeStamp(now2));
+
+ /* verify utc time has not change */
+ SHOULD_EQUAL_I(now.ToSeconds(), now2.ToSeconds());
+}
+
+/*----------------------------------------------------------------------
+| TestSuiteSetDateTimeZone
++---------------------------------------------------------------------*/
+static void
+TestSuiteSetDateTimeZone()
+{
+ NPT_TimeStamp now, now2;
+ NPT_DateTime today, today2;
+ NPT_Int32 tz;
+
+ /* get utc time */
+ SHOULD_SUCCEED(NPT_System::GetCurrentTimeStamp(now));
+
+ /* convert utc time to date */
+ SHOULD_SUCCEED(today.FromTimeStamp(now));
+
+ for (tz = -60*12; tz <= 60*12; tz+=30) {
+ /* convert date to another timezone */
+ today2 = today;
+ SHOULD_SUCCEED(today2.ChangeTimeZone(tz));
+
+ /* get timestamp from converted date */
+ SHOULD_SUCCEED(today2.ToTimeStamp(now2));
+
+ /* verify utc time has not change */
+ SHOULD_EQUAL_I(now.ToSeconds(), now2.ToSeconds());
+ }
+}
+
+/*----------------------------------------------------------------------
+| TestSuiteFormatTime
++---------------------------------------------------------------------*/
+static void
+TestSuiteFormatTime()
+{
+ NPT_DateTime gmt_today, tz_today;
+ NPT_TimeStamp now;
+ NPT_String output_s;
+
+ /* current time */
+ SHOULD_SUCCEED(NPT_System::GetCurrentTimeStamp(now));
+
+ /* get the date */
+ SHOULD_SUCCEED(gmt_today.FromTimeStamp(now));
+
+ /* print out current local date and daylight savings settings */
+ /* this should convert to GMT internally if dst is set */
+ printf("GMT time for Today is: %s\n", gmt_today.ToString().GetChars());
+
+ /* convert the date to GMT-8 */
+ tz_today = gmt_today;
+ SHOULD_SUCCEED(tz_today.ChangeTimeZone(-8*60));
+
+ /* this should convert to GMT internally if dst is set */
+ printf("(GMT-8) time for Today is: %s\n", tz_today.ToString(NPT_DateTime::FORMAT_RFC_1123).GetChars());
+ printf("(GMT-8) time for Today is: %s\n", tz_today.ToString(NPT_DateTime::FORMAT_RFC_1036).GetChars());
+ printf("(GMT-8) time for Today is: %s\n", tz_today.ToString(NPT_DateTime::FORMAT_ANSI).GetChars());
+ printf("(GMT-8) time for Today is: %s\n", tz_today.ToString(NPT_DateTime::FORMAT_W3C).GetChars());
+
+ /* print with RFC1123 */
+ printf("GMT time for Today is: %s\n", gmt_today.ToString(NPT_DateTime::FORMAT_RFC_1123).GetChars());
+ printf("GMT time for Today is: %s\n", gmt_today.ToString(NPT_DateTime::FORMAT_RFC_1036).GetChars());
+ printf("GMT time for Today is: %s\n", gmt_today.ToString(NPT_DateTime::FORMAT_ANSI).GetChars());
+ printf("GMT time for Today is: %s\n", gmt_today.ToString(NPT_DateTime::FORMAT_W3C).GetChars());
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int /*argc*/, char** /*argv*/)
+{
+ TestSuiteGetTime();
+ TestSuiteSetDateTimeZone();
+ TestSuiteFormatTime();
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.cpp b/lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.cpp
new file mode 100644
index 0000000..a0643a9
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.cpp
@@ -0,0 +1,405 @@
+/*****************************************************************
+|
+| Platinum - Ssdp Proxy
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "SsdpProxy.h"
+#include "PltUPnPHelper.h"
+
+#if defined (WIN32)
+#include <windows.h>
+#include <conio.h>
+#else
+#include <unistd.h>
+#endif
+
+NPT_SET_LOCAL_LOGGER("platinum.tools.ssdpproxy")
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+static struct {
+ NPT_UInt32 port;
+} Options;
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxy::PLT_SsdpProxy
++---------------------------------------------------------------------*/
+PLT_SsdpProxy::PLT_SsdpProxy() :
+ m_UnicastListener(NULL)
+{
+
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxy::~PLT_SsdpProxy
++---------------------------------------------------------------------*/
+PLT_SsdpProxy::~PLT_SsdpProxy()
+{
+ delete m_UnicastListener;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxy::Start
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpProxy::Start(NPT_UInt32 port)
+{
+ /* create a SSDP multicast listener task */
+ NPT_Socket* multicast_socket = new NPT_UdpMulticastSocket();
+ NPT_CHECK_SEVERE(multicast_socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900)));
+ PLT_SsdpListenTask* m_SsdpMulticastListenTask = new PLT_SsdpListenTask(multicast_socket, true);
+ NPT_CHECK_SEVERE(m_SsdpMulticastListenTask->AddListener(this));
+ NPT_CHECK_SEVERE(StartTask(m_SsdpMulticastListenTask));
+
+ /* create a SSDP unicast listener task */
+ /* any broadcast message sent to that, we will receive */
+ NPT_Socket* unicast_socket = new NPT_UdpSocket();
+ NPT_CHECK_SEVERE(unicast_socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, port)));
+ m_UnicastListener = new PLT_SsdpUnicastListener(this);
+ PLT_SsdpListenTask* m_SsdpUnicastListenTask = new PLT_SsdpListenTask(unicast_socket, false);
+ NPT_CHECK_SEVERE(m_SsdpUnicastListenTask->AddListener(m_UnicastListener));
+ NPT_CHECK_SEVERE(StartTask(m_SsdpUnicastListenTask));
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| CopyRequest
++---------------------------------------------------------------------*/
+static NPT_HttpRequest*
+CopyRequest(const NPT_HttpUrl& url, NPT_HttpRequest* request)
+{
+ NPT_HttpRequest* new_request = new NPT_HttpRequest(
+ url,
+ request->GetMethod(),
+ request->GetProtocol());
+ NPT_List<NPT_HttpHeader*>::Iterator headers = request->GetHeaders().GetHeaders().GetFirstItem();
+ while (headers) {
+ new_request->GetHeaders().AddHeader((*headers)->GetName(), (*headers)->GetValue());
+ ++headers;
+ }
+
+ return new_request;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxy::OnSsdpPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpProxy::OnSsdpPacket(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context)
+{
+ NPT_COMPILER_UNUSED(context);
+
+ // is it a forward message ?
+ if (request.GetHeaders().GetHeader("X_SsdpProxy"))
+ return NPT_SUCCESS;
+
+ request.GetHeaders().AddHeader("X_SsdpProxy", "forwarded");
+
+ // override MX to force a fast response
+ NPT_UInt32 MX;
+ if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetMX(request, MX))) {
+ PLT_UPnPMessageHelper::SetMX(request, 1);
+ }
+
+ // for each interface, send this request on the broadcast address
+ NPT_List<NPT_NetworkInterface*> if_list;
+ NPT_List<NPT_NetworkInterface*>::Iterator net_if;
+ NPT_List<NPT_NetworkInterfaceAddress>::Iterator net_if_addr;
+ NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(if_list));
+
+ for (net_if = if_list.GetFirstItem(); net_if; net_if++) {
+ if (!((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_BROADCAST) ||
+ ((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK))
+ continue;
+
+ for (net_if_addr = (*net_if)->GetAddresses().GetFirstItem(); net_if_addr; net_if_addr++) {
+ // copy request
+ NPT_HttpRequest* new_request = CopyRequest(
+ NPT_HttpUrl((*net_if_addr).GetBroadcastAddress().ToString(), 1900, request.GetUrl().GetPath()),
+ &request);
+
+ // create search task to send request in broadcast
+ // and forward unicast responses back to remote in unicast
+ PLT_SsdpProxyForwardTask* task = new PLT_SsdpProxyForwardTask(
+ new NPT_UdpSocket(),
+ new_request,
+ 10000,
+ context.GetRemoteAddress());
+ StartTask(task);
+ }
+ }
+
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+
+ // send special broadcast message for xbox
+ NPT_HttpRequest* new_request = CopyRequest(
+ NPT_HttpUrl("255.255.255.255", 1900, request.GetUrl().GetPath()),
+ &request);
+
+ // create search task to send request in broadcast
+ // and forward unicast responses back to remote in unicast
+ PLT_SsdpProxyForwardTask* task = new PLT_SsdpProxyForwardTask(
+ new NPT_UdpSocket(),
+ new_request,
+ 10000,
+ context.GetRemoteAddress());
+ StartTask(task);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxy::OnUnicastSsdpPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpProxy::OnUnicastSsdpPacket(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context)
+{
+ // is it a forward message ?
+ if (request.GetHeaders().GetHeader("X_SsdpProxy"))
+ return NPT_SUCCESS;
+
+ request.GetHeaders().AddHeader("X_SsdpProxy", "forwarded");
+
+ // look on which interface we received it and send the ssdp search request on this only
+ NPT_List<NPT_NetworkInterface*> if_list;
+ NPT_List<NPT_NetworkInterface*>::Iterator net_if;
+ NPT_List<NPT_NetworkInterfaceAddress>::Iterator net_if_addr;
+
+ NPT_CHECK_SEVERE(NPT_NetworkInterface::GetNetworkInterfaces(if_list));
+
+ for (net_if = if_list.GetFirstItem(); net_if; net_if++) {
+ //if (!((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) ||
+ // (*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
+ if ((*net_if)->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
+ continue;
+ }
+
+ for (net_if_addr = (*net_if)->GetAddresses().GetFirstItem(); net_if_addr; net_if_addr++) {
+ // by using the netmask on each interface, we can figure out if the remote IP address
+ // we received the request from matches the interface we want to multicast to.
+ // it's important to do that as to avoid sending a NOTIFY or M-SEARCH packet to a host
+ // that would not be reachable from the remote which sends this packet in the first place
+ int i=0;
+ while (i<4) {
+ if ((context.GetRemoteAddress().GetIpAddress().AsBytes()[i] & (*net_if_addr).GetNetMask().AsBytes()[i]) !=
+ ((*net_if_addr).GetPrimaryAddress().AsBytes()[i] & (*net_if_addr).GetNetMask().AsBytes()[i])) {
+ break;
+ }
+ i++;
+ }
+
+ /* check that we have a match */
+ if (i != 4) {
+ continue;
+ }
+
+ // override MX to force a fast response
+ NPT_UInt32 MX;
+ if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetMX(request, MX))) {
+ PLT_UPnPMessageHelper::SetMX(request, 1);
+ }
+
+ // unicast
+ // WMC doesn't respond to multicast searches issued from the same machine
+ // a work around is to send a unicast request!
+ // copy request and change host header
+ NPT_HttpRequest* unicast_request = CopyRequest(
+ NPT_HttpUrl((*net_if_addr).GetPrimaryAddress().ToString(), 1900, request.GetUrl().GetPath()),
+ &request);
+
+ // create unicast socket
+ NPT_UdpSocket* unicast_socket = new NPT_UdpSocket();
+ // create search task to send request in unicast
+ // and forward responses back to remote
+ PLT_SsdpProxyForwardTask* uncast_task = new PLT_SsdpProxyForwardTask(
+ unicast_socket,
+ unicast_request,
+ 10000,
+ context.GetRemoteAddress());
+ StartTask(uncast_task);
+
+ // multicast
+ // simply redirect request to 239.255.255.250
+ NPT_HttpRequest* new_request = CopyRequest(
+ NPT_HttpUrl("239.255.255.250", 1900, request.GetUrl().GetPath()),
+ &request);
+
+ // create multicast socket
+ NPT_UdpMulticastSocket* socket = new NPT_UdpMulticastSocket();
+ socket->SetInterface((*net_if_addr).GetPrimaryAddress());
+ socket->SetTimeToLive(4);
+
+ // create search task to send request in multicast
+ // and forward responses back to remote
+ PLT_SsdpProxyForwardTask* task = new PLT_SsdpProxyForwardTask(
+ socket,
+ new_request,
+ 10000,
+ context.GetRemoteAddress());
+ StartTask(task);
+ }
+ }
+
+ if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpUnicastListener::OnSsdpPacket
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpUnicastListener::OnSsdpPacket(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context)
+{
+ return m_Proxy->OnUnicastSsdpPacket(request, context);
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxyForwardTask::PLT_SsdpProxyForwardTask
++---------------------------------------------------------------------*/
+PLT_SsdpProxyForwardTask::PLT_SsdpProxyForwardTask(NPT_UdpSocket* socket,
+ NPT_HttpRequest* request,
+ NPT_Timeout timeout,
+ const NPT_SocketAddress& forward_address) :
+ PLT_SsdpSearchTask(socket, NULL, request, timeout, false),
+ m_ForwardAddress(forward_address)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxyForwardTask::ProcessResponse
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_SsdpProxyForwardTask::ProcessResponse(NPT_Result res,
+ NPT_HttpRequest* request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response)
+{
+ NPT_COMPILER_UNUSED(context);
+ NPT_COMPILER_UNUSED(request);
+
+ if (NPT_FAILED(res) || response == NULL) return NPT_FAILURE;
+
+ // use a memory stream to write the response
+ NPT_MemoryStream stream;
+ NPT_CHECK_SEVERE(response->Emit(stream));
+
+ // copy stream into a data packet and forward it
+ NPT_LargeSize size;
+ stream.GetSize(size);
+ if (size != (NPT_Size)size) return NPT_ERROR_OUT_OF_RANGE;
+
+ NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size);
+ NPT_UdpSocket socket;
+ return socket.Send(packet, &m_ForwardAddress);
+}
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit(char** args)
+{
+ fprintf(stderr, "usage: %s [-p <port>] \n", args[0]);
+ fprintf(stderr, "-p : optional upnp unicast ssdp port (default: 1901)\n");
+ exit(1);
+}
+
+/*----------------------------------------------------------------------
+| ParseCommandLine
++---------------------------------------------------------------------*/
+static void
+ParseCommandLine(char** args)
+{
+ const char* arg;
+ char** tmp = args+1;
+
+ /* default values */
+ Options.port = 1900;
+
+ while ((arg = *tmp++)) {
+ if (!strcmp(arg, "-p")) {
+ if (NPT_FAILED(NPT_ParseInteger32(*tmp++, Options.port, false))) {
+ fprintf(stderr, "ERROR: invalid argument\n");
+ PrintUsageAndExit(args);
+ }
+ } else {
+ fprintf(stderr, "ERROR: invalid arguments\n");
+ PrintUsageAndExit(args);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int argc, char** argv)
+{
+ NPT_COMPILER_UNUSED(argc);
+
+ //PLT_SetLogLevel(4);
+ PLT_SsdpProxy proxy;
+
+ /* parse command line */
+ ParseCommandLine(argv);
+
+ NPT_Result res = proxy.Start(Options.port);
+ if (res == NPT_ERROR_BIND_FAILED) {
+ fprintf(stderr, "ERROR: couldn't bind to port %d\n", Options.port);
+ return -1;
+ } else if (NPT_FAILED(res)) {
+ fprintf(stderr, "ERROR: unknown (%d)\n", res);
+ return -1;
+ }
+
+ fprintf(stdout, "Listening for SSDP unicast packets on port %d\n", Options.port);
+ fprintf(stdout, "Enter q to quit\n");
+
+ char buf[256];
+ while (gets(buf)) {
+ if (*buf == 'q')
+ break;
+ }
+
+ return 0;
+}
diff --git a/lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.h b/lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.h
new file mode 100644
index 0000000..3dc4bc9
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tools/SsdpProxy/SsdpProxy.h
@@ -0,0 +1,109 @@
+/*****************************************************************
+|
+| Platinum - Ssdp Proxy tool
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+#ifndef _PLT_SSDP_PROXY_H_
+#define _PLT_SSDP_PROXY_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltTaskManager.h"
+#include "PltSsdp.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class PLT_SsdpUnicastListener;
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxy class
++---------------------------------------------------------------------*/
+class PLT_SsdpProxy : public PLT_TaskManager,
+ public PLT_SsdpPacketListener
+{
+public:
+ PLT_SsdpProxy();
+ ~PLT_SsdpProxy();
+
+ NPT_Result Start(NPT_UInt32 port);
+
+ // PLT_SsdpPacketListener method
+ virtual NPT_Result OnSsdpPacket(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context);
+
+ // PLT_SsdpUnicastListener redirect
+ virtual NPT_Result OnUnicastSsdpPacket(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context);
+
+private:
+ PLT_SsdpUnicastListener* m_UnicastListener;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpUnicastListener class
++---------------------------------------------------------------------*/
+class PLT_SsdpUnicastListener : public PLT_SsdpPacketListener
+{
+public:
+ PLT_SsdpUnicastListener(PLT_SsdpProxy* proxy) : m_Proxy(proxy) {}
+
+ // PLT_SsdpPacketListener method
+ NPT_Result OnSsdpPacket(NPT_HttpRequest& request,
+ const NPT_HttpRequestContext& context);
+
+private:
+ PLT_SsdpProxy* m_Proxy;
+};
+
+/*----------------------------------------------------------------------
+| PLT_SsdpProxySearchResponseListener class
++---------------------------------------------------------------------*/
+class PLT_SsdpProxyForwardTask : public PLT_SsdpSearchTask
+{
+public:
+ PLT_SsdpProxyForwardTask(NPT_UdpSocket* socket,
+ NPT_HttpRequest* request,
+ NPT_Timeout timeout,
+ const NPT_SocketAddress& forward_address);
+
+ NPT_Result ProcessResponse(NPT_Result res,
+ NPT_HttpRequest* request,
+ const NPT_HttpRequestContext& context,
+ NPT_HttpResponse* response);
+
+private:
+ NPT_SocketAddress m_ForwardAddress;
+};
+
+#endif // _PLT_SSDP_PROXY_H_
diff --git a/lib/libUPnP/Platinum/Source/Tools/TextToHeader/TextToHeader.cpp b/lib/libUPnP/Platinum/Source/Tools/TextToHeader/TextToHeader.cpp
new file mode 100644
index 0000000..2e1aad7
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Tools/TextToHeader/TextToHeader.cpp
@@ -0,0 +1,267 @@
+/*****************************************************************
+|
+| Platinum - Tool text to .h
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| 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
+| 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.
+|
+| 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
+| GNU General Public License for more details.
+|
+| 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.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+static struct {
+ const char* in_filename;
+ const char* variable_name;
+ const char* header_name;
+ const char* out_filename;
+} Options;
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit(char** args)
+{
+ fprintf(stderr, "usage: %s [-v <variable> -h <header name>] <intput> <output>\n", args[0]);
+ fprintf(stderr, "-v : optional variable name\n");
+ fprintf(stderr, "-h : optional header name\n");
+ fprintf(stderr, "<input> : input scpd filename\n");
+ fprintf(stderr, "<output> : output filename\n");
+ exit(1);
+}
+
+/*----------------------------------------------------------------------
+| ParseCommandLine
++---------------------------------------------------------------------*/
+static void
+ParseCommandLine(char** args)
+{
+ const char* arg;
+ char** tmp = args+1;
+
+ /* default values */
+ Options.in_filename = NULL;
+ Options.variable_name = NULL;
+ Options.out_filename = NULL;
+
+ while ((arg = *tmp++)) {
+ if (!strcmp(arg, "-v")) {
+ Options.variable_name = *tmp++;
+ } else if (!strcmp(arg, "-h")) {
+ Options.header_name = *tmp++;
+ } else if (Options.in_filename == NULL) {
+ Options.in_filename = arg;
+ } else if (Options.out_filename == NULL) {
+ Options.out_filename = arg;
+ } else {
+ fprintf(stderr, "ERROR: too many arguments\n");
+ PrintUsageAndExit(args);
+ }
+ }
+
+ /* check args */
+ if (Options.in_filename == NULL) {
+ fprintf(stderr, "ERROR: input filename missing\n");
+ PrintUsageAndExit(args);
+ }
+ if (Options.out_filename == NULL) {
+ fprintf(stderr, "ERROR: output filename missing\n");
+ PrintUsageAndExit(args);
+ }
+}
+
+/*----------------------------------------------------------------------
+| PrintHex
++---------------------------------------------------------------------*/
+/*static void
+PrintHex(unsigned char* h, unsigned int size)
+{
+ unsigned int i;
+ for (i=0; i<size; i++) {
+ printf("%c%c",
+ h[i]>>4 >= 10 ?
+ 'A' + (h[i]>>4)-10 :
+ '0' + (h[i]>>4),
+ (h[i]&0xF) >= 10 ?
+ 'A' + (h[i]&0xF)-10 :
+ '0' + (h[i]&0xF));
+ }
+}*/
+
+/*----------------------------------------------------------------------
+| PrintHexForHeader
++---------------------------------------------------------------------*/
+static void
+PrintHexForHeader(FILE* out, unsigned char h)
+{
+ fprintf(out, "0x%c%c",
+ h>>4 >= 10 ?
+ 'A' + (h>>4)-10 :
+ '0' + (h>>4),
+ (h&0xF) >= 10 ?
+ 'A' + (h&0xF)-10 :
+ '0' + (h&0xF));
+}
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int /*argc*/, char** argv)
+{
+ FILE* in;
+ FILE* out;
+ unsigned char* data_block = NULL;
+ unsigned long data_block_size;
+ unsigned long k;
+ unsigned char col;
+
+ /* parse command line */
+ ParseCommandLine(argv);
+
+ /* open input */
+ in = fopen(Options.in_filename, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "ERROR: cannot open input file (%s): %s\n",
+ Options.in_filename, strerror(errno));
+ }
+
+ /* read data in one chunk */
+ {
+ struct stat info;
+ if (stat(Options.in_filename, &info)) {
+ fprintf(stderr, "ERROR: cannot get input file size\n");
+ return 1;
+ }
+
+ data_block_size = info.st_size;
+ data_block = (unsigned char*)new unsigned char[data_block_size+1];
+ if (data_block == NULL) {
+ fprintf(stderr, "ERROR: out of memory\n");
+ return 1;
+ }
+
+ if (fread(data_block, data_block_size, 1, in) != 1) {
+ fprintf(stderr, "ERROR: cannot read input file\n");
+ return 1;
+ }
+ data_block[data_block_size++] = 0;
+ }
+
+ /* open output */
+ out = fopen(Options.out_filename, "w+");
+ if (out == NULL) {
+ fprintf(stderr, "ERROR: cannot open out output file (%s): %s\n",
+ Options.out_filename, strerror(errno));
+ }
+ fprintf(out,
+"/*****************************************************************\n"
+"|\n"
+"| Platinum - %s SCPD\n"
+"|\n"
+"| Copyright (c) 2004-2008, Plutinosoft, LLC.\n"
+"| All rights reserved.\n"
+"| http://www.plutinosoft.com\n"
+"|\n"
+"| This program is free software; you can redistribute it and/or\n"
+"| modify it under the terms of the GNU General Public License\n"
+"| as published by the Free Software Foundation; either version 2\n"
+"| of the License, or (at your option) any later version.\n"
+"|\n"
+"| OEMs, ISVs, VARs and other distributors that combine and \n"
+"| distribute commercially licensed software with Platinum software\n"
+"| and do not wish to distribute the source code for the commercially\n"
+"| licensed software under version 2, or (at your option) any later\n"
+"| version, of the GNU General Public License (the \"GPL\") must enter\n"
+"| into a commercial license agreement with Plutinosoft, LLC.\n"
+"| \n"
+"| This program is distributed in the hope that it will be useful,\n"
+"| but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+"| GNU General Public License for more details.\n"
+"|\n"
+"| You should have received a copy of the GNU General Public License\n"
+"| along with this program; see the file LICENSE.txt. If not, write to\n"
+"| the Free Software Foundation, Inc., \n"
+"| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+"| http://www.gnu.org/licenses/gpl-2.0.html\n"
+"|\n"
+"****************************************************************/\n",
+ Options.header_name?Options.header_name:"");
+ fprintf(out, "\n"
+"/*----------------------------------------------------------------------\n"
+"| includes\n"
+"+---------------------------------------------------------------------*/\n");
+ fprintf(out, "#include \"NptTypes.h\"\n");
+ fprintf(out, "\n"
+"/*----------------------------------------------------------------------\n"
+"| globals\n"
+"+---------------------------------------------------------------------*/\n");
+ fprintf(out, "NPT_UInt8 %s[] =\n",
+ Options.variable_name?Options.variable_name:"kData");
+ fprintf(out, "{\n ");
+ col = 0;
+
+ /* rewind the input file */
+ fseek(in, 0, SEEK_SET);
+
+ for (k = 0; k < data_block_size; k++) {
+ //PrintHex(&data_block[k], 1);
+ PrintHexForHeader(out, data_block[k]);
+ if (k < data_block_size - 1) fprintf(out, ", ");
+
+ /* wrap around 20 columns */
+ if (++col > 19) {
+ col = 0;
+ fprintf(out, "\n ");
+ }
+ }
+
+ /* print footer */
+ fprintf(out, "\n};\n\n");
+
+ /* close file */
+ fclose(out);
+
+ /* close file */
+ fclose(in);
+
+ if (data_block) {
+ delete[] data_block;
+ }
+ return 0;
+}