129 lines
3.7 KiB
C++
129 lines
3.7 KiB
C++
/* This file is part of Clementine.
|
|
|
|
Clementine 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.
|
|
|
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "devicelister.h"
|
|
#include "wmdmdevice.h"
|
|
#include "wmdmlister.h"
|
|
#include "wmdmloader.h"
|
|
#include "wmdmthread.h"
|
|
#include "core/taskmanager.h"
|
|
#include "library/librarybackend.h"
|
|
|
|
#include <boost/scoped_array.hpp>
|
|
|
|
#include <cwchar>
|
|
#include <mswmdm.h>
|
|
|
|
#include <QUuid>
|
|
|
|
WmdmLoader::WmdmLoader(TaskManager* task_manager, LibraryBackend* backend,
|
|
boost::shared_ptr<ConnectedDevice> device)
|
|
: QObject(NULL),
|
|
device_(device),
|
|
task_manager_(task_manager),
|
|
backend_(backend)
|
|
{
|
|
original_thread_ = thread();
|
|
}
|
|
|
|
WmdmLoader::~WmdmLoader() {
|
|
}
|
|
|
|
void WmdmLoader::LoadDatabase() {
|
|
int task_id = task_manager_->StartTask(tr("Loading Windows Media device"));
|
|
emit TaskStarted(task_id);
|
|
|
|
boost::scoped_ptr<WmdmThread> thread(new WmdmThread);
|
|
|
|
// Get the device's canonical name
|
|
boost::shared_ptr<WmdmDevice> connected_device =
|
|
boost::static_pointer_cast<WmdmDevice>(device_);
|
|
WmdmLister* lister = static_cast<WmdmLister*>(connected_device->lister());
|
|
QString canonical_name = lister->DeviceCanonicalName(connected_device->unique_id());
|
|
|
|
IWMDMStorage* storage = thread->GetRootStorage(canonical_name);
|
|
QStringList path_components;
|
|
RecursiveExploreStorage(storage, &path_components);
|
|
storage->Release();
|
|
|
|
thread.reset();
|
|
|
|
// Need to remove all the existing songs in the database first
|
|
backend_->DeleteSongs(backend_->FindSongsInDirectory(1));
|
|
|
|
// Add the songs we've just loaded
|
|
backend_->AddOrUpdateSongs(songs_);
|
|
|
|
task_manager_->SetTaskFinished(task_id);
|
|
emit LoadFinished();
|
|
}
|
|
|
|
void WmdmLoader::RecursiveExploreStorage(IWMDMStorage* parent, QStringList* path_components) {
|
|
IWMDMEnumStorage* child_it = NULL;
|
|
parent->EnumStorage(&child_it);
|
|
|
|
IWMDMStorage* child = NULL;
|
|
ULONG num_retreived = 0;
|
|
while (child_it->Next(1, &child, &num_retreived) == S_OK && num_retreived == 1) {
|
|
const int kMaxLen = 255;
|
|
wchar_t name[kMaxLen];
|
|
child->GetName(name, kMaxLen);
|
|
|
|
DWORD attributes = 0;
|
|
_WAVEFORMATEX audio_format;
|
|
child->GetAttributes(&attributes, &audio_format);
|
|
|
|
path_components->append(QString::fromWCharArray(name));
|
|
if (attributes & WMDM_FILE_ATTR_FILE) {
|
|
LoadFile(child, path_components);
|
|
} else if (attributes & WMDM_FILE_ATTR_FOLDER) {
|
|
RecursiveExploreStorage(child, path_components);
|
|
}
|
|
path_components->removeLast();
|
|
|
|
child->Release();
|
|
}
|
|
child_it->Release();
|
|
}
|
|
|
|
void WmdmLoader::LoadFile(IWMDMStorage* file, const QStringList* path_components) {
|
|
// Convert to a IWMDMStorage3 so we can get metadata
|
|
IWMDMStorage3* storage3 = NULL;
|
|
if (file->QueryInterface(IID_IWMDMStorage3, (void**) &storage3))
|
|
return;
|
|
|
|
// Get the metadata interface
|
|
IWMDMMetaData* metadata = NULL;
|
|
if (storage3->GetMetadata(&metadata)) {
|
|
storage3->Release();
|
|
return;
|
|
}
|
|
storage3->Release();
|
|
|
|
// Store the metadata in here
|
|
Song song;
|
|
song.InitFromWmdm(metadata);
|
|
song.set_directory_id(1);
|
|
song.set_filename(path_components->join("/"));
|
|
|
|
metadata->Release();
|
|
|
|
if (song.is_valid())
|
|
songs_ << song;
|
|
}
|
|
|
|
|