Add almost-working support for writing to ipods

This commit is contained in:
David Sansome 2010-07-24 16:58:14 +00:00
parent a99afd75ff
commit b624be9800
9 changed files with 111 additions and 4 deletions

View File

@ -30,9 +30,11 @@ public:
virtual QString LocalPath() const { return QString(); }
virtual void StartCopy() {}
virtual bool CopyToStorage(const QString& source, const QString& destination,
const Song& metadata, bool overwrite,
bool remove_original) = 0;
virtual void FinishCopy() {}
};
Q_DECLARE_METATYPE(MusicStorage*);

View File

@ -35,6 +35,7 @@ Organise::Organise(TaskManager* task_manager, MusicStorage* destination,
copy_(copy),
overwrite_(overwrite),
files_(files),
started_(false),
task_id_(0),
progress_(0)
{
@ -56,8 +57,15 @@ void Organise::Start() {
}
void Organise::ProcessSomeFiles() {
if (!started_) {
destination_->StartCopy();
started_ = true;
}
// None left?
if (progress_ >= files_.count()) {
destination_->FinishCopy();
task_manager_->SetTaskFinished(task_id_);
// Move back to the original thread so deleteLater() can get called in

View File

@ -50,6 +50,8 @@ private:
const bool overwrite_;
QStringList files_;
bool started_;
int task_id_;
int progress_;
};

View File

@ -562,6 +562,38 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
d->filename_ = QString::fromLocal8Bit(track->ipod_path);
d->basefilename_ = QFileInfo(d->filename_).fileName();
}
static void CopyStr(const QString& str, gchar** dest_p) {
Q_ASSERT(*dest_p == NULL);
const QByteArray data = str.toUtf8();
const int size = data.size() + 1;
gchar* dest = new gchar[size];
std::copy(data.constData(), data.constData() + size, dest);
*dest_p = dest;
}
void Song::ToItdb(Itdb_Track *track) const {
CopyStr(d->title_, &track->title);
CopyStr(d->album_, &track->album);
CopyStr(d->artist_, &track->artist);
CopyStr(d->albumartist_, &track->albumartist);
CopyStr(d->composer_, &track->composer);
track->track_nr = d->track_;
track->cd_nr = d->disc_;
track->BPM = d->bpm_;
track->year = d->year_;
CopyStr(d->genre_, &track->genre);
CopyStr(d->comment_, &track->comment);
track->compilation = d->compilation_;
track->tracklen = d->length_ * 1000;
track->bitrate = d->bitrate_;
track->samplerate = d->samplerate_;
track->time_modified = d->mtime_;
track->time_added = d->ctime_;
track->size = d->filesize_;
track->type2 = d->filetype_ == Type_Mp4 ? 0 : 1;
}
#endif
void Song::MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle) {

View File

@ -128,6 +128,7 @@ class Song {
#ifdef HAVE_LIBGPOD
void InitFromItdb(Itdb_Track* track);
void ToItdb(Itdb_Track* track) const;
#endif
static QString Decode(const TagLib::String& tag, const QTextCodec* codec);

View File

@ -23,10 +23,11 @@
#include <QtDebug>
ConnectedDevice::ConnectedDevice(const QUrl&, DeviceLister* lister,
ConnectedDevice::ConnectedDevice(const QUrl& url, DeviceLister* lister,
const QString& unique_id, DeviceManager* manager,
int database_id, bool)
: QObject(manager),
url_(url),
lister_(lister),
unique_id_(unique_id),
database_id_(database_id),

View File

@ -51,6 +51,7 @@ protected:
void InitBackendDirectory(const QString& mount_point, bool first_time);
protected:
QUrl url_;
DeviceLister* lister_;
QString unique_id_;
int database_id_;

View File

@ -29,7 +29,8 @@ GPodDevice::GPodDevice(
int database_id, bool first_time)
: ConnectedDevice(url, lister, unique_id, manager, database_id, first_time),
loader_thread_(new QThread(this)),
loader_(new GPodLoader(url.path(), manager->task_manager(), backend_))
loader_(new GPodLoader(url.path(), manager->task_manager(), backend_)),
active_copy_db_(NULL)
{
InitBackendDirectory(url.path(), first_time);
model_->Init();
@ -44,13 +45,65 @@ GPodDevice::GPodDevice(
}
GPodDevice::~GPodDevice() {
}
void GPodDevice::StartCopy() {
active_copy_mutex_.lock();
// Load the iTunes database
GError* error = NULL;
active_copy_db_ = itdb_parse(url_.path().toLocal8Bit(), &error);
// Check for errors
if (!active_copy_db_) {
qDebug() << "GPodDevice error:" << error->message;
emit Error(QString::fromUtf8(error->message));
g_error_free(error);
}
}
bool GPodDevice::CopyToStorage(
const QString &source, const QString &destination,
const Song &metadata, bool overwrite, bool remove_original)
const QString& source, const QString&,
const Song& metadata, bool, bool remove_original)
{
if (!active_copy_db_)
return false;
// Create the track
Itdb_Track* track = itdb_track_new();
metadata.ToItdb(track);
// Add it to the DB and the master playlist
// The DB takes ownership of the track
itdb_track_add(active_copy_db_, track, -1);
Itdb_Playlist* mpl = itdb_playlist_mpl(active_copy_db_);
itdb_playlist_add_track(mpl, track, -1);
// Copy the file
GError* error = NULL;
itdb_cp_track_to_ipod(track, source.toLocal8Bit().constData(), &error);
if (error) {
qDebug() << "GPodDevice error:" << error->message;
emit Error(QString::fromUtf8(error->message));
g_error_free(error);
// Need to remove the track from the db again
itdb_track_remove(track);
return false;
}
return true;
}
void GPodDevice::FinishCopy() {
GError* error = NULL;
itdb_write(active_copy_db_, &error);
if (error) {
qDebug() << "GPodDevice error:" << error->message;
emit Error(QString::fromUtf8(error->message));
g_error_free(error);
}
active_copy_mutex_.unlock();
}

View File

@ -20,6 +20,8 @@
#include "connecteddevice.h"
#include "core/musicstorage.h"
#include <QMutex>
class GPodLoader;
class GPodDevice : public ConnectedDevice, public MusicStorage {
@ -36,12 +38,17 @@ public:
MusicStorage* storage() { return this; }
void StartCopy();
bool CopyToStorage(const QString &source, const QString &destination,
const Song &metadata, bool overwrite, bool remove_original);
void FinishCopy();
private:
QThread* loader_thread_;
GPodLoader* loader_;
QMutex active_copy_mutex_;
Itdb_iTunesDB* active_copy_db_;
};
#endif // GPODDEVICE_H