1
2 /*
3 * GPAC - Multimedia Framework C SDK
4 *
5 * Authors: Jean Le Feuvre
6 * Copyright (c) Telecom ParisTech 2009-2012
7 * All rights reserved
8 *
9 * This file is part of GPAC / Platinum UPnP module
10 *
11 * GPAC is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * GPAC is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 *
26 * ----------------------------------------------------------------------------------
27 * PLATINUM IS LICENSED UNDER GPL or commercial agreement - cf platinum license
28 * ----------------------------------------------------------------------------------
29 *
30 */
31
32
33 #include "GPACPlatinum.h"
34
GPAC_MediaController(PLT_CtrlPointReference & ctrlPoint,GF_UPnP * upnp)35 GPAC_MediaController::GPAC_MediaController(PLT_CtrlPointReference& ctrlPoint, GF_UPnP *upnp)
36 {
37 m_MediaController = new PLT_MediaController(ctrlPoint, this);
38 m_MediaBrowser = new PLT_MediaBrowser(ctrlPoint, this);
39
40 m_MediaServers = gf_list_new();
41 m_MediaRenderers = gf_list_new();
42 m_ControlPointLock = gf_mx_new("AVControlPoint");
43 m_pUPnP = upnp;
44 }
45
46
~GPAC_MediaController()47 GPAC_MediaController::~GPAC_MediaController()
48 {
49 delete m_MediaController;
50 m_MediaController=NULL;
51 delete m_MediaBrowser;
52 m_MediaBrowser=NULL;
53
54 while (gf_list_count(m_MediaServers)) {
55 GPAC_MediaServerItem*ms = (GPAC_MediaServerItem*)gf_list_get(m_MediaServers, 0);
56 gf_list_rem(m_MediaServers, 0);
57 delete ms;
58 }
59 gf_list_del(m_MediaServers);
60
61 while (gf_list_count(m_MediaRenderers)) {
62 GPAC_MediaRendererItem *ms = (GPAC_MediaRendererItem *)gf_list_get(m_MediaRenderers, 0);
63 gf_list_rem(m_MediaRenderers, 0);
64 delete ms;
65 }
66 gf_list_del(m_MediaRenderers);
67
68 gf_mx_del(m_ControlPointLock);
69 }
70
71
72
73
74 bool
OnMRAdded(PLT_DeviceDataReference & device)75 GPAC_MediaController::OnMRAdded(PLT_DeviceDataReference& device)
76 {
77 NPT_String uuid = device->GetUUID();
78
79 gf_mx_p(m_ControlPointLock);
80
81 // test if it's a media renderer
82 PLT_Service* service;
83 if (NPT_SUCCEEDED(device->FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", service))) {
84 gf_list_add(m_MediaRenderers, new GPAC_MediaRendererItem(device, uuid) );
85 }
86 m_pUPnP->OnMediaRendererAdd(device, 1);
87 gf_mx_v(m_ControlPointLock);
88 return true;
89 }
90
91
92 void
OnMRRemoved(PLT_DeviceDataReference & device)93 GPAC_MediaController::OnMRRemoved(PLT_DeviceDataReference& device)
94 {
95 NPT_String uuid = device->GetUUID();
96
97 gf_mx_p(m_ControlPointLock);
98
99 u32 i, count;
100 count = gf_list_count(m_MediaRenderers);
101 for (i=0; i<count; i++) {
102 GPAC_MediaRendererItem *ms = (GPAC_MediaRendererItem *) gf_list_get(m_MediaRenderers, i);
103 if (ms->m_UUID==uuid) {
104 delete ms;
105 gf_list_rem(m_MediaRenderers, i);
106 break;
107 }
108 }
109
110 m_pUPnP->OnMediaRendererAdd(device, 0);
111 gf_mx_v(m_ControlPointLock);
112 }
113
114 bool
OnMSAdded(PLT_DeviceDataReference & device)115 GPAC_MediaController::OnMSAdded(PLT_DeviceDataReference& device)
116 {
117 NPT_String uuid = device->GetUUID();
118
119 gf_mx_p(m_ControlPointLock);
120 // test if it's a media server
121 PLT_Service* service;
122 if (NPT_SUCCEEDED(device->FindServiceByType("urn:schemas-upnp-org:service:ContentDirectory:1", service))) {
123 gf_list_add(m_MediaServers, new GPAC_MediaServerItem(device, uuid) );
124 }
125 m_pUPnP->OnMediaServerAdd(device, 1);
126 gf_mx_v(m_ControlPointLock);
127 return true;
128 }
129
130
131 void
OnMSRemoved(PLT_DeviceDataReference & device)132 GPAC_MediaController::OnMSRemoved(PLT_DeviceDataReference& device)
133 {
134 NPT_String uuid = device->GetUUID();
135
136 gf_mx_p(m_ControlPointLock);
137 u32 i, count;
138 count = gf_list_count(m_MediaServers);
139 for (i=0; i<count; i++) {
140 GPAC_MediaServerItem *ms = (GPAC_MediaServerItem *) gf_list_get(m_MediaServers, i);
141 if (ms->m_UUID==uuid) {
142 delete ms;
143 gf_list_rem(m_MediaServers, i);
144 break;
145 }
146 }
147 m_pUPnP->OnMediaServerAdd(device, 0);
148 gf_mx_v(m_ControlPointLock);
149 }
150
151
152
153 NPT_Result
OnActionResponse(NPT_Result res,PLT_ActionReference & action,void * userdata)154 GPAC_MediaController::OnActionResponse(NPT_Result res,
155 PLT_ActionReference& action,
156 void* userdata)
157 {
158 return NPT_SUCCESS;
159 }
160
OnEventNotify(PLT_Service * service,NPT_List<PLT_StateVariable * > * vars)161 NPT_Result GPAC_MediaController::OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
162 {
163 return NPT_SUCCESS;
164 }
165
OnMRStateVariablesChanged(PLT_Service * service,NPT_List<PLT_StateVariable * > * vars)166 void GPAC_MediaController::OnMRStateVariablesChanged(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars )
167 {
168 u32 count;
169 u32 i;
170 s32 render_idx = -1;
171
172 count = gf_list_count(m_MediaRenderers);
173 for (i=0; i<count; i++) {
174 GPAC_MediaRendererItem *mr = (GPAC_MediaRendererItem *) gf_list_get(m_MediaRenderers, i);
175 if ( mr->m_device.AsPointer() == service->GetDevice() ) {
176 render_idx = i;
177 break;
178 }
179 }
180 if (render_idx < 0) return;
181
182 count = vars->GetItemCount();
183 for (i=0; i<count; i++) {
184 PLT_StateVariable *svar;
185 vars->Get(i, svar);
186 if (svar->GetName() == NPT_String("AbsoluteTimePosition")) {
187 u32 h, m, s;
188 if (sscanf((char *) svar->GetValue(), "%d:%d:%d", &h, &m, &s)==3) {
189 Double time = h*3600 + m*60 + s;
190 this->m_pUPnP->onTimeChanged(render_idx, time);
191 }
192 }
193 else if (svar->GetName() == NPT_String("CurrentTrackDuration")) {
194 u32 h, m, s;
195 if (sscanf((char *) svar->GetValue(), "%d:%d:%d", &h, &m, &s)==3) {
196 Double time = h*3600 + m*60 + s;
197 this->m_pUPnP->onDurationChanged(render_idx, time);
198 }
199 }
200
201 }
202 }
203
204
OnBrowseResult(NPT_Result res,PLT_DeviceDataReference & device,PLT_BrowseInfo * info,void * userdata)205 void GPAC_MediaController::OnBrowseResult(NPT_Result res, PLT_DeviceDataReference& device, PLT_BrowseInfo* info, void* userdata)
206 {
207 NPT_COMPILER_UNUSED(device);
208
209 NPT_COMPILER_UNUSED(device);
210
211 if (!userdata) return;
212
213 GPAC_BrowseDataReference* data = (GPAC_BrowseDataReference*) userdata;
214 (*data)->res = res;
215 if (NPT_SUCCEEDED(res) && info) {
216 (*data)->info = *info;
217 }
218 (*data)->shared_var.SetValue(1);
219 delete data;
220 }
221
222 void
OnMSStateVariablesChanged(PLT_Service * service,NPT_List<PLT_StateVariable * > * vars)223 GPAC_MediaController::OnMSStateVariablesChanged(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
224 {
225 GPAC_MediaServerItem *ms = NULL;
226 gf_mx_p(m_ControlPointLock);
227
228 u32 i, count;
229 count = gf_list_count(m_MediaServers);
230 for (i=0; i<count; i++) {
231 GPAC_MediaServerItem *ms = (GPAC_MediaServerItem *) gf_list_get(m_MediaServers, i);
232 if (ms->m_UUID==service->GetDevice()->GetUUID()) {
233 break;
234 }
235 ms = NULL;
236 }
237
238 if (!ms) {
239 gf_mx_v(m_ControlPointLock);
240 return;
241 }
242
243 PLT_StateVariable* var = PLT_StateVariable::Find(*vars, "ContainerUpdateIDs");
244 if (var) {
245 // variable found, parse value
246 NPT_String value = var->GetValue();
247 NPT_String item_id, update_id;
248 int index;
249
250 while (value.GetLength()) {
251 // look for container id
252 index = value.Find(',');
253 if (index < 0) break;
254 item_id = value.Left(index);
255 value = value.SubString(index+1);
256
257 // look for update id
258 if (value.GetLength()) {
259 index = value.Find(',');
260 update_id = (index<0)?value:value.Left(index);
261 value = (index<0)?"":value.SubString(index+1);
262
263 m_pUPnP->ContainerChanged(ms->m_device, item_id, update_id);
264 }
265 }
266 }
267 gf_mx_v(m_ControlPointLock);
268 }
269
270 NPT_Result
WaitForResponse(NPT_SharedVariable & shared_var)271 GPAC_MediaController::WaitForResponse(NPT_SharedVariable& shared_var)
272 {
273 return shared_var.WaitUntilEquals(1, 30000);
274 }
275
276
277 NPT_Result
Browse(GPAC_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)278 GPAC_MediaController::Browse(GPAC_BrowseDataReference& browse_data,
279 PLT_DeviceDataReference& device,
280 const char* object_id,
281 NPT_Int32 index,
282 NPT_Int32 count,
283 bool browse_metadata,
284 const char* filter,
285 const char* sort)
286 {
287 NPT_Result res;
288
289 browse_data->shared_var.SetValue(0);
290
291 // send off the browse packet. Note that this will
292 // not block. There is a call to WaitForResponse in order
293 // to block until the response comes back.
294 res = m_MediaBrowser->Browse(device,
295 (const char*)object_id,
296 index,
297 count,
298 browse_metadata,
299 filter,
300 sort,
301 new GPAC_BrowseDataReference(browse_data));
302 NPT_CHECK_SEVERE(res);
303
304 return WaitForResponse(browse_data->shared_var);
305 }
306
307 NPT_Result
Browse(GPAC_MediaServerItem * server,const char * object_id,const char * filter)308 GPAC_MediaController::Browse(GPAC_MediaServerItem *server, const char *object_id, const char *filter)
309 {
310 NPT_Result res = NPT_FAILURE;
311 NPT_Int32 index = 0;
312
313 // reset output params
314 server->m_BrowseResults = NULL;
315
316
317 do {
318 GPAC_BrowseDataReference browse_data(new GPAC_BrowseData());
319
320 // send off the browse packet. Note that this will
321 // not block. There is a call to WaitForResponse in order
322 // to block until the response comes back.
323 res = Browse(browse_data,
324 server->m_device,
325 (const char*)object_id,
326 index,
327 1024,
328 false,
329 filter,
330 "");
331 NPT_CHECK_LABEL_WARNING(res, done);
332
333 if (NPT_FAILED(browse_data->res)) {
334 res = browse_data->res;
335 NPT_CHECK_LABEL_WARNING(res, done);
336 }
337
338 if (browse_data->info.items->GetItemCount() == 0)
339 break;
340
341 if (server->m_BrowseResults.IsNull()) {
342 server->m_BrowseResults = browse_data->info.items;
343 } else {
344 server->m_BrowseResults->Add(*browse_data->info.items);
345 // clear the list items so that the data inside is not
346 // cleaned up by PLT_MediaItemList dtor since we copied
347 // each pointer into the new list.
348 browse_data->info.items->Clear();
349 }
350
351 // stop now if our list contains exactly what the server said it had
352 if (browse_data->info.tm && browse_data->info.tm == server->m_BrowseResults->GetItemCount())
353 break;
354
355 // ask for the next chunk of entries
356 index = server->m_BrowseResults->GetItemCount();
357 } while(1);
358
359 done:
360 return res;
361 }
362
363