1 /*
2  * Cantata
3  *
4  * Copyright (c) 2011-2020 Craig Drummond <craig.p.drummond@gmail.com>
5  *
6  * ----
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; see the file COPYING.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #ifndef FSDEVICE_H
25 #define FSDEVICE_H
26 
27 #include "device.h"
28 #include "mpd-interface/song.h"
29 #include "support/utils.h"
30 #include "freespaceinfo.h"
31 #include "models/musiclibraryitemroot.h"
32 #include "http/httpserver.h"
33 #include <QStringList>
34 #include <QElapsedTimer>
35 
36 class Thread;
37 
38 struct FileOnlySong : public Song
39 {
FileOnlySongFileOnlySong40     FileOnlySong(const Song &o) : Song(o) { }
41     bool operator==(const FileOnlySong &o) const { return file==o.file; }
42     bool operator<(const FileOnlySong &o) const { return file.compare(o.file)<0; }
43 };
44 
qHash(const FileOnlySong & key)45 inline uint qHash(const FileOnlySong &key)
46 {
47     return qHash(key.file);
48 }
49 
50 class MusicScanner : public QObject, public MusicLibraryProgressMonitor
51 {
52     Q_OBJECT
53 
54 public:
55     MusicScanner(const QString &id);
56     ~MusicScanner() override;
57 
58     void stop();
wasStopped()59     bool wasStopped() const override { return stopRequested; }
60     void readProgress(double pc) override;
61     void writeProgress(double pc) override;
62 
63 public Q_SLOTS:
64     void scan(const QString &folder, const QString &cacheFile, bool readCache, const QSet<FileOnlySong> &existingSongs);
65     void saveCache(const QString &cache, MusicLibraryItemRoot *lib);
66 
67 Q_SIGNALS:
68     void songCount(int c);
69     void libraryUpdated(MusicLibraryItemRoot *);
70     void cacheSaved();
71     void readingCache(int pc);
72     void savingCache(int pc);
73 
74 private:
75     void scanFolder(MusicLibraryItemRoot *library, const QString &topLevel, const QString &f, QSet<FileOnlySong> &existing, int level);
76 
77 private:
78     Thread *thread;
79     bool stopRequested;
80     int count;
81     QElapsedTimer timer;
82 };
83 
84 class FsDevice : public Device
85 {
86     Q_OBJECT
87 
88 public:
89     enum State {
90         Idle,
91         Updating,
92         SavingCache
93     };
94 
95     static const QLatin1String constCantataCacheFile;
96     static const QLatin1String constCantataSettingsFile;
97     static const QLatin1String constMusicFilenameSchemeKey;
98     static const QLatin1String constVfatSafeKey;
99     static const QLatin1String constAsciiOnlyKey;
100     static const QLatin1String constIgnoreTheKey;
101     static const QLatin1String constReplaceSpacesKey;
102     static const QLatin1String constCoverFileNameKey; // Cantata extension!
103     static const QLatin1String constCoverMaxSizeKey; // Cantata extension!
104     static const QLatin1String constVariousArtistsFixKey; // Cantata extension!
105     static const QLatin1String constTranscoderKey; // Cantata extension!
106     static const QLatin1String constUseCacheKey; // Cantata extension!
107     static const QLatin1String constDefCoverFileName;
108     static const QLatin1String constAutoScanKey; // Cantata extension!
109 
110     static bool readOpts(const QString &fileName, DeviceOptions &opts, bool readAll);
111     static void writeOpts(const QString &fileName, const DeviceOptions &opts, bool writeAll);
112 
113     FsDevice(MusicLibraryModel *m, Solid::Device &dev);
114     FsDevice(MusicLibraryModel *m, const QString &name, const QString &id);
115     ~FsDevice() override;
116 
117     void rescan(bool full=true) override;
118     void stop() override;
isRefreshing()119     bool isRefreshing() const override { return Idle!=state; }
path()120     QString path() const override { return audioFolder; }
coverFile()121     QString coverFile() const override { return opts.coverName; }
122     void addSong(const Song &s, bool overwrite, bool copyCover) override;
123     void copySongTo(const Song &s, const QString &musicPath, bool overwrite, bool copyCover) override;
124     void removeSong(const Song &s) override;
125     void cleanDirs(const QSet<QString> &dirs) override;
126     Covers::Image requestCover(const Song &s) override;
127     QString cacheFileName() const;
setAudioFolder()128     virtual void setAudioFolder() const { }
129     void saveCache() override;
130     void removeCache() override;
isStdFs()131     bool isStdFs() const override { return true; }
canPlaySongs()132     bool canPlaySongs() const override { return HttpServer::self()->isAlive(); }
133 
134 Q_SIGNALS:
135     // For talking to scanner...
136     void scan(const QString &folder, const QString &cacheFile, bool readCache, const QSet<FileOnlySong> &existingSongs);
137     void saveCache(const QString &cacheFile, MusicLibraryItemRoot *lib);
138 
139 protected:
140     void initScaner();
141     void startScanner(bool fullScan=true);
142     void stopScanner();
143     void clear() const;
144 
145 protected Q_SLOTS:
146     void savedCache();
147     void libraryUpdated(MusicLibraryItemRoot *lib);
148     void percent(int pc);
149     void addSongResult(int status);
150     void copySongToResult(int status);
151     void removeSongResult(int status);
152     void cleanDirsResult(int status);
153     void readingCache(int pc);
154     void savingCache(int pc);
155 
156 private:
157     void cacheStatus(const QString &msg, int prog);
158 
159 protected:
160     State state;
161     bool scanned;
162     int cacheProgress;
163     MusicScanner *scanner;
164     mutable QString audioFolder;
165     FreeSpaceInfo spaceInfo;
166 };
167 
168 #endif
169