diff --git a/LenaPi/controllers/MusicPlayer.cpp b/LenaPi/controllers/MusicPlayer.cpp index dbc4d5c..abbd9df 100644 --- a/LenaPi/controllers/MusicPlayer.cpp +++ b/LenaPi/controllers/MusicPlayer.cpp @@ -1,7 +1,7 @@ #include "MusicPlayer.h" #include #include - +#include MusicPlayer::MusicPlayer(QObject *parent) : QMediaPlayer(parent) @@ -98,7 +98,7 @@ bool MusicPlayer::hasPrevious() const /* player inits with currentIndex -1 and hence previousIndex = last index * until started. Yet, previousButton should initially be disabled. */ - return previousIndex >= 0 && previousIndex >= playlist()->currentIndex(); + return previousIndex >= 0 && previousIndex < playlist()->currentIndex(); } double MusicPlayer::getProgress() const @@ -111,17 +111,17 @@ double MusicPlayer::getProgress() const QString MusicPlayer::getMediaTitle() const { - return mMediaTitle; + return metaData("Title").toString(); } -QString MusicPlayer::getMediaLength() +QString MusicPlayer::getMediaDuration() const { - return timeToString(duration()); + return millisecondsToString(duration()); } -QString MusicPlayer::getTime() +QString MusicPlayer::getPosition() const { - return timeToString(position()); + return millisecondsToString(position()); } void MusicPlayer::clearPlaylist() @@ -144,7 +144,7 @@ void MusicPlayer::readMedia(const QString& path) } // add audio files to playlist - dir.setNameFilters({"*.mp3", "*.flac"}); + dir.setNameFilters(SettingsHandler::getAudioFileNameFilters()); auto files = dir.entryInfoList(QDir::Files); for(auto file:files){ auto fileName = file.absoluteFilePath(); @@ -153,11 +153,13 @@ void MusicPlayer::readMedia(const QString& path) } } -QString MusicPlayer::timeToString(int time) +QString MusicPlayer::millisecondsToString(int timeInMilliseconds) const { - int sec = time/1000; - int min = sec/60; - sec = sec-min*60; - QString secStr = (sec < 10) ? "0"+QString::number(sec) : QString::number(sec); - return QString::number(min) + ":" + secStr; + int seconds = timeInMilliseconds/1000; // ms to secons + int minutes = seconds/60; //seconds to minutes + seconds %= 60; // seconds remaining after subtracting minutes + // format according to [M]M:ss + // at leading zero to seconds if necessary + QString secStr = (seconds < 10) ? "0"+QString::number(seconds) : QString::number(seconds); + return QString::number(minutes) + ":" + secStr; } diff --git a/LenaPi/controllers/MusicPlayer.h b/LenaPi/controllers/MusicPlayer.h index 9e68c03..2b5e8c3 100644 --- a/LenaPi/controllers/MusicPlayer.h +++ b/LenaPi/controllers/MusicPlayer.h @@ -6,7 +6,10 @@ #include /** - * @brief MusicPlayer providing interface to QML and Navigation + * @brief MusicPlayer providing interface to QML and Navigation. + * + * Adds media from directory referenced by the current navigation item to + * playlist and provides interface to QML MusicPlayer. */ class MusicPlayer : public QMediaPlayer { @@ -17,9 +20,9 @@ class MusicPlayer : public QMediaPlayer Q_PROPERTY(bool pHasPrevious READ hasPrevious NOTIFY hasPreviousChanged) Q_PROPERTY(bool pIsPlaying READ isPlaying NOTIFY isPlayingChanged) Q_PROPERTY(double pProgress READ getProgress NOTIFY progressChanged) - Q_PROPERTY(QString pMediaLength READ getMediaLength NOTIFY mediaLengthChanged) - Q_PROPERTY(QString pTime READ getTime NOTIFY progressChanged) - Q_PROPERTY(QString pMediaTitle READ getMediaTitle NOTIFY mediaTitleChanged) + Q_PROPERTY(QString pMediaLength READ getMediaDuration NOTIFY mediaLengthChanged) + Q_PROPERTY(QString pTime READ getPosition NOTIFY progressChanged) + Q_PROPERTY(QString pMediaTitle READ getMediaTitle NOTIFY metaDataChanged) signals: void navigateTo(NavigationItemModel *item); @@ -29,12 +32,16 @@ signals: void isPlayingChanged(); void progressChanged(); void mediaLengthChanged(); - void mediaTitleChanged(); public: MusicPlayer(QObject *parent = Q_NULLPTR); ~MusicPlayer() =default; + /** + * @brief Init playlist with media from directory referenced by item. + * @param item Navigation item representing a leaf + * @see void readMedia(const QString& path) + */ void init(NavigationItemModel* item); /** @@ -42,23 +49,71 @@ public: * @return Path to media cover image. */ inline const QString& getCoverImageSource() const {return mCurrentItem->getImageSource();} - - + /** + * @brief Indicates whether the media player is currently playing a track. + * @return true if media player is playing a track. + */ bool isPlaying() const; + /** + * @brief Indicates whether there is a next item in the playlist. + * @return True if there is a next item in the playlist + * Does not wrap. + */ bool hasNext() const; + /** + * @brief Indicates whether there is a previous item in the playlist. + * @return True if there is a previous item in the playlist + * Does not wrap. + */ bool hasPrevious() const; + /** + * @brief Get media progress as value in between 0 and 1 + * @return Media progress + * 0 corresponds to the beginning and 1 to the end of the current track. + */ double getProgress() const; + /** + * @brief Get current media title extracted from media meta data (id3 tags) + * @return Current media title + */ QString getMediaTitle() const; - QString getMediaLength(); - QString getTime(); + /** + * @brief Get duration of the current track + * @return Duration of the current track formatted as string + * @see QMediaPlayer::duration() + * @see millisecondsToString(int timeInMilliseconds) const + */ + QString getMediaDuration() const; + /** + * @brief Get current position within the track + * @return Postion within the track formatted as string + * @see QMediaPlayer::position() + * @see millisecondsToString(int timeInMilliseconds) const + */ + QString getPosition() const; public slots: + /** + * @brief Navigate back to navgation list + */ void navigateBack(); + /** + * @brief Play or pause music depending on whether it is currently playing + */ void playPause(); + /** + * @brief Stop music and reset track to first track in playlist + */ void stopMusic(); + /** + * @brief Play next track in current playlist if available + */ void playNext(); + /** + * @brief Replay previoustrack in current playlist if available + */ void playPrevious(); private: @@ -66,20 +121,22 @@ private: * @brief Resets playlist to first track if playlist exists and is non-empty */ void resetPlaylistToFirstTrack(); + /** + * @brief Clear the current playlist + */ void clearPlaylist(); + /** + * @brief Add all media from path to playlist + * @param path Path to media + */ void readMedia(const QString& path); /** - * @brief Transforms time in milliseconds into a string + * @brief Format time in milliseconds acoording to [M]m:ss * @param time Time in ms - * @return - * @todo use QDateTime + * @return formateted string */ - QString timeToString(int time); + QString millisecondsToString(int timeInMilliseconds) const; - int mCurrentMediaItemLength = 0; - int mCurrentTime = 0; - double mCurrentMediaItemProgress = 0; - QString mMediaTitle = QString(""); NavigationItemModel* mCurrentItem = nullptr; }; diff --git a/LenaPi/controllers/NavigationController.cpp b/LenaPi/controllers/NavigationController.cpp index 0dc4a4f..ff2ad3c 100644 --- a/LenaPi/controllers/NavigationController.cpp +++ b/LenaPi/controllers/NavigationController.cpp @@ -1,4 +1,5 @@ #include "NavigationController.h" +#include #include #include @@ -75,18 +76,18 @@ bool NavigationController::checkContent(const QString &path) { bool valid = false; auto dir =QDir(path); + // directory must either contain subdirectories or media files auto subDirsNames = dir.entryList(QDir::AllDirs); if(subDirsNames.length() > 0) { valid = true; } else { + dir.setNameFilters(SettingsHandler::getAudioFileNameFilters()); auto fileNames = dir.entryList(QDir::Files); int numAudio = 0; for(auto file:fileNames){ - if(file.endsWith(".flac") || file.endsWith(".mp3")){ numAudio++; - } } - if(numAudio > 0) valid = true; + valid = numAudio > 0; } return valid; } diff --git a/LenaPi/controllers/SettingsHandler.h b/LenaPi/controllers/SettingsHandler.h index 83b9868..2b7cb8d 100644 --- a/LenaPi/controllers/SettingsHandler.h +++ b/LenaPi/controllers/SettingsHandler.h @@ -17,6 +17,12 @@ public: static SettingsHandler* createSettingsHandlerAndFillWithDefaultsIfMissing(QSettings* settings); + /** + * @brief Provides a name filter for QDir that can be used to filter all audio files with valid formats. + * @return name filter for QDir + */ + static QStringList getAudioFileNameFilters() {return {"*.mp3", "*.flac"};} + inline void setSettings(QSettings* settings) { mSettings = settings;} inline QSettings* getSettings() const { return mSettings; } void fillWithDefaultIfMissing();