diff --git a/.circleci/config.yml b/.circleci/config.yml index 530189e2..ef22c2ad 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -95,9 +95,7 @@ commands: libqt5-linguist-devel libcdio-devel libgpod-devel - libplist-devel libmtp-devel - libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files @@ -149,8 +147,6 @@ commands: taglib-devel libcdio-devel libgpod-devel - libplist-devel - libusbmuxd-devel libmtp-devel libchromaprint-devel fftw-devel @@ -213,8 +209,6 @@ commands: libchromaprint-devel libcdio-devel libgpod-devel - libplist-devel - libusbmuxd-devel libmtp-devel libjpeg-devel cairo-devel @@ -280,8 +274,6 @@ commands: lib64gstreamer-plugins-base1.0-devel lib64cdio-devel lib64gpod-devel - lib64plist-devel - lib64usbmuxd-devel lib64mtp-devel lib64raw1394-devel lib64chromaprint-devel @@ -335,9 +327,6 @@ commands: libcdio-dev libmtp-dev libgpod-dev - libimobiledevice-dev - libplist-dev - libusbmuxd-dev install_ubuntu_dependencies: @@ -389,9 +378,6 @@ commands: libcdio-dev libmtp-dev libgpod-dev - libimobiledevice-dev - libplist-dev - libusbmuxd-dev jobs: diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 6c26a420..8ab70e8a 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -53,9 +53,7 @@ jobs: libqt5-linguist-devel libcdio-devel libgpod-devel - libplist-devel libmtp-devel - libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files @@ -123,9 +121,7 @@ jobs: libqt5-linguist-devel libcdio-devel libgpod-devel - libplist-devel libmtp-devel - libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files @@ -201,9 +197,7 @@ jobs: libqt5-linguist-devel libcdio-devel libgpod-devel - libplist-devel libmtp-devel - libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files @@ -281,9 +275,7 @@ jobs: libqt5-linguist-devel libcdio-devel libgpod-devel - libplist-devel libmtp-devel - libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files @@ -363,9 +355,7 @@ jobs: qt6-qt5compat-devel libcdio-devel libgpod-devel - libplist-devel libmtp-devel - libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files @@ -434,8 +424,6 @@ jobs: taglib-devel libcdio-devel libgpod-devel - libplist-devel - libusbmuxd-devel libmtp-devel libchromaprint-devel fftw-devel @@ -518,8 +506,6 @@ jobs: libchromaprint-devel libcdio-devel libgpod-devel - libplist-devel - libusbmuxd-devel libmtp-devel libjpeg-devel cairo-devel @@ -607,8 +593,6 @@ jobs: lib64gstreamer-plugins-base1.0-devel lib64cdio-devel lib64gpod-devel - lib64plist-devel - lib64usbmuxd-devel lib64mtp-devel lib64raw1394-devel lib64chromaprint-devel @@ -684,9 +668,6 @@ jobs: libcdio-dev libmtp-dev libgpod-dev - libimobiledevice-dev - libplist-dev - libusbmuxd-dev - name: Create Build Environment shell: bash run: cmake -E make_directory build @@ -743,9 +724,6 @@ jobs: libcdio-dev libmtp-dev libgpod-dev - libimobiledevice-dev - libplist-dev - libusbmuxd-dev - name: Create Build Environment shell: bash run: cmake -E make_directory build @@ -807,9 +785,6 @@ jobs: libcdio-dev libmtp-dev libgpod-dev - libimobiledevice-dev - libplist-dev - libusbmuxd-dev - name: Create Build Environment shell: bash run: cmake -E make_directory build @@ -871,9 +846,6 @@ jobs: libcdio-dev libmtp-dev libgpod-dev - libimobiledevice-dev - libplist-dev - libusbmuxd-dev - name: Create Build Environment shell: bash run: cmake -E make_directory build @@ -935,9 +907,6 @@ jobs: libcdio-dev libmtp-dev libgpod-dev - libimobiledevice-dev - libplist-dev - libusbmuxd-dev - name: Create Build Environment shell: bash run: cmake -E make_directory build @@ -980,8 +949,6 @@ jobs: gst-libav libcdio libmtp - libimobiledevice - libplist create-dmg taglib @@ -1045,7 +1012,6 @@ jobs: -DENABLE_WIN32_CONSOLE=OFF -DENABLE_DBUS=OFF -DENABLE_LIBGPOD=OFF - -DENABLE_IMOBILEDEVICE=OFF -DENABLE_LIBMTP=OFF -DProtobuf_PROTOC_EXECUTABLE=/usr/src/strawberry-mxe/usr/x86_64-pc-linux-gnu/bin/protoc diff --git a/.travis.yml b/.travis.yml index c8065778..d3800ec0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ before_install: brew unlink python@2 || travis_terminate 1; brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint zlib taglib; brew install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav; - brew install libcdio libmtp libimobiledevice libplist; + brew install libcdio libmtp; brew install create-dmg; brew cask install sparkle; sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework /Library/Frameworks/Sparkle.framework; diff --git a/CMakeLists.txt b/CMakeLists.txt index 28bd0b2f..302316be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,9 +126,6 @@ pkg_check_modules(LIBPULSE libpulse) pkg_check_modules(CHROMAPRINT libchromaprint) pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92) pkg_check_modules(LIBMTP libmtp>=1.0) -pkg_check_modules(LIBIMOBILEDEVICE libimobiledevice-1.0) -pkg_search_module(LIBUSBMUXD libusbmuxd-2.0 libusbmuxd) -pkg_search_module(LIBPLIST libplist-2.0 libplist) find_package(Gettext) find_package(FFTW3) @@ -344,13 +341,6 @@ optional_component(LIBMTP ON "Devices: MTP support" DEPENDS "libmtp" LIBMTP_FOUND ) -optional_component(IMOBILEDEVICE ON "Devices: iPhone, iPod Touch, iPad and Apple TV support" - DEPENDS "libimobiledevice" LIBIMOBILEDEVICE_FOUND - DEPENDS "libplist" LIBPLIST_FOUND - DEPENDS "libusbmuxd" LIBUSBMUXD_FOUND - DEPENDS "libgpod" HAVE_LIBGPOD -) - optional_component(SPARKLE ON "Sparkle integration" DEPENDS "macOS" APPLE DEPENDS "Sparkle" SPARKLE diff --git a/Changelog b/Changelog index 017e76a2..5c75e96f 100644 --- a/Changelog +++ b/Changelog @@ -36,6 +36,7 @@ Unreleased: Removed features: * Removed Xine engine support. + * Removed broken imobiledevice (iPhone) support. 0.6.13: diff --git a/README.md b/README.md index 5f2f10cf..1a754459 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ You can also make a one-time payment through [paypal.me/jonaskvinge](https://pay * Support for multiple backends * Audio analyzer * Audio equalizer - * Transfer music to iPod, iPhone, MTP or mass-storage USB player + * Transfer music to iPod, MTP or mass-storage USB player * Scrobbler with support for [Last.fm](https://www.last.fm/), [Libre.fm](https://libre.fm/) and [ListenBrainz](https://listenbrainz.org/) * Subsonic and Tidal streaming support @@ -78,7 +78,6 @@ Optional dependencies: * Audio CD: [libcdio](https://www.gnu.org/software/libcdio/) * MTP devices: [libmtp](http://libmtp.sourceforge.net/) * iPod Classic devices: [libgpod](http://www.gtkpod.org/libgpod/) -* iPhone, iPod Touch, iPad and Apple TV devices: [libimobiledevice, libplist and libusbmuxd](https://www.libimobiledevice.org/) * Moodbar: [fftw3](http://www.fftw.org/) Either GStreamer or VLC engine is required, but only GStreamer is fully implemented so far. diff --git a/debian/control b/debian/control index 76f26a11..04b7069b 100644 --- a/debian/control +++ b/debian/control @@ -24,10 +24,7 @@ Build-Depends: debhelper (>= 11), libgstreamer-plugins-base1.0-dev, libcdio-dev, libgpod-dev, - libimobiledevice-dev, libmtp-dev, - libplist-dev, - libusbmuxd-dev, libchromaprint-dev, libfftw3-dev Standards-Version: 4.2.1 diff --git a/dist/unix/PKGBUILD.in b/dist/unix/PKGBUILD.in index 538428f6..0ce5032a 100644 --- a/dist/unix/PKGBUILD.in +++ b/dist/unix/PKGBUILD.in @@ -28,9 +28,6 @@ depends=( libgpod libcdio libmtp - libusbmuxd - libplist - libimobiledevice fftw ) optdepends=( diff --git a/dist/unix/strawberry.spec.in b/dist/unix/strawberry.spec.in index 04082102..90f88a05 100644 --- a/dist/unix/strawberry.spec.in +++ b/dist/unix/strawberry.spec.in @@ -106,7 +106,7 @@ Features: - Support for multiple backends - Audio analyzer - Audio equalizer - - Transfer music to iPod, iPhone, MTP or mass-storage USB player + - Transfer music to iPod, MTP or mass-storage USB player - Scrobbler with support for Last.fm, Libre.fm and ListenBrainz - Streaming support for Subsonic diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 05f4d467..ca12b314 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -101,11 +101,8 @@ parts: - libgstreamer-plugins-base1.0-dev - libvlc-dev - libcdio-dev - - libgpod-dev - - libimobiledevice-dev + - libgpod-devdev - libmtp-dev - - libplist-dev - - libusbmuxd-dev - libchromaprint-dev - libfftw3-dev @@ -131,9 +128,6 @@ parts: - libcdio17 - libgpod4 - libmtp9 - - libimobiledevice6 - - libplist3 - - libusbmuxd4 - libvlc5 - libvlccore9 - libtag1v5 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97a72ad5..eb7e3449 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -737,21 +737,6 @@ optional_source(HAVE_GIO HEADERS device/giolister.h ) -# imobiledevice backend and device -optional_source(HAVE_IMOBILEDEVICE - SOURCES - device/afcdevice.cpp - device/afcfile.cpp - device/afctransfer.cpp - device/ilister.cpp - device/imobiledeviceconnection.cpp - HEADERS - device/afcdevice.h - device/afcfile.h - device/afctransfer.h - device/ilister.h -) - # mtp device optional_source(HAVE_LIBMTP SOURCES @@ -1035,14 +1020,6 @@ if(HAVE_LIBMTP) link_directories(${LIBMTP_LIBRARY_DIRS}) endif(HAVE_LIBMTP) -if(HAVE_IMOBILEDEVICE) - link_directories( - ${LIBUSBMUXD_LIBRARY_DIRS} - ${LIBPLIST_LIBRARY_DIRS} - ${LIBIMOBILEDEVICE_LIBRARY_DIRS} - ) -endif(HAVE_IMOBILEDEVICE) - add_library(strawberry_lib STATIC ${SOURCES} ${MOC} @@ -1163,19 +1140,6 @@ if(HAVE_LIBMTP) target_link_libraries(strawberry_lib PRIVATE ${LIBMTP_LIBRARIES}) endif(HAVE_LIBMTP) -if(HAVE_IMOBILEDEVICE) - target_include_directories(strawberry_lib SYSTEM PRIVATE - ${LIBUSBMUXD_INCLUDE_DIRS} - ${LIBPLIST_INCLUDE_DIRS} - ${LIBIMOBILEDEVICE_INCLUDE_DIRS} - ) - target_link_libraries(strawberry_lib PRIVATE - ${LIBUSBMUXD_LIBRARIES} - ${LIBPLIST_LIBRARIES} - ${LIBIMOBILEDEVICE_LIBRARIES} - ) -endif(HAVE_IMOBILEDEVICE) - if(APPLE) target_link_libraries(strawberry_lib PRIVATE diff --git a/src/config.h.in b/src/config.h.in index 52945c43..31b00637 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -31,7 +31,6 @@ #cmakedefine HAVE_X11 #cmakedefine HAVE_UDISKS2 #cmakedefine HAVE_ALSA -#cmakedefine HAVE_IMOBILEDEVICE #cmakedefine HAVE_AUDIOCD #cmakedefine HAVE_LIBGPOD #cmakedefine HAVE_LIBMTP diff --git a/src/device/afcdevice.cpp b/src/device/afcdevice.cpp deleted file mode 100644 index 91693030..00000000 --- a/src/device/afcdevice.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#include "config.h" - -#include - -#include -#include -#include -#include -#include - -#include "core/application.h" -#include "core/utilities.h" -#include "core/song.h" -#include "afcdevice.h" -#include "afcfile.h" -#include "afctransfer.h" -#include "devicemanager.h" -#include "gpodloader.h" -#include "imobiledeviceconnection.h" - -AfcDevice::AfcDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, DeviceManager *manager, Application *app, const int database_id, const bool first_time) : GPodDevice(url, lister, unique_id, manager, app, database_id, first_time), transfer_(nullptr) {} - -AfcDevice::~AfcDevice() { - - Utilities::RemoveRecursive(local_path_); - - if (loader_) { - loader_->deleteLater(); - loader_ = nullptr; - } - - if (loader_thread_) { - loader_thread_->exit(); - loader_thread_->deleteLater(); - loader_thread_ = nullptr; - } - -} - -bool AfcDevice::Init() { - - // Make a new temporary directory for the iTunesDB. We copy it off the iPod so that libgpod can have a local directory to use. - local_path_ = Utilities::MakeTempDir(); - InitBackendDirectory(local_path_, first_time_, false); - model_->Init(); - - if (!loader_thread_) loader_thread_ = new QThread(); - - if (url_.isEmpty() || url_.path().isEmpty()) return false; - - transfer_ = new AfcTransfer(url_.host(), local_path_, app_->task_manager(), shared_from_this()); - transfer_->moveToThread(loader_thread_); - - connect(transfer_, SIGNAL(TaskStarted(int)), SIGNAL(TaskStarted(int))); - connect(transfer_, SIGNAL(CopyFinished(bool)), SLOT(CopyFinished(bool))); - - connect(loader_thread_, SIGNAL(started()), transfer_, SLOT(CopyFromDevice())); - loader_thread_->start(); - - return true; - -} - -void AfcDevice::CopyFinished(const bool success) { - - transfer_->deleteLater(); - transfer_ = nullptr; - - if (!success) { - app_->AddError(tr("An error occurred copying the iTunes database from the device")); - return; - } - - // Now load the songs from the local database - loader_ = new GPodLoader(local_path_, app_->task_manager(), backend_, shared_from_this()); - loader_->set_music_path_prefix("afc://" + url_.host()); - loader_->set_song_type(Song::FileType_Stream); - loader_->moveToThread(loader_thread_); - - connect(loader_, SIGNAL(Error(QString)), SLOT(LoaderError(QString))); - connect(loader_, SIGNAL(TaskStarted(int)), SIGNAL(TaskStarted(int))); - connect(loader_, SIGNAL(LoadFinished(Itdb_iTunesDB*, bool)), SLOT(LoadFinished(Itdb_iTunesDB*, bool))); - QMetaObject::invokeMethod(loader_, "LoadDatabase"); - -} - -bool AfcDevice::StartCopy(QList *supported_types) { - - GPodDevice::StartCopy(supported_types); - connection_.reset(new iMobileDeviceConnection(url_.host())); - - return true; - -} - -bool AfcDevice::CopyToStorage(const CopyJob &job) { - - Q_ASSERT(db_); - - Itdb_Track *track = AddTrackToITunesDb(job.metadata_); - - // Get an unused filename on the device - QString dest = connection_->GetUnusedFilename(db_, job.metadata_); - if (dest.isEmpty()) { - itdb_track_remove(track); - return false; - } - - // Copy the file - { - QFile source_file(job.source_); - AfcFile dest_file(connection_.get(), dest); - if (!Utilities::Copy(&source_file, &dest_file)) - return false; - } - - track->transferred = 1; - - // Set the filetype_marker - QString suffix = dest.section('.', -1, -1).toUpper(); - track->filetype_marker = 0; - for (int i=0 ; i<4 ; ++i) { - track->filetype_marker = track->filetype_marker << 8; - if (i >= suffix.length()) - track->filetype_marker |= ' '; - else - track->filetype_marker |= suffix[i].toLatin1(); - } - - // Set the filename - track->ipod_path = strdup(dest.toUtf8().constData()); - itdb_filename_fs2ipod(track->ipod_path); - - AddTrackToModel(track, "afc://" + url_.host()); - - // Remove the original if it was requested - if (job.remove_original_) { - QFile::remove(job.source_); - } - - return true; - -} - -void AfcDevice::FinishCopy(bool success) { - - // Temporarily unset the GUID so libgpod doesn't lock the device for syncing - itdb_device_set_sysinfo(db_->device, "FirewireGuid", nullptr); - - GPodDevice::FinishCopy(success); - - // Close the connection to the device - connection_.reset(); - -} - -void AfcDevice::FinaliseDatabase() { - - // Set the GUID again to lock the device for syncing - itdb_device_set_sysinfo(db_->device, "FirewireGuid", url_.host().toUtf8().constData()); - - // Copy the files back to the iPod - // No need to start another thread since we're already in the organizer thread - AfcTransfer transfer(url_.host(), local_path_, nullptr, shared_from_this()); - - itdb_start_sync(db_); - bool success = transfer.CopyToDevice(connection_.get()); - itdb_stop_sync(db_); - - if (!success) { - app_->AddError(tr("An error occurred copying the iTunes database onto the device")); - return; - } - -} - -bool AfcDevice::DeleteFromStorage(const DeleteJob &job) { - - const QString path = job.metadata_.url().toLocalFile(); - - if (!RemoveTrackFromITunesDb(path)) - return false; - - // Remove the file - if (afc_remove_path(connection_->afc(), path.toUtf8().constData()) != AFC_E_SUCCESS) - return false; - - // Remove it from our collection model - songs_to_remove_ << job.metadata_; - - return true; - -} diff --git a/src/device/afcdevice.h b/src/device/afcdevice.h deleted file mode 100644 index 6036ac07..00000000 --- a/src/device/afcdevice.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#ifndef AFCDEVICE_H -#define AFCDEVICE_H - -#include "config.h" - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "gpoddevice.h" - -class AfcTransfer; -class iMobileDeviceConnection; - -class AfcDevice : public GPodDevice { - Q_OBJECT - -public: - Q_INVOKABLE AfcDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, DeviceManager *manager, Application *app, const int database_id, const bool first_time); - ~AfcDevice() override; - - bool Init() override; - - static QStringList url_schemes() { return QStringList() << "afc"; } - - bool StartCopy(QList *supported_types) override; - bool CopyToStorage(const CopyJob &job) override; - void FinishCopy(const bool success) override; - - bool DeleteFromStorage(const DeleteJob &job) override; - - protected: - void FinaliseDatabase() override; - - private slots: - void CopyFinished(bool success); - - private: - void RemoveRecursive(const QString &path); - - private: - AfcTransfer *transfer_; - std::shared_ptr connection_; - - QString local_path_; -}; - -#endif // AFCDEVICE_H diff --git a/src/device/afcfile.cpp b/src/device/afcfile.cpp deleted file mode 100644 index 71300744..00000000 --- a/src/device/afcfile.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "config.h" - -#include - -#include -#include -#include -#include - -#include "afcfile.h" -#include "imobiledeviceconnection.h" - -AfcFile::AfcFile(iMobileDeviceConnection *connection, const QString &path, QObject *parent) - : QIODevice(parent), - connection_(connection), - handle_(0), - path_(path) -{ -} - -AfcFile::~AfcFile() { - close(); -} - -bool AfcFile::open(QIODevice::OpenMode mode) { - - afc_file_mode_t afc_mode; - switch (mode) { - case ReadOnly: - afc_mode = AFC_FOPEN_RDONLY; - break; - case WriteOnly: - afc_mode = AFC_FOPEN_WRONLY; - break; - case ReadWrite: - afc_mode = AFC_FOPEN_RW; - break; - - default: - afc_mode = AFC_FOPEN_RW; - } - afc_error_t err = afc_file_open(connection_->afc(), path_.toUtf8().constData(), afc_mode, &handle_); - if (err != AFC_E_SUCCESS) { - return false; - } - - return QIODevice::open(mode); - -} - -void AfcFile::close() { - - if (handle_) { - afc_file_close(connection_->afc(), handle_); - } - QIODevice::close(); - -} - -bool AfcFile::seek(qint64 pos) { - - afc_error_t err = afc_file_seek(connection_->afc(), handle_, pos, SEEK_SET); - if (err != AFC_E_SUCCESS) { - return false; - } - QIODevice::seek(pos); - return true; - -} - -qint64 AfcFile::readData(char *data, qint64 max_size) { - - uint32_t bytes_read = 0; - afc_error_t err = afc_file_read(connection_->afc(), handle_, data, max_size, &bytes_read); - if (err != AFC_E_SUCCESS) { - return -1; - } - return bytes_read; - -} - -qint64 AfcFile::writeData(const char *data, qint64 max_size) { - - uint32_t bytes_written = 0; - afc_error_t err = afc_file_write(connection_->afc(), handle_, data, max_size, &bytes_written); - if (err != AFC_E_SUCCESS) { - return -1; - } - return bytes_written; - -} - -qint64 AfcFile::size() const { - return connection_->GetFileInfo(path_, "st_size").toLongLong(); -} diff --git a/src/device/afcfile.h b/src/device/afcfile.h deleted file mode 100644 index e7dd57da..00000000 --- a/src/device/afcfile.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef AFCFILE_H -#define AFCFILE_H - -#include "config.h" - -#include -#include - -#include -#include -#include -#include - -class iMobileDeviceConnection; - -class AfcFile : public QIODevice { - Q_OBJECT - - public: - explicit AfcFile(iMobileDeviceConnection* connection, const QString &path, QObject *parent = nullptr); - ~AfcFile() override; - - // QIODevice - void close() override; - bool open(OpenMode mode) override; - bool seek(qint64 pos) override; - qint64 size() const override; - - private: - // QIODevice - qint64 readData(char *data, qint64 max_size) override; - qint64 writeData(const char *data, qint64 max_size) override; - - iMobileDeviceConnection *connection_; - uint64_t handle_; - - QString path_; -}; - -#endif diff --git a/src/device/afctransfer.cpp b/src/device/afctransfer.cpp deleted file mode 100644 index 32ed5f90..00000000 --- a/src/device/afctransfer.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#include "config.h" - -#include - -#include -#include -#include -#include -#include - -#include "core/utilities.h" -#include "core/taskmanager.h" -#include "afcfile.h" -#include "afctransfer.h" -#include "imobiledeviceconnection.h" - -AfcTransfer::AfcTransfer(const QString &uuid, const QString &local_destination, TaskManager *task_manager, std::shared_ptr device) - : QObject(nullptr), device_(device), task_manager_(task_manager), uuid_(uuid), local_destination_(local_destination) { - - original_thread_ = thread(); - - important_directories_ << "/iTunes_Control/Artwork"; - important_directories_ << "/iTunes_Control/Device"; - important_directories_ << "/iTunes_Control/iTunes"; - -} - -void AfcTransfer::CopyFromDevice() { - - int task_id = 0; - if (task_manager_) { - task_id = task_manager_->StartTask(tr("Copying iPod database")); - emit TaskStarted(task_id); - } - - // Connect to the device - - iMobileDeviceConnection c(uuid_); - - // Copy directories. If one fails we stop. - bool success = true; - for (const QString &dir : important_directories_) { - if (!CopyDirFromDevice(&c, dir)) { - success = false; - break; - } - } - - if (task_manager_) { - moveToThread(original_thread_); - task_manager_->SetTaskFinished(task_id); - emit CopyFinished(success); - } - -} - -bool AfcTransfer::CopyToDevice(iMobileDeviceConnection *connection) { - - // Connect to the device - if (!connection) - connection = new iMobileDeviceConnection(uuid_); - - for (const QString &dir : important_directories_) - if (!CopyDirToDevice(connection, dir)) - return false; - - return true; - -} - -bool AfcTransfer::CopyDirFromDevice(iMobileDeviceConnection *c, const QString &path) { - - for (const QString &filename : c->ReadDirectory(path, QDir::Files | QDir::NoDotAndDotDot)) { - if (!CopyFileFromDevice(c, path + "/" + filename)) - return false; - } - - for (const QString &dir : c->ReadDirectory(path, QDir::Dirs | QDir::NoDotAndDotDot)) { - if (!CopyDirFromDevice(c, path + "/" + dir)) - return false; - } - return true; - -} - -bool AfcTransfer::CopyDirToDevice(iMobileDeviceConnection *c, const QString &path) { - - QDir dir(local_destination_ + path); - - if (!c->Exists(path)) { - c->MkDir(path); - } - - for (const QString &i : dir.entryList(QDir::Files | QDir::NoDotAndDotDot)) { - if (!CopyFileToDevice(c, path + "/" + i)) - return false; - } - - for (const QString &i : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { - if (!CopyDirToDevice(c, path + "/" + i)) - return false; - } - - return true; - -} - -bool AfcTransfer::CopyFileFromDevice(iMobileDeviceConnection *c, const QString &path) { - - QString local_filename = local_destination_ + path; - QString local_dir = local_filename.section('/', 0, -2); - - QDir d; - d.mkpath(local_dir); - - QFile dest(local_filename); - AfcFile source(c, path); - - return Utilities::Copy(&source, &dest); - -} - -bool AfcTransfer::CopyFileToDevice(iMobileDeviceConnection *c, const QString &path) { - - QFile source(local_destination_ + path); - AfcFile dest(c, path); - - return Utilities::Copy(&source, &dest); - -} diff --git a/src/device/afctransfer.h b/src/device/afctransfer.h deleted file mode 100644 index 94c8c353..00000000 --- a/src/device/afctransfer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#ifndef AFCTRANSFER_H -#define AFCTRANSFER_H - -#include "config.h" - -#include - -#include -#include -#include -#include -#include - -class TaskManager; -class ConnectedDevice; -class iMobileDeviceConnection; - -class AfcTransfer : public QObject { - Q_OBJECT - - public: - explicit AfcTransfer(const QString &uuid, const QString &local_destination, TaskManager *task_manager, std::shared_ptr device); - - bool CopyToDevice(iMobileDeviceConnection *connection); - - public slots: - void CopyFromDevice(); - - signals: - void TaskStarted(int task_id); - void CopyFinished(bool success); - - private: - bool CopyDirFromDevice(iMobileDeviceConnection *c, const QString &path); - bool CopyDirToDevice(iMobileDeviceConnection *c, const QString &path); - bool CopyFileFromDevice(iMobileDeviceConnection *c, const QString &path); - bool CopyFileToDevice(iMobileDeviceConnection *c, const QString &path); - - private: - QThread *original_thread_; - std::shared_ptr device_; - TaskManager *task_manager_; - QString uuid_; - QString local_destination_; - - QStringList important_directories_; - -}; - -#endif // AFCTRANSFER_H diff --git a/src/device/devicemanager.cpp b/src/device/devicemanager.cpp index 827b67a0..e97b9d69 100644 --- a/src/device/devicemanager.cpp +++ b/src/device/devicemanager.cpp @@ -73,10 +73,6 @@ #ifdef HAVE_LIBMTP # include "mtpdevice.h" #endif -#ifdef HAVE_IMOBILEDEVICE -# include "afcdevice.h" -# include "ilister.h" -#endif #if defined(Q_OS_MACOS) and defined(HAVE_LIBMTP) # include "macosdevicelister.h" #endif @@ -125,9 +121,6 @@ DeviceManager::DeviceManager(Application *app, QObject *parent) #if defined(Q_OS_MACOS) and defined(HAVE_LIBMTP) AddLister(new MacOsDeviceLister); #endif -#ifdef HAVE_IMOBILEDEVICE - AddLister(new iLister); -#endif #if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER) AddDeviceClass(); @@ -143,10 +136,6 @@ DeviceManager::DeviceManager(Application *app, QObject *parent) AddDeviceClass(); #endif -#ifdef HAVE_IMOBILEDEVICE - AddDeviceClass(); -#endif - } DeviceManager::~DeviceManager() { diff --git a/src/device/ilister.cpp b/src/device/ilister.cpp deleted file mode 100644 index c7426f3d..00000000 --- a/src/device/ilister.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "ilister.h" -#include "imobiledeviceconnection.h" - -iLister::iLister() {} - -iLister::~iLister() {} - -bool iLister::Init() { - - idevice_event_subscribe(&EventCallback, reinterpret_cast(this)); - return true; - -} - -void iLister::EventCallback(const idevice_event_t *event, void *context) { - - iLister *me = reinterpret_cast(context); - - QString uuid = QString::fromUtf8(event->udid); - - switch (event->event) { - case IDEVICE_DEVICE_ADD: - me->DeviceAddedCallback(uuid); - break; - - case IDEVICE_DEVICE_REMOVE: - me->DeviceRemovedCallback(uuid); - break; - default: - break; - } -} - - -void iLister::DeviceAddedCallback(const QString uuid) { - - DeviceInfo info = ReadDeviceInfo(uuid); - if (!info.valid) return; - - QString id = UniqueId(uuid); - - QString name = MakeFriendlyName(id); - if (info.product_type == "iPhone 3,1" || info.product_type.startsWith("iPad")) { - // iPhone 4 and iPad unsupported by libgpod as of 0.7.94. - return; - } - - { - QMutexLocker l(&mutex_); - devices_[id] = info; - } - - emit DeviceAdded(id); - -} - -void iLister::DeviceRemovedCallback(const QString uuid) { - - QString id = UniqueId(uuid); - - { - QMutexLocker l(&mutex_); - if (!devices_.contains(id)) - return; - - devices_.remove(id); - } - - emit DeviceRemoved(id); - -} - -QString iLister::UniqueId(const QString uuid) { - return "ithing/" + uuid; -} - -QStringList iLister::DeviceUniqueIDs() { - return devices_.keys(); -} - -QVariantList iLister::DeviceIcons(const QString &id) { - Q_UNUSED(id); - return QVariantList() << "ipodtouchicon"; -} - -QString iLister::DeviceManufacturer(const QString &id) { - Q_UNUSED(id); - return "Apple"; -} - -QString iLister::DeviceModel(const QString &id) { - return LockAndGetDeviceInfo(id, &DeviceInfo::product_type); -} - -quint64 iLister::DeviceCapacity(const QString &id) { - return LockAndGetDeviceInfo(id, &DeviceInfo::total_bytes); -} - -quint64 iLister::DeviceFreeSpace(const QString &id) { - return LockAndGetDeviceInfo(id, &DeviceInfo::free_bytes); -} - -QVariantMap iLister::DeviceHardwareInfo(const QString &id) { - - QVariantMap ret; - ret[tr("Color")] = LockAndGetDeviceInfo(id, &DeviceInfo::colour); - ret["IMEI"] = LockAndGetDeviceInfo(id, &DeviceInfo::imei); - ret[tr("Password Protected")] = LockAndGetDeviceInfo(id, &DeviceInfo::password_protected); - ret[tr("Timezone")] = LockAndGetDeviceInfo(id, &DeviceInfo::timezone); - ret[tr("WiFi MAC Address")] = LockAndGetDeviceInfo(id, &DeviceInfo::wifi_mac); - ret[tr("Bluetooth MAC Address")] = LockAndGetDeviceInfo(id, &DeviceInfo::bt_mac); - - return ret; - -} - -QString iLister::MakeFriendlyName(const QString &id) { - - QString name = LockAndGetDeviceInfo(id, &DeviceInfo::name); - if (!name.isEmpty()) { - return name; - } - - QString model_id = LockAndGetDeviceInfo(id, &DeviceInfo::product_type); - - if (model_id.startsWith("iPhone")) { - QString version = model_id.right(3); - QChar major = version[0]; - QChar minor = version[2]; - if (major == '1' && minor == '1') { - return "iPhone"; - } - if (major == '1' && minor == '2') { - return "iPhone 3G"; - } - if (major == '2' && minor == '1') { - return "iPhone 3GS"; - } - if (major == '3' && minor == '1') { - return "iPhone 4"; - } - } - else if (model_id.startsWith("iPod")) { - return "iPod Touch"; - } - else if (model_id.startsWith("iPad")) { - return "iPad"; - } - return model_id; - -} - -QList iLister::MakeDeviceUrls(const QString &id) { - - QList ret; - - QString uuid = LockAndGetDeviceInfo(id, &DeviceInfo::uuid); - if (uuid.isEmpty()) - return ret; - - ret << QUrl("afc://" + uuid + "/"); - - return ret; - -} - -iLister::DeviceInfo iLister::ReadDeviceInfo(const QString uuid) { - - DeviceInfo ret; - - iMobileDeviceConnection conn(uuid); - if (!conn.is_valid()) return ret; - - ret.valid = conn.is_valid(); - ret.uuid = uuid; - ret.product_type = conn.GetProperty("ProductType").toString(); - ret.free_bytes = conn.GetProperty("AmountDataAvailable", "com.apple.disk_usage").toULongLong(); - ret.total_bytes = conn.GetProperty("TotalDataCapacity", "com.apple.disk_usage").toULongLong(); - ret.name = conn.GetProperty("DeviceName").toString(); - - ret.colour = conn.GetProperty("DeviceColor").toString(); - ret.imei = conn.GetProperty("InternationalMobileEquipmentIdentity").toString(); - ret.hardware = conn.GetProperty("HardwareModel").toString(); - ret.password_protected = conn.GetProperty("PasswordProtected").toBool(); - ret.os_version = conn.GetProperty("ProductVersion").toString(); - ret.timezone = conn.GetProperty("TimeZone").toString(); - ret.wifi_mac = conn.GetProperty("WiFiAddress").toString(); - ret.bt_mac = conn.GetProperty("BluetoothAddress").toString(); - - return ret; - -} - -void iLister::UpdateDeviceFreeSpace(const QString &id) { - - { - QMutexLocker l(&mutex_); - if (!devices_.contains(id)) - return; - - DeviceInfo &info = devices_[id]; - iMobileDeviceConnection conn(info.uuid); - - info.free_bytes = conn.GetProperty("AmountDataAvailable", "com.apple.disk_usage").toULongLong(); - } - - emit DeviceChanged(id); - -} diff --git a/src/device/ilister.h b/src/device/ilister.h deleted file mode 100644 index 78c6bd10..00000000 --- a/src/device/ilister.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#ifndef ILISTER_H -#define ILISTER_H - -#include "config.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "devicelister.h" - -class iLister : public DeviceLister { - Q_OBJECT - - public: - explicit iLister(); - ~iLister() override; - - int priority() const override { return 120; } - - QStringList DeviceUniqueIDs() override; - QVariantList DeviceIcons(const QString &id) override; - QString DeviceManufacturer(const QString &id) override; - QString DeviceModel(const QString &id) override; - quint64 DeviceCapacity(const QString &id) override; - quint64 DeviceFreeSpace(const QString &id) override; - QVariantMap DeviceHardwareInfo(const QString &id) override; - QString MakeFriendlyName(const QString &id) override; - QList MakeDeviceUrls(const QString &id) override; - - public slots: - void UpdateDeviceFreeSpace(const QString &id) override; - - private: - struct DeviceInfo { - DeviceInfo() : valid(false), free_bytes(0), total_bytes(0), password_protected(false) {} - - bool valid; - - QString uuid; - QString product_type; - quint64 free_bytes; - quint64 total_bytes; - QString name; // Name given to the iDevice by the user. - - // Extra information. - QString colour; - QString imei; - QString hardware; - bool password_protected; - QString os_version; - QString timezone; - QString wifi_mac; - QString bt_mac; - }; - - bool Init() override; - - static void EventCallback(const idevice_event_t *event, void *context); - - void DeviceAddedCallback(const QString uuid); - void DeviceRemovedCallback(const QString uuid); - - DeviceInfo ReadDeviceInfo(const QString uuid); - static QString UniqueId(const QString uuid); - - template - T LockAndGetDeviceInfo(const QString &id, T DeviceInfo::*field); - - private: - QMutex mutex_; - QMap devices_; -}; - -template -T iLister::LockAndGetDeviceInfo(const QString &id, T DeviceInfo::*field) { - QMutexLocker l(&mutex_); - if (!devices_.contains(id)) - return T(); - - return devices_[id].*field; -} - -#endif diff --git a/src/device/imobiledeviceconnection.cpp b/src/device/imobiledeviceconnection.cpp deleted file mode 100644 index 8394e28b..00000000 --- a/src/device/imobiledeviceconnection.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#include "config.h" - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) -# include -#endif - -#include "core/logging.h" -#include "imobiledeviceconnection.h" - -iMobileDeviceConnection::iMobileDeviceConnection(const QString uuid) : device_(nullptr), afc_(nullptr) { - - idevice_error_t err = idevice_new(&device_, uuid.toUtf8().constData()); - if (err != IDEVICE_E_SUCCESS) { - qLog(Warning) << "idevice_new error:" << err; - return; - } - - QByteArray label_ascii = QCoreApplication::applicationName().toUtf8(); - const char *label = label_ascii.constData(); - - lockdownd_client_t lockdown; - lockdownd_error_t lockdown_err = lockdownd_client_new_with_handshake(device_, &lockdown, label); - if (lockdown_err != LOCKDOWN_E_SUCCESS) { - qLog(Warning) << "lockdownd_client_new_with_handshake error:" << lockdown_err; - return; - } - - lockdownd_service_descriptor_t lockdown_service_desc; - lockdown_err = lockdownd_start_service(lockdown, "com.apple.afc", &lockdown_service_desc); - if (lockdown_err != LOCKDOWN_E_SUCCESS) { - qLog(Warning) << "lockdownd_start_service error:" << lockdown_err; - lockdownd_client_free(lockdown); - return; - } - - afc_error_t afc_err = afc_client_new(device_, lockdown_service_desc, &afc_); - if (afc_err != AFC_E_SUCCESS) { - qLog(Warning) << "afc_client_new error:" << afc_err; - lockdownd_client_free(lockdown); - return; - } - - lockdownd_client_free(lockdown); - -} - -iMobileDeviceConnection::~iMobileDeviceConnection() { - - if (afc_) { - afc_client_free(afc_); - } - if (device_) { - idevice_free(device_); - } - -} - -template -T GetPListValue(plist_t node, F f) { - T ret; - f(node, &ret); - return ret; -} - -QVariant iMobileDeviceConnection::GetProperty(const QString &property, const QString &domain) { - - if (!device_) return QVariant(); - - lockdownd_client_t lockdown; - QByteArray label_ascii = QCoreApplication::applicationName().toUtf8(); - const char *label = label_ascii.constData(); - - lockdownd_error_t lockdown_err = lockdownd_client_new_with_handshake(device_, &lockdown, label); - if (lockdown_err != LOCKDOWN_E_SUCCESS) { - qLog(Warning) << "lockdown error:" << lockdown_err; - return QVariant(); - } - - plist_t node = nullptr; - QByteArray domain_ascii = domain.toUtf8(); - const char *d = domain_ascii.isEmpty() ? nullptr : domain_ascii.constData(); - //const char *d = domain.isEmpty() ? nullptr : "com.apple.disk_usage"; - lockdownd_get_value(lockdown, d, property.toUtf8().constData(), &node); - lockdownd_client_free(lockdown); - - if (!node) { - qLog(Warning) << "get_value failed" << property << domain; - return QVariant(); - } - - switch (plist_get_node_type(node)) { - case PLIST_BOOLEAN: - return bool(GetPListValue(node, plist_get_bool_val)); - - case PLIST_UINT: - return QVariant::fromValue(GetPListValue(node, plist_get_uint_val)); - - case PLIST_STRING: { - char *data = GetPListValue(node, plist_get_string_val); - QString ret = QString::fromUtf8(data); - free(data); - return ret; - } - - default: - qLog(Warning) << "Unhandled PList type"; - return QVariant(); - } - -} - -QStringList iMobileDeviceConnection::ReadDirectory(const QString &path, QDir::Filters filters) { - - if (!afc_) return QStringList(); - - char **list = nullptr; - afc_error_t err = afc_read_directory(afc_, path.toUtf8().constData(), &list); - if (err != AFC_E_SUCCESS || !list) { - return QStringList(); - } - - QStringList ret; - for (char **p = list ; *p != nullptr ; ++p) { - QString filename = QString::fromUtf8(*p); - free(*p); - - if (filters == QDir::NoFilter) - ret << filename; - else { - if (filters & QDir::NoDotAndDotDot && (filename == "." || filename == "..")) - continue; - if (!(filters & QDir::Hidden) && filename.startsWith(".")) - continue; - - QString filetype = GetFileInfo(path + "/" + filename, "st_ifmt"); - if ((filetype == "S_IFREG" && (filters & QDir::Files)) || (filetype == "S_IFDIR" && (filters & QDir::Dirs)) || (filetype == "S_IFLNK" && (!(filters & QDir::NoSymLinks)))) - ret << filename; - } - } - free(list); - - return ret; - -} - -bool iMobileDeviceConnection::MkDir(const QString &path) { - - if (!afc_) return false; - - afc_error_t err = afc_make_directory(afc_, path.toUtf8().constData()); - return err == AFC_E_SUCCESS; -} - -QString iMobileDeviceConnection::GetFileInfo(const QString &path, const QString &key) { - - if (!afc_) return QString(); - - QString ret; - char **infolist = nullptr; - afc_error_t err = afc_get_file_info(afc_, path.toUtf8().constData(), &infolist); - if (err != AFC_E_SUCCESS || !infolist) { - qLog(Debug) << "afc_get_file_info error:" << path << err; - return ret; - } - - QString last_key; - for (char **p = infolist ; *p != nullptr ; ++p) { - if (last_key.isNull()) { - last_key = QString::fromUtf8(*p); - } - else { - if (last_key == key) - ret = QString::fromUtf8(*p); - last_key = QString(); - } - free(*p); - } - free(infolist); - return ret; - -} - -bool iMobileDeviceConnection::Exists(const QString &path) { - return !GetFileInfo(path, "st_ifmt").isNull(); -} - -QString iMobileDeviceConnection::GetUnusedFilename(Itdb_iTunesDB *itdb, const Song &metadata) { - - Q_UNUSED(itdb); - - // This function does the same as itdb_cp_get_dest_filename, except it accesses the device's filesystem through imobiledevice. - - // Get the total number of F.. directories - int total_musicdirs = 0; - for ( ; ; ++total_musicdirs) { - QString dir = QString::asprintf("/iTunes_Control/Music/F%02d", total_musicdirs); - - if (!Exists(dir)) - break; - } - - if (total_musicdirs <= 0) { - qLog(Warning) << "No 'F..'' directories found on iPod"; - return QString(); - } - - // Pick one at random -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - const int dir_num = QRandomGenerator::global()->bounded(total_musicdirs); -#else - const int dir_num = qrand() % total_musicdirs; -#endif - - QString dir = QString::asprintf("/iTunes_Control/Music/F%02d", dir_num); - - if (!Exists(dir)) { - qLog(Warning) << "Music directory doesn't exist:" << dir; - return QString(); - } - - // Use the same file extension as the original file, default to mp3. - QString extension = metadata.url().path().section('.', -1, -1).toLower(); - if (extension.isEmpty()) - extension = "mp3"; - - // Loop until we find an unused filename. - // Use the same naming convention as libgpod, which is "libgpod" + 6-digit random number - static const int kRandMax = 999999; - QString filename; - forever { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - filename = QString::asprintf("libgpod%06d", QRandomGenerator::global()->bounded(kRandMax)); -#else - filename = QString::asprintf("libgpod%06d", qrand() % kRandMax); -#endif - filename += "." + extension; - - if (!Exists(dir + "/" + filename)) - break; - } - - return dir + "/" + filename; - -} diff --git a/src/device/imobiledeviceconnection.h b/src/device/imobiledeviceconnection.h deleted file mode 100644 index a6bff221..00000000 --- a/src/device/imobiledeviceconnection.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Strawberry Music Player - * This file was part of Clementine. - * Copyright 2010, David Sansome - * - * 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 . - * - */ - -#ifndef IMOBILEDEVICECONNECTION_H -#define IMOBILEDEVICECONNECTION_H - -#include "config.h" - -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "core/song.h" - -class iMobileDeviceConnection { -public: - explicit iMobileDeviceConnection(const QString uuid); - ~iMobileDeviceConnection(); - - afc_client_t afc() { return afc_; } - - QVariant GetProperty(const QString &property, const QString &domain = QString()); - QStringList ReadDirectory(const QString &path, QDir::Filters filters = QDir::NoFilter); - bool MkDir(const QString &path); - - QString GetFileInfo(const QString &path, const QString &key); - bool Exists(const QString &path); - - QString GetUnusedFilename(Itdb_iTunesDB *itdb, const Song &metadata); - - bool is_valid() { return device_ && afc_; } - -private: - Q_DISABLE_COPY(iMobileDeviceConnection) - - idevice_t device_; - afc_client_t afc_; -}; - -#endif // IMOBILEDEVICECONNECTION_H