1 /*****************************************************************
3 | Platinum - AV Media Connect Device
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
7 | http://www.plutinosoft.com
9 | This program is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU General Public License
11 | as published by the Free Software Foundation; either version 2
12 | of the License, or (at your option) any later version.
14 | OEMs, ISVs, VARs and other distributors that combine and
15 | distribute commercially licensed software with Platinum software
16 | and do not wish to distribute the source code for the commercially
17 | licensed software under version 2, or (at your option) any later
18 | version, of the GNU General Public License (the "GPL") must enter
19 | into a commercial license agreement with Plutinosoft, LLC.
20 | licensing@plutinosoft.com
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU General Public License for more details.
27 | You should have received a copy of the GNU General Public License
28 | along with this program; see the file LICENSE.txt. If not, write to
29 | the Free Software Foundation, Inc.,
30 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 | http://www.gnu.org/licenses/gpl-2.0.html
33 ****************************************************************/
35 /*----------------------------------------------------------------------
37 +---------------------------------------------------------------------*/
40 #include "PltMediaConnect.h"
42 NPT_SET_LOCAL_LOGGER("platinum.devices.mediaconnect")
44 /*----------------------------------------------------------------------
46 +---------------------------------------------------------------------*/
47 extern NPT_UInt8 X_MS_MediaReceiverRegistrarSCPD
[];
48 extern NPT_UInt8 MS_ContentDirectorySCPD
[];
50 /*----------------------------------------------------------------------
51 | PLT_MediaConnect::PLT_MediaConnect
52 +---------------------------------------------------------------------*/
53 PLT_MediaConnect::PLT_MediaConnect(const char* friendly_name
,
54 bool add_hostname
/* = true */,
55 const char* udn
/* = NULL */,
56 NPT_UInt16 port
/* = 0 */,
57 bool port_rebind
/* = false */) :
58 PLT_MediaServer(friendly_name
, false, udn
, port
, port_rebind
),
59 m_AddHostname(add_hostname
)
63 /*----------------------------------------------------------------------
64 | PLT_MediaConnect::~PLT_MediaConnect
65 +---------------------------------------------------------------------*/
66 PLT_MediaConnect::~PLT_MediaConnect()
70 /*----------------------------------------------------------------------
71 | PLT_MediaConnect::SetupServices
72 +---------------------------------------------------------------------*/
74 PLT_MediaConnect::SetupServices()
76 NPT_Reference
<PLT_Service
> service(new PLT_Service(
78 "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
79 "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar",
80 "X_MS_MediaReceiverRegistrar"));
82 NPT_CHECK_FATAL(service
->SetSCPDXML((const char*) X_MS_MediaReceiverRegistrarSCPD
));
83 NPT_CHECK_FATAL(AddService(service
.AsPointer()));
85 service
->SetStateVariable("AuthorizationGrantedUpdateID", "1");
86 service
->SetStateVariable("AuthorizationDeniedUpdateID", "1");
87 service
->SetStateVariable("ValidationSucceededUpdateID", "0");
88 service
->SetStateVariable("ValidationRevokedUpdateID", "0");
91 return PLT_MediaServer::SetupServices();
94 /*----------------------------------------------------------------------
95 | PLT_MediaConnect::ProcessGetDescription
96 +---------------------------------------------------------------------*/
98 PLT_MediaConnect::ProcessGetDescription(NPT_HttpRequest
& request
,
99 const NPT_HttpRequestContext
& context
,
100 NPT_HttpResponse
& response
)
102 // lock to make sure another request is not modifying the device while we are already
103 NPT_AutoLock
lock(m_Lock
);
105 NPT_Result res
= NPT_SUCCESS
;
106 NPT_String oldModelName
= m_ModelName
;
107 NPT_String oldModelNumber
= m_ModelNumber
;
108 NPT_String oldModelURL
= m_ModelURL
;
109 NPT_String oldManufacturerURL
= m_ManufacturerURL
;
110 NPT_String oldDlnaDoc
= m_DlnaDoc
;
111 NPT_String oldDlnaCap
= m_DlnaCap
;
112 NPT_String oldAggregationFlags
= m_AggregationFlags
;
113 NPT_String oldFriendlyName
= m_FriendlyName
;
116 NPT_System::GetMachineName(hostname
);
118 PLT_DeviceSignature signature
= PLT_HttpHelper::GetDeviceSignature(request
);
120 if (signature
== PLT_DEVICE_XBOX_360
|| signature
== PLT_DEVICE_XBOX_ONE
/*|| signature == PLT_SONOS*/) {
121 // XBox needs to see something behind a ':' to even show it
122 if (m_AddHostname
&& hostname
.GetLength() > 0) {
123 m_FriendlyName
+= ": " + hostname
;
124 } else if (m_FriendlyName
.Find(":") == -1) {
125 m_FriendlyName
+= ": 1";
128 else if (m_AddHostname
&& hostname
.GetLength() > 0) {
129 m_FriendlyName
+= " (" + hostname
+ ")";
132 // change some things based on device signature from request
133 if (signature
== PLT_DEVICE_XBOX_360
|| signature
== PLT_DEVICE_XBOX_ONE
|| signature
== PLT_DEVICE_WMP
/*|| signature == PLT_SONOS*/) {
134 m_ModelName
= "Windows Media Player Sharing";
135 m_ModelNumber
= (signature
== PLT_DEVICE_SONOS
)?"3.0":"12.0";
136 m_ModelURL
= "http://www.microsoft.com/";//"http://go.microsoft.com/fwlink/?LinkId=105926";
137 m_Manufacturer
= (signature
== PLT_DEVICE_SONOS
)?"Microsoft":"Microsoft Corporation";
138 m_ManufacturerURL
= "http://www.microsoft.com/";
139 m_DlnaDoc
= (signature
== PLT_DEVICE_SONOS
)?"DMS-1.00":"DMS-1.50";
141 m_AggregationFlags
= "";
143 //PLT_UPnPMessageHelper::GenerateGUID(m_SerialNumber);
144 // TODO: http://msdn.microsoft.com/en-us/library/ff362657(PROT.10).aspx
145 // TODO: <serialNumber>GUID</serialNumber>
147 } else if (signature
== PLT_DEVICE_SONOS
) {
148 m_ModelName
= "Rhapsody";
149 m_ModelNumber
= "3.0";
150 } else if (signature
== PLT_DEVICE_PS3
) {
151 m_DlnaDoc
= "DMS-1.50";
153 m_AggregationFlags
= "10";
156 // return description with modified params
157 res
= PLT_MediaServer::ProcessGetDescription(request
, context
, response
);
159 // reset to old values now
160 m_FriendlyName
= oldFriendlyName
;
161 m_ModelName
= oldModelName
;
162 m_ModelNumber
= oldModelNumber
;
163 m_ModelURL
= oldModelURL
;
164 m_ManufacturerURL
= oldManufacturerURL
;
165 m_DlnaDoc
= oldDlnaDoc
;
166 m_DlnaCap
= oldDlnaCap
;
167 m_AggregationFlags
= oldAggregationFlags
;
172 /*----------------------------------------------------------------------
173 | PLT_MediaConnect::ProcessGetSCPD
174 +---------------------------------------------------------------------*/
176 PLT_MediaConnect::ProcessGetSCPD(PLT_Service
* service
,
177 NPT_HttpRequest
& request
,
178 const NPT_HttpRequestContext
& context
,
179 NPT_HttpResponse
& response
)
181 PLT_DeviceSignature signature
= PLT_HttpHelper::GetDeviceSignature(request
);
183 // Override SCPD response by providing an SCPD without a Search action
184 // to all devices except XBox or WMP which need it
185 if (service
->GetServiceType() == "urn:schemas-upnp-org:service:ContentDirectory:1" &&
186 signature
!= PLT_DEVICE_XBOX_360
&&
187 signature
!= PLT_DEVICE_XBOX_ONE
&&
188 signature
!= PLT_DEVICE_WMP
&&
189 signature
!= PLT_DEVICE_SONOS
) {
190 NPT_HttpEntity
* entity
;
191 PLT_HttpHelper::SetBody(response
, (const char*) MS_ContentDirectorySCPD
, &entity
);
192 entity
->SetContentType("text/xml; charset=\"utf-8\"");
196 return PLT_MediaServer::ProcessGetSCPD(service
, request
, context
, response
);
199 /*----------------------------------------------------------------------
200 | PLT_MediaConnect::OnAction
201 +---------------------------------------------------------------------*/
203 PLT_MediaConnect::OnAction(PLT_ActionReference
& action
,
205 const PLT_HttpRequestContext
& context
)
207 /* parse the action name */
208 NPT_String name
= action
->GetActionDesc().GetName();
210 /* handle X_MS_MediaReceiverRegistrar actions here */
211 if (name
.Compare("IsAuthorized") == 0) {
212 return OnIsAuthorized(action
);
214 if (name
.Compare("RegisterDevice") == 0) {
215 return OnRegisterDevice(action
);
217 if (name
.Compare("IsValidated") == 0) {
218 return OnIsValidated(action
);
221 return PLT_MediaServer::OnAction(action
, context
);
224 /*----------------------------------------------------------------------
225 | PLT_MediaConnect::OnIsAuthorized
226 +---------------------------------------------------------------------*/
228 PLT_MediaConnect::OnIsAuthorized(PLT_ActionReference
& action
)
230 NPT_CHECK_WARNING(action
->SetArgumentValue("Result", "1"));
234 /*----------------------------------------------------------------------
235 | PLT_MediaConnect::OnRegisterDevice
236 +---------------------------------------------------------------------*/
238 PLT_MediaConnect::OnRegisterDevice(PLT_ActionReference
& action
)
240 NPT_String reqMsgBase64
;
241 NPT_CHECK_WARNING(action
->GetArgumentValue("RegistrationReqMsg", reqMsgBase64
));
243 NPT_String respMsgBase64
;
244 NPT_CHECK_WARNING(action
->SetArgumentValue("RegistrationRespMsg", respMsgBase64
));
248 /*----------------------------------------------------------------------
249 | PLT_MediaConnect::OnIsValidated
250 +---------------------------------------------------------------------*/
252 PLT_MediaConnect::OnIsValidated(PLT_ActionReference
& action
)
254 NPT_CHECK_WARNING(action
->SetArgumentValue("Result", "1"));
258 /*----------------------------------------------------------------------
259 | PLT_MediaConnect::GetMappedObjectId
260 +---------------------------------------------------------------------*/
262 PLT_MediaConnect::GetMappedObjectId(const char* object_id
, NPT_String
& mapped_object_id
)
264 if (!object_id
) return NPT_ERROR_INVALID_PARAMETERS
;
266 // Reroute XBox 360 and WMP requests to our route
267 if (NPT_StringsEqual(object_id
, "15")) {
268 mapped_object_id
= "0/Videos"; // Videos
269 } else if (NPT_StringsEqual(object_id
, "16")) {
270 mapped_object_id
= "0/Photos"; // Photos
272 mapped_object_id
= object_id
;
278 /*----------------------------------------------------------------------
279 | PLT_FileMediaConnectDelegate::GetFilePath
280 +---------------------------------------------------------------------*/
282 PLT_FileMediaConnectDelegate::GetFilePath(const char* object_id
, NPT_String
& filepath
)
284 if (!object_id
) return NPT_ERROR_INVALID_PARAMETERS
;
286 // Reroute XBox 360 and WMP requests to our route
287 if (NPT_StringsEqual(object_id
, "15")) {
288 return PLT_FileMediaServerDelegate::GetFilePath("", filepath
); // Videos
289 } else if (NPT_StringsEqual(object_id
, "16")) {
290 return PLT_FileMediaServerDelegate::GetFilePath("", filepath
); // Photos
291 } else if (NPT_StringsEqual(object_id
, "13") || NPT_StringsEqual(object_id
, "4")) {
292 return PLT_FileMediaServerDelegate::GetFilePath("", filepath
); // Music
295 return PLT_FileMediaServerDelegate::GetFilePath(object_id
, filepath
);;
298 /*----------------------------------------------------------------------
299 | PLT_FileMediaConnectDelegate::OnSearchContainer
300 +---------------------------------------------------------------------*/
302 PLT_FileMediaConnectDelegate::OnSearchContainer(PLT_ActionReference
& action
,
303 const char* object_id
,
304 const char* search_criteria
,
306 NPT_UInt32 starting_index
,
307 NPT_UInt32 requested_count
,
308 const char* sort_criteria
,
309 const PLT_HttpRequestContext
& context
)
311 /* parse search criteria */
313 /* TODO: HACK TO PASS DLNA */
314 if (search_criteria
&& NPT_StringsEqual(search_criteria
, "Unknownfieldname")) {
316 NPT_LOG_WARNING_1("Unsupported or invalid search criteria %s", search_criteria
);
317 action
->SetError(708, "Unsupported or invalid search criteria");
321 /* locate the file from the object ID */
323 if (NPT_FAILED(GetFilePath(object_id
, dir
))) {
325 NPT_LOG_WARNING("ObjectID not found.");
326 action
->SetError(710, "No Such Container.");
330 /* retrieve the item type */
332 NPT_Result res
= NPT_File::GetInfo(dir
, &info
);
333 if (NPT_FAILED(res
) || (info
.m_Type
!= NPT_FileInfo::FILE_TYPE_DIRECTORY
)) {
335 NPT_LOG_WARNING("No such container");
336 action
->SetError(710, "No such container");
340 /* hack for now to return something back to XBox 360 */
341 return OnBrowseDirectChildren(action
,