File indexing completed on 2024-06-09 04:00:40
0001 /* 0002 SPDX-FileCopyrightText: 2010 Rafael Fernández López <ereslibre@kde.org> 0003 SPDX-FileCopyrightText: 2010 Lukas Tinkl <ltinkl@redhat.com> 0004 SPDX-FileCopyrightText: 2011 Matej Laitl <matej@laitl.cz> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "udevportablemediaplayer.h" 0010 0011 #include <QChar> 0012 #include <QDebug> 0013 #include <QFile> 0014 #include <QTextStream> 0015 #include <qstandardpaths.h> 0016 0017 using namespace Solid::Backends::UDev; 0018 0019 /** 0020 * Reads one value from media-player-info ini-like file. 0021 * 0022 * @param file file to open. May advance current seek position 0023 * @param group group name to read from, e.g. "Device" for [Device] group 0024 * @param key key name, e.g. "AccessProtocol" 0025 * @return value as a string or an empty string 0026 */ 0027 static QString readMpiValue(QIODevice &file, const QString &group, const QString &key) 0028 { 0029 QTextStream mpiStream(&file); 0030 QString line; 0031 QString currGroup; 0032 0033 while (!mpiStream.atEnd()) { 0034 line = mpiStream.readLine().trimmed(); // trimmed is needed for possible indentation 0035 if (line.isEmpty() || line.startsWith(QChar(';'))) { 0036 // skip empty and comment lines 0037 } else if (line.startsWith(QChar('[')) && line.endsWith(QChar(']'))) { 0038 currGroup = line.mid(1, line.length() - 2); // strip [ and ] 0039 } else if (line.indexOf(QChar('=')) != -1) { 0040 int index = line.indexOf(QChar('=')); 0041 if (currGroup == group && line.left(index) == key) { 0042 line = line.right(line.length() - index - 1); 0043 if (line.startsWith(QChar('"')) && line.endsWith(QChar('"'))) { 0044 line = line.mid(1, line.length() - 2); // strip enclosing double quotes 0045 } 0046 return line; 0047 } 0048 } else { 0049 qWarning() << "readMpiValue: cannot parse line:" << line; 0050 } 0051 } 0052 return QString(); 0053 } 0054 0055 PortableMediaPlayer::PortableMediaPlayer(UDevDevice *device) 0056 : DeviceInterface(device) 0057 { 0058 } 0059 0060 PortableMediaPlayer::~PortableMediaPlayer() 0061 { 0062 } 0063 0064 QStringList PortableMediaPlayer::supportedProtocols() const 0065 { 0066 /* There are multiple packages that set ID_MEDIA_PLAYER: 0067 * * gphoto2 sets it to numeric 1 (for _some_ cameras it supports) and it hopefully 0068 * means MTP-compatible device. 0069 * * libmtp >= 1.0.4 sets it to numeric 1 and this always denotes MTP-compatible player. 0070 * * media-player-info sets it to a string that denotes a name of the .mpi file with 0071 * additional info. 0072 */ 0073 if (m_device->property("ID_MEDIA_PLAYER").toInt() == 1) { 0074 return QStringList() << "mtp"; 0075 } 0076 0077 QString mpiFileName = mediaPlayerInfoFilePath(); 0078 if (mpiFileName.isEmpty()) { 0079 return QStringList(); 0080 } 0081 // we unfornutately cannot use QSettings as it cannot read unquoted valued with semicolons in it 0082 QFile mpiFile(mpiFileName); 0083 if (!mpiFile.open(QIODevice::ReadOnly | QIODevice::Text)) { 0084 qWarning() << "Cannot open" << mpiFileName << "for reading." 0085 << "Check your media-player-info installation."; 0086 return QStringList(); 0087 } 0088 QString value = readMpiValue(mpiFile, QString("Device"), QString("AccessProtocol")); 0089 return value.split(QChar(';'), Qt::SkipEmptyParts); 0090 } 0091 0092 QStringList PortableMediaPlayer::supportedDrivers(QString protocol) const 0093 { 0094 Q_UNUSED(protocol) 0095 QStringList res; 0096 0097 if (!supportedProtocols().isEmpty()) { 0098 res << "usb"; 0099 } 0100 if (m_device->property("USBMUX_SUPPORTED").toBool() == true) { 0101 res << "usbmux"; 0102 } 0103 return res; 0104 } 0105 0106 QVariant PortableMediaPlayer::driverHandle(const QString &driver) const 0107 { 0108 if (driver == "mtp" || driver == "usbmux") { 0109 return m_device->property("ID_SERIAL_SHORT"); 0110 } 0111 0112 return QVariant(); 0113 } 0114 0115 QString PortableMediaPlayer::mediaPlayerInfoFilePath() const 0116 { 0117 QString relativeFilename = m_device->property("ID_MEDIA_PLAYER").toString(); 0118 if (relativeFilename.isEmpty()) { 0119 qWarning() << "We attached PortableMediaPlayer interface to device" << m_device->udi() << "but m_device->property(\"ID_MEDIA_PLAYER\") is empty???"; 0120 return QString(); 0121 } 0122 relativeFilename.prepend("media-player-info/"); 0123 relativeFilename.append(".mpi"); 0124 QString filename = QStandardPaths::locate(QStandardPaths::GenericDataLocation, relativeFilename); 0125 if (filename.isEmpty()) { 0126 qWarning() << "media player info file" << relativeFilename << "not found under user and" 0127 << "system XDG data directories. Do you have media-player-info installed?"; 0128 } 0129 return filename; 0130 } 0131 0132 #include "moc_udevportablemediaplayer.cpp"