2018-02-27 18:06:05 +01:00
/*
* Strawberry Music Player
* This file was part of Clementine .
* Copyright 2010 , David Sansome < me @ davidsansome . com >
2021-03-20 21:14:47 +01:00
* Copyright 2018 - 2021 , Jonas Kvinge < jonas @ jkvinge . net >
2018-02-27 18:06:05 +01:00
*
* Strawberry is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Strawberry is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Strawberry . If not , see < http : //www.gnu.org/licenses/>.
2018-08-09 18:39:44 +02:00
*
2018-02-27 18:06:05 +01:00
*/
# include "config.h"
# include <memory>
2018-05-01 00:41:33 +02:00
# include <functional>
2018-02-27 18:06:05 +01:00
2020-02-09 02:29:35 +01:00
# include <QtGlobal>
2018-02-27 18:06:05 +01:00
# include <QApplication>
2018-05-01 00:41:33 +02:00
# include <QObject>
# include <QMetaObject>
# include <QThread>
2020-10-14 22:35:54 +02:00
# include <QtConcurrent>
2018-12-29 02:57:22 +01:00
# include <QAbstractItemModel>
2018-02-27 18:06:05 +01:00
# include <QDir>
2018-05-01 00:41:33 +02:00
# include <QList>
# include <QVariant>
# include <QString>
# include <QStringList>
# include <QStringBuilder>
# include <QUrl>
# include <QPixmap>
2018-02-27 18:06:05 +01:00
# include <QPainter>
2018-05-01 00:41:33 +02:00
# include <QMessageBox>
2018-02-27 18:06:05 +01:00
# include <QPushButton>
2018-05-01 00:41:33 +02:00
# include <QtDebug>
2018-02-27 18:06:05 +01:00
# include "devicemanager.h"
# include "core/application.h"
# include "core/database.h"
2018-05-01 00:41:33 +02:00
# include "core/iconloader.h"
2018-02-27 18:06:05 +01:00
# include "core/logging.h"
# include "core/musicstorage.h"
# include "core/taskmanager.h"
# include "core/utilities.h"
2018-12-29 02:57:22 +01:00
# include "core/simpletreemodel.h"
2018-05-01 00:41:33 +02:00
# include "filesystemdevice.h"
# include "connecteddevice.h"
# include "devicelister.h"
# include "devicedatabasebackend.h"
# include "devicestatefiltermodel.h"
2018-12-29 02:57:22 +01:00
# include "deviceinfo.h"
2018-02-27 18:06:05 +01:00
# if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER)
2018-05-01 00:41:33 +02:00
# include "cddalister.h"
# include "cddadevice.h"
2018-02-27 18:06:05 +01:00
# endif
2018-07-03 21:21:33 +02:00
# ifdef HAVE_DBUS
# ifdef HAVE_UDISKS2
# include "udisks2lister.h"
# endif
2018-02-27 18:06:05 +01:00
# endif
2018-12-29 02:57:22 +01:00
# ifdef HAVE_LIBMTP
# include "mtpdevice.h"
# endif
# if defined(Q_OS_MACOS) and defined(HAVE_LIBMTP)
2019-01-02 00:32:36 +01:00
# include "macosdevicelister.h"
2018-12-29 02:57:22 +01:00
# endif
# ifdef HAVE_LIBGPOD
# include "gpoddevice.h"
# endif
# ifdef HAVE_GIO
2021-07-11 09:49:38 +02:00
# include "giolister.h" // Needs to be last because of #undef signals.
2018-12-29 02:57:22 +01:00
# endif
2018-02-27 18:06:05 +01:00
const int DeviceManager : : kDeviceIconSize = 32 ;
const int DeviceManager : : kDeviceIconOverlaySize = 16 ;
DeviceManager : : DeviceManager ( Application * app , QObject * parent )
2018-12-29 02:57:22 +01:00
: SimpleTreeModel < DeviceInfo > ( new DeviceInfo ( this ) , parent ) ,
2021-07-11 07:40:57 +02:00
app_ ( app ) ,
not_connected_overlay_ ( IconLoader : : Load ( " edit-delete " ) ) {
2018-12-29 02:57:22 +01:00
2018-02-27 18:06:05 +01:00
thread_pool_ . setMaxThreadCount ( 1 ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( app_ - > task_manager ( ) , & TaskManager : : TasksChanged , this , & DeviceManager : : TasksChanged ) ;
2018-02-27 18:06:05 +01:00
// Create the backend in the database thread
backend_ = new DeviceDatabaseBackend ;
backend_ - > moveToThread ( app_ - > database ( ) - > thread ( ) ) ;
backend_ - > Init ( app_ - > database ( ) ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( this , & DeviceManager : : DeviceCreatedFromDB , this , & DeviceManager : : AddDeviceFromDB ) ;
2019-03-22 23:10:42 +01:00
2019-01-05 23:11:16 +01:00
// This reads from the database and contents on the database mutex, which can be very slow on startup.
2020-11-14 02:13:22 +01:00
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
( void ) QtConcurrent : : run ( & thread_pool_ , & DeviceManager : : LoadAllDevices , this ) ;
# else
( void ) QtConcurrent : : run ( & thread_pool_ , this , & DeviceManager : : LoadAllDevices ) ;
# endif
2018-02-27 18:06:05 +01:00
// This proxy model only shows connected devices
connected_devices_model_ = new DeviceStateFilterModel ( this ) ;
connected_devices_model_ - > setSourceModel ( this ) ;
2018-07-03 21:21:33 +02:00
// CD devices are detected via the DiskArbitration framework instead on MacOs.
2018-07-01 22:26:46 +02:00
# if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER) && !defined(Q_OS_MACOS)
2018-02-27 18:06:05 +01:00
AddLister ( new CddaLister ) ;
# endif
2018-07-03 21:21:33 +02:00
# if defined(HAVE_DBUS) && defined(HAVE_UDISKS2)
2018-02-27 18:06:05 +01:00
AddLister ( new Udisks2Lister ) ;
# endif
# ifdef HAVE_GIO
AddLister ( new GioLister ) ;
# endif
2018-07-01 22:26:46 +02:00
# if defined(Q_OS_MACOS) and defined(HAVE_LIBMTP)
2019-01-02 00:32:36 +01:00
AddLister ( new MacOsDeviceLister ) ;
2018-02-27 18:06:05 +01:00
# endif
# if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER)
AddDeviceClass < CddaDevice > ( ) ;
# endif
2019-01-26 17:18:26 +01:00
AddDeviceClass < FilesystemDevice > ( ) ;
2018-02-27 18:06:05 +01:00
# ifdef HAVE_LIBGPOD
AddDeviceClass < GPodDevice > ( ) ;
# endif
# ifdef HAVE_LIBMTP
AddDeviceClass < MtpDevice > ( ) ;
# endif
}
DeviceManager : : ~ DeviceManager ( ) {
for ( DeviceLister * lister : listers_ ) {
lister - > ShutDown ( ) ;
delete lister ;
}
2019-09-07 23:30:35 +02:00
listers_ . clear ( ) ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
delete root_ ;
2019-09-07 23:30:35 +02:00
root_ = nullptr ;
backend_ - > deleteLater ( ) ;
backend_ = nullptr ;
2019-07-24 19:16:51 +02:00
}
void DeviceManager : : Exit ( ) {
2019-09-07 23:30:35 +02:00
CloseDevices ( ) ;
}
void DeviceManager : : CloseDevices ( ) {
for ( DeviceInfo * info : devices_ ) {
if ( ! info - > device_ ) continue ;
if ( wait_for_exit_ . contains ( info - > device_ . get ( ) ) ) continue ;
wait_for_exit_ < < info - > device_ . get ( ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( info - > device_ . get ( ) , & ConnectedDevice : : destroyed , this , & DeviceManager : : DeviceDestroyed ) ;
2019-09-07 23:30:35 +02:00
info - > device_ - > Close ( ) ;
}
if ( wait_for_exit_ . isEmpty ( ) ) CloseListers ( ) ;
}
2019-07-24 19:16:51 +02:00
2019-09-07 23:30:35 +02:00
void DeviceManager : : CloseListers ( ) {
for ( DeviceLister * lister : listers_ ) {
if ( wait_for_exit_ . contains ( lister ) ) continue ;
wait_for_exit_ < < lister ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( lister , & DeviceLister : : ExitFinished , this , & DeviceManager : : ListerClosed ) ;
2019-09-07 23:30:35 +02:00
lister - > ExitAsync ( ) ;
}
if ( wait_for_exit_ . isEmpty ( ) ) CloseBackend ( ) ;
}
void DeviceManager : : CloseBackend ( ) {
if ( ! backend_ | | wait_for_exit_ . contains ( backend_ ) ) return ;
wait_for_exit_ < < backend_ ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( backend_ , & DeviceDatabaseBackend : : ExitFinished , this , & DeviceManager : : BackendClosed ) ;
2019-07-24 19:16:51 +02:00
backend_ - > ExitAsync ( ) ;
2019-01-21 17:44:37 +01:00
2018-02-27 18:06:05 +01:00
}
2019-09-07 23:30:35 +02:00
void DeviceManager : : BackendClosed ( ) {
2021-06-20 19:04:08 +02:00
QObject * obj = sender ( ) ;
2021-01-26 16:48:04 +01:00
QObject : : disconnect ( obj , nullptr , this , nullptr ) ;
2019-09-07 23:30:35 +02:00
qLog ( Debug ) < < obj < < " successfully closed. " ;
wait_for_exit_ . removeAll ( obj ) ;
if ( wait_for_exit_ . isEmpty ( ) ) emit ExitFinished ( ) ;
}
void DeviceManager : : ListerClosed ( ) {
2020-07-17 01:32:07 +02:00
DeviceLister * lister = qobject_cast < DeviceLister * > ( sender ( ) ) ;
2019-09-07 23:30:35 +02:00
if ( ! lister ) return ;
2021-01-26 16:48:04 +01:00
QObject : : disconnect ( lister , nullptr , this , nullptr ) ;
2019-09-07 23:30:35 +02:00
qLog ( Debug ) < < lister < < " successfully closed. " ;
wait_for_exit_ . removeAll ( lister ) ;
if ( wait_for_exit_ . isEmpty ( ) ) CloseBackend ( ) ;
}
void DeviceManager : : DeviceDestroyed ( ) {
2020-08-15 15:16:06 +02:00
ConnectedDevice * device = static_cast < ConnectedDevice * > ( sender ( ) ) ;
2019-09-07 23:30:35 +02:00
if ( ! wait_for_exit_ . contains ( device ) | | ! backend_ ) return ;
wait_for_exit_ . removeAll ( device ) ;
if ( wait_for_exit_ . isEmpty ( ) ) CloseListers ( ) ;
}
2018-02-27 18:06:05 +01:00
void DeviceManager : : LoadAllDevices ( ) {
Q_ASSERT ( QThread : : currentThread ( ) ! = qApp - > thread ( ) ) ;
2018-12-29 02:57:22 +01:00
2018-02-27 18:06:05 +01:00
DeviceDatabaseBackend : : DeviceList devices = backend_ - > GetAllDevices ( ) ;
for ( const DeviceDatabaseBackend : : Device & device : devices ) {
2019-01-21 17:44:37 +01:00
DeviceInfo * info = new DeviceInfo ( DeviceInfo : : Type_Device , root_ ) ;
2018-12-29 02:57:22 +01:00
info - > InitFromDb ( device ) ;
2019-03-22 23:10:42 +01:00
emit DeviceCreatedFromDB ( info ) ;
}
2019-07-25 17:56:28 +02:00
2019-09-07 23:30:35 +02:00
// This is done in a concurrent thread so close the unique DB connection.
2019-07-24 19:16:51 +02:00
backend_ - > Close ( ) ;
2019-03-22 23:10:42 +01:00
}
void DeviceManager : : AddDeviceFromDB ( DeviceInfo * info ) {
QStringList icon_names = info - > icon_name_ . split ( ' , ' ) ;
QVariantList icons ;
2021-06-20 19:04:08 +02:00
icons . reserve ( icon_names . count ( ) ) ;
2019-03-22 23:10:42 +01:00
for ( const QString & icon_name : icon_names ) {
icons < < icon_name ;
}
info - > LoadIcon ( icons , info - > friendly_name_ ) ;
DeviceInfo * existing = FindEquivalentDevice ( info ) ;
if ( existing ) {
qLog ( Info ) < < " Found existing device: " < < info - > friendly_name_ ;
existing - > icon_name_ = info - > icon_name_ ;
existing - > icon_ = info - > icon_ ;
QModelIndex idx = ItemToIndex ( existing ) ;
if ( idx . isValid ( ) ) emit dataChanged ( idx , idx ) ;
2020-09-02 19:35:13 +02:00
root_ - > Delete ( info - > row ) ;
2019-03-22 23:10:42 +01:00
}
else {
qLog ( Info ) < < " Device added from database: " < < info - > friendly_name_ ;
2021-10-30 02:21:29 +02:00
beginInsertRows ( ItemToIndex ( root_ ) , static_cast < int > ( devices_ . count ( ) ) , static_cast < int > ( devices_ . count ( ) ) ) ;
2018-02-27 18:06:05 +01:00
devices_ < < info ;
endInsertRows ( ) ;
}
}
2019-01-21 17:44:37 +01:00
QVariant DeviceManager : : data ( const QModelIndex & idx , int role ) const {
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) | | idx . column ( ) ! = 0 ) return QVariant ( ) ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
DeviceInfo * info = IndexToItem ( idx ) ;
2019-01-05 23:11:16 +01:00
if ( ! info ) return QVariant ( ) ;
2018-02-27 18:06:05 +01:00
switch ( role ) {
case Qt : : DisplayRole : {
QString text ;
2021-06-22 13:54:58 +02:00
if ( ! info - > friendly_name_ . isEmpty ( ) ) {
2018-12-29 02:57:22 +01:00
text = info - > friendly_name_ ;
2021-06-22 13:54:58 +02:00
}
else if ( info - > BestBackend ( ) ) {
2018-12-29 02:57:22 +01:00
text = info - > BestBackend ( ) - > unique_id_ ;
2021-06-22 13:54:58 +02:00
}
2018-02-27 18:06:05 +01:00
2021-06-22 13:54:58 +02:00
if ( info - > size_ > 0 ) {
2018-12-29 02:57:22 +01:00
text = text + QString ( " (%1) " ) . arg ( Utilities : : PrettySize ( info - > size_ ) ) ;
2021-06-22 13:54:58 +02:00
}
2018-12-29 02:57:22 +01:00
if ( info - > device_ . get ( ) ) info - > device_ - > Refresh ( ) ;
2018-02-27 18:06:05 +01:00
return text ;
}
case Qt : : DecorationRole : {
2018-12-29 02:57:22 +01:00
QPixmap pixmap = info - > icon_ . pixmap ( kDeviceIconSize ) ;
2018-02-27 18:06:05 +01:00
2019-09-07 23:30:35 +02:00
if ( info - > backends_ . isEmpty ( ) | | ! info - > BestBackend ( ) | | ! info - > BestBackend ( ) - > lister_ ) {
2018-02-27 18:06:05 +01:00
// Disconnected but remembered
QPainter p ( & pixmap ) ;
p . drawPixmap ( kDeviceIconSize - kDeviceIconOverlaySize , kDeviceIconSize - kDeviceIconOverlaySize , not_connected_overlay_ . pixmap ( kDeviceIconOverlaySize ) ) ;
}
return pixmap ;
}
case Role_FriendlyName :
2018-12-29 02:57:22 +01:00
return info - > friendly_name_ ;
2018-02-27 18:06:05 +01:00
case Role_UniqueId :
2019-01-05 23:11:16 +01:00
if ( ! info - > BestBackend ( ) ) return QString ( ) ;
2018-12-29 02:57:22 +01:00
return info - > BestBackend ( ) - > unique_id_ ;
2018-02-27 18:06:05 +01:00
case Role_IconName :
2018-12-29 02:57:22 +01:00
return info - > icon_name_ ;
2018-02-27 18:06:05 +01:00
case Role_Capacity :
case MusicStorage : : Role_Capacity :
2018-12-29 02:57:22 +01:00
return info - > size_ ;
2018-02-27 18:06:05 +01:00
case Role_FreeSpace :
case MusicStorage : : Role_FreeSpace :
2019-01-05 23:11:16 +01:00
return ( ( info - > BestBackend ( ) & & info - > BestBackend ( ) - > lister_ ) ? info - > BestBackend ( ) - > lister_ - > DeviceFreeSpace ( info - > BestBackend ( ) - > unique_id_ ) : QVariant ( ) ) ;
2018-02-27 18:06:05 +01:00
case Role_State :
2018-12-29 02:57:22 +01:00
if ( info - > device_ ) return State_Connected ;
2019-01-05 23:11:16 +01:00
if ( info - > BestBackend ( ) & & info - > BestBackend ( ) - > lister_ ) {
2018-12-29 02:57:22 +01:00
if ( info - > BestBackend ( ) - > lister_ - > DeviceNeedsMount ( info - > BestBackend ( ) - > unique_id_ ) ) return State_NotMounted ;
2018-02-27 18:06:05 +01:00
return State_NotConnected ;
}
return State_Remembered ;
case Role_UpdatingPercentage :
2018-12-29 02:57:22 +01:00
if ( info - > task_percentage_ = = - 1 ) return QVariant ( ) ;
return info - > task_percentage_ ;
2018-02-27 18:06:05 +01:00
case MusicStorage : : Role_Storage :
2021-08-23 21:21:08 +02:00
if ( ! info - > device_ & & info - > database_id_ ! = - 1 ) {
2019-01-21 17:44:37 +01:00
const_cast < DeviceManager * > ( this ) - > Connect ( info ) ;
2021-08-23 21:21:08 +02:00
}
2018-12-29 02:57:22 +01:00
if ( ! info - > device_ ) return QVariant ( ) ;
return QVariant : : fromValue < std : : shared_ptr < MusicStorage > > ( info - > device_ ) ;
2018-02-27 18:06:05 +01:00
case MusicStorage : : Role_StorageForceConnect :
2019-01-21 17:44:37 +01:00
if ( ! info - > BestBackend ( ) ) return QVariant ( ) ;
2018-12-29 02:57:22 +01:00
if ( ! info - > device_ ) {
2019-01-21 17:44:37 +01:00
if ( info - > database_id_ = = - 1 & & ! info - > BestBackend ( ) - > lister_ - > DeviceNeedsMount ( info - > BestBackend ( ) - > unique_id_ ) ) {
if ( info - > BestBackend ( ) - > lister_ - > AskForScan ( info - > BestBackend ( ) - > unique_id_ ) ) {
2018-02-27 18:06:05 +01:00
std : : unique_ptr < QMessageBox > dialog ( new QMessageBox ( QMessageBox : : Information , tr ( " Connect device " ) , tr ( " This is the first time you have connected this device. Strawberry will now scan the device to find music files - this may take some time. " ) , QMessageBox : : Cancel ) ) ;
2020-05-29 18:30:27 +02:00
QPushButton * pushbutton = dialog - > addButton ( tr ( " Connect device " ) , QMessageBox : : AcceptRole ) ;
2018-02-27 18:06:05 +01:00
dialog - > exec ( ) ;
2020-05-29 18:30:27 +02:00
if ( dialog - > clickedButton ( ) ! = pushbutton ) return QVariant ( ) ;
2018-02-27 18:06:05 +01:00
}
}
2019-01-21 17:44:37 +01:00
const_cast < DeviceManager * > ( this ) - > Connect ( info ) ;
2018-02-27 18:06:05 +01:00
}
2018-12-29 02:57:22 +01:00
if ( ! info - > device_ ) return QVariant ( ) ;
return QVariant : : fromValue < std : : shared_ptr < MusicStorage > > ( info - > device_ ) ;
2018-02-27 18:06:05 +01:00
case Role_MountPath : {
2018-12-29 02:57:22 +01:00
if ( ! info - > device_ ) return QVariant ( ) ;
2018-02-27 18:06:05 +01:00
2018-12-29 02:57:22 +01:00
QString ret = info - > device_ - > url ( ) . path ( ) ;
2018-02-27 18:06:05 +01:00
# ifdef Q_OS_WIN32
if ( ret . startsWith ( ' / ' ) ) ret . remove ( 0 , 1 ) ;
# endif
return QDir : : toNativeSeparators ( ret ) ;
}
case Role_TranscodeMode :
2018-12-29 02:57:22 +01:00
return info - > transcode_mode_ ;
2018-02-27 18:06:05 +01:00
case Role_TranscodeFormat :
2018-12-29 02:57:22 +01:00
return info - > transcode_format_ ;
2018-02-27 18:06:05 +01:00
case Role_SongCount :
2018-12-29 02:57:22 +01:00
if ( ! info - > device_ ) return QVariant ( ) ;
return info - > device_ - > song_count ( ) ;
2018-02-27 18:06:05 +01:00
2020-03-17 20:44:51 +01:00
case Role_CopyMusic :
if ( info - > BestBackend ( ) & & info - > BestBackend ( ) - > lister_ ) return info - > BestBackend ( ) - > lister_ - > CopyMusic ( ) ;
else return false ;
2018-02-27 18:06:05 +01:00
default :
return QVariant ( ) ;
}
2019-01-05 23:11:16 +01:00
2018-02-27 18:06:05 +01:00
}
void DeviceManager : : AddLister ( DeviceLister * lister ) {
listers_ < < lister ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( lister , & DeviceLister : : DeviceAdded , this , & DeviceManager : : PhysicalDeviceAdded ) ;
QObject : : connect ( lister , & DeviceLister : : DeviceRemoved , this , & DeviceManager : : PhysicalDeviceRemoved ) ;
QObject : : connect ( lister , & DeviceLister : : DeviceChanged , this , & DeviceManager : : PhysicalDeviceChanged ) ;
2018-02-27 18:06:05 +01:00
lister - > Start ( ) ;
}
2019-01-21 17:44:37 +01:00
DeviceInfo * DeviceManager : : FindDeviceById ( const QString & id ) const {
2018-02-27 18:06:05 +01:00
for ( int i = 0 ; i < devices_ . count ( ) ; + + i ) {
2018-12-29 02:57:22 +01:00
for ( const DeviceInfo : : Backend & backend : devices_ [ i ] - > backends_ ) {
2019-01-21 17:44:37 +01:00
if ( backend . unique_id_ = = id ) return devices_ [ i ] ;
2018-02-27 18:06:05 +01:00
}
}
2018-03-10 13:02:56 +01:00
2019-01-21 17:44:37 +01:00
return nullptr ;
2018-02-27 18:06:05 +01:00
}
2019-01-21 17:44:37 +01:00
DeviceInfo * DeviceManager : : FindDeviceByUrl ( const QList < QUrl > & urls ) const {
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
if ( urls . isEmpty ( ) ) return nullptr ;
2018-02-27 18:06:05 +01:00
for ( int i = 0 ; i < devices_ . count ( ) ; + + i ) {
2018-12-29 02:57:22 +01:00
for ( const DeviceInfo : : Backend & backend : devices_ [ i ] - > backends_ ) {
2018-02-27 18:06:05 +01:00
if ( ! backend . lister_ ) continue ;
2018-03-10 13:02:56 +01:00
QList < QUrl > device_urls = backend . lister_ - > MakeDeviceUrls ( backend . unique_id_ ) ;
2018-02-27 18:06:05 +01:00
for ( const QUrl & url : device_urls ) {
2019-01-21 17:44:37 +01:00
if ( urls . contains ( url ) ) return devices_ [ i ] ;
2018-02-27 18:06:05 +01:00
}
}
}
2018-03-10 13:02:56 +01:00
2019-01-21 17:44:37 +01:00
return nullptr ;
2018-02-27 18:06:05 +01:00
}
2019-03-22 23:10:42 +01:00
DeviceInfo * DeviceManager : : FindEquivalentDevice ( DeviceInfo * info ) const {
for ( const DeviceInfo : : Backend & backend : info - > backends_ ) {
DeviceInfo * match = FindDeviceById ( backend . unique_id_ ) ;
if ( match ) return match ;
}
return nullptr ;
}
2018-02-27 18:06:05 +01:00
void DeviceManager : : PhysicalDeviceAdded ( const QString & id ) {
DeviceLister * lister = qobject_cast < DeviceLister * > ( sender ( ) ) ;
2019-01-05 23:11:16 +01:00
if ( ! lister ) return ;
2018-02-27 18:06:05 +01:00
2019-01-05 23:11:16 +01:00
qLog ( Info ) < < " Device added: " < < id < < lister - > DeviceUniqueIDs ( ) ;
2018-02-27 18:06:05 +01:00
// Do we have this device already?
2019-01-21 17:44:37 +01:00
DeviceInfo * info = FindDeviceById ( id ) ;
if ( info ) {
2021-08-23 21:21:08 +02:00
for ( int backend_index = 0 ; backend_index < info - > backends_ . count ( ) ; + + backend_index ) {
2018-12-29 02:57:22 +01:00
if ( info - > backends_ [ backend_index ] . unique_id_ = = id ) {
info - > backends_ [ backend_index ] . lister_ = lister ;
2018-02-27 18:06:05 +01:00
break ;
}
}
2019-01-21 17:44:37 +01:00
QModelIndex idx = ItemToIndex ( info ) ;
if ( idx . isValid ( ) ) emit dataChanged ( idx , idx ) ;
2018-03-10 13:02:56 +01:00
}
else {
2018-02-27 18:06:05 +01:00
// Check if we have another device with the same URL
2019-01-21 17:44:37 +01:00
info = FindDeviceByUrl ( lister - > MakeDeviceUrls ( id ) ) ;
if ( info ) {
2018-02-27 18:06:05 +01:00
// Add this device's lister to the existing device
2018-12-29 02:57:22 +01:00
info - > backends_ < < DeviceInfo : : Backend ( lister , id ) ;
2018-02-27 18:06:05 +01:00
2018-05-01 00:41:33 +02:00
// If the user hasn't saved the device in the DB yet then overwrite the device's name and icon etc.
2019-09-07 23:30:35 +02:00
if ( info - > database_id_ = = - 1 & & info - > BestBackend ( ) & & info - > BestBackend ( ) - > lister_ = = lister ) {
2018-12-29 02:57:22 +01:00
info - > friendly_name_ = lister - > MakeFriendlyName ( id ) ;
info - > size_ = lister - > DeviceCapacity ( id ) ;
info - > LoadIcon ( lister - > DeviceIcons ( id ) , info - > friendly_name_ ) ;
2018-02-27 18:06:05 +01:00
}
2019-01-21 17:44:37 +01:00
QModelIndex idx = ItemToIndex ( info ) ;
if ( idx . isValid ( ) ) emit dataChanged ( idx , idx ) ;
2018-03-10 13:02:56 +01:00
}
else {
2018-02-27 18:06:05 +01:00
// It's a completely new device
2020-04-23 21:08:28 +02:00
info = new DeviceInfo ( DeviceInfo : : Type_Device , root_ ) ;
2018-12-29 02:57:22 +01:00
info - > backends_ < < DeviceInfo : : Backend ( lister , id ) ;
info - > friendly_name_ = lister - > MakeFriendlyName ( id ) ;
info - > size_ = lister - > DeviceCapacity ( id ) ;
info - > LoadIcon ( lister - > DeviceIcons ( id ) , info - > friendly_name_ ) ;
2021-10-30 02:21:29 +02:00
beginInsertRows ( ItemToIndex ( root_ ) , static_cast < int > ( devices_ . count ( ) ) , static_cast < int > ( devices_ . count ( ) ) ) ;
2018-02-27 18:06:05 +01:00
devices_ < < info ;
endInsertRows ( ) ;
}
}
}
void DeviceManager : : PhysicalDeviceRemoved ( const QString & id ) {
DeviceLister * lister = qobject_cast < DeviceLister * > ( sender ( ) ) ;
qLog ( Info ) < < " Device removed: " < < id ;
2019-01-21 17:44:37 +01:00
DeviceInfo * info = FindDeviceById ( id ) ;
if ( ! info ) return ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
QModelIndex idx = ItemToIndex ( info ) ;
if ( ! idx . isValid ( ) ) return ;
2018-02-27 18:06:05 +01:00
2018-12-29 02:57:22 +01:00
if ( info - > database_id_ ! = - 1 ) {
2018-02-27 18:06:05 +01:00
// Keep the structure around, but just "disconnect" it
2021-08-23 21:21:08 +02:00
for ( int backend_index = 0 ; backend_index < info - > backends_ . count ( ) ; + + backend_index ) {
2018-12-29 02:57:22 +01:00
if ( info - > backends_ [ backend_index ] . unique_id_ = = id ) {
info - > backends_ [ backend_index ] . lister_ = nullptr ;
2018-02-27 18:06:05 +01:00
break ;
}
}
2019-09-07 23:30:35 +02:00
if ( info - > device_ & & info - > device_ - > lister ( ) = = lister ) {
info - > device_ - > Close ( ) ;
}
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
if ( ! info - > device_ ) emit DeviceDisconnected ( idx ) ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
emit dataChanged ( idx , idx ) ;
2018-02-27 18:06:05 +01:00
}
else {
// If this was the last lister for the device then remove it from the model
2021-08-23 21:21:08 +02:00
for ( int backend_index = 0 ; backend_index < info - > backends_ . count ( ) ; + + backend_index ) {
2018-12-29 02:57:22 +01:00
if ( info - > backends_ [ backend_index ] . unique_id_ = = id ) {
info - > backends_ . removeAt ( backend_index ) ;
2018-02-27 18:06:05 +01:00
break ;
}
}
2018-12-29 02:57:22 +01:00
if ( info - > backends_ . isEmpty ( ) ) {
2019-01-21 17:44:37 +01:00
beginRemoveRows ( ItemToIndex ( root_ ) , idx . row ( ) , idx . row ( ) ) ;
devices_ . removeAll ( info ) ;
root_ - > Delete ( info - > row ) ;
2018-02-27 18:06:05 +01:00
endRemoveRows ( ) ;
}
}
}
void DeviceManager : : PhysicalDeviceChanged ( const QString & id ) {
DeviceLister * lister = qobject_cast < DeviceLister * > ( sender ( ) ) ;
Q_UNUSED ( lister ) ;
2019-01-21 17:44:37 +01:00
DeviceInfo * info = FindDeviceById ( id ) ;
if ( ! info ) return ;
2018-02-27 18:06:05 +01:00
// TODO
2018-12-29 02:57:22 +01:00
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
std : : shared_ptr < ConnectedDevice > DeviceManager : : Connect ( const QModelIndex & idx ) {
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
std : : shared_ptr < ConnectedDevice > ret ;
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info ) return ret ;
return Connect ( info ) ;
}
std : : shared_ptr < ConnectedDevice > DeviceManager : : Connect ( DeviceInfo * info ) {
2018-02-27 18:06:05 +01:00
std : : shared_ptr < ConnectedDevice > ret ;
2019-01-21 17:44:37 +01:00
if ( ! info ) return ret ;
if ( info - > device_ ) { // Already connected
return info - > device_ ;
}
if ( ! info - > BestBackend ( ) | | ! info - > BestBackend ( ) - > lister_ ) { // Not physically connected
2018-02-27 18:06:05 +01:00
return ret ;
2019-01-21 17:44:37 +01:00
}
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
if ( info - > BestBackend ( ) - > lister_ - > DeviceNeedsMount ( info - > BestBackend ( ) - > unique_id_ ) ) { // Mount the device
2019-09-07 23:30:35 +02:00
info - > BestBackend ( ) - > lister_ - > MountDeviceAsync ( info - > BestBackend ( ) - > unique_id_ ) ;
2018-02-27 18:06:05 +01:00
return ret ;
}
2018-12-29 02:57:22 +01:00
bool first_time = ( info - > database_id_ = = - 1 ) ;
2018-02-27 18:06:05 +01:00
if ( first_time ) {
// We haven't stored this device in the database before
2018-12-29 02:57:22 +01:00
info - > database_id_ = backend_ - > AddDevice ( info - > SaveToDb ( ) ) ;
2018-02-27 18:06:05 +01:00
}
// Get the device URLs
2018-12-29 02:57:22 +01:00
QList < QUrl > urls = info - > BestBackend ( ) - > lister_ - > MakeDeviceUrls ( info - > BestBackend ( ) - > unique_id_ ) ;
2018-02-27 18:06:05 +01:00
if ( urls . isEmpty ( ) ) return ret ;
// Take the first URL that we have a handler for
QUrl device_url ;
for ( const QUrl & url : urls ) {
qLog ( Info ) < < " Connecting " < < url ;
// Find a device class for this URL's scheme
if ( device_classes_ . contains ( url . scheme ( ) ) ) {
device_url = url ;
break ;
}
2018-05-01 00:41:33 +02:00
// If we get here it means that this URL scheme wasn't supported.
// If it was "ipod" or "mtp" then the user compiled out support and the device won't work properly.
2018-02-27 18:06:05 +01:00
if ( url . scheme ( ) = = " mtp " | | url . scheme ( ) = = " gphoto2 " ) {
if ( QMessageBox : : critical ( nullptr , tr ( " This device will not work properly " ) ,
tr ( " This is an MTP device, but you compiled Strawberry without libmtp support. " ) + " " +
tr ( " If you continue, this device will work slowly and songs copied to it may not work. " ) ,
QMessageBox : : Abort , QMessageBox : : Ignore ) = = QMessageBox : : Abort )
return ret ;
}
if ( url . scheme ( ) = = " ipod " ) {
if ( QMessageBox : : critical ( nullptr , tr ( " This device will not work properly " ) ,
tr ( " This is an iPod, but you compiled Strawberry without libgpod support. " ) + " " +
tr ( " If you continue, this device will work slowly and songs copied to it may not work. " ) ,
QMessageBox : : Abort , QMessageBox : : Ignore ) = = QMessageBox : : Abort )
return ret ;
}
}
if ( device_url . isEmpty ( ) ) {
// Munge the URL list into a string list
QStringList url_strings ;
2021-06-20 19:04:08 +02:00
url_strings . reserve ( urls . count ( ) ) ;
2018-02-27 18:06:05 +01:00
for ( const QUrl & url : urls ) {
url_strings < < url . toString ( ) ;
}
app_ - > AddError ( tr ( " This type of device is not supported: %1 " ) . arg ( url_strings . join ( " , " ) ) ) ;
return ret ;
}
QMetaObject meta_object = device_classes_ . value ( device_url . scheme ( ) ) ;
QObject * instance = meta_object . newInstance (
Q_ARG ( QUrl , device_url ) ,
2018-12-29 02:57:22 +01:00
Q_ARG ( DeviceLister * , info - > BestBackend ( ) - > lister_ ) ,
Q_ARG ( QString , info - > BestBackend ( ) - > unique_id_ ) ,
2019-01-21 17:44:37 +01:00
Q_ARG ( DeviceManager * , this ) ,
Q_ARG ( Application * , app_ ) ,
Q_ARG ( int , info - > database_id_ ) ,
Q_ARG ( bool , first_time ) ) ;
2018-12-29 02:57:22 +01:00
2020-07-17 01:32:07 +02:00
ret . reset ( qobject_cast < ConnectedDevice * > ( instance ) ) ;
2018-02-27 18:06:05 +01:00
if ( ! ret ) {
qLog ( Warning ) < < " Could not create device for " < < device_url . toString ( ) ;
2018-12-29 02:57:22 +01:00
return ret ;
2018-02-27 18:06:05 +01:00
}
2018-12-29 02:57:22 +01:00
bool result = ret - > Init ( ) ;
if ( ! result ) {
qLog ( Warning ) < < " Could not connect to device " < < device_url . toString ( ) ;
return ret ;
2018-02-27 18:06:05 +01:00
}
2018-12-29 02:57:22 +01:00
info - > device_ = ret ;
2019-01-05 23:17:20 +01:00
2019-01-21 17:44:37 +01:00
QModelIndex idx = ItemToIndex ( info ) ;
if ( ! idx . isValid ( ) ) return ret ;
emit dataChanged ( idx , idx ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( info - > device_ . get ( ) , & ConnectedDevice : : TaskStarted , this , & DeviceManager : : DeviceTaskStarted ) ;
QObject : : connect ( info - > device_ . get ( ) , & ConnectedDevice : : SongCountUpdated , this , & DeviceManager : : DeviceSongCountUpdated ) ;
QObject : : connect ( info - > device_ . get ( ) , & ConnectedDevice : : DeviceConnectFinished , this , & DeviceManager : : DeviceConnectFinished ) ;
QObject : : connect ( info - > device_ . get ( ) , & ConnectedDevice : : DeviceCloseFinished , this , & DeviceManager : : DeviceCloseFinished ) ;
2019-01-21 18:58:54 +01:00
ret - > ConnectAsync ( ) ;
2018-02-27 18:06:05 +01:00
return ret ;
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : DeviceConnectFinished ( const QString & id , const bool success ) {
2019-01-21 18:58:54 +01:00
DeviceInfo * info = FindDeviceById ( id ) ;
if ( ! info ) return ;
QModelIndex idx = ItemToIndex ( info ) ;
if ( ! idx . isValid ( ) ) return ;
if ( success ) {
emit DeviceConnected ( idx ) ;
}
else {
2019-09-07 23:30:35 +02:00
info - > device_ - > Close ( ) ;
}
}
void DeviceManager : : DeviceCloseFinished ( const QString & id ) {
DeviceInfo * info = FindDeviceById ( id ) ;
if ( ! info ) return ;
info - > device_ . reset ( ) ;
QModelIndex idx = ItemToIndex ( info ) ;
if ( ! idx . isValid ( ) ) return ;
emit DeviceDisconnected ( idx ) ;
emit dataChanged ( idx , idx ) ;
if ( info - > unmount_ & & info - > BestBackend ( ) & & info - > BestBackend ( ) - > lister_ ) {
info - > BestBackend ( ) - > lister_ - > UnmountDeviceAsync ( info - > BestBackend ( ) - > unique_id_ ) ;
}
if ( info - > forget_ ) {
RemoveFromDB ( info , idx ) ;
2019-01-21 18:58:54 +01:00
}
}
2021-06-20 19:04:08 +02:00
DeviceInfo * DeviceManager : : GetDevice ( const QModelIndex & idx ) const {
2019-01-21 17:44:37 +01:00
DeviceInfo * info = IndexToItem ( idx ) ;
return info ;
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
std : : shared_ptr < ConnectedDevice > DeviceManager : : GetConnectedDevice ( const QModelIndex & idx ) const {
2019-01-21 17:44:37 +01:00
std : : shared_ptr < ConnectedDevice > ret ;
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info ) return ret ;
return info - > device_ ;
2018-02-27 18:06:05 +01:00
}
2019-01-21 17:44:37 +01:00
std : : shared_ptr < ConnectedDevice > DeviceManager : : GetConnectedDevice ( DeviceInfo * info ) const {
std : : shared_ptr < ConnectedDevice > ret ;
if ( ! info ) return ret ;
return info - > device_ ;
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
int DeviceManager : : GetDatabaseId ( const QModelIndex & idx ) const {
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) ) return - 1 ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info ) return - 1 ;
return info - > database_id_ ;
}
2021-06-20 19:04:08 +02:00
DeviceLister * DeviceManager : : GetLister ( const QModelIndex & idx ) const {
2019-01-05 23:11:16 +01:00
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) ) return nullptr ;
2019-01-05 23:11:16 +01:00
2019-01-21 17:44:37 +01:00
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info | | ! info - > BestBackend ( ) ) return nullptr ;
return info - > BestBackend ( ) - > lister_ ;
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : Disconnect ( DeviceInfo * info , const QModelIndex & idx ) {
2018-02-27 18:06:05 +01:00
2019-09-15 20:27:32 +02:00
Q_UNUSED ( idx ) ;
2019-09-07 23:30:35 +02:00
info - > device_ - > Close ( ) ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : Forget ( const QModelIndex & idx ) {
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) ) return ;
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info ) return ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
if ( info - > database_id_ = = - 1 ) return ;
2019-09-07 23:30:35 +02:00
if ( info - > device_ ) {
info - > forget_ = true ;
Disconnect ( info , idx ) ;
}
else {
RemoveFromDB ( info , idx ) ;
}
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : RemoveFromDB ( DeviceInfo * info , const QModelIndex & idx ) {
2019-01-21 17:44:37 +01:00
backend_ - > RemoveDevice ( info - > database_id_ ) ;
info - > database_id_ = - 1 ;
2019-04-08 18:46:11 +02:00
if ( ! info - > BestBackend ( ) | | ! info - > BestBackend ( ) - > lister_ ) { // It's not attached any more so remove it from the list
2019-01-21 17:44:37 +01:00
beginRemoveRows ( ItemToIndex ( root_ ) , idx . row ( ) , idx . row ( ) ) ;
devices_ . removeAll ( info ) ;
root_ - > Delete ( info - > row ) ;
2018-02-27 18:06:05 +01:00
endRemoveRows ( ) ;
}
2019-01-21 17:44:37 +01:00
else { // It's still attached, set the name and icon back to what they were originally
2018-12-29 02:57:22 +01:00
const QString id = info - > BestBackend ( ) - > unique_id_ ;
2018-02-27 18:06:05 +01:00
2018-12-29 02:57:22 +01:00
info - > friendly_name_ = info - > BestBackend ( ) - > lister_ - > MakeFriendlyName ( id ) ;
info - > LoadIcon ( info - > BestBackend ( ) - > lister_ - > DeviceIcons ( id ) , info - > friendly_name_ ) ;
2021-03-21 04:47:11 +01:00
emit dataChanged ( idx , idx ) ;
2018-02-27 18:06:05 +01:00
}
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : SetDeviceOptions ( const QModelIndex & idx , const QString & friendly_name , const QString & icon_name , const MusicStorage : : TranscodeMode mode , const Song : : FileType format ) {
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) ) return ;
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info ) return ;
2018-02-27 18:06:05 +01:00
2018-12-29 02:57:22 +01:00
info - > friendly_name_ = friendly_name ;
info - > LoadIcon ( QVariantList ( ) < < icon_name , friendly_name ) ;
info - > transcode_mode_ = mode ;
info - > transcode_format_ = format ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
emit dataChanged ( idx , idx ) ;
2018-02-27 18:06:05 +01:00
2021-08-23 21:21:08 +02:00
if ( info - > database_id_ ! = - 1 ) {
2018-12-29 02:57:22 +01:00
backend_ - > SetDeviceOptions ( info - > database_id_ , friendly_name , icon_name , mode , format ) ;
2021-08-23 21:21:08 +02:00
}
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : DeviceTaskStarted ( const int id ) {
2018-02-27 18:06:05 +01:00
ConnectedDevice * device = qobject_cast < ConnectedDevice * > ( sender ( ) ) ;
if ( ! device ) return ;
for ( int i = 0 ; i < devices_ . count ( ) ; + + i ) {
2018-12-29 02:57:22 +01:00
DeviceInfo * info = devices_ [ i ] ;
if ( info - > device_ . get ( ) = = device ) {
QModelIndex index = ItemToIndex ( info ) ;
2019-01-05 23:17:20 +01:00
if ( ! index . isValid ( ) ) continue ;
2018-12-29 02:57:22 +01:00
active_tasks_ [ id ] = index ;
info - > task_percentage_ = 0 ;
emit dataChanged ( index , index ) ;
2018-02-27 18:06:05 +01:00
return ;
}
}
}
void DeviceManager : : TasksChanged ( ) {
QList < TaskManager : : Task > tasks = app_ - > task_manager ( ) - > GetTasks ( ) ;
QList < QPersistentModelIndex > finished_tasks = active_tasks_ . values ( ) ;
for ( const TaskManager : : Task & task : tasks ) {
if ( ! active_tasks_ . contains ( task . id ) ) continue ;
2019-01-21 17:44:37 +01:00
QPersistentModelIndex idx = active_tasks_ [ task . id ] ;
if ( ! idx . isValid ( ) ) continue ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
DeviceInfo * info = IndexToItem ( idx ) ;
2021-08-23 21:21:08 +02:00
if ( task . progress_max ) {
2021-10-11 22:28:28 +02:00
info - > task_percentage_ = static_cast < int > ( static_cast < float > ( task . progress ) / static_cast < float > ( task . progress_max ) * 100 ) ;
2021-08-23 21:21:08 +02:00
}
else {
2018-12-29 02:57:22 +01:00
info - > task_percentage_ = 0 ;
2021-08-23 21:21:08 +02:00
}
2018-12-29 02:57:22 +01:00
2019-01-21 17:44:37 +01:00
emit dataChanged ( idx , idx ) ;
finished_tasks . removeAll ( idx ) ;
2018-12-29 02:57:22 +01:00
2018-02-27 18:06:05 +01:00
}
2019-01-21 17:44:37 +01:00
for ( const QPersistentModelIndex & idx : finished_tasks ) {
if ( ! idx . isValid ( ) ) continue ;
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info ) continue ;
2018-02-27 18:06:05 +01:00
2018-12-29 02:57:22 +01:00
info - > task_percentage_ = - 1 ;
2019-01-21 17:44:37 +01:00
emit dataChanged ( idx , idx ) ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
active_tasks_ . remove ( active_tasks_ . key ( idx ) ) ;
2018-02-27 18:06:05 +01:00
}
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : UnmountAsync ( const QModelIndex & idx ) {
2019-01-21 17:44:37 +01:00
Q_ASSERT ( QMetaObject : : invokeMethod ( this , " Unmount " , Q_ARG ( QModelIndex , idx ) ) ) ;
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : Unmount ( const QModelIndex & idx ) {
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) ) return ;
DeviceInfo * info = IndexToItem ( idx ) ;
if ( ! info ) return ;
2018-02-27 18:06:05 +01:00
2018-12-29 02:57:22 +01:00
if ( info - > database_id_ ! = - 1 & & ! info - > device_ ) return ;
2018-02-27 18:06:05 +01:00
2019-09-07 23:30:35 +02:00
if ( info - > device_ ) {
info - > unmount_ = true ;
Disconnect ( info , idx ) ;
}
else if ( info - > BestBackend ( ) & & info - > BestBackend ( ) - > lister_ ) {
info - > BestBackend ( ) - > lister_ - > UnmountDeviceAsync ( info - > BestBackend ( ) - > unique_id_ ) ;
}
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
void DeviceManager : : DeviceSongCountUpdated ( const int count ) {
2018-02-27 18:06:05 +01:00
2019-09-15 20:27:32 +02:00
Q_UNUSED ( count ) ;
2018-02-27 18:06:05 +01:00
ConnectedDevice * device = qobject_cast < ConnectedDevice * > ( sender ( ) ) ;
if ( ! device ) return ;
2019-01-21 17:44:37 +01:00
DeviceInfo * info = FindDeviceById ( device - > unique_id ( ) ) ;
if ( ! info ) return ;
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
QModelIndex idx = ItemToIndex ( info ) ;
if ( ! idx . isValid ( ) ) return ;
2019-01-05 23:11:16 +01:00
2019-01-21 17:44:37 +01:00
emit dataChanged ( idx , idx ) ;
2018-12-29 02:57:22 +01:00
}
2018-02-27 18:06:05 +01:00
2019-09-15 20:27:32 +02:00
QString DeviceManager : : DeviceNameByID ( const QString & unique_id ) {
2018-12-29 02:57:22 +01:00
2019-01-21 17:44:37 +01:00
DeviceInfo * info = FindDeviceById ( unique_id ) ;
2019-01-05 23:11:16 +01:00
if ( ! info ) return QString ( ) ;
2019-01-21 17:44:37 +01:00
QModelIndex idx = ItemToIndex ( info ) ;
if ( ! idx . isValid ( ) ) return QString ( ) ;
2019-01-05 23:11:16 +01:00
2019-01-21 17:44:37 +01:00
return data ( idx , DeviceManager : : Role_FriendlyName ) . toString ( ) ;
2018-12-29 02:57:22 +01:00
}