You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
amarok/amarok/src/mediadevice/daap/daapclient.cpp

881 lines
27 KiB

/***************************************************************************
* copyright: (C) 2006, 2007 Ian Monroe <ian@monroe.nu> *
* (C) 2006 Seb Ruiz <me@sebruiz.net> *
* (C) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com>
***************************************************************************/
/***************************************************************************
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef AMAROK_DAAPCLIENT_CPP
#define AMAROK_DAAPCLIENT_CPP
#include "addhostbase.h"
#include "collectiondb.h"
#include "collectionbrowser.h"
#include "daapreader/reader.h"
#include "daapreader/authentication/contentfetcher.h"
#include "daapclient.h"
#include "daapserver.h"
#include "debug.h"
#include "mediabrowser.h"
#include "playlist.h"
#include "proxy.h"
#include "statusbar/statusbar.h"
#include "tagdialog.h"
#include <tqcheckbox.h>
#include <tqmetaobject.h>
#include <tqobjectlist.h>
#include <tqlabel.h>
#include <tqpixmap.h>
#include <tqtimer.h>
#include <tqtooltip.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <knuminput.h>
#include <kpassdlg.h>
#include <kpopupmenu.h>
#include <kresolver.h>
#include <kstandarddirs.h> //loading icons
#include <ktempfile.h>
#include <ktoolbar.h>
#include <ktoolbarbutton.h>
#if DNSSD_SUPPORT
#include <dnssd/remoteservice.h>
#include <dnssd/servicebase.h>
#include <dnssd/servicebrowser.h>
#endif
AMAROK_EXPORT_PLUGIN( DaapClient )
DaapClient::DaapClient()
: MediaDevice()
#if DNSSD_SUPPORT
, m_browser( 0 )
#endif
, m_connected( false )
, m_sharingServer( 0 )
, m_broadcastServerCheckBox( 0 )
, m_broadcastServer( false ) // to abide by "all ports closed" policy, we default to not broadcasting music
{
DEBUG_BLOCK
setName( "daapclient" );
m_name = i18n( "Shared Music" );
m_hasMountPoint = false;
m_autoDeletePodcasts = false;
m_syncStats = false;
m_transcode = false;
m_transcodeAlways = false;
m_transcodeRemove = false;
m_configure = false;
m_customButton = true;
m_transfer = false;
KToolBar *toolbar = MediaBrowser::instance()->getToolBar();
KToolBarButton *customButton = toolbar->getButton( MediaBrowser::CUSTOM );
customButton->setText( i18n("Add computer") );
toolbar = CollectionBrowser::instance()->getToolBar();
toolbar->setIconText( KToolBar::IconTextRight, false );
m_broadcastButton = new KToolBarButton( "connect_creating", 0, toolbar, "broadcast_button",
i18n("Share My Music") );
m_broadcastButton->setToggle( true );
TQToolTip::add( customButton, i18n( "List music from a remote host" ) );
TQToolTip::add( m_broadcastButton, i18n( "If this button is checked, then your music will be exported to the network" ) );
connect( m_broadcastButton, TQT_SIGNAL( toggled(int) ), TQT_SLOT( broadcastButtonToggled() ) );
MediaBrowser::instance()->insertChild( this );
}
DaapClient::~DaapClient()
{
#if DNSSD_SUPPORT
delete m_browser;
#endif
}
bool
DaapClient::isConnected()
{
return m_connected;
}
bool
DaapClient::getCapacity( KIO::filesize_t* /* total */, KIO::filesize_t* /* available */ )
{
return false;
}
bool
DaapClient::lockDevice(bool /*tryOnly = false*/ )
{
return true;
}
void
DaapClient::unlockDevice()
{
return;
}
bool
DaapClient::openDevice(bool /* silent=false */)
{
DEBUG_BLOCK
m_connected = true;
#if DNSSD_SUPPORT
if ( !m_browser )
{
m_browser = new DNSSD::ServiceBrowser("_daap._tcp");
m_browser->setName("daapServiceBrowser");
connect( m_browser, TQT_SIGNAL( serviceAdded( DNSSD::RemoteService::Ptr ) ),
this, TQT_SLOT( foundDaap ( DNSSD::RemoteService::Ptr ) ) );
connect( m_browser, TQT_SIGNAL( serviceRemoved( DNSSD::RemoteService::Ptr ) ),
this, TQT_SLOT( serverOffline ( DNSSD::RemoteService::Ptr ) ) );
m_browser->startBrowse();
}
#endif
TQStringList sl = AmarokConfig::manuallyAddedServers();
foreach( sl )
{
TQStringList current = TQStringList::split(":", (*it) );
TQString host = current.first();
TQ_UINT16 port = current.last().toInt();
TQString ip = resolve( host );
if( ip != "0" )
{
newHost( host, host, ip, port );
}
}
if( m_broadcastServer )
m_sharingServer = new DaapServer( this, "DaapServer" );
return true;
}
bool
DaapClient::closeDevice()
{
m_view->clear();
TQObjectList* readers = queryList( "Daap::Reader");
TQObject* itRead;
for( itRead = readers->first(); itRead; itRead = readers->next() )
{
static_cast<Daap::Reader*>(itRead)->logoutRequest();
delete m_servers[ itRead->name() ];
m_servers.remove( itRead->name() );
}
m_connected = false;
m_servers.clear();
#if DNSSD_SUPPORT
m_serverItemMap.clear();
delete m_browser;
m_browser = 0;
#endif
delete m_sharingServer;
m_sharingServer = 0;
return true;
}
KURL
DaapClient::getProxyUrl( const KURL& url )
{
DEBUG_BLOCK
Daap::Proxy* daapProxy = new Daap::Proxy( url, this, "daapProxy" );
return daapProxy->proxyUrl();
}
void
DaapClient::synchronizeDevice()
{
return;
}
MediaItem*
DaapClient::copyTrackToDevice(const MetaBundle& /* bundle */)
{
return 0;
}
MediaItem*
DaapClient::trackExists( const MetaBundle& )
{
return 0;
}
int
DaapClient::deleteItemFromDevice( MediaItem* /*item*/, int /*flags*/ )
{
return 0;
}
void
DaapClient::rmbPressed( TQListViewItem* qitem, const TQPoint& point, int )
{
DEBUG_BLOCK
enum Actions { APPEND, LOAD, TQUEUE, INFO, CONNECT, REMOVE, DOWNLOAD };
MediaItem *item = dynamic_cast<MediaItem *>(qitem);
ServerItem* sitem = dynamic_cast<ServerItem *>(qitem);
if( !item )
return;
KURL::List urls;
KPopupMenu menu( m_view );
switch( item->type() )
{
case MediaItem::DIRECTORY:
menu.insertItem( SmallIconSet( "connect_creating" ), i18n( "&Connect" ), CONNECT );
if( sitem && !m_serverItemMap.tqcontains( sitem->key() ) )
{
menu.insertItem( SmallIconSet( "remove" ), i18n("&Remove Computer"), REMOVE );
}
{
TQStringList sl = m_serverItemMap.keys();
foreach( sl )
{
debug() << (*it) << endl;
}
debug() << sitem->key() << endl;
}
break;
default:
urls = m_view->nodeBuildDragList( 0 );
menu.insertItem( SmallIconSet( Amarok::icon( "playlist" ) ), i18n( "&Load" ), LOAD );
menu.insertItem( SmallIconSet( Amarok::icon( "add_playlist" ) ), i18n( "&Append to Playlist" ), APPEND );
menu.insertItem( SmallIconSet( Amarok::icon( "fastforward" ) ), i18n( "&Queue Tracks" ), TQUEUE );
menu.insertSeparator();
menu.insertItem( SmallIconSet( Amarok::icon( "playlist" ) ), i18n( "&Copy Files to Collection..." ), DOWNLOAD );
// albums and artists don't have bundles, so they crash... :(
if( item->bundle() )
{
menu.insertItem( SmallIconSet( Amarok::icon( "info" ) ), i18n( "Track &Information..." ), INFO );
}
break;
}
int id = menu.exec( point );
switch( id )
{
case CONNECT:
if( ServerItem *s = dynamic_cast<ServerItem *>(item) )
{
s->reset();
}
item->setOpen( true );
break;
case LOAD:
Playlist::instance()->insertMedia( urls, Playlist::Replace );
break;
case APPEND:
Playlist::instance()->insertMedia( urls, Playlist::Append );
break;
case TQUEUE:
Playlist::instance()->insertMedia( urls, Playlist::Queue );
break;
case INFO:
{
// The tag dialog automatically disables the widgets if the file is not local, which it is not.
TagDialog *dialog = new TagDialog( *item->bundle(), 0 );
dialog->show();
}
break;
case REMOVE:
if( sitem )
{
TQStringList mas = AmarokConfig::manuallyAddedServers();
mas.remove( sitem->key() );
AmarokConfig::setManuallyAddedServers( mas );
delete sitem;
}
break;
case DOWNLOAD:
downloadSongs( urls );
break;
}
}
void
DaapClient::downloadSongs( KURL::List urls )
{
DEBUG_BLOCK
KURL::List realStreamUrls;
KURL::List::Iterator it;
for( it = urls.begin(); it != urls.end(); ++it )
realStreamUrls << Daap::Proxy::realStreamUrl( (*it), getSession( (*it).host() + ':' + TQString::number( (*it).port() ) ) );
ThreadManager::instance()->queueJob( new DaapDownloader( realStreamUrls ) );
}
void
DaapClient::serverOffline( DNSSD::RemoteService::Ptr service )
{
#if DNSSD_SUPPORT
DEBUG_BLOCK
TQString key = serverKey( service.data() );
if( m_serverItemMap.tqcontains( key ) )
{
ServerItem* removeMe = m_serverItemMap[ key ];
if( removeMe )
{
delete removeMe;
removeMe = 0;
}
else
warning() << "root item already null" << endl;
m_serverItemMap.remove( key );
}
else
warning() << "removing non-existant service" << endl;
#endif
}
#if DNSSD_SUPPORT
TQString
DaapClient::serverKey( const DNSSD::RemoteService* service ) const
{
return ServerItem::key( service->hostName(), service->port() );
}
#endif
void
DaapClient::foundDaap( DNSSD::RemoteService::Ptr service )
{
#if DNSSD_SUPPORT
DEBUG_BLOCK
connect( service, TQT_SIGNAL( resolved( bool ) ), this, TQT_SLOT( resolvedDaap( bool ) ) );
service->resolveAsync();
#endif
}
void
DaapClient::resolvedDaap( bool success )
{
#if DNSSD_SUPPORT
DEBUG_BLOCK
const DNSSD::RemoteService* service = dynamic_cast<const DNSSD::RemoteService*>(sender());
if( !success || !service ) return;
debug() << service->serviceName() << ' ' << service->hostName() << ' ' << service->domain() << ' ' << service->type() << endl;
TQString ip = resolve( service->hostName() );
if( ip == "0" || m_serverItemMap.tqcontains(serverKey( service )) ) //same server from multiple interfaces
return;
m_serverItemMap[ serverKey( service ) ] = newHost( service->serviceName(), service->hostName(), ip, service->port() );
#endif
}
void
DaapClient::createTree( const TQString& /*host*/, Daap::SongList bundles )
{
DEBUG_BLOCK
const Daap::Reader* callback = dynamic_cast<const Daap::Reader*>(sender());
if( !callback )
{
debug() << "No callback!" << endl;
return;
}
{
const TQString hostKey = callback->name();
ServerInfo* si = new ServerInfo();
si->sessionId = callback->sessionId();
m_servers[ hostKey ] = si;
}
ServerItem* root = callback->rootMediaItem();
TQStringList artists = bundles.keys();
foreach( artists )
{
MediaItem* tqparentArtist = new MediaItem( root );
tqparentArtist->setType( MediaItem::ARTIST );
Daap::AlbumList albumMap = *( bundles.tqfind(*it) );
tqparentArtist->setText( 0, (*albumMap.begin()).getFirst()->artist() ); //map was made case insensitively
//just get the displayed-case from
//the first track
TQStringList albums = albumMap.keys();
for ( TQStringList::Iterator itAlbum = albums.begin(); itAlbum != albums.end(); ++itAlbum )
{
MediaItem* tqparentAlbum = new MediaItem( tqparentArtist );
tqparentAlbum->setType( MediaItem::ALBUM );
MetaBundle* track;
Daap::TrackList trackList = *albumMap.tqfind(*itAlbum);
tqparentAlbum->setText( 0, trackList.getFirst()->album() );
for( track = trackList.first(); track; track = trackList.next() )
{
if( m_removeDuplicates && trackExistsInCollection( track ) )
continue;
MediaItem* childTrack = new MediaItem( tqparentAlbum );
childTrack->setText( 0, track->title() );
childTrack->setType( MediaItem::TRACK );
childTrack->setBundle( track );
childTrack->m_order = track->track();
}
if( !tqparentAlbum->childCount() )
delete tqparentAlbum;
}
if( !tqparentArtist->childCount() )
delete tqparentArtist;
}
root->resetTitle();
root->stopAnimation();
root->setOpen( true );
}
int
DaapClient::incRevision( const TQString& host )
{
if( m_servers.tqcontains(host) )
{
m_servers[host]->revisionID++;
return m_servers[host]->revisionID;
}
else
return 0;
}
int
DaapClient::getSession( const TQString& host )
{
if( m_servers.tqcontains(host) )
return m_servers[host]->sessionId;
else
return -1;
}
void
DaapClient::customClicked()
{
class AddHostDialog : public KDialogBase
{
public:
AddHostDialog( TQWidget *tqparent )
: KDialogBase( tqparent, "DaapAddHostDialog", true, i18n( "Add Computer" ) , Ok|Cancel)
{
m_base = new AddHostBase( this, "DaapAddHostBase" );
m_base->m_downloadPixmap->setPixmap( TQPixmap( KGlobal::iconLoader()->iconPath( Amarok::icon( "download" ), -KIcon::SizeEnormous ) ) );
m_base->m_hostName->setFocus();
setMainWidget( m_base );
}
AddHostBase* m_base;
};
AddHostDialog dialog( 0 );
if( dialog.exec() == TQDialog::Accepted ) {
TQString ip = resolve( dialog.m_base->m_hostName->text() );
if( ip == "0" )
Amarok::StatusBar::instance()->shortMessage( i18n("Could not resolve %1.").tqarg( dialog.m_base->m_hostName->text() ) );
else
{
TQString key = ServerItem::key( dialog.m_base->m_hostName->text(), dialog.m_base->m_portInput->value() );
if( !AmarokConfig::manuallyAddedServers().tqcontains( key ) )
{
TQStringList mas = AmarokConfig::manuallyAddedServers();
mas.append( key );
AmarokConfig::setManuallyAddedServers( mas );
}
newHost( dialog.m_base->m_hostName->text(), dialog.m_base->m_hostName->text(), ip, dialog.m_base->m_portInput->value() );
}
}
}
ServerItem*
DaapClient::newHost( const TQString& serviceName, const TQString& host, const TQString& ip, const TQ_INT16 port )
{
if( ip.isEmpty() ) return 0;
return new ServerItem( m_view, this, ip, port, serviceName, host );
}
void
DaapClient::passwordPrompt()
{
class PasswordDialog : public KDialogBase
{
public:
PasswordDialog( TQWidget *tqparent )
: KDialogBase( tqparent, "PasswordDialog", true, i18n( "Password Required" ) , Ok|Cancel)
{
makeHBoxMainWidget();
KGuiItem ok( KStdGuiItem::ok() );
ok.setText( i18n( "Login" ) );
ok.setToolTip( i18n("Login to the music share with the password given.") );
setButtonOK( ok );
TQLabel* passIcon = new TQLabel( mainWidget(), "passicon" );
passIcon->setPixmap( TQPixmap( KGlobal::iconLoader()->iconPath( "password", -KIcon::SizeHuge ) ) );
TQHBox* loginArea = new TQHBox( mainWidget(), "passhbox" );
new TQLabel( i18n( "Password:"), loginArea, "passlabel" );
m_input = new KPasswordEdit( loginArea, "passedit" );
m_input->setFocus();
}
KPasswordEdit* m_input;
};
Daap::Reader* callback = dynamic_cast<Daap::Reader*>( const_cast<TQT_BASE_OBJECT_NAME*>( sender() ) );
if (!callback) {
debug() << "No callback!" << endl;
return;
}
ServerItem* root = callback->rootMediaItem();
PasswordDialog dialog( 0 );
if( dialog.exec() == TQDialog::Accepted )
{
Daap::Reader* reader = new Daap::Reader( callback->host(), callback->port(), root, TQString( dialog.m_input->password() ), this, callback->name() );
root->setReader( reader );
connect( reader, TQT_SIGNAL( daapBundles( const TQString&, Daap::SongList ) ),
this, TQT_SLOT( createTree( const TQString&, Daap::SongList ) ) );
connect( reader, TQT_SIGNAL( passwordRequired() ), this, TQT_SLOT( passwordPrompt() ) );
connect( reader, TQT_SIGNAL( httpError( const TQString& ) ), root, TQT_SLOT( httpError( const TQString& ) ) );
reader->loginRequest();
}
else
{
root->setOpen( false );
root->resetTitle();
root->unLoaded();
}
callback->deleteLater();
}
TQString
DaapClient::resolve( const TQString& hostname )
{
KNetwork::KResolver resolver( hostname );
resolver.setFamily( KNetwork::KResolver::KnownFamily ); //A druidic incantation from Thiago. Works around a KResolver bug #132851
resolver.start();
if( resolver.wait( 5000 ) )
{
KNetwork::KResolverResults results = resolver.results();
if( results.error() )
debug() << "Error resolving " << hostname << ": ("
<< resolver.errorString( results.error() ) << ")" << endl;
if( !results.empty() )
{
TQString ip = results[0].address().asInet().ipAddress().toString();
debug() << "ip found is " << ip << endl;
return ip;
}
}
return "0"; //error condition
}
const bool
DaapClient::trackExistsInCollection( MetaBundle *bundle )
{
/// FIXME slow.
QueryBuilder qb;
qb.addMatch( QueryBuilder::tabSong , QueryBuilder::valTitle, bundle->title() , true, false );
qb.addMatch( QueryBuilder::tabArtist, QueryBuilder::valName , bundle->artist(), true, false );
qb.addMatch( QueryBuilder::tabAlbum , QueryBuilder::valName , bundle->album() , true, false );
qb.addReturnFunctionValue( QueryBuilder::funcCount, QueryBuilder::tabSong, QueryBuilder::valURL );
TQStringList values = qb.run();
return ( values[0].toInt() > 0 );
}
/// Configuration Dialog Extension
void
DaapClient::addConfigElements( TQWidget * tqparent )
{
m_broadcastServerCheckBox = new TQCheckBox( "Broadcast my music", tqparent );
m_broadcastServerCheckBox->setChecked( m_broadcastServer );
m_removeDuplicatesCheckBox = new TQCheckBox( "Hide songs in my collection", tqparent );
m_removeDuplicatesCheckBox->setChecked( m_removeDuplicates );
TQToolTip::add( m_removeDuplicatesCheckBox, i18n( "Enabling this may reduce connection times" ) );
}
void
DaapClient::removeConfigElements( TQWidget * /* tqparent */ )
{
if( m_broadcastServerCheckBox != 0 )
delete m_broadcastServerCheckBox;
if( m_removeDuplicatesCheckBox != 0 )
delete m_removeDuplicatesCheckBox;
m_broadcastServerCheckBox = 0;
m_removeDuplicatesCheckBox = 0;
}
void
DaapClient::loadConfig()
{
MediaDevice::loadConfig();
m_broadcastServer = configBool( "broadcastServer", false );
m_removeDuplicates = configBool( "removeDuplicates", false );
// don't undo all the work we just did at startup
m_broadcastButton->blockSignals( true );
m_broadcastButton->setOn( m_broadcastServer );
m_broadcastButton->blockSignals( false );
}
void
DaapClient::applyConfig()
{
if( m_broadcastServerCheckBox )
m_broadcastServer = m_broadcastServerCheckBox->isChecked();
if( m_removeDuplicatesCheckBox )
m_removeDuplicates = m_removeDuplicatesCheckBox->isChecked();
setConfigBool( "broadcastServer" , m_broadcastServer );
setConfigBool( "removeDuplicates", m_removeDuplicates );
}
void
DaapClient::broadcastButtonToggled()
{
DEBUG_BLOCK
m_broadcastServer = !m_broadcastServer;
switch( m_broadcastServer )
{
case false:
debug() << "turning daap server off" << endl;
if( m_sharingServer )
delete m_sharingServer;
m_sharingServer = 0;
break;
case true:
debug() << "turning daap server on" << endl;
if( !m_sharingServer )
m_sharingServer = new DaapServer( this, "DaapServer" );
break;
}
}
////////////////////////////////////////////////////////////////////////////////
// CLASS ServerItem
////////////////////////////////////////////////////////////////////////////////
ServerItem::ServerItem( TQListView* tqparent, DaapClient* client, const TQString& ip, TQ_UINT16 port, const TQString& title, const TQString& host )
: MediaItem( tqparent )
, m_daapClient( client )
, m_reader( 0 )
, m_ip( ip )
, m_port( port )
, m_title( title )
, m_host( host )
, m_loaded( false )
, m_loading1( new TQPixmap( locate("data", "amarok/images/loading1.png" ) ) )
, m_loading2( new TQPixmap( locate("data", "amarok/images/loading2.png" ) ) )
{
setText( 0, title );
setType( MediaItem::DIRECTORY );
}
ServerItem::~ServerItem()
{
delete m_reader;
m_reader = 0;
}
void
ServerItem::reset()
{
delete m_reader;
m_reader = 0;
m_loaded = 0;
TQListViewItem *c = firstChild();
TQListViewItem *n;
while( c ) {
n = c->nextSibling();
delete c;
c = n;
}
}
void
ServerItem::setOpen( bool o )
{
if( !o )
{
MediaItem::setOpen( o );
return;
}
if( !m_loaded )
{
//starts loading animation
m_iconCounter = 1;
startAnimation();
connect( &m_animationTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotAnimation()) );
setText( 0, i18n( "Loading %1").tqarg( text( 0 ) ) );
Daap::Reader* reader = new Daap::Reader( m_ip, m_port, this,
TQString(), m_daapClient, ( m_ip + ":3689" ).ascii() );
setReader ( reader );
connect( reader, TQT_SIGNAL( daapBundles( const TQString&, Daap::SongList ) ),
m_daapClient, TQT_SLOT( createTree( const TQString&, Daap::SongList ) ) );
connect( reader, TQT_SIGNAL( passwordRequired() ), m_daapClient, TQT_SLOT( passwordPrompt() ) );
connect( reader, TQT_SIGNAL( httpError( const TQString& ) ), this, TQT_SLOT( httpError( const TQString& ) ) );
reader->loginRequest();
m_loaded = true;
}
else
MediaItem::setOpen( true );
}
void
ServerItem::startAnimation()
{
if( !m_animationTimer.isActive() )
m_animationTimer.start( ANIMATION_INTERVAL );
}
void
ServerItem::stopAnimation()
{
m_animationTimer.stop();
setType( MediaItem::DIRECTORY ); //restore icon
}
void
ServerItem::slotAnimation()
{
m_iconCounter % 2 ?
setPixmap( 0, *m_loading1 ):
setPixmap( 0, *m_loading2 );
m_iconCounter++;
}
void
ServerItem::httpError( const TQString& errorString )
{
stopAnimation();
resetTitle();
Amarok::StatusBar::instance()->longMessage( i18n( "The following error occurred while trying to connect to the remote server:<br>%1").tqarg( errorString ) );
m_reader->deleteLater();
m_reader = 0;
m_loaded = false;
}
////////////////////////////////////////////////////////////////////////////////
// CLASS DaapDownloader
////////////////////////////////////////////////////////////////////////////////
DaapDownloader::DaapDownloader( KURL::List urls ) : Job( "DaapDownloader" )
, m_urls( urls )
, m_ready( false )
, m_successful( false )
, m_errorOccured( false )
{
// setDescription( i18n( "Downloading song from remote computer." ) ); //no new strings,uncomment after string freeze
setDescription( i18n( "Downloading Media..." ) );
}
bool
DaapDownloader::doJob()
{
DEBUG_BLOCK
KURL::List::iterator urlIt = m_urls.begin();
Daap::ContentFetcher* http = new Daap::ContentFetcher( (*urlIt).host(), (*urlIt).port(), TQString(), this );
connect( http, TQT_SIGNAL( requestFinished( int, bool ) ), this, TQT_SLOT( downloadFinished( int, bool ) ) );
connect( http, TQT_SIGNAL( dataReadProgress( int, int ) ), this, TQT_SLOT( dataReadProgress( int, int ) ) );
connect( http, TQT_SIGNAL( httpError( const TQString& ) ), this, TQT_SLOT( downloadFailed( const TQString& ) ) );
while( !isAborted() && !m_errorOccured && urlIt != m_urls.end() )
{
m_ready = false;
debug() << "downloading " << (*urlIt).path() << endl;
setProgressTotalSteps( 100 );
KTempFile* tempNewFile = new KTempFile( TQString(), '.' + TQFileInfo( (*urlIt).path() ).extension() );
tempNewFile->setAutoDelete( true );
m_tempFileList.append( tempNewFile );
http->getDaap( (*urlIt).path() + (*urlIt).query(), TQT_TQIODEVICE(tempNewFile->file()) );
while( !m_ready && !isAborted() )
{
msleep( 100 ); //Sleep 100 msec
}
debug() << "finished " << (*urlIt).path() << endl;
++urlIt;
}
debug() << "returning " << m_successful << endl;
http->deleteLater();
http = 0;
return m_successful;
}
void
DaapDownloader::downloadFinished( int /*id*/, bool error )
{
DEBUG_BLOCK
m_tempFileList.last()->close();
setProgress100Percent(); //just to make sure
m_successful = !error;
m_ready = true;
}
void
DaapDownloader::completeJob()
{
DEBUG_BLOCK
KURL path;
KURL::List tempUrlList;
for( TQValueList<KTempFile*>::Iterator itTemps = m_tempFileList.begin(); itTemps != m_tempFileList.end(); ++itTemps )
{
path.setPath( (*itTemps)->name() );
tempUrlList << path;
}
CollectionView::instance()->organizeFiles( tempUrlList, i18n( "Copy Files To Collection" ), false );
for( TQValueList<KTempFile*>::Iterator itTemps = m_tempFileList.begin(); itTemps != m_tempFileList.end(); ++itTemps )
delete (*itTemps); //autodelete is true, so file is unlinked now
m_tempFileList.clear();
}
void
DaapDownloader::dataReadProgress( int done, int total )
{
setProgress( int( ( float(done) / float(total) ) * 100.0 ) );
}
void
DaapDownloader::downloadFailed( const TQString & error )
{
// Amarok::StatusBar::instance()->longMessageThreadSafe( i18n( "An error occured while downloading from remote music server." ), Amarok::StatusBar::Error );
DEBUG_BLOCK
debug() << "failed on " << error << endl;
m_successful = false;
m_errorOccured = true;
m_ready = true;
}
#include "daapclient.moc"
#endif /* AMAROK_DAAPCLIENT_CPP */