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"