diff --git a/src/MainWindow.h b/src/MainWindow.h index 6ee77742c..afc88a02b 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -144,6 +144,7 @@ class MainWindow : public QMainWindow // realtime signals void notifyTelemetryUpdate(const RealtimeData &rtData) { telemetryUpdate(rtData); } void notifyErgFileSelected(ErgFile *x) { ergFileSelected(x); } + void notifyMediaSelected( QString x) { mediaSelected(x); } void notifySetNow(long now) { setNow(now); } void notifyNewLap() { emit newLap(); } void notifyStart() { emit start(); } @@ -180,6 +181,7 @@ class MainWindow : public QMainWindow // realtime void telemetryUpdate(RealtimeData rtData); void ergFileSelected(ErgFile *); + void mediaSelected(QString); void setNow(long); void newLap(); void start(); diff --git a/src/TrainTool.cpp b/src/TrainTool.cpp index 8ddc2fcba..39e3c3d92 100644 --- a/src/TrainTool.cpp +++ b/src/TrainTool.cpp @@ -35,6 +35,10 @@ #include "ANTlocalController.h" #include "NullController.h" +#ifdef GC_HAVE_VLC +// Media selection helper +#include "VideoWindow.h" +#endif TrainTool::TrainTool(MainWindow *parent, const QDir &home) : GcWindow(parent), home(home), main(parent) { @@ -70,6 +74,19 @@ TrainTool::TrainTool(MainWindow *parent, const QDir &home) : GcWindow(parent), h serverTree->expandItem(allServers); #endif +#ifdef GC_HAVE_VLC + mediaTree = new QTreeWidget; + mediaTree->setFrameStyle(QFrame::NoFrame); + mediaTree->setColumnCount(1); + mediaTree->setSelectionMode(QAbstractItemView::SingleSelection); + mediaTree->header()->hide(); + mediaTree->setAlternatingRowColors (false); + mediaTree->setIndentation(5); + allMedia = new QTreeWidgetItem(mediaTree, HEAD_TYPE); + allMedia->setText(0, tr("Video / Media")); + mediaTree->expandItem(allMedia); +#endif + deviceTree = new QTreeWidget; deviceTree->setFrameStyle(QFrame::NoFrame); deviceTree->setSelectionMode(QAbstractItemView::MultiSelection); @@ -130,11 +147,17 @@ TrainTool::TrainTool(MainWindow *parent, const QDir &home) : GcWindow(parent), h trainSplitter->addWidget(deviceTree); //trainSplitter->addWidget(serverTree); trainSplitter->addWidget(workoutTree); +#ifdef GC_HAVE_VLC + trainSplitter->addWidget(mediaTree); +#endif // handle config changes //connect(serverTree,SIGNAL(itemSelectionChanged()), this, SLOT(serverTreeWidgetSelectionChanged())); connect(deviceTree,SIGNAL(itemSelectionChanged()), this, SLOT(deviceTreeWidgetSelectionChanged())); connect(workoutTree,SIGNAL(itemSelectionChanged()), this, SLOT(workoutTreeWidgetSelectionChanged())); +#ifdef GC_HAVE_VLC + connect(mediaTree,SIGNAL(itemSelectionChanged()), this, SLOT(mediaTreeWidgetSelectionChanged())); +#endif connect(main, SIGNAL(configChanged()), this, SLOT(configChanged())); // connect train tool buttons! @@ -243,6 +266,20 @@ TrainTool::configChanged() work->setText(0, name); } +#ifdef GC_HAVE_VLC + // MEDIA + QList media = allMedia->takeChildren(); + for (int i=0; isetText(0, video); + } +#endif + // Athlete FTP=285; // default to 285 if zones are not set int range = main->zones()->whichRange(QDate::currentDate()); @@ -396,6 +433,31 @@ TrainTool::listWorkoutFiles(const QDir &dir) const return dir.entryList(filters, QDir::Files, QDir::Name); } +void +TrainTool::mediaTreeWidgetSelectionChanged() +{ + assert(mediaTree->selectedItems().size() <= 1); + if (mediaTree->selectedItems().isEmpty()) + media = NULL; + else { + QTreeWidgetItem *which = mediaTree->selectedItems().first(); + if (which->type() != WORKOUT_TYPE) + media = NULL; + else + media = which; + } + + // which one is selected? + if (currentMedia() == NULL || currentMedia()->type() != WORKOUT_TYPE) { + main->notifyMediaSelected(""); + return; + } + + QVariant workoutDir = appsettings->value(this, GC_WORKOUTDIR); + QString fileName = workoutDir.toString() + "/" + currentMedia()->text(0); // filename + main->notifyMediaSelected(fileName); +} + /*-------------------------------------------------------------------------------- * Was realtime window, now local and manages controller and chart updates etc *------------------------------------------------------------------------------*/ diff --git a/src/TrainTool.h b/src/TrainTool.h index 4f66fd5e6..2c802e034 100644 --- a/src/TrainTool.h +++ b/src/TrainTool.h @@ -80,7 +80,9 @@ class TrainTool : public GcWindow GoldenClient *streamController; // send out to const QTreeWidgetItem *currentWorkout() { return workout; } + const QTreeWidgetItem *currentMedia() { return media; } const QTreeWidgetItem *workoutItems() { return allWorkouts; } + const QTreeWidgetItem *mediaItems() { return allMedia; } const QTreeWidgetItem *currentServer() { return server; } const QTreeWidgetItem *serverItems() { return allServers; } @@ -118,6 +120,7 @@ class TrainTool : public GcWindow void serverTreeWidgetSelectionChanged(); void deviceTreeWidgetSelectionChanged(); void workoutTreeWidgetSelectionChanged(); + void mediaTreeWidgetSelectionChanged(); void configChanged(); public slots: @@ -146,16 +149,20 @@ class TrainTool : public GcWindow const QDir home; MainWindow *main; + QSplitter *trainSplitter; QTreeWidget *workoutTree; QTreeWidget *deviceTree; - QTreeWidgetItem *allWorkouts; - QTreeWidgetItem *workout; - QSplitter *trainSplitter; QTreeWidget *serverTree; + QTreeWidget *mediaTree; + QTreeWidgetItem *allServers; + QTreeWidgetItem *allMedia; QTreeWidgetItem *allDevices; QTreeWidgetItem *server; + QTreeWidgetItem *allWorkouts; + QTreeWidgetItem *workout; + QTreeWidgetItem *media; // those buttons QFrame *buttonPanel; diff --git a/src/VideoWindow.cpp b/src/VideoWindow.cpp index e32470ce6..2c03688e2 100644 --- a/src/VideoWindow.cpp +++ b/src/VideoWindow.cpp @@ -47,19 +47,16 @@ GcWindow(parent), home(home), main(parent) /* Create a new item */ // XXX need to add controls - not everyone is going to want to play a video from // my desktop!!! - m = libvlc_media_new_path(inst, "/home/markl/Videos/fightclub.mp4"); + + m = NULL; //vlc_exceptions(&exceptions); /* Create a media player playing environement */ mp = libvlc_media_player_new (inst); //vlc_exceptions(&exceptions); - /* set the media to playback */ - libvlc_media_player_set_media (mp, m); //vlc_exceptions(&exceptions); - /* No need to keep the media now */ - libvlc_media_release (m); /* This is a non working code that show how to hooks into a window, * if we have a window around */ @@ -78,8 +75,12 @@ GcWindow(parent), home(home), main(parent) libvlc_media_player_set_nsobject (mp, view); #endif - /* play the media_player */ - libvlc_media_player_play (mp); + connect(main, SIGNAL(stop()), this, SLOT(stopPlayback())); + connect(main, SIGNAL(start()), this, SLOT(startPlayback())); + connect(main, SIGNAL(pause()), this, SLOT(pausePlayback())); + connect(main, SIGNAL(unpause()), this, SLOT(resumePlayback())); + connect(main, SIGNAL(mediaSelected(QString)), this, SLOT(mediaSelected(QString))); + } VideoWindow::~VideoWindow() @@ -89,8 +90,12 @@ VideoWindow::~VideoWindow() x11Container->discardClient(); #endif - // stop playback & wipe player - libvlc_media_player_stop (mp); + stopPlayback(); + + /* No need to keep the media now */ + if (m) libvlc_media_release (m); + + /* nor the player */ libvlc_media_player_release (mp); // unload vlc @@ -101,3 +106,102 @@ void VideoWindow::resizeEvent(QResizeEvent * ) { // do nothing .. for now } + +void VideoWindow::startPlayback() +{ + + if (!m) return; // ignore if no media selected + + // stop playback & wipe player + libvlc_media_player_stop (mp); + + /* set the media to playback */ + libvlc_media_player_set_media (mp, m); + + /* play the media_player */ + libvlc_media_player_play (mp); +} +void VideoWindow::stopPlayback() +{ + if (!m) return; // ignore if no media selected + + // stop playback & wipe player + libvlc_media_player_stop (mp); +} + +void VideoWindow::pausePlayback() +{ + if (!m) return; // ignore if no media selected + + // stop playback & wipe player + libvlc_media_player_pause (mp); +} + +void VideoWindow::resumePlayback() +{ + if (!m) return; // ignore if no media selected + + // stop playback & wipe player + libvlc_media_player_pause (mp); +} + +void VideoWindow::mediaSelected(QString filename) +{ + // stop any current playback + stopPlayback(); + + // release whatever is already loaded + if (m) libvlc_media_release(m); + m = NULL; + + if (filename != "" && QFile(filename).exists()) { + + /* open media */ + m = libvlc_media_new_path(inst, filename.toLatin1()); + + /* set the media to playback */ + if (m) libvlc_media_player_set_media (mp, m); + } +} + +MediaHelper::MediaHelper() +{ + // config paramaters to libvlc + const char * const vlc_args[] = { + "-I", "dummy", /* Don't use any interface */ + "--ignore-config", /* Don't use VLC's config */ + "--extraintf=logger", //log anything + "--verbose=-1" // -1 = no output at all + }; + + /* Load the VLC engine */ + inst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args); +} + +MediaHelper::~MediaHelper() +{ + // unload vlc + libvlc_release (inst); +} + +QStringList +MediaHelper::listMedia(QDir dir) +{ + QStringList returning; + + // whizz through every file in the directory + // and try and open it, if we succeed then huzzah + // otherwise ignore it + foreach(QString name, dir.entryList()) { + + libvlc_media_t *m = libvlc_media_new_path(inst, QString(dir.absolutePath() + "/" + name).toLatin1()); + + if (m) { + + libvlc_media_parse(m); + if (libvlc_media_get_duration(m) > 0) returning << name; + libvlc_media_release(m); + } + } + return returning; +} diff --git a/src/VideoWindow.h b/src/VideoWindow.h index 533ff0c1c..6b4549625 100644 --- a/src/VideoWindow.h +++ b/src/VideoWindow.h @@ -43,6 +43,22 @@ extern "C" { #include #endif +class MediaHelper +{ + public: + + MediaHelper(); + ~MediaHelper(); + + // get a list of supported media + // found in the supplied directory + QStringList listMedia(QDir directory); + + private: + + libvlc_instance_t * inst; +}; + class VideoWindow : public GcWindow { Q_OBJECT @@ -58,6 +74,12 @@ class VideoWindow : public GcWindow public slots: + void startPlayback(); + void stopPlayback(); + void pausePlayback(); + void resumePlayback(); + void mediaSelected(QString filename); + protected: void resizeEvent(QResizeEvent *);