1 /* 2 * Strawberry Music Player 3 * This file was part of Clementine. 4 * Copyright 2010, David Sansome <me@davidsansome.com> 5 * Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net> 6 * 7 * Strawberry is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * Strawberry is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with Strawberry. If not, see <http://www.gnu.org/licenses/>. 19 * 20 */ 21 22 #ifndef SONGLOADER_H 23 #define SONGLOADER_H 24 25 #include "config.h" 26 27 #include <memory> 28 #include <functional> 29 #include <glib.h> 30 31 #ifdef HAVE_GSTREAMER 32 # include <gst/gst.h> 33 #endif 34 35 #include <QtGlobal> 36 #include <QObject> 37 #include <QThreadPool> 38 #include <QByteArray> 39 #include <QSet> 40 #include <QString> 41 #include <QStringList> 42 #include <QUrl> 43 44 #include "song.h" 45 46 class QTimer; 47 class Player; 48 class CollectionBackendInterface; 49 class PlaylistParser; 50 class ParserBase; 51 class CueParser; 52 53 #if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER) 54 class CddaSongLoader; 55 #endif 56 57 class SongLoader : public QObject { 58 Q_OBJECT 59 public: 60 explicit SongLoader(CollectionBackendInterface *collection, const Player *player, QObject *parent = nullptr); 61 ~SongLoader() override; 62 63 enum Result { 64 Success, 65 Error, 66 BlockingLoadRequired, 67 }; 68 69 static const int kDefaultTimeout; 70 url()71 const QUrl &url() const { return url_; } songs()72 const SongList &songs() const { return songs_; } 73 timeout()74 int timeout() const { return timeout_; } set_timeout(int msec)75 void set_timeout(int msec) { timeout_ = msec; } 76 77 // If Success is returned the songs are fully loaded. If BlockingLoadRequired is returned LoadFilenamesBlocking() needs to be called next. 78 Result Load(const QUrl &url); 79 // Loads the files with only filenames. When finished, songs() contains a complete list of all Song objects, but without metadata. 80 // This method is blocking, do not call it from the UI thread. 81 SongLoader::Result LoadFilenamesBlocking(); 82 // Completely load songs previously loaded with LoadFilenamesBlocking(). 83 // When finished, the Song objects in songs() contain metadata now. This method is blocking, do not call it from the UI thread. 84 void LoadMetadataBlocking(); 85 Result LoadAudioCD(); 86 errors()87 QStringList errors() { return errors_; } 88 89 signals: 90 void AudioCDTracksLoadFinished(); 91 void LoadAudioCDFinished(bool success); 92 void LoadRemoteFinished(); 93 94 private slots: 95 void ScheduleTimeout(); 96 void Timeout(); 97 void StopTypefind(); 98 #if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER) 99 void AudioCDTracksLoadFinishedSlot(const SongList &songs, const QString &error); 100 void AudioCDTracksTagsLoaded(const SongList &songs); 101 #endif // HAVE_AUDIOCD && HAVE_GSTREAMER 102 103 private: 104 enum State { WaitingForType, WaitingForMagic, WaitingForData, Finished }; 105 106 Result LoadLocal(const QString &filename); 107 SongLoader::Result LoadLocalAsync(const QString &filename); 108 void EffectiveSongLoad(Song *song); 109 Result LoadLocalPartial(const QString &filename); 110 void LoadLocalDirectory(const QString &filename); 111 void LoadPlaylist(ParserBase *parser, const QString &filename); 112 113 void AddAsRawStream(); 114 115 #ifdef HAVE_GSTREAMER 116 Result LoadRemote(); 117 118 // GStreamer callbacks 119 static void TypeFound(GstElement *typefind, uint probability, GstCaps *caps, void *self); 120 static GstPadProbeReturn DataReady(GstPad*, GstPadProbeInfo *info, gpointer self); 121 static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage*, gpointer); 122 static gboolean BusCallback(GstBus*, GstMessage*, gpointer); 123 124 void StopTypefindAsync(bool success); 125 void ErrorMessageReceived(GstMessage *msg); 126 void EndOfStreamReached(); 127 void MagicReady(); 128 bool IsPipelinePlaying(); 129 #endif 130 131 void ScheduleTimeoutAsync(); 132 133 private: 134 static QSet<QString> sRawUriSchemes; 135 136 QUrl url_; 137 SongList songs_; 138 139 QTimer *timeout_timer_; 140 PlaylistParser *playlist_parser_; 141 CueParser *cue_parser_; 142 143 // For async loads 144 std::function<Result()> preload_func_; 145 int timeout_; 146 State state_; 147 bool success_; 148 ParserBase *parser_; 149 QString mime_type_; 150 QByteArray buffer_; 151 CollectionBackendInterface *collection_; 152 const Player *player_; 153 154 #ifdef HAVE_GSTREAMER 155 std::shared_ptr<GstElement> pipeline_; 156 #endif 157 158 QThreadPool thread_pool_; 159 160 QStringList errors_; 161 162 }; 163 164 #endif // SONGLOADER_H 165