1 /*****************************************************************
2 |
3 |   Platinum - Miccro Media Controller
4 |
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
6 | All rights reserved.
7 | http://www.plutinosoft.com
8 |
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.
13 |
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
21 |
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.
26 |
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
32 |
33 ****************************************************************/
34 
35 /*----------------------------------------------------------------------
36 |   includes
37 +---------------------------------------------------------------------*/
38 #include "PltMicroMediaController.h"
39 #include "PltLeaks.h"
40 #include "PltDownloader.h"
41 
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdlib.h>
45 
46 //NPT_SET_LOCAL_LOGGER("platinum.tests.micromediacontroller")
47 
48 /*----------------------------------------------------------------------
49 |   PLT_MicroMediaController::PLT_MicroMediaController
50 +---------------------------------------------------------------------*/
PLT_MicroMediaController(PLT_CtrlPointReference & ctrlPoint)51 PLT_MicroMediaController::PLT_MicroMediaController(PLT_CtrlPointReference& ctrlPoint) :
52     PLT_SyncMediaBrowser(ctrlPoint),
53     PLT_MediaController(ctrlPoint)
54 {
55     // create the stack that will be the directory where the
56     // user is currently browsing.
57     // push the root directory onto the directory stack.
58     m_CurBrowseDirectoryStack.Push("0");
59 
60     PLT_MediaController::SetDelegate(this);
61 }
62 
63 /*----------------------------------------------------------------------
64 |   PLT_MicroMediaController::PLT_MicroMediaController
65 +---------------------------------------------------------------------*/
~PLT_MicroMediaController()66 PLT_MicroMediaController::~PLT_MicroMediaController()
67 {
68 }
69 
70 /*
71 *  Remove trailing white space from a string
72 */
strchomp(char * str)73 static void strchomp(char* str)
74 {
75     if (!str) return;
76     char* e = str+NPT_StringLength(str)-1;
77 
78     while (e >= str && *e) {
79         if ((*e != ' ')  &&
80             (*e != '\t') &&
81             (*e != '\r') &&
82             (*e != '\n'))
83         {
84             *(e+1) = '\0';
85             break;
86         }
87         --e;
88     }
89 }
90 
91 /*----------------------------------------------------------------------
92 |   PLT_MicroMediaController::ChooseIDFromTable
93 +---------------------------------------------------------------------*/
94 /*
95  * Presents a list to the user, allows the user to choose one item.
96  *
97  * Parameters:
98  *		PLT_StringMap: A map that contains the set of items from
99  *                        which the user should choose.  The key should be a unique ID,
100  *						 and the value should be a string describing the item.
101  *       returns a NPT_String with the unique ID.
102  */
103 const char*
ChooseIDFromTable(PLT_StringMap & table)104 PLT_MicroMediaController::ChooseIDFromTable(PLT_StringMap& table)
105 {
106     printf("Select one of the following:\n");
107 
108     NPT_List<PLT_StringMapEntry*> entries = table.GetEntries();
109     if (entries.GetItemCount() == 0) {
110         printf("None available\n");
111     } else {
112         // display the list of entries
113         NPT_List<PLT_StringMapEntry*>::Iterator entry = entries.GetFirstItem();
114         int count = 0;
115         while (entry) {
116             printf("%d)\t%s (%s)\n", ++count, (const char*)(*entry)->GetValue(), (const char*)(*entry)->GetKey());
117             ++entry;
118         }
119 
120         int index, watchdog = 3;
121         char buffer[1024];
122 
123         // wait for input
124         while (watchdog > 0) {
125             fgets(buffer, 1024, stdin);
126             strchomp(buffer);
127 
128             if (1 != sscanf(buffer, "%d", &index)) {
129                 printf("Please enter a number\n");
130             } else if (index < 0 || index > count)	{
131                 printf("Please choose one of the above, or 0 for none\n");
132                 watchdog--;
133                 index = 0;
134             } else {
135                 watchdog = 0;
136             }
137         }
138 
139         // find the entry back
140         if (index != 0) {
141             entry = entries.GetFirstItem();
142             while (entry && --index) {
143                 ++entry;
144             }
145             if (entry) {
146                 return (*entry)->GetKey();
147             }
148         }
149     }
150 
151     return NULL;
152 }
153 
154 /*----------------------------------------------------------------------
155 |   PLT_MicroMediaController::PopDirectoryStackToRoot
156 +---------------------------------------------------------------------*/
157 void
PopDirectoryStackToRoot(void)158 PLT_MicroMediaController::PopDirectoryStackToRoot(void)
159 {
160     NPT_String val;
161     while (NPT_SUCCEEDED(m_CurBrowseDirectoryStack.Peek(val)) && val.Compare("0")) {
162         m_CurBrowseDirectoryStack.Pop(val);
163     }
164 }
165 
166 /*----------------------------------------------------------------------
167 |   PLT_MicroMediaController::OnMSAdded
168 +---------------------------------------------------------------------*/
169 bool
OnMSAdded(PLT_DeviceDataReference & device)170 PLT_MicroMediaController::OnMSAdded(PLT_DeviceDataReference& device)
171 {
172     // Issue special action upon discovering MediaConnect server
173     PLT_Service* service;
174     if (NPT_SUCCEEDED(device->FindServiceByType("urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:*", service))) {
175         PLT_ActionReference action;
176         PLT_SyncMediaBrowser::m_CtrlPoint->CreateAction(
177             device,
178             "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
179             "IsAuthorized",
180             action);
181         if (!action.IsNull()) {
182             action->SetArgumentValue("DeviceID", "");
183             PLT_SyncMediaBrowser::m_CtrlPoint->InvokeAction(action, 0);
184         }
185 
186         PLT_SyncMediaBrowser::m_CtrlPoint->CreateAction(
187             device,
188             "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
189             "IsValidated",
190             action);
191         if (!action.IsNull()) {
192             action->SetArgumentValue("DeviceID", "");
193             PLT_SyncMediaBrowser::m_CtrlPoint->InvokeAction(action, 0);
194         }
195     }
196 
197     return true;
198 }
199 
200 /*----------------------------------------------------------------------
201 |   PLT_MicroMediaController::OnMRAdded
202 +---------------------------------------------------------------------*/
203 bool
OnMRAdded(PLT_DeviceDataReference & device)204 PLT_MicroMediaController::OnMRAdded(PLT_DeviceDataReference& device)
205 {
206     NPT_String uuid = device->GetUUID();
207 
208     // test if it's a media renderer
209     PLT_Service* service;
210     if (NPT_SUCCEEDED(device->FindServiceByType("urn:schemas-upnp-org:service:AVTransport:*", service))) {
211         NPT_AutoLock lock(m_MediaRenderers);
212         m_MediaRenderers.Put(uuid, device);
213     }
214 
215     return true;
216 }
217 
218 /*----------------------------------------------------------------------
219 |   PLT_MicroMediaController::OnMRRemoved
220 +---------------------------------------------------------------------*/
221 void
OnMRRemoved(PLT_DeviceDataReference & device)222 PLT_MicroMediaController::OnMRRemoved(PLT_DeviceDataReference& device)
223 {
224     NPT_String uuid = device->GetUUID();
225 
226     {
227         NPT_AutoLock lock(m_MediaRenderers);
228         m_MediaRenderers.Erase(uuid);
229     }
230 
231     {
232         NPT_AutoLock lock(m_CurMediaRendererLock);
233 
234         // if it's the currently selected one, we have to get rid of it
235         if (!m_CurMediaRenderer.IsNull() && m_CurMediaRenderer == device) {
236             m_CurMediaRenderer = NULL;
237         }
238     }
239 }
240 
241 /*----------------------------------------------------------------------
242 |   PLT_MicroMediaController::OnMRStateVariablesChanged
243 +---------------------------------------------------------------------*/
244 void
OnMRStateVariablesChanged(PLT_Service * service,NPT_List<PLT_StateVariable * > * vars)245 PLT_MicroMediaController::OnMRStateVariablesChanged(PLT_Service*                  service,
246                                                     NPT_List<PLT_StateVariable*>* vars)
247 {
248     NPT_String uuid = service->GetDevice()->GetUUID();
249     NPT_List<PLT_StateVariable*>::Iterator var = vars->GetFirstItem();
250     while (var) {
251         printf("Received state var \"%s:%s:%s\" changes: \"%s\"\n",
252                (const char*)uuid,
253                (const char*)service->GetServiceID(),
254                (const char*)(*var)->GetName(),
255                (const char*)(*var)->GetValue());
256         ++var;
257     }
258 }
259 
260 /*----------------------------------------------------------------------
261 |   PLT_MicroMediaController::ChooseIDGetCurMediaServerFromTable
262 +---------------------------------------------------------------------*/
263 void
GetCurMediaServer(PLT_DeviceDataReference & server)264 PLT_MicroMediaController::GetCurMediaServer(PLT_DeviceDataReference& server)
265 {
266     NPT_AutoLock lock(m_CurMediaServerLock);
267 
268     if (m_CurMediaServer.IsNull()) {
269         printf("No server selected, select one with setms\n");
270     } else {
271         server = m_CurMediaServer;
272     }
273 }
274 
275 /*----------------------------------------------------------------------
276 |   PLT_MicroMediaController::GetCurMediaRenderer
277 +---------------------------------------------------------------------*/
278 void
GetCurMediaRenderer(PLT_DeviceDataReference & renderer)279 PLT_MicroMediaController::GetCurMediaRenderer(PLT_DeviceDataReference& renderer)
280 {
281     NPT_AutoLock lock(m_CurMediaRendererLock);
282 
283     if (m_CurMediaRenderer.IsNull()) {
284         printf("No renderer selected, select one with setmr\n");
285     } else {
286         renderer = m_CurMediaRenderer;
287     }
288 }
289 
290 /*----------------------------------------------------------------------
291 |   PLT_MicroMediaController::DoBrowse
292 +---------------------------------------------------------------------*/
293 NPT_Result
DoBrowse(const char * object_id,bool metadata)294 PLT_MicroMediaController::DoBrowse(const char* object_id, /* = NULL */
295                                    bool        metadata  /* = false */)
296 {
297     NPT_Result res = NPT_FAILURE;
298     PLT_DeviceDataReference device;
299 
300     GetCurMediaServer(device);
301     if (!device.IsNull()) {
302         NPT_String cur_object_id;
303         m_CurBrowseDirectoryStack.Peek(cur_object_id);
304 
305         // send off the browse packet and block
306         res = BrowseSync(
307             device,
308             object_id?object_id:(const char*)cur_object_id,
309             m_MostRecentBrowseResults,
310             metadata);
311     }
312 
313     return res;
314 }
315 
316 /*----------------------------------------------------------------------
317 |   PLT_MicroMediaController::HandleCmd_getms
318 +---------------------------------------------------------------------*/
319 void
HandleCmd_getms()320 PLT_MicroMediaController::HandleCmd_getms()
321 {
322     PLT_DeviceDataReference device;
323     GetCurMediaServer(device);
324     if (!device.IsNull()) {
325         printf("Current media server: %s\n", (const char*)device->GetFriendlyName());
326     } else {
327         // this output is taken care of by the GetCurMediaServer call
328     }
329 }
330 
331 /*----------------------------------------------------------------------
332 |   PLT_MicroMediaController::HandleCmd_getmr
333 +---------------------------------------------------------------------*/
334 void
HandleCmd_getmr()335 PLT_MicroMediaController::HandleCmd_getmr()
336 {
337     PLT_DeviceDataReference device;
338     GetCurMediaRenderer(device);
339     if (!device.IsNull()) {
340         printf("Current media renderer: %s\n", (const char*)device->GetFriendlyName());
341     } else {
342         // this output is taken care of by the GetCurMediaRenderer call
343     }
344 }
345 
346 /*----------------------------------------------------------------------
347 |   PLT_MicroMediaController::ChooseDevice
348 +---------------------------------------------------------------------*/
349 PLT_DeviceDataReference
ChooseDevice(const NPT_Lock<PLT_DeviceMap> & deviceList)350 PLT_MicroMediaController::ChooseDevice(const NPT_Lock<PLT_DeviceMap>& deviceList)
351 {
352     PLT_StringMap            namesTable;
353     PLT_DeviceDataReference* result = NULL;
354     NPT_String               chosenUUID;
355     NPT_AutoLock             lock(m_MediaServers);
356 
357     // create a map with the device UDN -> device Name
358     const NPT_List<PLT_DeviceMapEntry*>& entries = deviceList.GetEntries();
359     NPT_List<PLT_DeviceMapEntry*>::Iterator entry = entries.GetFirstItem();
360     while (entry) {
361         PLT_DeviceDataReference device = (*entry)->GetValue();
362         NPT_String              name   = device->GetFriendlyName();
363         namesTable.Put((*entry)->GetKey(), name);
364 
365         ++entry;
366     }
367 
368     // ask user to choose
369     chosenUUID = ChooseIDFromTable(namesTable);
370     if (chosenUUID.GetLength()) {
371         deviceList.Get(chosenUUID, result);
372     }
373 
374     return result?*result:PLT_DeviceDataReference(); // return empty reference if not device was selected
375 }
376 
377 /*----------------------------------------------------------------------
378 |   PLT_MicroMediaController::HandleCmd_setms
379 +---------------------------------------------------------------------*/
380 void
HandleCmd_setms()381 PLT_MicroMediaController::HandleCmd_setms()
382 {
383     NPT_AutoLock lock(m_CurMediaServerLock);
384 
385     PopDirectoryStackToRoot();
386     m_CurMediaServer = ChooseDevice(GetMediaServersMap());
387 }
388 
389 /*----------------------------------------------------------------------
390 |   PLT_MicroMediaController::HandleCmd_setmr
391 +---------------------------------------------------------------------*/
392 void
HandleCmd_setmr()393 PLT_MicroMediaController::HandleCmd_setmr()
394 {
395     NPT_AutoLock lock(m_CurMediaRendererLock);
396 
397     m_CurMediaRenderer = ChooseDevice(m_MediaRenderers);
398 }
399 
400 /*----------------------------------------------------------------------
401 |   PLT_MicroMediaController::HandleCmd_ls
402 +---------------------------------------------------------------------*/
403 void
HandleCmd_ls()404 PLT_MicroMediaController::HandleCmd_ls()
405 {
406     DoBrowse();
407 
408     if (!m_MostRecentBrowseResults.IsNull()) {
409         printf("There were %d results\n", m_MostRecentBrowseResults->GetItemCount());
410 
411         NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
412         while (item) {
413             if ((*item)->IsContainer()) {
414                 printf("Container: %s (%s)\n", (*item)->m_Title.GetChars(), (*item)->m_ObjectID.GetChars());
415             } else {
416                 printf("Item: %s (%s)\n", (*item)->m_Title.GetChars(), (*item)->m_ObjectID.GetChars());
417             }
418             ++item;
419         }
420 
421         m_MostRecentBrowseResults = NULL;
422     }
423 }
424 
425 /*----------------------------------------------------------------------
426 |   PLT_MicroMediaController::HandleCmd_info
427 +---------------------------------------------------------------------*/
428 void
HandleCmd_info()429 PLT_MicroMediaController::HandleCmd_info()
430 {
431     NPT_String              object_id;
432     PLT_StringMap           tracks;
433     PLT_DeviceDataReference device;
434 
435     // issue a browse
436     DoBrowse();
437 
438     if (!m_MostRecentBrowseResults.IsNull()) {
439         // create a map item id -> item title
440         NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
441         while (item) {
442             if (!(*item)->IsContainer()) {
443                 tracks.Put((*item)->m_ObjectID, (*item)->m_Title);
444             }
445             ++item;
446         }
447 
448         // let the user choose which one
449         object_id = ChooseIDFromTable(tracks);
450 
451         if (object_id.GetLength()) {
452             // issue a browse with metadata
453             DoBrowse(object_id, true);
454 
455             // look back for the PLT_MediaItem in the results
456             PLT_MediaObject* track = NULL;
457             if (!m_MostRecentBrowseResults.IsNull() &&
458                 NPT_SUCCEEDED(NPT_ContainerFind(*m_MostRecentBrowseResults, PLT_MediaItemIDFinder(object_id), track))) {
459 
460                 // display info
461                 printf("Title: %s \n", track->m_Title.GetChars());
462                 printf("OjbectID: %s\n", track->m_ObjectID.GetChars());
463                 printf("Class: %s\n", track->m_ObjectClass.type.GetChars());
464                 printf("Creator: %s\n", track->m_Creator.GetChars());
465                 printf("Date: %s\n", track->m_Date.GetChars());
466                 for (NPT_List<PLT_AlbumArtInfo>::Iterator iter = track->m_ExtraInfo.album_arts.GetFirstItem();
467                      iter;
468                      iter++) {
469                     printf("Art Uri: %s\n", (*iter).uri.GetChars());
470                     printf("Art Uri DLNA Profile: %s\n", (*iter).dlna_profile.GetChars());
471                 }
472                 for (NPT_Cardinal i=0;i<track->m_Resources.GetItemCount(); i++) {
473                     printf("\tResource[%d].uri: %s\n", i, track->m_Resources[i].m_Uri.GetChars());
474                     printf("\tResource[%d].profile: %s\n", i, track->m_Resources[i].m_ProtocolInfo.ToString().GetChars());
475                     printf("\tResource[%d].duration: %d\n", i, track->m_Resources[i].m_Duration);
476                     printf("\tResource[%d].size: %d\n", i, (int)track->m_Resources[i].m_Size);
477                     printf("\n");
478                 }
479                 printf("Didl: %s\n", (const char*)track->m_Didl);
480             } else {
481                 printf("Couldn't find the track\n");
482             }
483         }
484 
485         m_MostRecentBrowseResults = NULL;
486     }
487 }
488 
489 /*----------------------------------------------------------------------
490 |   PLT_MicroMediaController::HandleCmd_download
491 +---------------------------------------------------------------------*/
492 void
HandleCmd_download()493 PLT_MicroMediaController::HandleCmd_download()
494 {
495     NPT_String              object_id;
496     PLT_StringMap           tracks;
497     PLT_DeviceDataReference device;
498 
499     // issue a browse
500     DoBrowse();
501 
502     if (!m_MostRecentBrowseResults.IsNull()) {
503         // create a map item id -> item title
504         NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
505         while (item) {
506             if (!(*item)->IsContainer()) {
507                 tracks.Put((*item)->m_ObjectID, (*item)->m_Title);
508             }
509             ++item;
510         }
511 
512         // let the user choose which one
513         object_id = ChooseIDFromTable(tracks);
514 
515         if (object_id.GetLength()) {
516             // issue a browse with metadata
517             DoBrowse(object_id, true);
518 
519             // look back for the PLT_MediaItem in the results
520             PLT_MediaObject* track = NULL;
521             if (!m_MostRecentBrowseResults.IsNull() &&
522                 NPT_SUCCEEDED(NPT_ContainerFind(*m_MostRecentBrowseResults, PLT_MediaItemIDFinder(object_id), track))) {
523 
524                 if (track->m_Resources.GetItemCount() > 0) {
525                     printf("\tResource[0].uri: %s\n", track->m_Resources[0].m_Uri.GetChars());
526                     printf("\n");
527                     NPT_HttpUrl url(track->m_Resources[0].m_Uri.GetChars());
528                     if (url.IsValid()) {
529                         // Extract filename from URL
530                         NPT_String filename = NPT_FilePath::BaseName(url.GetPath(true).GetChars(), false);
531                         NPT_String extension = NPT_FilePath::FileExtension(url.GetPath(true).GetChars());
532                         printf("Downloading %s%s\n", filename.GetChars(), extension.GetChars());
533 
534                         for (int i=0; i<3; i++) {
535                             NPT_String filepath = NPT_String::Format("%s_%d%s", filename.GetChars(), i, extension.GetChars());
536 
537                             // Open file for writing
538                             NPT_File file(filepath);
539                             file.Open(NPT_FILE_OPEN_MODE_WRITE | NPT_FILE_OPEN_MODE_CREATE | NPT_FILE_OPEN_MODE_TRUNCATE);
540                             NPT_OutputStreamReference output;
541                             file.GetOutputStream(output);
542 
543                             // trigger 3 download
544                             PLT_Downloader* downloader = new PLT_Downloader(url, output);
545                             NPT_TimeInterval delay(5.);
546                             m_DownloadTaskManager.StartTask(downloader, &delay);
547                         }
548                     }
549                 } else {
550                     printf("No resources found");
551                 }
552             } else {
553                 printf("Couldn't find the track\n");
554             }
555         }
556 
557         m_MostRecentBrowseResults = NULL;
558     }
559 }
560 
561 /*----------------------------------------------------------------------
562 |   PLT_MicroMediaController::HandleCmd_cd
563 +---------------------------------------------------------------------*/
564 void
HandleCmd_cd(const char * command)565 PLT_MicroMediaController::HandleCmd_cd(const char* command)
566 {
567     NPT_String    newobject_id;
568     PLT_StringMap containers;
569 
570     // if command has parameter, push it to stack and return
571     NPT_String id = command;
572     NPT_List<NPT_String> args = id.Split(" ");
573     if (args.GetItemCount() >= 2) {
574         args.Erase(args.GetFirstItem());
575         id = NPT_String::Join(args, " ");
576         m_CurBrowseDirectoryStack.Push(id);
577         return;
578     }
579 
580     // list current directory to let user choose
581     DoBrowse();
582 
583     if (!m_MostRecentBrowseResults.IsNull()) {
584         NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
585         while (item) {
586             if ((*item)->IsContainer()) {
587                 containers.Put((*item)->m_ObjectID, (*item)->m_Title);
588             }
589             ++item;
590         }
591 
592         newobject_id = ChooseIDFromTable(containers);
593         if (newobject_id.GetLength()) {
594             m_CurBrowseDirectoryStack.Push(newobject_id);
595         }
596 
597         m_MostRecentBrowseResults = NULL;
598     }
599 }
600 
601 /*----------------------------------------------------------------------
602 |   PLT_MicroMediaController::HandleCmd_cdup
603 +---------------------------------------------------------------------*/
604 void
HandleCmd_cdup()605 PLT_MicroMediaController::HandleCmd_cdup()
606 {
607     // we don't want to pop the root off now....
608     NPT_String val;
609     m_CurBrowseDirectoryStack.Peek(val);
610     if (val.Compare("0")) {
611         m_CurBrowseDirectoryStack.Pop(val);
612     } else {
613         printf("Already at root\n");
614     }
615 }
616 
617 /*----------------------------------------------------------------------
618 |   PLT_MicroMediaController::HandleCmd_pwd
619 +---------------------------------------------------------------------*/
620 void
HandleCmd_pwd()621 PLT_MicroMediaController::HandleCmd_pwd()
622 {
623     NPT_Stack<NPT_String> tempStack;
624     NPT_String val;
625 
626     while (NPT_SUCCEEDED(m_CurBrowseDirectoryStack.Peek(val))) {
627         m_CurBrowseDirectoryStack.Pop(val);
628         tempStack.Push(val);
629     }
630 
631     while (NPT_SUCCEEDED(tempStack.Peek(val))) {
632         tempStack.Pop(val);
633         printf("%s/", (const char*)val);
634         m_CurBrowseDirectoryStack.Push(val);
635     }
636     printf("\n");
637 }
638 
639 /*----------------------------------------------------------------------
640 |   PLT_MicroMediaController::HandleCmd_open
641 +---------------------------------------------------------------------*/
642 void
HandleCmd_open()643 PLT_MicroMediaController::HandleCmd_open()
644 {
645     NPT_String              object_id;
646     PLT_StringMap           tracks;
647     PLT_DeviceDataReference device;
648 
649     GetCurMediaRenderer(device);
650     if (!device.IsNull()) {
651         // get the protocol info to try to see in advance if a track would play on the device
652 
653         // issue a browse
654         DoBrowse();
655 
656         if (!m_MostRecentBrowseResults.IsNull()) {
657             // create a map item id -> item title
658             NPT_List<PLT_MediaObject*>::Iterator item = m_MostRecentBrowseResults->GetFirstItem();
659             while (item) {
660                 if (!(*item)->IsContainer()) {
661                     tracks.Put((*item)->m_ObjectID, (*item)->m_Title);
662                 }
663                 ++item;
664             }
665 
666             // let the user choose which one
667             object_id = ChooseIDFromTable(tracks);
668             if (object_id.GetLength()) {
669                 // look back for the PLT_MediaItem in the results
670                 PLT_MediaObject* track = NULL;
671                 if (NPT_SUCCEEDED(NPT_ContainerFind(*m_MostRecentBrowseResults, PLT_MediaItemIDFinder(object_id), track))) {
672                     if (track->m_Resources.GetItemCount() > 0) {
673                         // look for best resource to use by matching each resource to a sink advertised by renderer
674                         NPT_Cardinal resource_index = 0;
675                         if (NPT_FAILED(FindBestResource(device, *track, resource_index))) {
676                             printf("No matching resource\n");
677                             return;
678                         }
679 
680                         // invoke the setUri
681                         printf("Issuing SetAVTransportURI with url=%s & didl=%s",
682                             (const char*)track->m_Resources[resource_index].m_Uri,
683                             (const char*)track->m_Didl);
684                         SetAVTransportURI(device, 0, track->m_Resources[resource_index].m_Uri, track->m_Didl, NULL);
685                     } else {
686                         printf("Couldn't find the proper resource\n");
687                     }
688 
689                 } else {
690                     printf("Couldn't find the track\n");
691                 }
692             }
693 
694             m_MostRecentBrowseResults = NULL;
695         }
696     }
697 }
698 
699 /*----------------------------------------------------------------------
700 |   PLT_MicroMediaController::HandleCmd_play
701 +---------------------------------------------------------------------*/
702 void
HandleCmd_play()703 PLT_MicroMediaController::HandleCmd_play()
704 {
705     PLT_DeviceDataReference device;
706     GetCurMediaRenderer(device);
707     if (!device.IsNull()) {
708         Play(device, 0, "1", NULL);
709     }
710 }
711 
712 /*----------------------------------------------------------------------
713 |   PLT_MicroMediaController::HandleCmd_seek
714 +---------------------------------------------------------------------*/
715 void
HandleCmd_seek(const char * command)716 PLT_MicroMediaController::HandleCmd_seek(const char* command)
717 {
718     PLT_DeviceDataReference device;
719     GetCurMediaRenderer(device);
720     if (!device.IsNull()) {
721         // remove first part of command ("seek")
722         NPT_String target = command;
723         NPT_List<NPT_String> args = target.Split(" ");
724         if (args.GetItemCount() < 2) return;
725 
726         args.Erase(args.GetFirstItem());
727         target = NPT_String::Join(args, " ");
728 
729         Seek(device, 0, (target.Find(":")!=-1)?"REL_TIME":"X_DLNA_REL_BYTE", target, NULL);
730     }
731 }
732 
733 /*----------------------------------------------------------------------
734 |   PLT_MicroMediaController::HandleCmd_stop
735 +---------------------------------------------------------------------*/
736 void
HandleCmd_stop()737 PLT_MicroMediaController::HandleCmd_stop()
738 {
739     PLT_DeviceDataReference device;
740     GetCurMediaRenderer(device);
741     if (!device.IsNull()) {
742         Stop(device, 0, NULL);
743     }
744 }
745 
746 /*----------------------------------------------------------------------
747 |   PLT_MicroMediaController::HandleCmd_mute
748 +---------------------------------------------------------------------*/
749 void
HandleCmd_mute()750 PLT_MicroMediaController::HandleCmd_mute()
751 {
752     PLT_DeviceDataReference device;
753     GetCurMediaRenderer(device);
754     if (!device.IsNull()) {
755         SetMute(device, 0, "Master", true, NULL);
756     }
757 }
758 
759 /*----------------------------------------------------------------------
760 |   PLT_MicroMediaController::HandleCmd_unmute
761 +---------------------------------------------------------------------*/
762 void
HandleCmd_unmute()763 PLT_MicroMediaController::HandleCmd_unmute()
764 {
765     PLT_DeviceDataReference device;
766     GetCurMediaRenderer(device);
767     if (!device.IsNull()) {
768         SetMute(device, 0, "Master", false, NULL);
769     }
770 }
771 
772 /*----------------------------------------------------------------------
773 |   PLT_MicroMediaController::HandleCmd_help
774 +---------------------------------------------------------------------*/
775 void
HandleCmd_help()776 PLT_MicroMediaController::HandleCmd_help()
777 {
778     printf("\n\nNone of the commands take arguments.  The commands with a * \n");
779     printf("signify ones that will prompt the user for more information once\n");
780     printf("the command is called\n\n");
781     printf("The available commands are:\n\n");
782     printf(" quit    -   shutdown the Control Point\n");
783     printf(" exit    -   same as quit\n");
784 
785     printf(" setms   - * select a media server to become the active media server\n");
786     printf(" getms   -   print the friendly name of the active media server\n");
787     printf(" ls      -   list the contents of the current directory on the active \n");
788     printf("             media server\n");
789     printf(" info    -   display media info\n");
790     printf(" down    -   download media to current directory\n");
791     printf(" cd      - * traverse down one level in the content tree on the active\n");
792     printf("             media server\n");
793     printf(" cd ..   -   traverse up one level in the content tree on the active\n");
794     printf("             media server\n");
795     printf(" pwd     -   print the path from the root to your current position in the \n");
796     printf("             content tree on the active media server\n");
797     printf(" setmr   - * select a media renderer to become the active media renderer\n");
798     printf(" getmr   -   print the friendly name of the active media renderer\n");
799     printf(" open    -   set the uri on the active media renderer\n");
800     printf(" play    -   play the active uri on the active media renderer\n");
801     printf(" stop    -   stop the active uri on the active media renderer\n");
802     printf(" seek    -   issue a seek command\n");
803     printf(" mute    -   mute the active media renderer\n");
804     printf(" unmute  -   unmute the active media renderer\n");
805 
806     printf(" help    -   print this help message\n\n");
807 }
808 
809 /*----------------------------------------------------------------------
810 |   PLT_MicroMediaController::ProcessCommandLoop
811 +---------------------------------------------------------------------*/
812 void
ProcessCommandLoop()813 PLT_MicroMediaController::ProcessCommandLoop()
814 {
815     char command[2048];
816     bool abort = false;
817 
818     command[0] = '\0';
819     while (!abort) {
820         printf("command> ");
821         fflush(stdout);
822         fgets(command, 2048, stdin);
823         strchomp(command);
824 
825         if (0 == strcmp(command, "quit") || 0 == strcmp(command, "exit")) {
826             abort = true;
827         } else if (0 == strcmp(command, "setms")) {
828             HandleCmd_setms();
829         } else if (0 == strcmp(command, "getms")) {
830             HandleCmd_getms();
831         } else if (0 == strncmp(command, "ls", 2)) {
832             HandleCmd_ls();
833         } else if (0 == strcmp(command, "info")) {
834             HandleCmd_info();
835         } else if (0 == strcmp(command, "down")) {
836             HandleCmd_download();
837         } else if (0 == strcmp(command, "cd")) {
838             HandleCmd_cd(command);
839         } else if (0 == strcmp(command, "cd ..")) {
840             HandleCmd_cdup();
841         } else if (0 == strcmp(command, "pwd")) {
842             HandleCmd_pwd();
843         } else if (0 == strcmp(command, "setmr")) {
844             HandleCmd_setmr();
845         } else if (0 == strcmp(command, "getmr")) {
846             HandleCmd_getmr();
847         } else if (0 == strcmp(command, "open")) {
848             HandleCmd_open();
849         } else if (0 == strcmp(command, "play")) {
850             HandleCmd_play();
851         } else if (0 == strcmp(command, "stop")) {
852             HandleCmd_stop();
853         } else if (0 == strncmp(command, "seek", 4)) {
854             HandleCmd_seek(command);
855         } else if (0 == strcmp(command, "mute")) {
856             HandleCmd_mute();
857         } else if (0 == strcmp(command, "unmute")) {
858             HandleCmd_mute();
859         } else if (0 == strcmp(command, "help")) {
860             HandleCmd_help();
861         } else if (0 == strcmp(command, "")) {
862             // just prompt again
863         } else {
864             printf("Unrecognized command: %s\n", command);
865             HandleCmd_help();
866         }
867     }
868 }
869 
870