1 /* This file is part of Clementine.
2    Copyright 2010, David Sansome <me@davidsansome.com>
3 
4    Clementine is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    Clementine is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #ifndef DEVICEMANAGER_H
19 #define DEVICEMANAGER_H
20 
21 #include "devicedatabasebackend.h"
22 
23 #include <memory>
24 
25 #include <QAbstractItemModel>
26 #include <QIcon>
27 #include <QThreadPool>
28 
29 #include "core/simpletreemodel.h"
30 #include "deviceinfo.h"
31 #include "library/librarymodel.h"
32 
33 class Application;
34 class ConnectedDevice;
35 class DeviceLister;
36 class DeviceStateFilterModel;
37 
38 class DeviceManager : public SimpleTreeModel<DeviceInfo> {
39   Q_OBJECT
40 
41  public:
42   DeviceManager(Application* app, QObject* parent = nullptr);
43   ~DeviceManager();
44 
45   enum Role {
46     Role_State = LibraryModel::LastRole,
47     Role_UniqueId,
48     Role_FriendlyName,
49     Role_Capacity,
50     Role_FreeSpace,
51     Role_IconName,
52     Role_UpdatingPercentage,
53     Role_MountPath,
54     Role_TranscodeMode,
55     Role_TranscodeFormat,
56     Role_SongCount,
57     LastRole,
58   };
59 
60   enum State {
61     State_Remembered,
62     State_NotMounted,
63     State_NotConnected,
64     State_Connected,
65   };
66 
67   static const int kDeviceIconSize;
68   static const int kDeviceIconOverlaySize;
69 
connected_devices_model()70   DeviceStateFilterModel* connected_devices_model() const {
71     return connected_devices_model_;
72   }
73 
74   // Get info about devices
75   int GetDatabaseId(const QModelIndex& idx) const;
76   DeviceLister* GetLister(QModelIndex idx) const;
77   std::shared_ptr<ConnectedDevice> GetConnectedDevice(QModelIndex idx) const;
78   std::shared_ptr<ConnectedDevice> GetConnectedDevice(DeviceInfo* info) const;
79 
80   DeviceInfo* FindDeviceById(const QString& id) const;
81   DeviceInfo* FindDeviceByUrl(const QList<QUrl>& url) const;
82   DeviceInfo* FindEquivalentDevice(DeviceInfo* info) const;
83 
84   // Actions on devices
85   std::shared_ptr<ConnectedDevice> Connect(DeviceInfo* info);
86   std::shared_ptr<ConnectedDevice> Connect(QModelIndex idx);
87   void Disconnect(QModelIndex idx);
88   void Forget(QModelIndex idx);
89   void UnmountAsync(QModelIndex idx);
90 
91   void SetDeviceOptions(QModelIndex idx, const QString& friendly_name,
92                         const QString& icon_name,
93                         MusicStorage::TranscodeMode mode,
94                         Song::FileType format);
95 
96   // QAbstractItemModel
97   QVariant data(const QModelIndex& idx, int role = Qt::DisplayRole) const;
98 
99  public slots:
100   void Unmount(QModelIndex idx);
101 
102  signals:
103   void DeviceConnected(QModelIndex idx);
104   void DeviceDisconnected(QModelIndex idx);
105   void DeviceCreatedFromDb(DeviceInfo* info);
106 
107  private slots:
108   void PhysicalDeviceAdded(const QString& id);
109   void PhysicalDeviceRemoved(const QString& id);
110   void PhysicalDeviceChanged(const QString& id);
111   void DeviceTaskStarted(int id);
112   void TasksChanged();
113   void DeviceSongCountUpdated(int count);
114   void LoadAllDevices();
115   void DeviceConnectFinished(const QString& id, bool success);
116   void AddDeviceFromDb(DeviceInfo* info);
117 
118  protected:
LazyPopulate(DeviceInfo * item)119   void LazyPopulate(DeviceInfo* item) { LazyPopulate(item, true); }
120   void LazyPopulate(DeviceInfo* item, bool signal);
121 
122  private:
123 
124   void AddLister(DeviceLister* lister);
125   template <typename T>
126   void AddDeviceClass();
127 
128   DeviceDatabaseBackend::Device InfoToDatabaseDevice(const DeviceInfo& info)
129       const;
130 
131  private:
132   Application* app_;
133   DeviceDatabaseBackend* backend_;
134 
135   DeviceStateFilterModel* connected_devices_model_;
136 
137   QIcon not_connected_overlay_;
138 
139   QList<DeviceLister*> listers_;
140   QList<DeviceInfo*> devices_;
141 
142   QMultiMap<QString, QMetaObject> device_classes_;
143 
144   // Map of task ID to device index
145   QMap<int, QPersistentModelIndex> active_tasks_;
146 
147   QThreadPool thread_pool_;
148 };
149 
150 template <typename T>
AddDeviceClass()151 void DeviceManager::AddDeviceClass() {
152   QStringList schemes = T::url_schemes();
153   QMetaObject obj = T::staticMetaObject;
154 
155   for (const QString& scheme : schemes) {
156     device_classes_.insert(scheme, obj);
157   }
158 }
159 
160 #endif  // DEVICEMANAGER_H
161