|
|
|
/***************************************************************************
|
|
|
|
app.cpp - description
|
|
|
|
-------------------
|
|
|
|
begin : Mit Okt 23 14:35:18 CEST 2002
|
|
|
|
copyright : (C) 2002 by Mark Kretschmann
|
|
|
|
email : markey@web.de
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* 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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "amarok.h"
|
|
|
|
#include "amarokconfig.h"
|
|
|
|
#include "amarokdcophandler.h"
|
|
|
|
#include "app.h"
|
|
|
|
#include "atomicstring.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "configdialog.h"
|
|
|
|
#include "contextbrowser.h"
|
|
|
|
#include "collectionbrowser.h"
|
|
|
|
#include "dbsetup.h" //firstRunWizard()
|
|
|
|
#include "debug.h"
|
|
|
|
#include "devicemanager.h"
|
|
|
|
#include "mediadevicemanager.h"
|
|
|
|
#include "enginebase.h"
|
|
|
|
#include "enginecontroller.h"
|
|
|
|
#include "equalizersetup.h"
|
|
|
|
#include "firstrunwizard.h"
|
|
|
|
#include "mediabrowser.h"
|
|
|
|
#include "metabundle.h"
|
|
|
|
#include "mountpointmanager.h"
|
|
|
|
#include "osd.h"
|
|
|
|
#include "playerwindow.h"
|
|
|
|
#include "playlist.h"
|
|
|
|
#include "playlistbrowser.h"
|
|
|
|
#include "playlistwindow.h"
|
|
|
|
#include "pluginmanager.h"
|
|
|
|
#include "refreshimages.h"
|
|
|
|
#include "scriptmanager.h"
|
|
|
|
#include "scrobbler.h"
|
|
|
|
#include "statusbar.h"
|
|
|
|
#include "systray.h"
|
|
|
|
#include "threadmanager.h"
|
|
|
|
#include "tracktooltip.h" //engineNewMetaData()
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include <kconfigdialogmanager.h>
|
|
|
|
#include <kcombobox.h> //firstRunWizard()
|
|
|
|
#include <kcmdlineargs.h> //initCliArgs()
|
|
|
|
#include <kcursor.h> //Amarok::OverrideCursor
|
|
|
|
#include <kedittoolbar.h> //slotConfigToolbars()
|
|
|
|
#include <kglobalaccel.h> //initGlobalShortcuts()
|
|
|
|
#include <kglobalsettings.h> //applyColorScheme()
|
|
|
|
#include <kiconloader.h> //amarok Icon
|
|
|
|
#include <kkeydialog.h> //slotConfigShortcuts()
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kmessagebox.h> //applySettings(), genericEventHandler()
|
|
|
|
#include <krun.h> //Amarok::invokeBrowser()
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kurldrag.h> //genericEventHandler()
|
|
|
|
#include <kaboutdata.h>
|
|
|
|
#include <kio/job.h>
|
|
|
|
|
|
|
|
#include <tqevent.h> //genericEventHandler()
|
|
|
|
#include <tqeventloop.h> //applySettings()
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqobjectlist.h> //applyColorScheme()
|
|
|
|
#include <tqpalette.h> //applyColorScheme()
|
|
|
|
#include <tqpixmap.h> //TQPixmap::setDefaultOptimization()
|
|
|
|
#include <tqpopupmenu.h> //genericEventHandler
|
|
|
|
#include <tqtimer.h> //showHyperThreadingWarning()
|
|
|
|
#include <tqtooltip.h> //default tooltip for trayicon
|
|
|
|
|
|
|
|
// For the HyperThreading fix
|
|
|
|
#ifdef __linux__
|
|
|
|
#ifdef SCHEDAFFINITY_SUPPORT
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sched.h>
|
|
|
|
#endif //SCHEDAFFINITY_SUPPORT
|
|
|
|
#endif //__linux__
|
|
|
|
|
|
|
|
TQMutex Debug::mutex;
|
|
|
|
TQMutex Amarok::globalDirsMutex;
|
|
|
|
|
|
|
|
int App::mainThreadId = 0;
|
|
|
|
|
|
|
|
#ifdef TQ_WS_MAC
|
|
|
|
#include <qt_mac.h>
|
|
|
|
|
|
|
|
static AEEventHandlerUPP appleEventProcessorUPP = 0;
|
|
|
|
|
|
|
|
OSStatus
|
|
|
|
appleEventProcessor(const AppleEvent *ae, AppleEvent *, long /*handlerRefCon*/)
|
|
|
|
{
|
|
|
|
OSType aeID = typeWildCard;
|
|
|
|
OSType aeClass = typeWildCard;
|
|
|
|
AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0);
|
|
|
|
AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);
|
|
|
|
|
|
|
|
if(aeClass == kCoreEventClass)
|
|
|
|
{
|
|
|
|
if(aeID == kAEReopenApplication)
|
|
|
|
{
|
|
|
|
if( PlaylistWindow::self() )
|
|
|
|
PlaylistWindow::self()->show();
|
|
|
|
}
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
return eventNotHandledErr;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LIBAMAROK_EXPORT KAboutData aboutData( "amarok",
|
|
|
|
I18N_NOOP( "Amarok" ), APP_VERSION,
|
|
|
|
I18N_NOOP( "The audio player for KDE" ), KAboutData::License_GPL,
|
|
|
|
I18N_NOOP( "(C) 2002-2003, Mark Kretschmann\n(C) 2003-2007, The Amarok Development Squad\n(C) 2007-2011, The Trinity Desktop Project" ),
|
|
|
|
I18N_NOOP( "IRC:\nirc.freenode.net - #amarok, #amarok.de, #amarok.es\n\nFeedback:\namarok@kde.org\n\n(Build Date: " __DATE__ ")" ),
|
|
|
|
( "http://amarok.kde.org" ) );
|
|
|
|
|
|
|
|
App::App()
|
|
|
|
: KApplication(KApplication::openX11RGBADisplay())
|
|
|
|
, m_pPlayerWindow( 0 ) //will be created in applySettings()
|
|
|
|
{
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
#ifdef TQ_WS_MAC
|
|
|
|
// this is inspired by OpenSceneGraph: osgDB/FilePath.cpp
|
|
|
|
|
|
|
|
// Start with the the Bundle PlugIns directory.
|
|
|
|
|
|
|
|
// Get the main bundle first. No need to retain or release it since
|
|
|
|
// we are not keeping a reference
|
|
|
|
CFBundleRef myBundle = CFBundleGetMainBundle();
|
|
|
|
if( myBundle )
|
|
|
|
{
|
|
|
|
// CFBundleGetMainBundle will return a bundle ref even if
|
|
|
|
// the application isn't part of a bundle, so we need to
|
|
|
|
// check
|
|
|
|
// if the path to the bundle ends in ".app" to see if it is
|
|
|
|
// a
|
|
|
|
// proper application bundle. If it is, the plugins path is
|
|
|
|
// added
|
|
|
|
CFURLRef urlRef = CFBundleCopyBundleURL(myBundle);
|
|
|
|
if(urlRef)
|
|
|
|
{
|
|
|
|
char bundlePath[1024];
|
|
|
|
if( CFURLGetFileSystemRepresentation( urlRef, true, (UInt8 *)bundlePath, sizeof(bundlePath) ) )
|
|
|
|
{
|
|
|
|
TQCString bp( bundlePath );
|
|
|
|
size_t len = bp.length();
|
|
|
|
if( len > 4 && bp.right( 4 ) == ".app" )
|
|
|
|
{
|
|
|
|
bp.append( "/Contents/MacOS" );
|
|
|
|
TQCString path = getenv( "PATH" );
|
|
|
|
if( path.length() > 0 )
|
|
|
|
{
|
|
|
|
path.prepend( ":" );
|
|
|
|
}
|
|
|
|
path.prepend( bp );
|
|
|
|
debug() << "setting PATH=" << path << endl;
|
|
|
|
setenv("PATH", path, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// docs say we are responsible for releasing CFURLRef
|
|
|
|
CFRelease(urlRef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TQPixmap::setDefaultOptimization( TQPixmap::MemoryOptim );
|
|
|
|
|
|
|
|
//needs to be created before the wizard
|
|
|
|
new Amarok::DcopPlayerHandler(); // Must be created first
|
|
|
|
new Amarok::DcopPlaylistHandler();
|
|
|
|
new Amarok::DcopPlaylistBrowserHandler();
|
|
|
|
new Amarok::DcopContextBrowserHandler();
|
|
|
|
new Amarok::DcopCollectionHandler();
|
|
|
|
new Amarok::DcopMediaBrowserHandler();
|
|
|
|
new Amarok::DcopScriptHandler();
|
|
|
|
new Amarok::DcopDevicesHandler();
|
|
|
|
|
|
|
|
fixHyperThreading();
|
|
|
|
// tell AtomicString that this is the GUI thread
|
|
|
|
if ( !AtomicString::isMainThread() )
|
|
|
|
qWarning("AtomicString was initialized from a thread other than the GUI "
|
|
|
|
"thread. This could lead to memory leaks.");
|
|
|
|
|
|
|
|
#ifdef TQ_WS_MAC
|
|
|
|
appleEventProcessorUPP = AEEventHandlerUPP(appleEventProcessor);
|
|
|
|
AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, appleEventProcessorUPP, (long)this, true);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TQTimer::singleShot( 0, this, TQT_SLOT( continueInit() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
App::~App()
|
|
|
|
{
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
// Hiding the OSD before exit prevents crash
|
|
|
|
Amarok::OSD::instance()->hide();
|
|
|
|
|
|
|
|
EngineBase* const engine = EngineController::engine();
|
|
|
|
|
|
|
|
if ( AmarokConfig::resumePlayback() ) {
|
|
|
|
if ( engine->state() != Engine::Empty ) {
|
|
|
|
AmarokConfig::setResumeTrack( EngineController::instance()->playingURL().prettyURL() );
|
|
|
|
AmarokConfig::setResumeTime( engine->position() );
|
|
|
|
}
|
|
|
|
else AmarokConfig::setResumeTrack( TQString() ); //otherwise it'll play previous resume next time!
|
|
|
|
}
|
|
|
|
|
|
|
|
EngineController::instance()->endSession(); //records final statistics
|
|
|
|
EngineController::instance()->detach( this );
|
|
|
|
|
|
|
|
// do even if trayicon is not shown, it is safe
|
|
|
|
Amarok::config()->writeEntry( "HiddenOnExit", mainWindow()->isHidden() );
|
|
|
|
|
|
|
|
CollectionDB::instance()->stopScan();
|
|
|
|
|
|
|
|
delete m_pPlayerWindow; //sets some XT keys
|
|
|
|
delete m_pPlaylistWindow; //sets some XT keys
|
|
|
|
|
|
|
|
ThreadManager::deleteInstance(); //waits for jobs to finish
|
|
|
|
|
|
|
|
// this must be deleted before the connection to the Xserver is
|
|
|
|
// severed, or we risk a crash when the TQApplication is exited,
|
|
|
|
// I asked Trolltech! *smug*
|
|
|
|
delete Amarok::OSD::instance();
|
|
|
|
|
|
|
|
AmarokConfig::setVersion( APP_VERSION );
|
|
|
|
AmarokConfig::writeConfig();
|
|
|
|
|
|
|
|
//need to unload the engine before the kapplication is destroyed
|
|
|
|
PluginManager::unload( engine );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include <dcopref.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
// grabbed from KsCD source, kompatctdisk.cpp
|
|
|
|
TQString urlToDevice(const TQString& device)
|
|
|
|
{
|
|
|
|
KURL deviceUrl(device);
|
|
|
|
if (deviceUrl.protocol() == "media" || deviceUrl.protocol() == "system")
|
|
|
|
{
|
|
|
|
DCOPRef mediamanager( "kded", "mediamanager" );
|
|
|
|
DCOPReply reply = mediamanager.call( "properties(TQString)", deviceUrl.fileName() );
|
|
|
|
TQStringList properties = reply;
|
|
|
|
|
|
|
|
if (!reply.isValid() || properties.count() < 6)
|
|
|
|
{
|
|
|
|
debug() << "Invalid reply from mediamanager" << endl;
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug() << "Reply from mediamanager " << properties[5] << endl;
|
|
|
|
return properties[5];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return device;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void App::handleCliArgs() //static
|
|
|
|
{
|
|
|
|
static char cwd[PATH_MAX];
|
|
|
|
KCmdLineArgs* const args = KCmdLineArgs::parsedArgs();
|
|
|
|
|
|
|
|
if ( args->isSet( "cwd" ) )
|
|
|
|
{
|
|
|
|
strncpy(cwd, args->getOption( "cwd" ), sizeof(cwd) );
|
|
|
|
cwd[sizeof(cwd)-1] = '\0';
|
|
|
|
KCmdLineArgs::setCwd( cwd );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool haveArgs = false;
|
|
|
|
if ( args->count() > 0 )
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
|
|
|
|
KURL::List list;
|
|
|
|
for( int i = 0; i < args->count(); i++ )
|
|
|
|
{
|
|
|
|
KURL url = args->url( i );
|
|
|
|
if( url.protocol() == "itpc" || url.protocol() == "pcast" )
|
|
|
|
PlaylistBrowser::instance()->addPodcast( url );
|
|
|
|
else
|
|
|
|
list << url;
|
|
|
|
}
|
|
|
|
|
|
|
|
int options = Playlist::DefaultOptions;
|
|
|
|
if( args->isSet( "queue" ) )
|
|
|
|
options = Playlist::Queue;
|
|
|
|
else if( args->isSet( "append" ) || args->isSet( "enqueue" ) )
|
|
|
|
options = Playlist::Append;
|
|
|
|
else if( args->isSet( "load" ) )
|
|
|
|
options = Playlist::Replace;
|
|
|
|
|
|
|
|
if( args->isSet( "play" ) )
|
|
|
|
options |= Playlist::DirectPlay;
|
|
|
|
|
|
|
|
Playlist::instance()->insertMedia( list, options );
|
|
|
|
}
|
|
|
|
|
|
|
|
//we shouldn't let the user specify two of these since it is pointless!
|
|
|
|
//so we prioritise, pause > stop > play > next > prev
|
|
|
|
//thus pause is the least destructive, followed by stop as brakes are the most important bit of a car(!)
|
|
|
|
//then the others seemed sensible. Feel free to modify this order, but please leave justification in the cvs log
|
|
|
|
//I considered doing some sanity checks (eg only stop if paused or playing), but decided it wasn't worth it
|
|
|
|
else if ( args->isSet( "pause" ) )
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
EngineController::instance()->pause();
|
|
|
|
}
|
|
|
|
else if ( args->isSet( "stop" ) )
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
EngineController::instance()->stop();
|
|
|
|
}
|
|
|
|
else if ( args->isSet( "play-pause" ) )
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
EngineController::instance()->playPause();
|
|
|
|
}
|
|
|
|
else if ( args->isSet( "play" ) ) //will restart if we are playing
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
EngineController::instance()->play();
|
|
|
|
}
|
|
|
|
else if ( args->isSet( "next" ) )
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
EngineController::instance()->next();
|
|
|
|
}
|
|
|
|
else if ( args->isSet( "previous" ) )
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
EngineController::instance()->previous();
|
|
|
|
}
|
|
|
|
else if (args->isSet("cdplay"))
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
TQString device = args->getOption("cdplay");
|
|
|
|
device = DeviceManager::instance()->convertMediaUrlToDevice( device );
|
|
|
|
KURL::List urls;
|
|
|
|
if (EngineController::engine()->getAudioCDContents(device, urls)) {
|
|
|
|
Playlist::instance()->insertMedia(
|
|
|
|
urls, Playlist::Replace|Playlist::DirectPlay);
|
|
|
|
} else { // Default behaviour
|
|
|
|
debug() <<
|
|
|
|
"Sorry, the engine doesn't support direct play from AudioCD..."
|
|
|
|
<< endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( args->isSet( "toggle-playlist-window" ) )
|
|
|
|
{
|
|
|
|
haveArgs = true;
|
|
|
|
pApp->m_pPlaylistWindow->showHide();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool firstTime = true;
|
|
|
|
if( !firstTime && !haveArgs )
|
|
|
|
pApp->m_pPlaylistWindow->activate();
|
|
|
|
firstTime = false;
|
|
|
|
|
|
|
|
args->clear(); //free up memory
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// INIT
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void App::initCliArgs( int argc, char *argv[] ) //static
|
|
|
|
{
|
|
|
|
static KCmdLineOptions options[] =
|
|
|
|
{
|
|
|
|
{ "+[URL(s)]", I18N_NOOP( "Files/URLs to open" ), 0 },
|
|
|
|
{ "r", 0, 0 },
|
|
|
|
{ "previous", I18N_NOOP( "Skip backwards in playlist" ), 0 },
|
|
|
|
{ "p", 0, 0 },
|
|
|
|
{ "play", I18N_NOOP( "Start playing current playlist" ), 0 },
|
|
|
|
{ "t", 0, 0 },
|
|
|
|
{ "play-pause", I18N_NOOP( "Play if stopped, pause if playing" ), 0 },
|
|
|
|
{ "pause", I18N_NOOP( "Pause playback" ), 0 },
|
|
|
|
{ "s", 0, 0 },
|
|
|
|
{ "stop", I18N_NOOP( "Stop playback" ), 0 },
|
|
|
|
{ "f", 0, 0 },
|
|
|
|
{ "next", I18N_NOOP( "Skip forwards in playlist" ), 0 },
|
|
|
|
{ ":", I18N_NOOP("Additional options:"), 0 },
|
|
|
|
{ "a", 0, 0 },
|
|
|
|
{ "append", I18N_NOOP( "Append files/URLs to playlist" ), 0 },
|
|
|
|
{ "e", 0, 0 },
|
|
|
|
{ "enqueue", I18N_NOOP("See append, available for backwards compatability"), 0 },
|
|
|
|
{ "queue", I18N_NOOP("Queue URLs after the currently playing track"), 0 },
|
|
|
|
{ "l", 0, 0 },
|
|
|
|
{ "load", I18N_NOOP("Load URLs, replacing current playlist"), 0 },
|
|
|
|
{ "m", 0, 0 },
|
|
|
|
{ "toggle-playlist-window", I18N_NOOP("Toggle the Playlist-window"), 0 },
|
|
|
|
{ "wizard", I18N_NOOP( "Run first-run wizard" ), 0 },
|
|
|
|
{ "engine <name>", I18N_NOOP( "Use the <name> engine" ), 0 },
|
|
|
|
{ "cwd <directory>", I18N_NOOP( "Base for relative filenames/URLs" ), 0 },
|
|
|
|
{ "cdplay <device>", I18N_NOOP("Play an AudioCD from <device>"), 0 },
|
|
|
|
//FIXME: after string freeze { "cdplay <device>", I18N_NOOP("Play an AudioCD from <device> or system:/media/<device>"), 0 },
|
|
|
|
{ 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
KCmdLineArgs::reset();
|
|
|
|
KCmdLineArgs::init( argc, argv, &::aboutData ); //calls KApplication::addCmdLineOptions()
|
|
|
|
KCmdLineArgs::addCmdLineOptions( options ); //add our own options
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include <kaction.h>
|
|
|
|
#include <kshortcutlist.h>
|
|
|
|
void App::initGlobalShortcuts()
|
|
|
|
{
|
|
|
|
EngineController* const ec = EngineController::instance();
|
|
|
|
|
|
|
|
m_pGlobalAccel->insert( "play", i18n( "Play" ), 0, KKey("WIN+x"), 0,
|
|
|
|
ec, TQT_SLOT( play() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "pause", i18n( "Pause" ), 0, 0, 0,
|
|
|
|
ec, TQT_SLOT( pause() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "play_pause", i18n( "Play/Pause" ), 0, KKey("WIN+c"), 0,
|
|
|
|
ec, TQT_SLOT( playPause() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "stop", i18n( "Stop" ), 0, KKey("WIN+v"), 0,
|
|
|
|
ec, TQT_SLOT( stop() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "stop_after_global", i18n( "Stop Playing After Current Track" ), 0, KKey("WIN+CTRL+v"), 0,
|
|
|
|
TQT_TQOBJECT(Playlist::instance()->qscrollview()), TQT_SLOT( toggleStopAfterCurrentTrack() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "next", i18n( "Next Track" ), 0, KKey("WIN+b"), 0,
|
|
|
|
ec, TQT_SLOT( next() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "prev", i18n( "Previous Track" ), 0, KKey("WIN+z"), 0,
|
|
|
|
ec, TQT_SLOT( previous() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "volup", i18n( "Increase Volume" ), 0, KKey("WIN+KP_Add"), 0,
|
|
|
|
ec, TQT_SLOT( increaseVolume() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "voldn", i18n( "Decrease Volume" ), 0, KKey("WIN+KP_Subtract"), 0,
|
|
|
|
ec, TQT_SLOT( decreaseVolume() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "seekforward", i18n( "Seek Forward" ), 0, KKey("WIN+Shift+KP_Add"), 0,
|
|
|
|
ec, TQT_SLOT( seekForward() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "seekbackward", i18n( "Seek Backward" ), 0, KKey("WIN+Shift+KP_Subtract"), 0,
|
|
|
|
ec, TQT_SLOT( seekBackward() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "playlist_add", i18n( "Add Media..." ), 0, KKey("WIN+a"), 0,
|
|
|
|
TQT_TQOBJECT(m_pPlaylistWindow), TQT_SLOT( slotAddLocation() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "show", i18n( "Toggle Playlist Window" ), 0, KKey("WIN+p"), 0,
|
|
|
|
TQT_TQOBJECT(m_pPlaylistWindow), TQT_SLOT( showHide() ), true, true );
|
|
|
|
#ifdef TQ_WS_X11
|
|
|
|
m_pGlobalAccel->insert( "osd", i18n( "Show OSD" ), 0, KKey("WIN+o"), 0,
|
|
|
|
TQT_TQOBJECT(Amarok::OSD::instance()), TQT_SLOT( forceToggleOSD() ), true, true );
|
|
|
|
#endif
|
|
|
|
m_pGlobalAccel->insert( "mute", i18n( "Mute Volume" ), 0, KKey("WIN+m"), 0,
|
|
|
|
ec, TQT_SLOT( mute() ), true, true );
|
|
|
|
|
|
|
|
m_pGlobalAccel->insert( "rating1", i18n( "Rate Current Track: 1" ), 0, KKey("WIN+1"), 0,
|
|
|
|
TQT_TQOBJECT(this), TQT_SLOT( setRating1() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "rating2", i18n( "Rate Current Track: 2" ), 0, KKey("WIN+2"), 0,
|
|
|
|
TQT_TQOBJECT(this), TQT_SLOT( setRating2() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "rating3", i18n( "Rate Current Track: 3" ), 0, KKey("WIN+3"), 0,
|
|
|
|
TQT_TQOBJECT(this), TQT_SLOT( setRating3() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "rating4", i18n( "Rate Current Track: 4" ), 0, KKey("WIN+4"), 0,
|
|
|
|
TQT_TQOBJECT(this), TQT_SLOT( setRating4() ), true, true );
|
|
|
|
m_pGlobalAccel->insert( "rating5", i18n( "Rate Current Track: 5" ), 0, KKey("WIN+5"), 0,
|
|
|
|
TQT_TQOBJECT(this), TQT_SLOT( setRating5() ), true, true );
|
|
|
|
|
|
|
|
m_pGlobalAccel->setConfigGroup( "Shortcuts" );
|
|
|
|
m_pGlobalAccel->readSettings( kapp->config() );
|
|
|
|
m_pGlobalAccel->updateConnections();
|
|
|
|
|
|
|
|
//TODO fix kde accel system so that kactions find appropriate global shortcuts
|
|
|
|
// and there is only one configure shortcuts dialog
|
|
|
|
|
|
|
|
KActionCollection* const ac = Amarok::actionCollection();
|
|
|
|
KAccelShortcutList list( m_pGlobalAccel );
|
|
|
|
|
|
|
|
for( uint i = 0; i < list.count(); ++i )
|
|
|
|
{
|
|
|
|
KAction *action = ac->action( list.name( i ).latin1() );
|
|
|
|
|
|
|
|
if( action )
|
|
|
|
{
|
|
|
|
//this is a hack really, also it means there may be two calls to the slot for the shortcut
|
|
|
|
action->setShortcutConfigurable( false );
|
|
|
|
action->setShortcut( list.shortcut( i ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void App::fixHyperThreading()
|
|
|
|
{
|
|
|
|
/** Workaround for stability issues with HyperThreading CPU's, @see BUG 99199.
|
|
|
|
* First we detect the presence of HyperThreading. If active, we bind amarokapp
|
|
|
|
* to the first CPU only (hard affinity).
|
|
|
|
*
|
|
|
|
* @see http://www-128.ibm.com/developerworks/linux/library/l-affinity.html
|
|
|
|
* @see http://www.linuxjournal.com/article/6799
|
|
|
|
* (articles on processor affinity with the linux kernel)
|
|
|
|
*/
|
|
|
|
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
TQString line;
|
|
|
|
uint cpuCount = 0;
|
|
|
|
TQFile cpuinfo( "/proc/cpuinfo" );
|
|
|
|
if ( cpuinfo.open( IO_ReadOnly ) ) {
|
|
|
|
while ( cpuinfo.readLine( line, 20000 ) != -1 ) {
|
|
|
|
if ( line.startsWith( "flags" ) )
|
|
|
|
cpuCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If multiple CPUs are listed with the HT flag, we got HyperThreading enabled
|
|
|
|
if ( cpuCount > 1 ) {
|
|
|
|
debug() << "SMP system detected. Enabling WORKAROUND.\n";
|
|
|
|
|
|
|
|
// If the library is new enough try and call sched_setaffinity.
|
|
|
|
#ifdef SCHEDAFFINITY_SUPPORT
|
|
|
|
cpu_set_t mask;
|
|
|
|
CPU_ZERO( &mask ); // Initializes all the bits in the mask to zero
|
|
|
|
CPU_SET( 0, &mask ); // Sets only the bit corresponding to cpu
|
|
|
|
#ifdef SCHEDAFFINITY_3PARAMS
|
|
|
|
if ( sched_setaffinity( 0, sizeof(mask), &mask ) == -1 )
|
|
|
|
#else //SCHEDAFFINITY_3PARAMS
|
|
|
|
if ( sched_setaffinity( 0, &mask ) == -1 )
|
|
|
|
#endif //SCHEDAFFINITY_3PARAMS
|
|
|
|
{
|
|
|
|
warning() << "sched_setaffinity() call failed with error code: " << errno << endl;
|
|
|
|
TQTimer::singleShot( 0, this, TQT_SLOT( showHyperThreadingWarning() ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else //SCHEDAFFINITY_SUPPORT
|
|
|
|
warning()<<"glibc failed checks for sched_setaffinity" << endl;
|
|
|
|
TQTimer::singleShot( 0, this, TQT_SLOT( showHyperThreadingWarning() ) );
|
|
|
|
#endif //SCHEDAFFINITY_SUPPORT
|
|
|
|
}
|
|
|
|
else { debug() << "Workaround not enabled" << endl; }
|
|
|
|
#else //__linux__
|
|
|
|
debug() << "SCHEDAFFINITY_SUPPORT disabled since this isn't Linux" << endl;
|
|
|
|
#endif //__linux__
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void App::showHyperThreadingWarning() // SLOT
|
|
|
|
{
|
|
|
|
const TQString text =
|
|
|
|
i18n( "<p>You are using a system with multiple CPUs. "
|
|
|
|
"Please note that Amarok may be unstable with this "
|
|
|
|
"configuration.</p>"
|
|
|
|
"<p>If your system has hyperthreading, you can improve Amarok's stability by using the Linux kernel option 'NOHT', "
|
|
|
|
"or by disabling <i>HyperThreading</i> in your BIOS setup.</p>"
|
|
|
|
"<p>More information can be found in the README file. For further assistance "
|
|
|
|
"join us at #amarok on irc.freenode.net.</p>" );
|
|
|
|
|
|
|
|
KMessageBox::information( 0, text, i18n( "Warning" ), "showHyperThreadingWarning" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// METHODS
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include <taglib/id3v1tag.h>
|
|
|
|
#include <taglib/tbytevector.h>
|
|
|
|
#include <tqtextcodec.h>
|
|
|
|
|
|
|
|
//this class is only used in this module, so I figured I may as well define it
|
|
|
|
//here and save creating another header/source file combination
|
|
|
|
|
|
|
|
class ID3v1StringHandler : public TagLib::ID3v1::StringHandler
|
|
|
|
{
|
|
|
|
TQTextCodec *m_codec;
|
|
|
|
|
|
|
|
virtual TagLib::String parse( const TagLib::ByteVector &data ) const
|
|
|
|
{
|
|
|
|
return QStringToTString( m_codec->toUnicode( data.data(), data.size() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual TagLib::ByteVector render( const TagLib::String &ts ) const
|
|
|
|
{
|
|
|
|
const TQCString qcs = m_codec->fromUnicode( TStringToQString(ts) );
|
|
|
|
return TagLib::ByteVector( qcs, qcs.length() );
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
ID3v1StringHandler( int codecIndex )
|
|
|
|
: m_codec( TQTextCodec::codecForIndex( codecIndex ) )
|
|
|
|
{
|
|
|
|
debug() << "codec: " << m_codec << endl;
|
|
|
|
debug() << "codec-name: " << m_codec->name() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3v1StringHandler( TQTextCodec *codec )
|
|
|
|
: m_codec( codec )
|
|
|
|
{
|
|
|
|
debug() << "codec: " << m_codec << endl;
|
|
|
|
debug() << "codec-name: " << m_codec->name() << endl;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//SLOT
|
|
|
|
void App::applySettings( bool firstTime )
|
|
|
|
{
|
|
|
|
///Called when the configDialog is closed with OK or Apply
|
|
|
|
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
//determine and apply colors first
|
|
|
|
applyColorScheme();
|
|
|
|
|
|
|
|
#ifdef TQ_WS_X11
|
|
|
|
TrackToolTip::instance()->removeFromWidget( m_pTray );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( AmarokConfig::showPlayerWindow() )
|
|
|
|
{
|
|
|
|
if( !m_pPlayerWindow )
|
|
|
|
{
|
|
|
|
//the player Window becomes the main Window
|
|
|
|
//it is the focus for hideWithMainWindow behaviour etc.
|
|
|
|
//it gets the majestic "Amarok" caption
|
|
|
|
m_pPlaylistWindow->setCaption( kapp->makeStdCaption( i18n("Playlist") ) );
|
|
|
|
|
|
|
|
m_pPlayerWindow = new PlayerWidget( m_pPlaylistWindow, "PlayerWindow", firstTime && AmarokConfig::playlistWindowEnabled() );
|
|
|
|
|
|
|
|
//don't show PlayerWindow on firstTime, that is done below
|
|
|
|
//we need to explicately set the PL button if it's the first time
|
|
|
|
if( !firstTime ) m_pPlayerWindow->show();
|
|
|
|
|
|
|
|
|
|
|
|
connect( m_pPlayerWindow, TQT_SIGNAL(playlistToggled( bool )), m_pPlaylistWindow, TQT_SLOT(showHide()) );
|
|
|
|
|
|
|
|
#ifdef TQ_WS_X11
|
|
|
|
//TODO get this to work!
|
|
|
|
//may work if you set no parent for the systray?
|
|
|
|
//KWin::setSystemTrayWindowFor( m_pTray->winId(), m_pPlayerWindow->winId() );
|
|
|
|
|
|
|
|
delete m_pTray; m_pTray = new Amarok::TrayIcon( m_pPlayerWindow );
|
|
|
|
|
|
|
|
//make tray icon behave properly after selecting to show or hide player window
|
|
|
|
m_pTray->engineStateChanged(EngineController::instance()->engine()->state(), EngineController::instance()->engine()->state());
|
|
|
|
m_pTray->engineNewMetaData(EngineController::instance()->bundle(), false);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//make player window minimal if it was last time
|
|
|
|
if( AmarokConfig::playerWindowMinimalView() ){
|
|
|
|
m_pPlayerWindow->setMinimalView( true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
//this is called in the PlayerWindow ctor, hence the else
|
|
|
|
m_pPlayerWindow->applySettings();
|
|
|
|
|
|
|
|
} else if( m_pPlayerWindow ) {
|
|
|
|
#ifdef TQ_WS_X11
|
|
|
|
delete m_pTray; m_pTray = new Amarok::TrayIcon( m_pPlaylistWindow );
|
|
|
|
m_pTray->engineStateChanged(EngineController::instance()->engine()->state(), EngineController::instance()->engine()->state());
|
|
|
|
m_pTray->engineNewMetaData(EngineController::instance()->bundle(), false);
|
|
|
|
#endif
|
|
|
|
delete m_pPlayerWindow; m_pPlayerWindow = 0;
|
|
|
|
|
|
|
|
//Set the caption correctly.
|
|
|
|
if ( !EngineController::instance()->bundle().prettyTitle().isEmpty() )
|
|
|
|
m_pPlaylistWindow->setCaption( i18n("Amarok - %1").tqarg( EngineController::instance()->bundle().veryNiceTitle() ) );
|
|
|
|
else
|
|
|
|
m_pPlaylistWindow->setCaption( "Amarok" );
|
|
|
|
|
|
|
|
|
|
|
|
//m_pPlaylistWindow->show(); //must be shown //we do below now
|
|
|
|
|
|
|
|
//ensure that at least one Menu is plugged into an accessible UI element
|
|
|
|
if( !AmarokConfig::showMenuBar() && !Amarok::actionCollection()->action( "amarok_menu" )->isPlugged() )
|
|
|
|
playlistWindow()->createGUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
playlistWindow()->applySettings();
|
|
|
|
Scrobbler::instance()->applySettings();
|
|
|
|
Amarok::OSD::instance()->applySettings();
|
|
|
|
CollectionDB::instance()->applySettings();
|
|
|
|
#ifdef TQ_WS_X11
|
|
|
|
m_pTray->setShown( AmarokConfig::showTrayIcon() );
|
|
|
|
TrackToolTip::instance()->addToWidget( m_pTray );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//on startup we need to show the window, but only if it wasn't hidden on exit
|
|
|
|
//and always if the trayicon isn't showing
|
|
|
|
TQWidget* main_window = mainWindow();
|
|
|
|
#ifdef TQ_WS_X11
|
|
|
|
if( ( main_window && firstTime && !Amarok::config()->readBoolEntry( "HiddenOnExit", false ) ) || ( main_window && !AmarokConfig::showTrayIcon() ) )
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
main_window->show();
|
|
|
|
|
|
|
|
//takes longer but feels shorter. Crazy eh? :)
|
|
|
|
kapp->eventLoop()->processEvents( TQEventLoop::ExcludeUserInput );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{ //<Engine>
|
|
|
|
EngineBase *engine = EngineController::engine();
|
|
|
|
|
|
|
|
if( firstTime || AmarokConfig::soundSystem() !=
|
|
|
|
PluginManager::getService( engine )->property( "X-KDE-Amarok-name" ).toString() )
|
|
|
|
{
|
|
|
|
//will unload engine for us first if necessary
|
|
|
|
engine = EngineController::instance()->loadEngine();
|
|
|
|
}
|
|
|
|
|
|
|
|
engine->setXfadeLength( AmarokConfig::crossfade() ? AmarokConfig::crossfadeLength() : 0 );
|
|
|
|
engine->setVolume( AmarokConfig::masterVolume() );
|
|
|
|
|
|
|
|
engine->setEqualizerEnabled( AmarokConfig::equalizerEnabled() );
|
|
|
|
if ( AmarokConfig::equalizerEnabled() )
|
|
|
|
engine->setEqualizerParameters( AmarokConfig::equalizerPreamp(), AmarokConfig::equalizerGains() );
|
|
|
|
|
|
|
|
Amarok::actionCollection()->action("play_audiocd")->setEnabled( EngineController::hasEngineProperty( "HasKIO" ) || EngineController::hasEngineProperty("HasCDDA"));
|
|
|
|
} //</Engine>
|
|
|
|
|
|
|
|
{ //<Collection>
|
|
|
|
CollectionView::instance()->renderView(true);
|
|
|
|
} //</Collection>
|
|
|
|
{ //<Context>
|
|
|
|
ContextBrowser::instance()->renderView();
|
|
|
|
} //</Context>
|
|
|
|
|
|
|
|
{ // delete unneeded cover images from cache
|
|
|
|
const TQString size = TQString::number( AmarokConfig::coverPreviewSize() ) + '@';
|
|
|
|
const TQDir cacheDir = Amarok::saveLocation( "albumcovers/cache/" );
|
|
|
|
const TQStringList obsoleteCovers = cacheDir.entryList( "*" );
|
|
|
|
foreach( obsoleteCovers )
|
|
|
|
if ( !(*it).startsWith( size ) && !(*it).startsWith( "50@" ) )
|
|
|
|
TQFile( cacheDir.filePath( *it ) ).remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
//if ( !firstTime )
|
|
|
|
// Bizarrely and ironically calling this causes crashes for
|
|
|
|
// some people! FIXME
|
|
|
|
//AmarokConfig::writeConfig();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//SLOT
|
|
|
|
void
|
|
|
|
App::continueInit()
|
|
|
|
{
|
|
|
|
DEBUG_BLOCK
|
|
|
|
const KCmdLineArgs* const args = KCmdLineArgs::parsedArgs();
|
|
|
|
bool restoreSession = args->count() == 0 || args->isSet( "append" ) || args->isSet( "enqueue" )
|
|
|
|
|| Amarok::config()->readBoolEntry( "AppendAsDefault", false );
|
|
|
|
|
|
|
|
// Make this instance so it can start receiving signals
|
|
|
|
MoodServer::instance();
|
|
|
|
|
|
|
|
// Remember old folder setup, so we can detect changes after the wizard was used
|
|
|
|
//const TQStringList oldCollectionFolders = MountPointManager::instance()->collectionFolders();
|
|
|
|
|
|
|
|
|
|
|
|
if ( Amarok::config()->readBoolEntry( "First Run", true ) || args->isSet( "wizard" ) ) {
|
|
|
|
std::cout << "STARTUP\n" << std::flush; //hide the splashscreen
|
|
|
|
firstRunWizard();
|
|
|
|
Amarok::config()->writeEntry( "First Run", false );
|
|
|
|
Amarok::config()->sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
CollectionDB::instance()->checkDatabase();
|
|
|
|
|
|
|
|
m_pMediaDeviceManager = MediaDeviceManager::instance();
|
|
|
|
m_pGlobalAccel = new KGlobalAccel( TQT_TQOBJECT(this) );
|
|
|
|
m_pPlaylistWindow = new PlaylistWindow();
|
|
|
|
#ifdef TQ_WS_X11
|
|
|
|
m_pTray = new Amarok::TrayIcon( m_pPlaylistWindow );
|
|
|
|
#endif
|
|
|
|
m_pPlaylistWindow->init(); //creates the playlist, browsers, etc.
|
|
|
|
//init playlist window as soon as the database is guaranteed to be usable
|
|
|
|
//connect( CollectionDB::instance(), TQT_SIGNAL( databaseUpdateDone() ), m_pPlaylistWindow, TQT_SLOT( init() ) );
|
|
|
|
initGlobalShortcuts();
|
|
|
|
//load previous playlist in separate thread
|
|
|
|
if ( restoreSession && AmarokConfig::savePlaylist() )
|
|
|
|
{
|
|
|
|
Playlist::instance()->restoreSession();
|
|
|
|
//Debug::stamp();
|
|
|
|
//p->restoreSession();
|
|
|
|
}
|
|
|
|
if( args->isSet( "engine" ) ) {
|
|
|
|
// we correct some common errors (case issues, missing -engine off the end)
|
|
|
|
TQString engine = args->getOption( "engine" ).lower();
|
|
|
|
if( engine.startsWith( "gstreamer" ) ) engine = "gst-engine";
|
|
|
|
if( !engine.endsWith( "engine" ) ) engine += "-engine";
|
|
|
|
|
|
|
|
AmarokConfig::setSoundSystem( engine );
|
|
|
|
}
|
|
|
|
Debug::stamp();
|
|
|
|
//create engine, show PlayerWindow, show TrayIcon etc.
|
|
|
|
applySettings( true );
|
|
|
|
Debug::stamp();
|
|
|
|
// Start ScriptManager. Must be created _after_ PlaylistWindow.
|
|
|
|
ScriptManager::instance();
|
|
|
|
Debug::stamp();
|
|
|
|
//notify loader application that we have started
|
|
|
|
std::cout << "STARTUP\n" << std::flush;
|
|
|
|
|
|
|
|
//after this point only analyzer and temporary pixmaps will be created
|
|
|
|
TQPixmap::setDefaultOptimization( TQPixmap::BestOptim );
|
|
|
|
|
|
|
|
//do after applySettings(), or the OSD will flicker and other wierdness!
|
|
|
|
//do before restoreSession()!
|
|
|
|
EngineController::instance()->attach( this );
|
|
|
|
|
|
|
|
//set a default interface
|
|
|
|
engineStateChanged( Engine::Empty );
|
|
|
|
|
|
|
|
if ( AmarokConfig::resumePlayback() && restoreSession && !args->isSet( "stop" ) ) {
|
|
|
|
//restore session as long as the user didn't specify media to play etc.
|
|
|
|
//do this after applySettings() so OSD displays correctly
|
|
|
|
EngineController::instance()->restoreSession();
|
|
|
|
}
|
|
|
|
|
|
|
|
CollectionDB *collDB = CollectionDB::instance();
|
|
|
|
//Collection scan is triggered in firstRunWizard if the colelction folder setup was changed in the wizard
|
|
|
|
|
|
|
|
// If database version is updated, the collection needs to be rescanned.
|
|
|
|
// Works also if the collection is empty for some other reason
|
|
|
|
// (e.g. deleted collection.db)
|
|
|
|
if ( CollectionDB::instance()->isEmpty() )
|
|
|
|
{
|
|
|
|
//connect( collDB, TQT_SIGNAL( databaseUpdateDone() ), collDB, TQT_SLOT( startScan() ) );
|
|
|
|
collDB->startScan();
|
|
|
|
}
|
|
|
|
else if ( AmarokConfig::monitorChanges() )
|
|
|
|
//connect( collDB, TQT_SIGNAL( databaseUpdateDone() ), collDB, TQT_SLOT( scanModifiedDirs() ) );
|
|
|
|
collDB->scanModifiedDirs();
|
|
|
|
|
|
|
|
|
|
|
|
handleCliArgs();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
App::applyColorScheme()
|
|
|
|
{
|
|
|
|
TQColorGroup group;
|
|
|
|
using Amarok::ColorScheme::AltBase;
|
|
|
|
int h, s, v;
|
|
|
|
TQWidget* const browserBar = TQT_TQWIDGET( playlistWindow()->child( "BrowserBar" ) );
|
|
|
|
TQWidget* const contextBrowser = TQT_TQWIDGET( ContextBrowser::instance() );
|
|
|
|
|
|
|
|
if( AmarokConfig::schemeKDE() )
|
|
|
|
{
|
|
|
|
AltBase = KGlobalSettings::alternateBackgroundColor();
|
|
|
|
|
|
|
|
playlistWindow()->unsetPalette();
|
|
|
|
browserBar->unsetPalette();
|
|
|
|
contextBrowser->unsetPalette();
|
|
|
|
|
|
|
|
PlayerWidget::determineAmarokColors();
|
|
|
|
}
|
|
|
|
|
|
|
|
else if( AmarokConfig::schemeAmarok() )
|
|
|
|
{
|
|
|
|
group = TQApplication::tqpalette().active();
|
|
|
|
const TQColor bg( Amarok::blue );
|
|
|
|
AltBase.setRgb( 57, 64, 98 );
|
|
|
|
|
|
|
|
group.setColor( TQColorGroup::Text, TQt::white );
|
|
|
|
group.setColor( TQColorGroup::Link, 0xCCCCCC );
|
|
|
|
group.setColor( TQColorGroup::Base, bg );
|
|
|
|
group.setColor( TQColorGroup::Foreground, 0xd7d7ef );
|
|
|
|
group.setColor( TQColorGroup::Background, AltBase );
|
|
|
|
|
|
|
|
group.setColor( TQColorGroup::Button, AltBase );
|
|
|
|
group.setColor( TQColorGroup::ButtonText, 0xd7d7ef );
|
|
|
|
|
|
|
|
// group.setColor( TQColorGroup::Light, TQt::cyan /*lighter than Button color*/ );
|
|
|
|
// group.setColor( TQColorGroup::Midlight, TQt::blue /*between Button and Light*/ );
|
|
|
|
// group.setColor( TQColorGroup::Dark, TQt::green /*darker than Button*/ );
|
|
|
|
// group.setColor( TQColorGroup::Mid, TQt::red /*between Button and Dark*/ );
|
|
|
|
// group.setColor( TQColorGroup::Shadow, TQt::yellow /*a very dark color. By default, the shadow color is TQt::black*/ );
|
|
|
|
|
|
|
|
group.setColor( TQColorGroup::Highlight, TQt::white );
|
|
|
|
group.setColor( TQColorGroup::HighlightedText, bg );
|
|
|
|
//group.setColor( TQColorGroup::BrightText, TQColor( 0xff, 0x40, 0x40 ) ); //GlowColor
|
|
|
|
|
|
|
|
AltBase.getHsv( &h, &s, &v );
|
|
|
|
group.setColor( TQColorGroup::Midlight, TQColor( h, s/3, (int)(v * 1.2), TQColor::Hsv ) ); //column separator in playlist
|
|
|
|
|
|
|
|
//TODO set all colours, even button colours, that way we can change the dark,
|
|
|
|
//light, etc. colours and Amarok scheme will look much better
|
|
|
|
|
|
|
|
using namespace Amarok::ColorScheme;
|
|
|
|
Base = Amarok::blue;
|
|