MythTV master
videoplayercommand.cpp
Go to the documentation of this file.
1// Standard UNIX C headers
2#include <algorithm>
3
4// Qt
5#include <QDir>
6
7// MythTV
16
17// MythFrontend
18#include "videoplayercommand.h"
19
20namespace
21{
22 QString ShellEscape(const QString &src)
23 {
24 return QString(src)
25 .replace("\"", "\\\"")
26 .replace("`", "\\`")
27 .replace("\\$", "\\$");
28 }
29
30 QString ExpandPlayCommand(const QString &command, const QString &filename)
31 {
32 // If handler contains %d, substitute default player command
33 // This would be used to add additional switches to the default without
34 // needing to retype the whole default command. But, if the
35 // command and the default command both contain %s, drop the %s from
36 // the default since the new command already has it
37 //
38 // example: default: mplayer -fs %s
39 // custom : %d -ao alsa9:spdif %s
40 // result : mplayer -fs -ao alsa9:spdif %s
41 QString tmp = command;
42 if (tmp.contains("%d"))
43 {
44 QString default_handler =
45 gCoreContext->GetSetting("VideoDefaultPlayer");
46 if (tmp.contains("%s") && default_handler.contains("%s"))
47 default_handler = default_handler.replace("%s", "");
48 tmp.replace("%d", default_handler);
49 }
50
51 QString arg = QString("\"%1\"").arg(ShellEscape(filename));
52
53 if (tmp.contains("%s"))
54 return tmp.replace("%s", arg);
55
56 return QString("%1 %2").arg(tmp, arg);
57 }
58}
59
61
63{
64 protected:
65 VideoPlayProc() = default;
67
68 public:
69 virtual ~VideoPlayProc() = default;
70 VideoPlayProc(const VideoPlayProc&) = default;
71
72 // returns true if item played
73 virtual bool Play() const = 0;
74
75 virtual QString GetCommandDisplayName() const = 0;
76
77 virtual VideoPlayProc *Clone() const = 0;
78};
79
81
83{
84 private:
85 VideoPlayHandleMedia(QString handler, QString mrl,
86 QString plot, QString title, QString subtitle,
87 QString director, int season, int episode, QString inetref,
88 std::chrono::minutes length, QString year, QString id) :
89 m_handler(std::move(handler)), m_mrl(std::move(mrl)),
90 m_plot(std::move(plot)), m_title(std::move(title)),
91 m_subtitle(std::move(subtitle)),
92 m_director(std::move(director)), m_season(season),
93 m_episode(episode), m_inetref(std::move(inetref)),
94 m_length(length), m_year(std::move(year)),
95 m_id(std::move(id))
96 {
97 }
98
99 public:
100 static VideoPlayHandleMedia *Create(const QString &handler,
101 const QString &mrl, const QString &plot, const QString &title,
102 const QString &subtitle, const QString &director,
103 int season, int episode, const QString &inetref,
104 std::chrono::minutes length, const QString &year, const QString &id)
105 {
106 return new VideoPlayHandleMedia(handler, mrl, plot, title, subtitle,
107 director, season, episode, inetref, length, year, id);
108 }
109
110 bool Play() const override // VideoPlayProc
111 {
115 }
116
117 QString GetCommandDisplayName() const override // VideoPlayProc
118 {
119 return m_handler;
120 }
121
122 VideoPlayHandleMedia *Clone() const override // VideoPlayProc
123 {
124 return new VideoPlayHandleMedia(*this);
125 }
126
127 private:
128 QString m_handler;
129 QString m_mrl;
130 QString m_plot;
131 QString m_title;
132 QString m_subtitle;
133 QString m_director;
136 QString m_inetref;
137 std::chrono::minutes m_length;
138 QString m_year;
139 QString m_id;
140};
141
143
145{
146 private:
147 VideoPlayMythSystem(QString disp_command,
148 QString play_command) :
149 m_displayCommand(std::move(disp_command)), m_playCommand(std::move(play_command))
150 {
151 }
152
153 public:
154 static VideoPlayMythSystem *Create(const QString &command,
155 const QString &filename)
156 {
157 return new VideoPlayMythSystem(command,
158 ExpandPlayCommand(command, filename));
159 }
160
161 bool Play() const override // VideoPlayProc
162 {
164
165 return true;
166 }
167
168 QString GetCommandDisplayName() const override // VideoPlayProc
169 {
170 return m_displayCommand;
171 }
172
173 VideoPlayMythSystem *Clone() const override // VideoPlayProc
174 {
175 return new VideoPlayMythSystem(*this);
176 }
177
178 private:
181};
182
184
186{
187 public:
189
191 {
192 auto playerclone = [](auto *player) { return player->Clone(); };
193 std::ranges::transform(other.m_playerProcs,
194 std::back_inserter(m_playerProcs), playerclone);
195 }
196
198
200 {
202 }
203
204 void AltPlayerFor(const VideoMetadata *item)
205 {
206 if (item)
207 {
208 QString play_command =
209 gCoreContext->GetSetting("mythvideo.VideoAlternatePlayer");
210 QString filename;
211
212 if (item->IsHostSet())
213 {
215 item->GetFilename());
216 }
217 else
218 {
219 filename = item->GetFilename();
220 }
221
222 if (!play_command.isEmpty())
223 {
224 AddPlayer(play_command, filename, item->GetPlot(),
225 item->GetTitle(), item->GetSubtitle(),
226 item->GetDirector(), item->GetSeason(),
227 item->GetEpisode(), item->GetInetRef(),
228 item->GetLength(), QString::number(item->GetYear()),
229 QString::number(item->GetID()));
230 }
231 else
232 {
233 PlayerFor(filename, item);
234 }
235 }
236 }
237
238 void PlayerFor(const VideoMetadata *item)
239 {
240 if (item)
241 {
242 const QString& play_command = item->GetPlayCommand();
243 QString filename;
244
245 if (item->IsHostSet())
246 {
248 item->GetFilename());
249 }
250 else
251 {
252 filename = item->GetFilename();
253 }
254
255 if (!play_command.isEmpty())
256 {
257 AddPlayer(play_command, filename, item->GetPlot(),
258 item->GetTitle(), item->GetSubtitle(),
259 item->GetDirector(), item->GetSeason(),
260 item->GetEpisode(), item->GetInetRef(),
261 item->GetLength(), QString::number(item->GetYear()),
262 QString::number(item->GetID()));
263 }
264 else
265 {
266 PlayerFor(filename, item);
267 }
268 }
269 }
270
271 void PlayerFor(const QString &filename, const VideoMetadata *extraData = nullptr)
272 {
273 QString extension = filename.section(".", -1, -1);
274 QDir dir_test(QString("%1/VIDEO_TS").arg(filename));
275 if (dir_test.exists())
276 extension = "VIDEO_TS";
277 QDir bd_dir_test(QString("%1/BDMV").arg(filename));
278 if (bd_dir_test.exists())
279 extension = "BDMV";
280
281 QString play_command = gCoreContext->GetSetting("VideoDefaultPlayer");
282
285 auto sameext = [extension](const auto & fa)
286 { return fa.extension.toLower() == extension.toLower() &&
287 !fa.use_default; };
288 auto fa = std::ranges::find_if(fa_list, sameext);
289 if (fa != fa_list.cend())
290 play_command = fa->playcommand;
291
292 if (play_command.trimmed().isEmpty())
293 play_command = "Internal";
294
295 QString plot;
296 QString title = VideoMetadata::FilenameToMeta(filename, 1);
297 QString subtitle = VideoMetadata::FilenameToMeta(filename, 4);
298 QString director;
299 int season = 0;
300 int episode = 0;
301 QString inetref;
302 std::chrono::minutes length = 0min;
303 QString year = QString::number(VIDEO_YEAR_DEFAULT);
304 QString id;
305
306 if (extraData)
307 {
308 plot = extraData->GetPlot();
309 title = extraData->GetTitle();
310 subtitle = extraData->GetSubtitle();
311 director = extraData->GetDirector();
312 season = extraData->GetSeason();
313 episode = extraData->GetEpisode();
314 inetref = extraData->GetInetRef();
315 length = extraData->GetLength();
316 year = QString::number(extraData->GetYear());
317 id = QString::number(extraData->GetID());
318 }
319
320 AddPlayer(play_command, filename, plot, title, subtitle, director,
321 season, episode, inetref, length, year, id);
322 }
323
325 {
326 for (auto & player : m_playerProcs)
327 delete player;
328 m_playerProcs.clear();
329 }
330
331 void Play() const
332 {
333 // Do this until one of the players returns true
334 (void)std::ranges::any_of(m_playerProcs,
335 [](auto *player){ return player->Play(); } );
336 }
337
338 QString GetCommandDisplayName() const
339 {
340 if (!m_playerProcs.empty())
341 return m_playerProcs.front()->GetCommandDisplayName();
342 return {};
343 }
344
345 private:
346 void AddPlayer(const QString &player, const QString &filename,
347 const QString &plot, const QString &title, const QString &subtitle,
348 const QString &director, int season, int episode, const QString &inetref,
349 std::chrono::minutes length, const QString &year, const QString &id)
350 {
352 plot, title, subtitle, director, season, episode, inetref,
353 length, year, id));
355 }
356
357 private:
358 using player_list = std::vector<VideoPlayProc *>;
360};
361
363
365{
367 ret.m_d->AltPlayerFor(item);
368 return ret;
369}
370
372{
374 ret.m_d->PlayerFor(item);
375 return ret;
376}
377
379{
381 ret.m_d->PlayerFor(filename);
382 return ret;
383}
384
387{
388}
389
391{
392 delete m_d;
393 m_d = nullptr;
394}
395
397 : m_d(new VideoPlayerCommandPrivate(*other.m_d))
398{
399}
400
402{
403 if (this != &rhs)
404 {
405 delete m_d;
407 }
408 return *this;
409}
410
412{
413 LCD *lcd = LCD::Get();
414
415 if (lcd) {
416 lcd->setFunctionLEDs(FUNC_TV, false);
417 lcd->setFunctionLEDs(FUNC_MOVIE, true);
418 }
421 m_d->Play();
424 GetMythMainWindow()->raise();
425 GetMythMainWindow()->activateWindow();
426 if (lcd)
427 lcd->setFunctionLEDs(FUNC_MOVIE, false);
428}
429
431{
432 return m_d->GetCommandDisplayName();
433}
static FileAssociations & getFileAssociation()
Definition: dbaccess.cpp:840
const association_list & getList() const
Definition: dbaccess.cpp:815
std::vector< file_association > association_list
Definition: dbaccess.h:154
Definition: lcddevice.h:170
static LCD * Get(void)
Definition: lcddevice.cpp:68
void setFunctionLEDs(enum LCDFunctionSet func, bool on)
Definition: lcddevice.cpp:426
void emitTVPlaybackStopped(void)
QString GetSetting(const QString &key, const QString &defaultval="")
void WantingPlayback(QObject *sender)
All the objects that have registered using MythCoreContext::RegisterForPlayback but sender will be ca...
void PauseIdleTimer(bool Pause)
Pause the idle timeout timer.
bool HandleMedia(const QString &Handler, const QString &Mrl, const QString &Plot="", const QString &Title="", const QString &Subtitle="", const QString &Director="", int Season=0, int Episode=0, const QString &Inetref="", std::chrono::minutes LenMins=2h, const QString &Year="1895", const QString &Id="", bool UseBookmarks=false)
static QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
const QString & GetHost() const
bool IsHostSet() const
int GetYear() const
const QString & GetTitle() const
static QString FilenameToMeta(const QString &file_name, int position)
unsigned int GetID() const
std::chrono::minutes GetLength() const
const QString & GetInetRef() const
const QString & GetDirector() const
const QString & GetSubtitle() const
int GetSeason() const
const QString & GetPlayCommand() const
const QString & GetPlot() const
int GetEpisode() const
const QString & GetFilename() const
VideoPlayHandleMedia * Clone() const override
QString GetCommandDisplayName() const override
VideoPlayHandleMedia(QString handler, QString mrl, QString plot, QString title, QString subtitle, QString director, int season, int episode, QString inetref, std::chrono::minutes length, QString year, QString id)
std::chrono::minutes m_length
bool Play() const override
static VideoPlayHandleMedia * Create(const QString &handler, const QString &mrl, const QString &plot, const QString &title, const QString &subtitle, const QString &director, int season, int episode, const QString &inetref, std::chrono::minutes length, const QString &year, const QString &id)
bool Play() const override
VideoPlayMythSystem(QString disp_command, QString play_command)
QString GetCommandDisplayName() const override
VideoPlayMythSystem * Clone() const override
static VideoPlayMythSystem * Create(const QString &command, const QString &filename)
VideoPlayerCommandPrivate & operator=(const VideoPlayerCommandPrivate &rhs)=delete
void AltPlayerFor(const VideoMetadata *item)
VideoPlayerCommandPrivate()=default
VideoPlayerCommandPrivate(const VideoPlayerCommandPrivate &other)
void PlayerFor(const VideoMetadata *item)
std::vector< VideoPlayProc * > player_list
void PlayerFor(const QString &filename, const VideoMetadata *extraData=nullptr)
void AddPlayer(const QString &player, const QString &filename, const QString &plot, const QString &title, const QString &subtitle, const QString &director, int season, int episode, const QString &inetref, std::chrono::minutes length, const QString &year, const QString &id)
static VideoPlayerCommand AltPlayerFor(const VideoMetadata *item)
class VideoPlayerCommandPrivate * m_d
VideoPlayerCommand & operator=(const VideoPlayerCommand &rhs)
static VideoPlayerCommand PlayerFor(const VideoMetadata *item)
QString GetCommandDisplayName() const
Returns the player command suitable for display to the user.
@ FUNC_TV
Definition: lcddevice.h:164
@ FUNC_MOVIE
Definition: lcddevice.h:161
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythMainWindow * GetMythMainWindow(void)
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
QString ExpandPlayCommand(const QString &command, const QString &filename)
virtual QString GetCommandDisplayName() const =0
VideoPlayProc()=default
VideoPlayProc & operator=(const VideoPlayProc &)
VideoPlayProc(const VideoPlayProc &)=default
virtual ~VideoPlayProc()=default
virtual VideoPlayProc * Clone() const =0
virtual bool Play() const =0
static constexpr uint16_t VIDEO_YEAR_DEFAULT
Definition: videometadata.h:18