vdr-plugin-drmdevice 2.0.0-46418f1
menu.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2
13#include <string>
14
15#include <vdr/interface.h>
16#include <vdr/osdbase.h>
17#include <vdr/plugin.h>
18#include <vdr/videodir.h>
19
20#include "device.h"
21#include "logger.h"
22#include "mediaplayer.h"
23#include "menu.h"
24
29 int c0, int c1, int c2, int c3, int c4)
30 : cOsdMenu(title, c0, c1, c2, c3, c4),
31 m_pDevice(device)
32{
33 pMenu = this;
34 m_playlist.clear();
35
36 if (cDrmDeviceControl::Control() && cDrmDeviceControl::Control()->Player()->GetFirstPlaylistEntry()) {
37 LOGDEBUG2(L_MEDIA, "mediaplayer: %s: pointer to cDrmDeviceControl exist.", __FUNCTION__);
38 PlayListMenu(); // Test if PL!!!
39 } else {
40 MainMenu();
41 }
42}
43
48
56static inline cOsdItem *SeparatorName(const char *label)
57{
58 return new cOsdItem(cString::sprintf("%s:", label), osUnknown, false);
59}
60
68static inline cOsdItem *SeparatorSpace(void)
69{
70 return new cOsdItem(" ", osUnknown, false);
71}
72
77{
78 int current;
79
80 current = Current(); // get current menu item index
81 Clear(); // clear the menu
82
83 // pip
84 if (m_pDevice->UsePip()) {
85 Add(SeparatorName("PIP"));
86 Add(new cOsdItem(hk(tr(" Toggle")), osUser1));
87 Add(new cOsdItem(hk(tr(" Channel +")), osUser2));
88 Add(new cOsdItem(hk(tr(" Channel -")), osUser3));
89 Add(new cOsdItem(hk(tr(" Swap channels")), osUser4));
90 Add(new cOsdItem(hk(tr(" Swap position")), osUser5));
91 Add(new cOsdItem(hk(tr(" Switch to pip channel")), osUser6));
92 }
93
95
96 // detach
97 Add(SeparatorName("Detach"));
98 Add(new cOsdItem(hk(tr(" Detach device")), osUser7));
99
101
102 // mediaplayer
103 Add(SeparatorName("Mediaplayer"));
104 Add(new cOsdItem(hk(tr(" play file / make play list")), osUser8));
105 Add(new cOsdItem(hk(tr(" select play list")), osUser9));
106
107 SetCurrent(Get(current)); // restore selected menu entry
108 Display();
109}
110
128
135 switch (code) {
136 // pip
137 case PIPTOGGLEONOFF:
139 break;
140 case PIPCHANNELUP:
142 break;
143 case PIPCHANNELDOWN:
145 break;
146 case PIPCHANNELSWAP:
148 break;
149 case PIPPOSITIONSWAP:
151 break;
154 break;
155 // detach/ attach
156 case DETACHDEVICE:
157 m_pDevice->Detach();
158 break;
159 case ATTACHDEVICE:
160 m_pDevice->Attach();
161 break;
162 default:
163 break;
164 }
165}
166
173{
175 cOsdItem *item;
176
177 switch (m_hotkeyState) {
179 if (key == kBlue) {
180 if (!m_pDevice->UsePip())
181 return osEnd;
182
184 return osContinue;
185 }
186 if (key == kRed) {
188 return osContinue;
189 }
190 break;
191 case HotkeyState::Blue: // pip
192 if (k0 <= key && key <= k9) {
193 int hotkeyCode = static_cast<int>(PIPKEYBASE) + static_cast<int>(key) - static_cast<int>(k0);
196 return osEnd;
197 }
199 break;
200 case HotkeyState::Red: // detach/ attach
201 if (k0 <= key && key <= k9) {
202 int hotkeyCode = static_cast<int>(DETACHKEYBASE) + static_cast<int>(key) - static_cast<int>(k0);
205 return osEnd;
206 }
208 break;
209 }
210
211 item = (cOsdItem *) Get(Current());
212 state = cOsdMenu::ProcessKey(key);
213
214 switch (state) {
215 // pip
216 case osUser1: // toggle pip
218 return osEnd;
219 case osUser2: // pip channel +
221 return osEnd;
222 case osUser3: // pip channel -
224 return osEnd;
225 case osUser4: // pip channel swap
227 return osEnd;
228 case osUser5: // pip position swap
230 return osEnd;
231 case osUser6: // pip switch main stream back to pip stream and close pip
233 return osEnd;
234
235 // detach
236 case osUser7: // detach device
237 m_pDevice->Detach();
238 return osEnd;
239
240 // mediaplayer
241 case osUser8: // play file / make play list
242 m_path = cVideoDirectory::Name();
244 return osContinue;
245 case osUser9: // select play list
246 m_path = cPlugin::ConfigDirectory("drmdevice");
248 return osContinue;
249 default:
250 break;
251 }
252
253 switch (key) {
254 case kOk:
255 if (strcasestr(item->Text(), "[..]")) {
256 std::string newPath = m_path.substr(0 ,m_path.find_last_of("/"));
257
258 if (!m_lastItem.empty())
259 m_lastItem.clear();
260 m_lastItem = m_path.substr(m_path.find_last_of("/") + 1);
261
262 m_path = newPath;
263 FindFileMenu(m_path.c_str(), NULL);
264 break;
265 }
266 if (cDrmDeviceControl::Control() && cDrmDeviceControl::Control()->Player()->GetCurrentPlaylistEntry()) {
267 cDrmDeviceControl::Control()->Player()->SetEntry(Current());
268// PlayListMenu();
269 break;
270 }
271 if (IsValidMediaFile(item->Text())) {
272 PlayMedia(item->Text());
273 return osEnd;
274 } else {
275 std::string newPath = m_path + "/" + item->Text();
276 struct stat sb;
277 if (stat(newPath.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
278 m_path = newPath;
279 FindFileMenu(newPath.c_str(), NULL);
280 }
281 }
282 break;
283 case kRed:
284 if (cDrmDeviceControl::Control() && cDrmDeviceControl::Control()->Player()->GetCurrentPlaylistEntry()) {
285 cDrmDeviceControl::Control()->Player()->ToggleRandomPlay();
286 PlayListMenu();
287 break;
288 }
289 if (m_playlist.empty()) {
290 if (IsValidMediaFile(item->Text())) {
291 PlayMedia(item->Text());
292 return osEnd;
293 }
294 } else {
295 m_path = cPlugin::ConfigDirectory("drmdevice");
296 PlayMedia(m_playlist.c_str());
297 return osEnd;
298 }
299 break;
300 case kGreen:
302 cDrmDeviceControl::Control()->Player()->JumpSec(-60);
303 } else {
304 MakePlayList(item->Text(), "w");
305 Interface->Confirm(tr("New Playlist"), 1, true);
306 if (!m_lastItem.empty())
307 m_lastItem.clear();
308 m_lastItem = item->Text();
309 FindFileMenu(m_path.c_str(), NULL);
310 }
311 break;
312 case kYellow:
314 cDrmDeviceControl::Control()->Player()->JumpSec(60);
315 } else {
316 MakePlayList(item->Text(), "a");
317 Interface->Confirm(tr("Added to Playlist"), 1, true);
318 }
319 break;
320 case kBlue:
322 break;
323 case kPlay:
324 if (IsValidMediaFile(item->Text())) {
325 PlayMedia(item->Text());
326 return osEnd;
327 }
328 break;
329 case kNext:
331 cDrmDeviceControl::Control()->Player()->Stop();
332 break;
333 default:
334 break;
335 }
336
337 return state;
338}
339
340/*****************************************************************************
341 * Mediaplayer sub menus
342 ****************************************************************************/
343
348{
349 cPlaylistEntry *entry = cDrmDeviceControl::Control()->Player()->GetFirstPlaylistEntry();
350 Clear();
351 while (1) {
352 std::string p_string = entry->OsdItemString();
353 Add(new cOsdItem(p_string.c_str()), (entry == cDrmDeviceControl::Control()->Player()->GetCurrentPlaylistEntry()));
354
355 if (!entry->GetNextEntry())
356 break;
357
358 entry = entry->GetNextEntry();
359 }
360 SetHelp(cDrmDeviceControl::Control()->Player()->IsRandomPlayActive() ? "Random Play" : " No Random Play",
361 "Jump -1 min", "Jump +1 min", "End player");
362 Display();
363}
364
369{
370 struct dirent **dirList;
371 int n, i;
372
373 if ((n = scandir(cPlugin::ConfigDirectory("drmdevice"), &dirList, NULL, alphasort)) == -1) {
374 LOGERROR("mediaplayer: %s: searching PL in %s failed (%d): %m", __FUNCTION__,
375 cPlugin::ConfigDirectory("drmdevice"), errno);
376 return;
377 }
378
379 Clear();
380 for (i = 0; i < n; i++) {
381 if (dirList[i]->d_name[0] != '.' && (strcasestr(dirList[i]->d_name, ".M3U"))) {
382 Add(new cOsdItem(dirList[i]->d_name));
383 }
384 }
385 SetHelp("Play PL", NULL, NULL, NULL);
386 Display();
387}
388
396{
397 struct dirent **dirList;
398 int n, i;
399 const char * sp;
400
401 if (!searchPath.size())
402 sp = "/";
403 else
404 sp = searchPath.c_str();
405
406 if (!playlist) {
407 Clear();
408 if (searchPath.size())
409 Add(new cOsdItem("[..]"));
410 }
411
412 if ((n = scandir(sp, &dirList, NULL, alphasort)) == -1) {
413 LOGERROR("mediaplayer: %s: scanning directory %s failed (%d): %m", __FUNCTION__, sp, errno);
414 } else {
415 struct stat fileAttributs;
416 for (i = 0; i < n; i++) {
417 std::string str = searchPath + "/" + dirList[i]->d_name;
418 if (stat(str.c_str(), &fileAttributs) == -1) {
419 LOGERROR("mediaplayer: %s: stat on %s failed (%d): %m", __FUNCTION__, str.c_str(), errno);
420 } else {
421 if (S_ISDIR(fileAttributs.st_mode) && dirList[i]->d_name[0] != '.') {
422 if (playlist) {
423 FindFileMenu(str.c_str(), playlist);
424 } else {
425 Add(new cOsdItem(dirList[i]->d_name),
426 !m_lastItem.compare(0, m_lastItem.length(), dirList[i]->d_name));
427 }
428 }
429 }
430 }
431 for (i = 0; i < n; i++) {
432 std::string str = searchPath + "/" + dirList[i]->d_name;
433 if (stat(str.c_str(), &fileAttributs) == -1) {
434 LOGERROR("mediaplayer: %s: stat on %s failed (%d): %m", __FUNCTION__, str.c_str(), errno);
435 } else {
436 if (S_ISREG(fileAttributs.st_mode) && dirList[i]->d_name[0] != '.') {
437 if (playlist) {
439 fprintf(playlist, "%s/%s\n", searchPath.c_str(),
440 dirList[i]->d_name);
441 } else {
442 Add(new cOsdItem(dirList[i]->d_name));
443 }
444 }
445 }
446 }
447 }
448
449 if (!playlist) {
450 SetHelp( m_playlist.empty() ? "Play File" : "Play PL", "New PL", "Add to PL", NULL);
451// SetHelp(Control->Player->Running ? NULL : "Set new PL",
452// Control->Player->Running ? "Play Menu" : "Select PL");
453 Display();
454 }
455}
456
463void cDeviceMenu::MakePlayList(const char * target, const char * mode)
464{
465 if (m_playlist.empty())
466 m_playlist = "/default.m3u";
467
468 std::string plPath = cPlugin::ConfigDirectory("drmdevice");
469 plPath.append(m_playlist.c_str());
470 FILE *playlist = fopen(plPath.c_str(), mode);
471
472 if (!playlist)
473 return;
474
476 fprintf(playlist, "%s/%s\n", m_path.c_str(), target);
477 } else {
478 std::string str = m_path + "/" + target;
479 FindFileMenu(str.c_str(), playlist);
480 }
481
483}
484
490void cDeviceMenu::PlayMedia(const char *name)
491{
492 std::string aim = m_path + "/" + name;
494 cControl::Launch(new cDrmDeviceControl(aim.c_str(), m_pDevice));
495 } else {
496 LOGERROR("mediaplayer: %s: can't start %s", __FUNCTION__, aim.c_str());
497 }
498}
499
506bool cDeviceMenu::IsValidMediaFile(const char *name)
507{
508 if (strcasestr(name, ".MP3") ||
509 strcasestr(name, ".MP4") ||
510 strcasestr(name, ".MKV") ||
511 strcasestr(name, ".MPG") ||
512 strcasestr(name, ".AVI") ||
513 strcasestr(name, ".M2TS") ||
514 strcasestr(name, ".MPEG") ||
515 strcasestr(name, ".M3U") ||
516 strcasestr(name, ".TS")) {
517
518 return true;
519 }
520
521 return false;
522}
void SelectPlaylistMenu(void)
Create mediaplayer select playlist menu.
Definition menu.cpp:368
HotkeyState m_hotkeyState
Definition menu.h:57
virtual eOSState ProcessKey(eKeys)
Handle key event.
Definition menu.cpp:172
std::string m_playlist
Definition menu.h:69
std::string m_path
Definition menu.h:67
bool IsValidMediaFile(const char *)
Test if it's a media file - at least if it has the right file extension...
Definition menu.cpp:506
void FindFileMenu(std::string, FILE *)
Create mediaplayer sub menu find file or make a play list.
Definition menu.cpp:395
void PlayListMenu(void)
Create mediaplayer playlist menu.
Definition menu.cpp:347
std::string m_lastItem
Definition menu.h:68
cOutputDevice * m_pDevice
Definition menu.h:55
void MainMenu(void)
Create main menu.
Definition menu.cpp:76
void PlayMedia(const char *)
Play media file.
Definition menu.cpp:490
cDeviceMenu(const char *, cOutputDevice *, int=0, int=0, int=0, int=0, int=0)
Build main or playlist menu.
Definition menu.cpp:28
void HandleHotKey(int)
Handle a key code which was compose by hotkey handling in ProcessKey()
Definition menu.cpp:134
virtual ~cDeviceMenu()
Definition menu.cpp:44
void MakePlayList(const char *, const char *)
Make a play list.
Definition menu.cpp:463
Media Player Control.
static cDrmDeviceControl * Control()
Output Device Implementation.
Definition device.h:72
void PipChannelChange(int)
Definition device.cpp:1452
void Detach(void)
Detach the device.
Definition device.cpp:1343
bool UsePip(void)
Definition device.h:197
void Attach(void)
Attach the device again.
Definition device.cpp:1365
void PipChannelSwap(bool)
Definition device.cpp:1453
void PipToggle(void)
Definition device.cpp:1451
void PipSwapPosition(void)
Definition device.cpp:1454
Playlist Entry.
Definition mediaplayer.h:34
Output Device Header File.
static cOsdItem * SeparatorName(const char *label)
Create a seperator item.
Definition menu.cpp:56
Hotkeys
Hotkeys.
Definition menu.cpp:116
static cOsdItem * SeparatorSpace(void)
Create a seperator item.
Definition menu.cpp:68
@ PIPCHANNELSWAP
Definition menu.cpp:121
@ PIPCHANNELDOWN
Definition menu.cpp:120
@ DETACHKEYBASE
Definition menu.cpp:124
@ PIPPOSITIONSWAP
Definition menu.cpp:122
@ PIPCHANNELSWITCHBACK
Definition menu.cpp:123
@ DETACHDEVICE
Definition menu.cpp:125
@ ATTACHDEVICE
Definition menu.cpp:126
@ PIPTOGGLEONOFF
Definition menu.cpp:118
@ PIPCHANNELUP
Definition menu.cpp:119
@ PIPKEYBASE
Definition menu.cpp:117
@ Initial
Definition menu.h:33
@ Red
Definition menu.h:35
@ Blue
Definition menu.h:34
#define LOGDEBUG2
log to LOG_DEBUG and add a prefix
Definition logger.h:48
#define LOGERROR
log to LOG_ERR
Definition logger.h:40
@ L_MEDIA
mediaplayer logs
Definition logger.h:68
static cDeviceMenu * pMenu
Main Menu Instance.
Definition menu.h:47
Logger Header File.
Mediaplayer Header File.
Plugin Main Menu Header File.
int code
Definition openglosd.h:33