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 DEVICE_H
25 #define DEVICE_H
26 
27 #include "models/musiclibraryitemroot.h"
28 #include "mpd-interface/song.h"
29 #include "gui/covers.h"
30 #include "config.h"
31 #ifdef ENABLE_DEVICES_SUPPORT
32 #include "deviceoptions.h"
33 #include "solid-lite/device.h"
34 #endif
35 
36 class QWidget;
37 class QImage;
38 class QTemporaryFile;
39 class MusicLibraryModel;
40 
41 // MOC requires the QObject class to be first. But due to models storing void pointers, and
42 // needing to cast these - the model prefers MusicLibraryItemRoot to be first!
43 #ifdef Q_MOC_RUN
44 class Device : public QObject, public MusicLibraryItemRoot
45 #else
46 class Device : public MusicLibraryItemRoot, public QObject
47 #endif
48 {
49     Q_OBJECT
50 
51 public:
52     #ifdef ENABLE_DEVICES_SUPPORT
53     static const QLatin1String constNoCover;
54     static const QLatin1String constEmbedCover;
55     static Device * create(MusicLibraryModel *m, const QString &id);
56     static bool fixVariousArtists(const QString &file, Song &song, bool applyFix);
57     static void embedCover(const QString &file, Song &song, unsigned int coverMaxSize);
58     static QTemporaryFile * copySongToTemp(Song &song);
59     static bool isLossless(const QString &file);
60     #endif
61     static void moveDir(const QString &from, const QString &to, const QString &base, const QString &coverFile);
62     static void cleanDir(const QString &dir, const QString &base, const QString &coverFile, int level=0);
63 
64     enum Status {
65         Ok,
66         FileExists,
67         SongExists,
68         DirCreationFaild,
69         SourceFileDoesNotExist,
70         SongDoesNotExist,
71         Failed,
72         NotConnected,
73         CodecNotAvailable,
74         TranscodeFailed,
75         FailedToCreateTempFile,
76         ReadFailed,
77         WriteFailed,
78         NoSpace,
79         FailedToUpdateTags,
80         Cancelled,
81         FailedToLockDevice,
82 
83         // These are for online services...
84         DownloadFailed
85     };
86 
87     enum DevType {
88         Ums,
89         Mtp,
90         RemoteFs,
91         AudioCd
92     };
93 
94     #ifndef ENABLE_DEVICES_SUPPORT
Device(MusicLibraryModel * m,const QString & name,const QString & id)95     Device(MusicLibraryModel *m, const QString &name, const QString &id)
96         : MusicLibraryItemRoot(name)
97         , update(0)
98         , needToFixVa(false)
99         , jobAbortRequested(false)
100         , transcoding(false) {
101         Q_UNUSED(m)
102         Q_UNUSED(id)
103     }
104     #else
105     Device(MusicLibraryModel *m, Solid::Device &dev, bool albumArtistSupport=true, bool flat=false);
106     Device(MusicLibraryModel *m, const QString &name, const QString &id);
107     #endif
108 
~Device()109     ~Device() override { }
110 
icon()111     QIcon icon() const override { return icn; }
112     Song fixPath(const Song &orig, bool fullPath) const override;
coverFile()113     virtual QString coverFile() const { return QString(); }
114     virtual bool isConnected() const=0;
115     virtual void rescan(bool full=true)=0;
116     virtual void stop()=0;
connectionStateChanged()117     virtual void connectionStateChanged() { }
toggle()118     virtual void toggle() { }
119     virtual bool isRefreshing() const=0;
isIdle()120     bool isIdle() const { return isConnected() && !isRefreshing(); }
configure(QWidget *)121     virtual void configure(QWidget *) { }
122     virtual QString path() const =0;
123     virtual void addSong(const Song &s, bool overwrite, bool copyCover)=0;
124     virtual void copySongTo(const Song &s, const QString &musicPath, bool overwrite, bool copyCover)=0;
125     virtual void removeSong(const Song &s)=0;
126     virtual void cleanDirs(const QSet<QString> &dirs)=0;
requestCover(const Song &)127     virtual Covers::Image requestCover(const Song &) { return Covers::Image(); }
128     virtual double usedCapacity()=0;
129     virtual QString capacityString()=0;
130     virtual qint64 freeSpace()=0;
131     virtual DevType devType() const=0;
removeCache()132     virtual void removeCache() { }
isDevice()133     bool isDevice() const override { return true; }
134 
135     #ifdef ENABLE_DEVICES_SUPPORT
136     virtual void saveCache();
id()137     const QString & id() const override { return deviceId; }
138     void applyUpdate();
haveUpdate()139     bool haveUpdate() const { return nullptr!=update; }
newRows()140     int newRows() const { return update ? update->childCount() : 0; }
options()141     const DeviceOptions & options() const { return opts; }
setOptions(const DeviceOptions & o)142     void setOptions(const DeviceOptions &o) { opts=o; saveOptions(); }
143     virtual void saveOptions()=0;
statusMessage()144     const QString & statusMessage() const { return statusMsg; }
isConfigured()145     bool isConfigured() { return configured; }
abortJob()146     virtual void abortJob() { jobAbortRequested=true; }
abortRequested()147     bool abortRequested() const { return jobAbortRequested; }
canPlaySongs()148     bool canPlaySongs() const override { return false; }
supportsDisconnect()149     virtual bool supportsDisconnect() const { return false; }
isStdFs()150     virtual bool isStdFs() const { return false; }
subText()151     virtual QString subText() { return QString(); }
152     QModelIndex index() const override;
153     void updateStatus();
154 
155 public Q_SLOTS:
156     void setStatusMessage(const QString &message);
157     void songCount(int c);
158     void updatePercentage(int pc);
159     #endif
160 
161 Q_SIGNALS:
162     void connected(const QString &id);
163     void disconnected(const QString &id);
164     void updating(const QString &id, bool s);
165     void actionStatus(int status, bool copiedCover=false);
166     void progress(int pc);
167     void error(const QString &);
168     void cover(const Song &song, const QImage &img);
169     void cacheSaved();
170     void configurationChanged();
171     void play(const QList<Song> &songs);
172     void updatedDetails(const QList<Song> &songs);
173     void renamed();
174 
175 protected:
176     #ifdef ENABLE_DEVICES_SUPPORT
177     DeviceOptions opts;
178     bool configured;
179     Solid::Device solidDev;
180     QString deviceId;
181     Song currentSong;
182     #endif
183     MusicLibraryItemRoot *update;
184     QString currentDestFile;
185     QString statusMsg;
186     bool needToFixVa;
187     bool jobAbortRequested;
188     bool transcoding;
189     QIcon icn;
190 };
191 
192 #endif
193