MythTV  master
videoplayercommand.cpp
Go to the documentation of this file.
1 #include <QDir>
2 
3 #include "mythcontext.h"
4 
5 #include "mythmainwindow.h"
6 #include "mythsystemlegacy.h"
7 #include "remoteutil.h"
8 #include "lcddevice.h"
9 #include "mythmiscutil.h"
10 #include "dbaccess.h"
11 #include "videometadata.h"
12 #include "videoutils.h"
13 
14 #include "videoplayercommand.h"
15 
16 namespace
17 {
18  QString ShellEscape(const QString &src)
19  {
20  return QString(src)
21  .replace(QRegExp("\""), "\\\"")
22  .replace(QRegExp("`"), "\\`")
23  .replace(QRegExp("\\$"), "\\$");
24  }
25 
26  QString ExpandPlayCommand(const QString &command, const QString &filename)
27  {
28  // If handler contains %d, substitute default player command
29  // This would be used to add additional switches to the default without
30  // needing to retype the whole default command. But, if the
31  // command and the default command both contain %s, drop the %s from
32  // the default since the new command already has it
33  //
34  // example: default: mplayer -fs %s
35  // custom : %d -ao alsa9:spdif %s
36  // result : mplayer -fs -ao alsa9:spdif %s
37  QString tmp = command;
38  if (tmp.contains("%d"))
39  {
40  QString default_handler =
41  gCoreContext->GetSetting("VideoDefaultPlayer");
42  if (tmp.contains("%s") && default_handler.contains("%s"))
43  default_handler = default_handler.replace(QRegExp("%s"), "");
44  tmp.replace(QRegExp("%d"), default_handler);
45  }
46 
47  QString arg = QString("\"%1\"").arg(ShellEscape(filename));
48 
49  if (tmp.contains("%s"))
50  return tmp.replace(QRegExp("%s"), arg);
51 
52  return QString("%1 %2").arg(tmp).arg(arg);
53  }
54 }
55 
57 
59 {
60  protected:
61  VideoPlayProc() = default;
63 
64  public:
65  virtual ~VideoPlayProc() = default;
66  VideoPlayProc(const VideoPlayProc&) = default;
67 
68  // returns true if item played
69  virtual bool Play() const = 0;
70 
71  virtual QString GetCommandDisplayName() const = 0;
72 
73  virtual VideoPlayProc *Clone() const = 0;
74 };
75 
77 
79 {
80  private:
81  VideoPlayHandleMedia(QString handler, QString mrl,
82  QString plot, QString title, QString subtitle,
83  QString director, int season, int episode, QString inetref,
84  int length, QString year, QString id) :
85  m_handler(std::move(handler)), m_mrl(std::move(mrl)),
86  m_plot(std::move(plot)), m_title(std::move(title)),
87  m_subtitle(std::move(subtitle)),
88  m_director(std::move(director)), m_season(season),
89  m_episode(episode), m_inetref(std::move(inetref)),
90  m_length(length), m_year(std::move(year)),
91  m_id(std::move(id))
92  {
93  }
94 
95  public:
96  static VideoPlayHandleMedia *Create(const QString &handler,
97  const QString &mrl, const QString &plot, const QString &title,
98  const QString &subtitle, const QString &director,
99  int season, int episode, const QString &inetref,
100  int length, const QString &year, const QString &id)
101  {
102  return new VideoPlayHandleMedia(handler, mrl, plot, title, subtitle,
103  director, season, episode, inetref, length, year, id);
104  }
105 
106  bool Play() const override // VideoPlayProc
107  {
111  }
112 
113  QString GetCommandDisplayName() const override // VideoPlayProc
114  {
115  return m_handler;
116  }
117 
118  VideoPlayHandleMedia *Clone() const override // VideoPlayProc
119  {
120  return new VideoPlayHandleMedia(*this);
121  }
122 
123  private:
124  QString m_handler;
125  QString m_mrl;
126  QString m_plot;
127  QString m_title;
128  QString m_subtitle;
129  QString m_director;
130  int m_season;
132  QString m_inetref;
133  int m_length;
134  QString m_year;
135  QString m_id;
136 };
137 
139 
141 {
142  private:
143  VideoPlayMythSystem(QString disp_command,
144  QString play_command) :
145  m_display_command(std::move(disp_command)), m_play_command(std::move(play_command))
146  {
147  }
148 
149  public:
150  static VideoPlayMythSystem *Create(const QString &command,
151  const QString &filename)
152  {
153  return new VideoPlayMythSystem(command,
154  ExpandPlayCommand(command, filename));
155  }
156 
157  bool Play() const override // VideoPlayProc
158  {
160 
161  return true;
162  }
163 
164  QString GetCommandDisplayName() const override // VideoPlayProc
165  {
166  return m_display_command;
167  }
168 
169  VideoPlayMythSystem *Clone() const override // VideoPlayProc
170  {
171  return new VideoPlayMythSystem(*this);
172  }
173 
174  private:
176  QString m_play_command;
177 };
178 
180 
182 {
183  public:
184  VideoPlayerCommandPrivate() = default;
185 
187  {
188  for (player_list::const_iterator p = other.m_player_procs.begin();
189  p != other.m_player_procs.end(); ++p)
190  {
191  m_player_procs.push_back((*p)->Clone());
192  }
193  }
194 
196 
198  {
199  ClearPlayerList();
200  }
201 
202  void AltPlayerFor(const VideoMetadata *item)
203  {
204  if (item)
205  {
206  QString play_command =
207  gCoreContext->GetSetting("mythvideo.VideoAlternatePlayer");
208  QString filename;
209 
210  if (item->IsHostSet())
211  filename = generate_file_url("Videos", item->GetHost(),
212  item->GetFilename());
213  else
214  filename = item->GetFilename();
215 
216  if (play_command.length())
217  {
218  AddPlayer(play_command, filename, item->GetPlot(),
219  item->GetTitle(), item->GetSubtitle(),
220  item->GetDirector(), item->GetSeason(),
221  item->GetEpisode(), item->GetInetRef(),
222  item->GetLength(), QString::number(item->GetYear()),
223  QString::number(item->GetID()));
224  }
225  else
226  {
227  PlayerFor(filename, item);
228  }
229  }
230  }
231 
232  void PlayerFor(const VideoMetadata *item)
233  {
234  if (item)
235  {
236  QString play_command = item->GetPlayCommand();
237  QString filename;
238 
239  if (item->IsHostSet())
240  filename = generate_file_url("Videos", item->GetHost(),
241  item->GetFilename());
242  else
243  filename = item->GetFilename();
244 
245  if (play_command.length())
246  {
247  AddPlayer(play_command, filename, item->GetPlot(),
248  item->GetTitle(), item->GetSubtitle(),
249  item->GetDirector(), item->GetSeason(),
250  item->GetEpisode(), item->GetInetRef(),
251  item->GetLength(), QString::number(item->GetYear()),
252  QString::number(item->GetID()));
253  }
254  else
255  {
256  PlayerFor(filename, item);
257  }
258  }
259  }
260 
261  void PlayerFor(const QString &filename, const VideoMetadata *extraData = nullptr)
262  {
263  QString extension = filename.section(".", -1, -1);
264  QDir dir_test(QString("%1/VIDEO_TS").arg(filename));
265  if (dir_test.exists())
266  extension = "VIDEO_TS";
267  QDir bd_dir_test(QString("%1/BDMV").arg(filename));
268  if (bd_dir_test.exists())
269  extension = "BDMV";
270 
271  QString play_command = gCoreContext->GetSetting("VideoDefaultPlayer");
272 
273  const FileAssociations::association_list fa_list =
275  for (FileAssociations::association_list::const_iterator p =
276  fa_list.begin(); p != fa_list.end(); ++p)
277  {
278  if (p->extension.toLower() == extension.toLower() &&
279  !p->use_default)
280  {
281  play_command = p->playcommand;
282  break;
283  }
284  }
285 
286  if (play_command.trimmed().isEmpty())
287  play_command = "Internal";
288 
289  QString plot;
290  QString title = VideoMetadata::FilenameToMeta(filename, 1);
291  QString subtitle = VideoMetadata::FilenameToMeta(filename, 4);
292  QString director;
293  int season = 0;
294  int episode = 0;
295  QString inetref;
296  int length = 0;
297  QString year = QString::number(VIDEO_YEAR_DEFAULT);
298  QString id;
299 
300  if (extraData)
301  {
302  plot = extraData->GetPlot();
303  title = extraData->GetTitle();
304  subtitle = extraData->GetSubtitle();
305  director = extraData->GetDirector();
306  season = extraData->GetSeason();
307  episode = extraData->GetEpisode();
308  inetref = extraData->GetInetRef();
309  length = extraData->GetLength();
310  year = QString::number(extraData->GetYear());
311  id = QString::number(extraData->GetID());
312  }
313 
314  AddPlayer(play_command, filename, plot, title, subtitle, director,
315  season, episode, inetref, length, year, id);
316  }
317 
319  {
320  for (player_list::iterator p = m_player_procs.begin();
321  p != m_player_procs.end(); ++p)
322  {
323  delete *p;
324  }
325  m_player_procs.clear();
326  }
327 
328  void Play() const
329  {
330  for (player_list::const_iterator p = m_player_procs.begin();
331  p != m_player_procs.end(); ++p)
332  {
333  if ((*p)->Play()) break;
334  }
335  }
336 
337  QString GetCommandDisplayName() const
338  {
339  if (!m_player_procs.empty())
340  return m_player_procs.front()->GetCommandDisplayName();
341  return QString();
342  }
343 
344  private:
345  void AddPlayer(const QString &player, const QString &filename,
346  const QString &plot, const QString &title, const QString &subtitle,
347  const QString &director, int season, int episode, const QString &inetref,
348  int length, const QString &year, const QString &id)
349  {
350  m_player_procs.push_back(VideoPlayHandleMedia::Create(player, filename,
351  plot, title, subtitle, director, season, episode, inetref,
352  length, year, id));
353  m_player_procs.push_back(VideoPlayMythSystem::Create(player, filename));
354  }
355 
356  private:
357  typedef std::vector<VideoPlayProc *> player_list;
359 };
360 
362 
364 {
365  VideoPlayerCommand ret;
366  ret.m_d->AltPlayerFor(item);
367  return ret;
368 }
369 
371 {
372  VideoPlayerCommand ret;
373  ret.m_d->PlayerFor(item);
374  return ret;
375 }
376 
378 {
379  VideoPlayerCommand ret;
380  ret.m_d->PlayerFor(filename);
381  return ret;
382 }
383 
385 {
387 }
388 
390 {
391  delete m_d;
392  m_d = nullptr;
393 }
394 
396 {
397  m_d = new VideoPlayerCommandPrivate(*other.m_d);
398 }
399 
401 {
402  if (this != &rhs)
403  {
404  delete m_d;
405  m_d = new VideoPlayerCommandPrivate(*rhs.m_d);
406  }
407  return *this;
408 }
409 
411 {
412  LCD *lcd = LCD::Get();
413 
414  if (lcd) {
415  lcd->setFunctionLEDs(FUNC_TV, false);
416  lcd->setFunctionLEDs(FUNC_MOVIE, true);
417  }
418  gCoreContext->WantingPlayback(nullptr);
420  m_d->Play();
423  GetMythMainWindow()->raise();
424  GetMythMainWindow()->activateWindow();
425  if (GetMythMainWindow()->currentWidget())
426  GetMythMainWindow()->currentWidget()->setFocus();
427  if (lcd)
428  lcd->setFunctionLEDs(FUNC_MOVIE, false);
429 }
430 
432 {
433  return m_d->GetCommandDisplayName();
434 }
void PlayerFor(const QString &filename, const VideoMetadata *extraData=nullptr)
virtual VideoPlayProc * Clone() const =0
int GetLength() const
QString GetCommandDisplayName() const
Returns the player command suitable for display to the user.
const QString & GetPlayCommand() const
VideoPlayHandleMedia(QString handler, QString mrl, QString plot, QString title, QString subtitle, QString director, int season, int episode, QString inetref, int length, QString year, QString id)
int GetSeason() const
QWidget * currentWidget(void)
VideoPlayMythSystem * Clone() const override
std::vector< file_association > association_list
Definition: dbaccess.h:153
void AltPlayerFor(const VideoMetadata *item)
VideoPlayerCommandPrivate(const VideoPlayerCommandPrivate &other)
const association_list & getList() const
Definition: dbaccess.cpp:810
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, int length, const QString &year, const QString &id)
static VideoPlayerCommand AltPlayerFor(const VideoMetadata *item)
virtual ~VideoPlayProc()=default
static VideoPlayMythSystem * Create(const QString &command, const QString &filename)
bool IsHostSet() const
VideoPlayProc & operator=(const VideoPlayProc &)
const QString & GetDirector() const
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void PlayerFor(const VideoMetadata *item)
bool Play() const override
static guint32 * tmp
Definition: goom_core.c:35
unsigned int GetID() const
class VideoPlayerCommandPrivate * m_d
virtual QString GetCommandDisplayName() const =0
static LCD * Get(void)
Definition: lcddevice.cpp:65
int GetYear() const
VideoPlayerCommand & operator=(const VideoPlayerCommand &rhs)
const QString & GetPlot() const
void emitTVPlaybackStopped(void)
int GetEpisode() const
QString GetSetting(const QString &key, const QString &defaultval="")
virtual bool Play() const =0
QString GetCommandDisplayName() const override
QString GetCommandDisplayName() const override
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, int length, const QString &year, const QString &id)
static QString FilenameToMeta(const QString &file_name, int position)
static VideoPlayerCommand PlayerFor(const VideoMetadata *item)
uint myth_system(const QString &command, uint flags, uint timeout)
const QString & GetHost() const
static FileAssociations & getFileAssociation()
Definition: dbaccess.cpp:835
MythMainWindow * GetMythMainWindow(void)
VideoPlayerCommandPrivate & operator=(const VideoPlayerCommandPrivate &rhs)=delete
void PauseIdleTimer(bool pause)
const QString & GetFilename() const
VideoPlayHandleMedia * Clone() const override
VideoPlayerCommandPrivate()=default
Definition: lcddevice.h:165
QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
Definition: videoutils.h:65
std::vector< VideoPlayProc * > player_list
const QString & GetSubtitle() const
VideoPlayMythSystem(QString disp_command, QString play_command)
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="", int lenMins=120, const QString &year="1895", const QString &id="", bool useBookmarks=false)
const QString & GetInetRef() const
const QString & GetTitle() const
void WantingPlayback(QObject *sender)
All the objects that have registered using MythCoreContext::RegisterForPlayback but sender will be ca...
void setFunctionLEDs(enum LCDFunctionSet func, bool on)
Definition: lcddevice.cpp:426
VideoPlayProc()=default
bool Play() const override