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