00001 #include <QDir>
00002
00003 #include "mythcontext.h"
00004
00005 #include "mythmainwindow.h"
00006 #include "mythsystem.h"
00007 #include "remoteutil.h"
00008 #include "lcddevice.h"
00009 #include "mythmiscutil.h"
00010 #include "dbaccess.h"
00011 #include "videometadata.h"
00012 #include "videoutils.h"
00013
00014 #include "videoplayercommand.h"
00015
00016 namespace
00017 {
00018 QString ShellEscape(const QString &src)
00019 {
00020 return QString(src)
00021 .replace(QRegExp("\""), "\\\"")
00022 .replace(QRegExp("`"), "\\`")
00023 .replace(QRegExp("\\$"), "\\$");
00024 }
00025
00026 QString ExpandPlayCommand(const QString &command, const QString &filename)
00027 {
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 QString tmp = command;
00038 if (tmp.contains("%d"))
00039 {
00040 QString default_handler =
00041 gCoreContext->GetSetting("VideoDefaultPlayer");
00042 if (tmp.contains("%s") && default_handler.contains("%s"))
00043 default_handler = default_handler.replace(QRegExp("%s"), "");
00044 tmp.replace(QRegExp("%d"), default_handler);
00045 }
00046
00047 QString arg = QString("\"%1\"").arg(ShellEscape(filename));
00048
00049 if (tmp.contains("%s"))
00050 return tmp.replace(QRegExp("%s"), arg);
00051
00052 return QString("%1 %2").arg(tmp).arg(arg);
00053 }
00054 }
00055
00057
00058 struct VideoPlayProc
00059 {
00060 protected:
00061 VideoPlayProc() {}
00062 VideoPlayProc &operator=(const VideoPlayProc &);
00063
00064 public:
00065 virtual ~VideoPlayProc() {}
00066
00067
00068 virtual bool Play() const = 0;
00069
00070 virtual QString GetCommandDisplayName() const = 0;
00071
00072 virtual VideoPlayProc *Clone() const = 0;
00073 };
00074
00076
00077 class VideoPlayHandleMedia : public VideoPlayProc
00078 {
00079 private:
00080 VideoPlayHandleMedia(const QString &handler, const QString &mrl,
00081 const QString &plot, const QString &title, const QString &subtitle,
00082 const QString &director, int season, int episode, const QString &inetref,
00083 int length, const QString &year, const QString &id) :
00084 m_handler(handler), m_mrl(mrl), m_plot(plot), m_title(title),
00085 m_subtitle(subtitle), m_director(director), m_season(season),
00086 m_episode(episode), m_inetref(inetref), m_length(length), m_year(year),
00087 m_id(id)
00088 {
00089 }
00090
00091 public:
00092 static VideoPlayHandleMedia *Create(const QString &handler,
00093 const QString &mrl, const QString &plot, const QString &title,
00094 const QString &subtitle, const QString &director,
00095 int season, int episode, const QString &inetref,
00096 int length, const QString &year, const QString &id)
00097 {
00098 return new VideoPlayHandleMedia(handler, mrl, plot, title, subtitle,
00099 director, season, episode, inetref, length, year, id);
00100 }
00101
00102 bool Play() const
00103 {
00104 return GetMythMainWindow()->HandleMedia(m_handler, m_mrl,
00105 m_plot, m_title, m_subtitle, m_director, m_season,
00106 m_episode, m_inetref, m_length, m_year, m_id, true);
00107 }
00108
00109 QString GetCommandDisplayName() const
00110 {
00111 return m_handler;
00112 }
00113
00114 VideoPlayHandleMedia *Clone() const
00115 {
00116 return new VideoPlayHandleMedia(*this);
00117 }
00118
00119 private:
00120 QString m_handler;
00121 QString m_mrl;
00122 QString m_plot;
00123 QString m_title;
00124 QString m_subtitle;
00125 QString m_director;
00126 int m_season;
00127 int m_episode;
00128 QString m_inetref;
00129 int m_length;
00130 QString m_year;
00131 QString m_id;
00132 };
00133
00135
00136 class VideoPlayMythSystem : public VideoPlayProc
00137 {
00138 private:
00139 VideoPlayMythSystem(const QString &disp_command,
00140 const QString &play_command) :
00141 m_display_command(disp_command), m_play_command(play_command)
00142 {
00143 }
00144
00145 public:
00146 static VideoPlayMythSystem *Create(const QString &command,
00147 const QString &filename)
00148 {
00149 return new VideoPlayMythSystem(command,
00150 ExpandPlayCommand(command, filename));
00151 }
00152
00153 bool Play() const
00154 {
00155 sendPlaybackStart();
00156 GetMythMainWindow()->PauseIdleTimer(true);
00157 myth_system(m_play_command);
00158 sendPlaybackEnd();
00159 GetMythMainWindow()->PauseIdleTimer(false);
00160
00161 return true;
00162 }
00163
00164 QString GetCommandDisplayName() const
00165 {
00166 return m_display_command;
00167 }
00168
00169 VideoPlayMythSystem *Clone() const
00170 {
00171 return new VideoPlayMythSystem(*this);
00172 }
00173
00174 private:
00175 QString m_display_command;
00176 QString m_play_command;
00177 };
00178
00180
00181 class VideoPlayerCommandPrivate
00182 {
00183 private:
00184 VideoPlayerCommandPrivate &operator=(const VideoPlayerCommandPrivate &rhs);
00185
00186 public:
00187 VideoPlayerCommandPrivate() {}
00188
00189 VideoPlayerCommandPrivate(const VideoPlayerCommandPrivate &other)
00190 {
00191 for (player_list::const_iterator p = other.m_player_procs.begin();
00192 p != other.m_player_procs.end(); ++p)
00193 {
00194 m_player_procs.push_back((*p)->Clone());
00195 }
00196 }
00197
00198 ~VideoPlayerCommandPrivate()
00199 {
00200 ClearPlayerList();
00201 }
00202
00203 void AltPlayerFor(const VideoMetadata *item)
00204 {
00205 if (item)
00206 {
00207 QString play_command =
00208 gCoreContext->GetSetting("mythvideo.VideoAlternatePlayer");
00209 QString filename;
00210
00211 if (item->IsHostSet())
00212 filename = generate_file_url("Videos", item->GetHost(),
00213 item->GetFilename());
00214 else
00215 filename = item->GetFilename();
00216
00217 if (play_command.length())
00218 {
00219 AddPlayer(play_command, filename, item->GetPlot(),
00220 item->GetTitle(), item->GetSubtitle(),
00221 item->GetDirector(), item->GetSeason(),
00222 item->GetEpisode(), item->GetInetRef(),
00223 item->GetLength(), QString::number(item->GetYear()),
00224 QString::number(item->GetID()));
00225 }
00226 else
00227 {
00228 PlayerFor(filename, item);
00229 }
00230 }
00231 }
00232
00233 void PlayerFor(const VideoMetadata *item)
00234 {
00235 if (item)
00236 {
00237 QString play_command = item->GetPlayCommand();
00238 QString filename;
00239
00240 if (item->IsHostSet())
00241 filename = generate_file_url("Videos", item->GetHost(),
00242 item->GetFilename());
00243 else
00244 filename = item->GetFilename();
00245
00246 if (play_command.length())
00247 {
00248 AddPlayer(play_command, filename, item->GetPlot(),
00249 item->GetTitle(), item->GetSubtitle(),
00250 item->GetDirector(), item->GetSeason(),
00251 item->GetEpisode(), item->GetInetRef(),
00252 item->GetLength(), QString::number(item->GetYear()),
00253 QString::number(item->GetID()));
00254 }
00255 else
00256 {
00257 PlayerFor(filename, item);
00258 }
00259 }
00260 }
00261
00262 void PlayerFor(const QString &filename, const VideoMetadata *extraData = 0)
00263 {
00264 QString extension = filename.section(".", -1, -1);
00265 QDir dir_test(QString("%1/VIDEO_TS").arg(filename));
00266 if (dir_test.exists())
00267 extension = "VIDEO_TS";
00268 QDir bd_dir_test(QString("%1/BDMV").arg(filename));
00269 if (bd_dir_test.exists())
00270 extension = "BDMV";
00271
00272 QString play_command = gCoreContext->GetSetting("VideoDefaultPlayer");
00273
00274 const FileAssociations::association_list fa_list =
00275 FileAssociations::getFileAssociation().getList();
00276 for (FileAssociations::association_list::const_iterator p =
00277 fa_list.begin(); p != fa_list.end(); ++p)
00278 {
00279 if (p->extension.toLower() == extension.toLower() &&
00280 !p->use_default)
00281 {
00282 play_command = p->playcommand;
00283 break;
00284 }
00285 }
00286
00287 if (play_command.trimmed().isEmpty())
00288 play_command = "Internal";
00289
00290 QString plot;
00291 QString title = VideoMetadata::FilenameToMeta(filename, 1);
00292 QString subtitle = VideoMetadata::FilenameToMeta(filename, 4);
00293 QString director;
00294 int season = 0;
00295 int episode = 0;
00296 QString inetref;
00297 int length = 0;
00298 QString year = QString::number(VIDEO_YEAR_DEFAULT);
00299 QString id;
00300
00301 if (extraData)
00302 {
00303 plot = extraData->GetPlot();
00304 title = extraData->GetTitle();
00305 subtitle = extraData->GetSubtitle();
00306 director = extraData->GetDirector();
00307 season = extraData->GetSeason();
00308 episode = extraData->GetEpisode();
00309 inetref = extraData->GetInetRef();
00310 length = extraData->GetLength();
00311 year = QString::number(extraData->GetYear());
00312 id = QString::number(extraData->GetID());
00313 }
00314
00315 AddPlayer(play_command, filename, plot, title, subtitle, director,
00316 season, episode, inetref, length, year, id);
00317 }
00318
00319 void ClearPlayerList()
00320 {
00321 for (player_list::iterator p = m_player_procs.begin();
00322 p != m_player_procs.end(); ++p)
00323 {
00324 delete *p;
00325 }
00326 m_player_procs.clear();
00327 }
00328
00329 void Play() const
00330 {
00331 for (player_list::const_iterator p = m_player_procs.begin();
00332 p != m_player_procs.end(); ++p)
00333 {
00334 if ((*p)->Play()) break;
00335 }
00336 }
00337
00338 QString GetCommandDisplayName() const
00339 {
00340 if (!m_player_procs.empty())
00341 return m_player_procs.front()->GetCommandDisplayName();
00342 return QString();
00343 }
00344
00345 private:
00346 void AddPlayer(const QString &player, const QString &filename,
00347 const QString &plot, const QString &title, const QString &subtitle,
00348 const QString &director, int season, int episode, const QString &inetref,
00349 int length, const QString &year, const QString &id)
00350 {
00351 m_player_procs.push_back(VideoPlayHandleMedia::Create(player, filename,
00352 plot, title, subtitle, director, season, episode, inetref,
00353 length, year, id));
00354 m_player_procs.push_back(VideoPlayMythSystem::Create(player, filename));
00355 }
00356
00357 private:
00358 typedef std::vector<VideoPlayProc *> player_list;
00359 player_list m_player_procs;
00360 };
00361
00363
00364 VideoPlayerCommand VideoPlayerCommand::AltPlayerFor(const VideoMetadata *item)
00365 {
00366 VideoPlayerCommand ret;
00367 ret.m_d->AltPlayerFor(item);
00368 return ret;
00369 }
00370
00371 VideoPlayerCommand VideoPlayerCommand::PlayerFor(const VideoMetadata *item)
00372 {
00373 VideoPlayerCommand ret;
00374 ret.m_d->PlayerFor(item);
00375 return ret;
00376 }
00377
00378 VideoPlayerCommand VideoPlayerCommand::PlayerFor(const QString &filename)
00379 {
00380 VideoPlayerCommand ret;
00381 ret.m_d->PlayerFor(filename);
00382 return ret;
00383 }
00384
00385 VideoPlayerCommand::VideoPlayerCommand() : m_d(0)
00386 {
00387 m_d = new VideoPlayerCommandPrivate;
00388 }
00389
00390 VideoPlayerCommand::~VideoPlayerCommand()
00391 {
00392 delete m_d;
00393 m_d = 0;
00394 }
00395
00396 VideoPlayerCommand::VideoPlayerCommand(const VideoPlayerCommand &other)
00397 {
00398 m_d = new VideoPlayerCommandPrivate(*other.m_d);
00399 }
00400
00401 VideoPlayerCommand &VideoPlayerCommand::operator=(const VideoPlayerCommand &rhs)
00402 {
00403 if (this != &rhs)
00404 {
00405 delete m_d;
00406 m_d = new VideoPlayerCommandPrivate(*rhs.m_d);
00407 }
00408 return *this;
00409 }
00410
00411 void VideoPlayerCommand::Play() const
00412 {
00413 LCD *lcd = LCD::Get();
00414
00415 if (lcd) {
00416 lcd->setFunctionLEDs(FUNC_TV, false);
00417 lcd->setFunctionLEDs(FUNC_MOVIE, true);
00418 }
00419 m_d->Play();
00420 GetMythMainWindow()->raise();
00421 GetMythMainWindow()->activateWindow();
00422 if (GetMythMainWindow()->currentWidget())
00423 GetMythMainWindow()->currentWidget()->setFocus();
00424 if (lcd)
00425 lcd->setFunctionLEDs(FUNC_MOVIE, false);
00426 }
00427
00428 QString VideoPlayerCommand::GetCommandDisplayName() const
00429 {
00430 return m_d->GetCommandDisplayName();
00431 }