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(const QString &handler, const QString &mrl,
82  const QString &plot, const QString &title, const QString &subtitle,
83  const QString &director, int season, int episode, const QString &inetref,
84  int length, const QString &year, const QString &id) :
85  m_handler(handler), m_mrl(mrl), m_plot(plot), m_title(title),
86  m_subtitle(subtitle), m_director(director), m_season(season),
87  m_episode(episode), m_inetref(inetref), m_length(length), m_year(year),
88  m_id(id)
89  {
90  }
91 
92  public:
93  static VideoPlayHandleMedia *Create(const QString &handler,
94  const QString &mrl, const QString &plot, const QString &title,
95  const QString &subtitle, const QString &director,
96  int season, int episode, const QString &inetref,
97  int length, const QString &year, const QString &id)
98  {
99  return new VideoPlayHandleMedia(handler, mrl, plot, title, subtitle,
100  director, season, episode, inetref, length, year, id);
101  }
102 
103  bool Play() const override // VideoPlayProc
104  {
108  }
109 
110  QString GetCommandDisplayName() const override // VideoPlayProc
111  {
112  return m_handler;
113  }
114 
115  VideoPlayHandleMedia *Clone() const override // VideoPlayProc
116  {
117  return new VideoPlayHandleMedia(*this);
118  }
119 
120  private:
121  QString m_handler;
122  QString m_mrl;
123  QString m_plot;
124  QString m_title;
125  QString m_subtitle;
126  QString m_director;
127  int m_season;
129  QString m_inetref;
130  int m_length;
131  QString m_year;
132  QString m_id;
133 };
134 
136 
138 {
139  private:
140  VideoPlayMythSystem(const QString &disp_command,
141  const QString &play_command) :
142  m_display_command(disp_command), m_play_command(play_command)
143  {
144  }
145 
146  public:
147  static VideoPlayMythSystem *Create(const QString &command,
148  const QString &filename)
149  {
150  return new VideoPlayMythSystem(command,
151  ExpandPlayCommand(command, filename));
152  }
153 
154  bool Play() const override // VideoPlayProc
155  {
157 
158  return true;
159  }
160 
161  QString GetCommandDisplayName() const override // VideoPlayProc
162  {
163  return m_display_command;
164  }
165 
166  VideoPlayMythSystem *Clone() const override // VideoPlayProc
167  {
168  return new VideoPlayMythSystem(*this);
169  }
170 
171  private:
173  QString m_play_command;
174 };
175 
177 
179 {
180  public:
181  VideoPlayerCommandPrivate() = default;
182 
184  {
185  for (player_list::const_iterator p = other.m_player_procs.begin();
186  p != other.m_player_procs.end(); ++p)
187  {
188  m_player_procs.push_back((*p)->Clone());
189  }
190  }
191 
193 
195  {
196  ClearPlayerList();
197  }
198 
199  void AltPlayerFor(const VideoMetadata *item)
200  {
201  if (item)
202  {
203  QString play_command =
204  gCoreContext->GetSetting("mythvideo.VideoAlternatePlayer");
205  QString filename;
206 
207  if (item->IsHostSet())
208  filename = generate_file_url("Videos", item->GetHost(),
209  item->GetFilename());
210  else
211  filename = item->GetFilename();
212 
213  if (play_command.length())
214  {
215  AddPlayer(play_command, filename, item->GetPlot(),
216  item->GetTitle(), item->GetSubtitle(),
217  item->GetDirector(), item->GetSeason(),
218  item->GetEpisode(), item->GetInetRef(),
219  item->GetLength(), QString::number(item->GetYear()),
220  QString::number(item->GetID()));
221  }
222  else
223  {
224  PlayerFor(filename, item);
225  }
226  }
227  }
228 
229  void PlayerFor(const VideoMetadata *item)
230  {
231  if (item)
232  {
233  QString play_command = item->GetPlayCommand();
234  QString filename;
235 
236  if (item->IsHostSet())
237  filename = generate_file_url("Videos", item->GetHost(),
238  item->GetFilename());
239  else
240  filename = item->GetFilename();
241 
242  if (play_command.length())
243  {
244  AddPlayer(play_command, filename, item->GetPlot(),
245  item->GetTitle(), item->GetSubtitle(),
246  item->GetDirector(), item->GetSeason(),
247  item->GetEpisode(), item->GetInetRef(),
248  item->GetLength(), QString::number(item->GetYear()),
249  QString::number(item->GetID()));
250  }
251  else
252  {
253  PlayerFor(filename, item);
254  }
255  }
256  }
257 
258  void PlayerFor(const QString &filename, const VideoMetadata *extraData = nullptr)
259  {
260  QString extension = filename.section(".", -1, -1);
261  QDir dir_test(QString("%1/VIDEO_TS").arg(filename));
262  if (dir_test.exists())
263  extension = "VIDEO_TS";
264  QDir bd_dir_test(QString("%1/BDMV").arg(filename));
265  if (bd_dir_test.exists())
266  extension = "BDMV";
267 
268  QString play_command = gCoreContext->GetSetting("VideoDefaultPlayer");
269 
270  const FileAssociations::association_list fa_list =
272  for (FileAssociations::association_list::const_iterator p =
273  fa_list.begin(); p != fa_list.end(); ++p)
274  {
275  if (p->extension.toLower() == extension.toLower() &&
276  !p->use_default)
277  {
278  play_command = p->playcommand;
279  break;
280  }
281  }
282 
283  if (play_command.trimmed().isEmpty())
284  play_command = "Internal";
285 
286  QString plot;
287  QString title = VideoMetadata::FilenameToMeta(filename, 1);
288  QString subtitle = VideoMetadata::FilenameToMeta(filename, 4);
289  QString director;
290  int season = 0;
291  int episode = 0;
292  QString inetref;
293  int length = 0;
294  QString year = QString::number(VIDEO_YEAR_DEFAULT);
295  QString id;
296 
297  if (extraData)
298  {
299  plot = extraData->GetPlot();
300  title = extraData->GetTitle();
301  subtitle = extraData->GetSubtitle();
302  director = extraData->GetDirector();
303  season = extraData->GetSeason();
304  episode = extraData->GetEpisode();
305  inetref = extraData->GetInetRef();
306  length = extraData->GetLength();
307  year = QString::number(extraData->GetYear());
308  id = QString::number(extraData->GetID());
309  }
310 
311  AddPlayer(play_command, filename, plot, title, subtitle, director,
312  season, episode, inetref, length, year, id);
313  }
314 
316  {
317  for (player_list::iterator p = m_player_procs.begin();
318  p != m_player_procs.end(); ++p)
319  {
320  delete *p;
321  }
322  m_player_procs.clear();
323  }
324 
325  void Play() const
326  {
327  for (player_list::const_iterator p = m_player_procs.begin();
328  p != m_player_procs.end(); ++p)
329  {
330  if ((*p)->Play()) break;
331  }
332  }
333 
334  QString GetCommandDisplayName() const
335  {
336  if (!m_player_procs.empty())
337  return m_player_procs.front()->GetCommandDisplayName();
338  return QString();
339  }
340 
341  private:
342  void AddPlayer(const QString &player, const QString &filename,
343  const QString &plot, const QString &title, const QString &subtitle,
344  const QString &director, int season, int episode, const QString &inetref,
345  int length, const QString &year, const QString &id)
346  {
347  m_player_procs.push_back(VideoPlayHandleMedia::Create(player, filename,
348  plot, title, subtitle, director, season, episode, inetref,
349  length, year, id));
350  m_player_procs.push_back(VideoPlayMythSystem::Create(player, filename));
351  }
352 
353  private:
354  typedef std::vector<VideoPlayProc *> player_list;
356 };
357 
359 
361 {
362  VideoPlayerCommand ret;
363  ret.m_d->AltPlayerFor(item);
364  return ret;
365 }
366 
368 {
369  VideoPlayerCommand ret;
370  ret.m_d->PlayerFor(item);
371  return ret;
372 }
373 
375 {
376  VideoPlayerCommand ret;
377  ret.m_d->PlayerFor(filename);
378  return ret;
379 }
380 
382 {
384 }
385 
387 {
388  delete m_d;
389  m_d = nullptr;
390 }
391 
393 {
394  m_d = new VideoPlayerCommandPrivate(*other.m_d);
395 }
396 
398 {
399  if (this != &rhs)
400  {
401  delete m_d;
402  m_d = new VideoPlayerCommandPrivate(*rhs.m_d);
403  }
404  return *this;
405 }
406 
408 {
409  LCD *lcd = LCD::Get();
410 
411  if (lcd) {
412  lcd->setFunctionLEDs(FUNC_TV, false);
413  lcd->setFunctionLEDs(FUNC_MOVIE, true);
414  }
415  gCoreContext->WantingPlayback(nullptr);
417  m_d->Play();
420  GetMythMainWindow()->raise();
421  GetMythMainWindow()->activateWindow();
422  if (GetMythMainWindow()->currentWidget())
423  GetMythMainWindow()->currentWidget()->setFocus();
424  if (lcd)
425  lcd->setFunctionLEDs(FUNC_MOVIE, false);
426 }
427 
429 {
430  return m_d->GetCommandDisplayName();
431 }
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
int GetSeason() const
QWidget * currentWidget(void)
VideoPlayMythSystem * Clone() const override
VideoPlayHandleMedia(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)
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:811
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)
VideoPlayMythSystem(const QString &disp_command, const QString &play_command)
const QString & GetHost() const
static FileAssociations & getFileAssociation()
Definition: dbaccess.cpp:836
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
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:427
VideoPlayProc()=default
bool Play() const override