/***************************************************************************
* 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 ;
TDEToolBar * toolbar = MediaBrowser : : instance ( ) - > getToolBar ( ) ;
TDEToolBarButton * customButton = toolbar - > getButton ( MediaBrowser : : CUSTOM ) ;
customButton - > setText ( i18n ( " Add computer " ) ) ;
toolbar = CollectionBrowser : : instance ( ) - > getToolBar ( ) ;
toolbar - > setIconText ( TDEToolBar : : IconTextRight , false ) ;
m_broadcastButton = new TDEToolBarButton ( " 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 ( TDEIO : : filesize_t * /* total */ , TDEIO : : 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 , QUEUE , INFO , CONNECT , REMOVE , DOWNLOAD } ;
MediaItem * item = dynamic_cast < MediaItem * > ( qitem ) ;
ServerItem * sitem = dynamic_cast < ServerItem * > ( qitem ) ;
if ( ! item )
return ;
KURL : : List urls ;
TDEPopupMenu menu ( m_view ) ;
switch ( item - > type ( ) )
{
case MediaItem : : DIRECTORY :
menu . insertItem ( SmallIconSet ( " connect_creating " ) , i18n ( " &Connect " ) , CONNECT ) ;
if ( sitem & & ! m_serverItemMap . contains ( 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 " ) , QUEUE ) ;
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 QUEUE :
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 . contains ( 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 . contains ( 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 * parentArtist = new MediaItem ( root ) ;
parentArtist - > setType ( MediaItem : : ARTIST ) ;
Daap : : AlbumList albumMap = * ( bundles . find ( * it ) ) ;
parentArtist - > 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 * parentAlbum = new MediaItem ( parentArtist ) ;
parentAlbum - > setType ( MediaItem : : ALBUM ) ;
MetaBundle * track ;
Daap : : TrackList trackList = * albumMap . find ( * itAlbum ) ;
parentAlbum - > setText ( 0 , trackList . getFirst ( ) - > album ( ) ) ;
for ( track = trackList . first ( ) ; track ; track = trackList . next ( ) )
{
if ( m_removeDuplicates & & trackExistsInCollection ( track ) )
continue ;
MediaItem * childTrack = new MediaItem ( parentAlbum ) ;
childTrack - > setText ( 0 , track - > title ( ) ) ;
childTrack - > setType ( MediaItem : : TRACK ) ;
childTrack - > setBundle ( track ) ;
childTrack - > m_order = track - > track ( ) ;
}
if ( ! parentAlbum - > childCount ( ) )
delete parentAlbum ;
}
if ( ! parentArtist - > childCount ( ) )
delete parentArtist ;
}
root - > resetTitle ( ) ;
root - > stopAnimation ( ) ;
root - > setOpen ( true ) ;
}
int
DaapClient : : incRevision ( const TQString & host )
{
if ( m_servers . contains ( host ) )
{
m_servers [ host ] - > revisionID + + ;
return m_servers [ host ] - > revisionID ;
}
else
return 0 ;
}
int
DaapClient : : getSession ( const TQString & host )
{
if ( m_servers . contains ( host ) )
return m_servers [ host ] - > sessionId ;
else
return - 1 ;
}
void
DaapClient : : customClicked ( )
{
class AddHostDialog : public KDialogBase
{
public :
AddHostDialog ( TQWidget * parent )
: KDialogBase ( parent , " DaapAddHostDialog " , true , i18n ( " Add Computer " ) , Ok | Cancel )
{
m_base = new AddHostBase ( this , " DaapAddHostBase " ) ;
m_base - > m_downloadPixmap - > setPixmap ( TQPixmap ( TDEGlobal : : 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. " ) . arg ( 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 ( ) . contains ( 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 * parent )
: KDialogBase ( parent , " 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 ( TDEGlobal : : 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 * parent )
{
m_broadcastServerCheckBox = new TQCheckBox ( " Broadcast my music " , parent ) ;
m_broadcastServerCheckBox - > setChecked ( m_broadcastServer ) ;
m_removeDuplicatesCheckBox = new TQCheckBox ( " Hide songs in my collection " , parent ) ;
m_removeDuplicatesCheckBox - > setChecked ( m_removeDuplicates ) ;
TQToolTip : : add ( m_removeDuplicatesCheckBox , i18n ( " Enabling this may reduce connection times " ) ) ;
}
void
DaapClient : : removeConfigElements ( TQWidget * /* parent */ )
{
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 * parent , DaapClient * client , const TQString & ip , TQ_UINT16 port , const TQString & title , const TQString & host )
: MediaItem ( parent )
, 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 " ) . arg ( 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 " ) . arg ( 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 */