/***************************************************************************
                          KTfxWidget.cpp  -  main widget
                             -------------------                                         
    begin                : Tue Sep 21 13:07:04 MEST 1999
                                           
    copyright            : (C) 1999 by David Banz                         
    email                : neo@sakura-audio.cx
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "KTfxWidget.h"

extern KApplication *mykapp;
extern void sigHandlerINT(int signal);

KTfxWidget::KTfxWidget( QWidget* parent, const char* name ):KTfxControlData( parent, name )
{
	p=0;	// no process object, yet
	splashScreen=0;	// no splash-screen either
	
	// check for tfmx-play first
	checkTfx();
	// do major part of i18n initialization
	i18nInitBulk();		
	// set all intial defaults
	initParanoia();
	// read config file
	readConfig();	
	// credits	
	qtarch_StatusBar->setText("TFMXcess "VERSION);
	// connect buttons
	buttonInit();
	// add accelerator for keyboard events and connect keys
	accInit();
	// evalutate command-line arguments
	evalComm();
	// update display with preloaded song et al., start player
	initPreload();
	// setup dropzone for DND
	setupDropzone();	
	// install signal handler
	signal (SIGINT, &sigHandlerINT);

	// the following must be done AFTER	readConfig() !
	if (showSplash) {
		// create the nice splash screen...
		KTfxSplash* splashScreen = new KTfxSplash( 0, "Sakura Audio presents...");
		// ...let's show it...
		splashScreen->show();
		// ...and hide it after ten seconds
		QTimer::singleShot( 10*1000, splashScreen, SLOT(hide()) );
	}

	// Greetings!
	cout << "Mina-san, konnichi wa! ^_^" << endl;	
}

KTfxWidget::~KTfxWidget()
{
	cout << endl << "See you later...special greetings to Anime no Tomodachi..." << endl;
}

void KTfxWidget::closeEvent(QCloseEvent*)
{
	quitTfx();	// close application and player when widget is closed
}

// ################ helper method for the SIGINT handler to avoid segfaults ######
void KTfxWidget::signalHelperINT()
{
	quitTfx();	// close application and player when SIGINT is caught
}

// ########## button slots #########

void KTfxWidget::stopTfx()
{
	// stop tfmx player if playing
	stopCore();
	saveConfig();
}

void KTfxWidget::quitTfx()
{
	// stop tfmx player
	stopTfx();
	// quit application		
	mykapp->quit();
}

void KTfxWidget::openTfx()
{
	// overloaded, call openTfx "without" a filename
	openTfx(0);
}

void KTfxWidget::openTfx(QString myFile)
{
	QString newFile;
	// check for parameter
	if (myFile!=0)
		// if a filename is given, use it instead of opening a file browser
		newFile = myFile;
	else {
		// else open dialog to get tfmxFile
		newFile = KFileDialog::getOpenFileName(browseDir, "mdat.*", this, "open tfmx file");
	}
	QFileInfo fi( newFile );	// to check for mdat file
	if ( (samplePath(newFile)!=0)&&(!newFile.isEmpty())&&(fi.fileName().left(5)=="mdat.")&&(fi.isFile())&&(fi.isReadable()) ) {
		// stop player
		stopTfx();
		// get new browse dir from dir path of selected file
		browseDir = fi.dirPath(TRUE);
		// start player
		tfmxFile=newFile;
		open=1;
		song=0;
		playCore();
	}
	saveConfig();
}

void KTfxWidget::playTfx()
{
	if (playing==0) {
		if (open==0) {
			openTfx();
		}
		else {
			playCore();
		}
	}
	saveConfig();
}

void KTfxWidget::songUp()
{
	if (song<31) {
		song++;
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	}	
	saveConfig();
}

void KTfxWidget::songDown()
{
	if (song>0) {
		song--;
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	}
	saveConfig();
}
	
void KTfxWidget::bitsHi()
{
	if (bits==8) {
		bits=16;
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	}	
	saveConfig();
}

void KTfxWidget::bitsLo()
{
	if (bits==16) {
		bits=8;
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	}	
	saveConfig();
}

void KTfxWidget::freqUp()
{
	if (freq<44) {
		switch(freq) {
			case 32: freq=44;break;
			case 22: freq=32;break;
			case 16: freq=22;break;
			case 11: freq=16;break;
		}
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	}	
	saveConfig();
}

void KTfxWidget::freqDown()
{
	if (freq>11) {
		switch(freq) {
			case 44: freq=32;break;
			case 32: freq=22;break;
			case 22: freq=16;break;
			case 16: freq=11;break;
		}
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	}
	saveConfig();
}

// toggle oversampling + button
void KTfxWidget::toggleOsampButton()
{
	if (qtarch_OverSample->isChecked())
		qtarch_OverSample->setChecked(FALSE);
	else
		qtarch_OverSample->setChecked(TRUE);

	toggleOversampling();	
}

// toggle oversampling
void KTfxWidget::toggleOversampling()
{
	if (playing==1) {
		stopTfx();
		playTfx();
	}
}

// modify channel separation...

void KTfxWidget::setMono()
{
	if (separation!=0) {
		separation=0;
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	saveConfig();
	}
}

void KTfxWidget::setHeadphones()
{
	if (separation!=1) {
		separation=1;
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	saveConfig();
	}
}

void KTfxWidget::setStereo()
{
	if (separation!=2) {
		separation=2;
		if (playing==1) {
			stopTfx();
			playTfx();
		}
		else updateLcd();
	saveConfig();
	}
}

void KTfxWidget::addTipBulk(){
	// the big block that adds all the tooltips
	QToolTip::add( qtarch_FileBar, tipFileBar );
	QToolTip::add( qtarch_SongLcd, tipSongLcd );
	QToolTip::add( qtarch_BitLcd, tipBitLcd );
	QToolTip::add( qtarch_FreqLcd, tipFreqLcd );
	QToolTip::add( qtarch_StatusBar, tipStatusBar[playing] );
	QToolTip::add( qtarch_PlayButton, tipPlayButton );
	QToolTip::add( qtarch_OpenButton, tipOpenButton );
	QToolTip::add( qtarch_StopButton, tipStopButton );
	QToolTip::add( qtarch_QuitButton, tipQuitButton );
	QToolTip::add( qtarch_DownButton, tipDownButton );
	QToolTip::add( qtarch_UpButton, tipUpButton );
	QToolTip::add( qtarch_EightButton, tipEightButton );
	QToolTip::add( qtarch_SixteenButton, tipSixteenButton );
	QToolTip::add( qtarch_HiButton, tipHiButton );
	QToolTip::add( qtarch_LoButton, tipLoButton );
	QToolTip::add( qtarch_ToolTipCheck, tipToolTipCheck );
	QToolTip::add( qtarch_HelpButton, tipHelpButton );
	QToolTip::add( qtarch_AboutButton, tipAboutButton );		
	QToolTip::add( qtarch_MonoButton, tipMonoButton );
	QToolTip::add( qtarch_HeadphonesButton, tipHeadphonesButton );
	QToolTip::add( qtarch_StereoButton, tipStereoButton );
	QToolTip::add( qtarch_SeparationBar, tipSeparation[separation] );	
	QToolTip::add( qtarch_OverSample, tipOversampling );
}

void KTfxWidget::removeTipBulk(){
	// the big block that removes all the tooltips
	QToolTip::remove( qtarch_FileBar );
	QToolTip::remove( qtarch_SongLcd );
	QToolTip::remove( qtarch_BitLcd );
	QToolTip::remove( qtarch_FreqLcd );
	QToolTip::remove( qtarch_StatusBar );
	QToolTip::remove( qtarch_PlayButton );
	QToolTip::remove( qtarch_OpenButton );
	QToolTip::remove( qtarch_StopButton );
	QToolTip::remove( qtarch_QuitButton );
	QToolTip::remove( qtarch_DownButton );
	QToolTip::remove( qtarch_UpButton );
	QToolTip::remove( qtarch_EightButton );
	QToolTip::remove( qtarch_SixteenButton );
	QToolTip::remove( qtarch_HiButton );
	QToolTip::remove( qtarch_LoButton );
	QToolTip::remove( qtarch_ToolTipCheck );
	QToolTip::remove( qtarch_HelpButton );
	QToolTip::remove( qtarch_AboutButton );
	QToolTip::remove( qtarch_MonoButton );
	QToolTip::remove( qtarch_StereoButton );
	QToolTip::remove( qtarch_HeadphonesButton );
	QToolTip::remove( qtarch_SeparationBar );
	QToolTip::remove( qtarch_OverSample );
}

void KTfxWidget::toggleTip()
{
	// turn tooltips off or on, depending on status of checkbox
	if (qtarch_ToolTipCheck->isChecked()) {
		addTipBulk();
	}
	else {
		removeTipBulk();
	}
	saveConfig();
}

void KTfxWidget::tipOff()
{
	// force tooltips off
	if (qtarch_ToolTipCheck->isChecked()) {
		removeTipBulk();
		qtarch_ToolTipCheck->setChecked(FALSE);
	}
	saveConfig();
}

void KTfxWidget::tipOn()
{
	// force tooltips on
	if (!qtarch_ToolTipCheck->isChecked()) {
		addTipBulk();
		qtarch_ToolTipCheck->setChecked(TRUE);
	}
	saveConfig();
}

void KTfxWidget::toggleCheckTip()
{
	// toggle checkbox and tooltips
	if (qtarch_ToolTipCheck->isChecked())
		tipOff();
	else
		tipOn();
	saveConfig();
}

void KTfxWidget::help()
{
	// call HTML help
	kapp->invokeHTMLHelp("tfmxcess/index.html","");
}

void KTfxWidget::about()
{
	// create about box
	QMessageBox* aboutBox = new QMessageBox( "tfmxcess",
		aboutStr[0]+(QString)VERSION+(QString)" ("+(QString)INTERNAL_DESIGNATION+(QString)")\n"+aboutStr[1]+(QString)"\n\n"+aboutStr[2]+(QString)"\n"+aboutStr[3],
		QMessageBox::Information,
		QMessageBox::Ok | QMessageBox::Default,0,0);

	// use the application icon as icon pixmap
	aboutBox->setIconPixmap(mykapp->getIcon());

	// set the button text with i18n
	aboutBox->setButtonText( QMessageBox::Ok, i18n("OK") );
	
	// make sure the box cannot be resized by the user (a common mistake made by
	// most KDE applications, as I have noticed)
	// - no one should want it to be larger and if you make it smaller (=too small),
	// it looks rather chaotic...
	aboutBox->adjustSize();
	aboutBox->setFixedSize(aboutBox->size());
	
	// construction done...let's show the about-box!
	aboutBox->exec();
	// finally, remove the box
	delete aboutBox;
}
// ############### config file access #######################

void KTfxWidget::readConfig()
{
  KConfig* config = KApplication::getKApplication()->getConfig();
	config->setGroup("tfmxcess");
	bits=config->readNumEntry("Bits",16);
	freq=config->readNumEntry("Freq",44);
	browseDir=config->readEntry("BrowseDir",0);
	preloadSong=config->readEntry("RecentFile",0);
	song=preloadSubsong=config->readNumEntry("RecentSong",0);

	int boolTip=config->readNumEntry("Tooltips",FALSE);
	
	separation=config->readNumEntry("Separation",1);

	int boolSample=config->readNumEntry("Oversampling",FALSE);
	
	int major=config->readNumEntry("Major",-1);
	int minor=config->readNumEntry("Minor",-1);
	int patch=config->readNumEntry("Patch",-1);
	
	// determine whether to show the splash screen...
	showSplash=false;
	if ( (major*minor*patch) < 0) showSplash=true;
  else if (MAJOR>major) showSplash=true;
  else if (MINOR>minor) showSplash=true;
  else if (PATCH>patch) showSplash=true;
	
	// set oversampling
	if (boolSample==TRUE)
		qtarch_OverSample->setChecked(TRUE);
	else
		qtarch_OverSample->setChecked(FALSE);
		
	// here we set the tooltips according to the config file
	if (boolTip==TRUE)
		tipOn();
	else
		tipOff();
	
	// now we check whether the file from the config file really exists
	QFileInfo fi4( preloadSong );
	if (!((fi4.exists())&&(fi4.isFile())&&(fi4.isReadable())&&(fi4.fileName().left(5)=="mdat."))) {
		preloadSong=0;	// reset preload song
		browseDir = 0;	// reset browse dir
		song=0;					// reset subsong
	}
}

void KTfxWidget::saveConfig()
{
	// get new browse dir from dir. path of current songfile
	QFileInfo fi( tfmxFile );
	browseDir = fi.dirPath(TRUE);
	
  KConfig* config = KApplication::getKApplication()->getConfig();
	config->setGroup("tfmxcess");
	config->writeEntry("Bits",this->bits);
	config->writeEntry("Freq",this->freq);
	config->writeEntry("BrowseDir",this->browseDir);
	config->writeEntry("RecentFile",this->tfmxFile);
	config->writeEntry("RecentSong",this->song);
	config->writeEntry("Tooltips",(int)this->qtarch_ToolTipCheck->isChecked());
	config->writeEntry("Separation",this->separation);
	config->writeEntry("Oversampling",(int)this->qtarch_OverSample->isChecked());
	config->writeEntry("Major",MAJOR);
	config->writeEntry("Minor",MINOR);
	config->writeEntry("Patch",PATCH);
	config->sync();
}

void KTfxWidget::checkTfx()
{
	// initilialize translation for error box:
	// we don't do this in i18nInitBulk(), because if an error occurs right here,
	// there is no need to go through the rest of the i18n code anyway
	noTfxStr[0]=i18n("Error!");
	noTfxStr[1]=i18n("The required binary tfmx-play cannot not");
	noTfxStr[2]=i18n("be executed. Check path/permissions.");
  noTfxStr[3]=i18n("Quit");	// this is the button text!
/*	if (system("which tfmx-play 1>/dev/null 2>/dev/null") != 0) {	// if tfmx-play is not found, show error message and exit
		KMsgBox::message(this,"tfmxcess",noTfxStr[0]+"\n\n"+noTfxStr[1]+"\n"+noTfxStr[2],4,noTfxStr[3]);
		exit(1);
	}*/
}

// ################ initially connect buttons ###################

void KTfxWidget::buttonInit()
{
	connect( qtarch_QuitButton, SIGNAL(clicked()), this, SLOT(quitTfx()));
	connect( qtarch_PlayButton, SIGNAL(clicked()), this, SLOT(playTfx()));
	connect( qtarch_StopButton, SIGNAL(clicked()), this, SLOT(stopTfx()));
	connect( qtarch_OpenButton, SIGNAL(clicked()), this, SLOT(openTfx()));
	
	connect( qtarch_UpButton, SIGNAL(clicked()), this, SLOT(songUp()));
	connect( qtarch_DownButton, SIGNAL(clicked()), this, SLOT(songDown()));
	
	connect( qtarch_EightButton, SIGNAL(clicked()), this, SLOT(bitsLo()));
	connect( qtarch_SixteenButton, SIGNAL(clicked()), this, SLOT(bitsHi()));
	
	connect( qtarch_HiButton, SIGNAL(clicked()), this, SLOT(freqUp()));
	connect( qtarch_LoButton, SIGNAL(clicked()), this, SLOT(freqDown()));

	connect( qtarch_ToolTipCheck, SIGNAL(clicked()), this, SLOT(toggleTip()));

	connect( qtarch_HelpButton, SIGNAL(clicked()), this, SLOT(help()));
	connect( qtarch_AboutButton, SIGNAL(clicked()), this, SLOT(about()));

	connect( qtarch_StereoButton, SIGNAL(clicked()), this, SLOT(setStereo()));
	connect( qtarch_HeadphonesButton, SIGNAL(clicked()), this, SLOT(setHeadphones()));
	connect( qtarch_MonoButton, SIGNAL(clicked()), this, SLOT(setMono()));
	
	connect( qtarch_OverSample, SIGNAL(clicked()), this, SLOT(toggleOversampling()));
}


// ################# accelerator stuff ########################

void KTfxWidget::accInit()
{
	acc = new QAccel( this );
	
	acc->connectItem( acc->insertItem(Key_H), this, SLOT(help()) );
 	acc->connectItem( acc->insertItem(Key_A),	this, SLOT(about()) );
	
	acc->connectItem( acc->insertItem(Key_P),	this, SLOT(playTfx()) );
	acc->connectItem( acc->insertItem(Key_S),	this, SLOT(stopTfx()) );
	acc->connectItem( acc->insertItem(Key_O),	this, SLOT(openTfx()) );
	acc->connectItem( acc->insertItem(Key_Q),	this, SLOT(quitTfx()) );

	acc->connectItem( acc->insertItem(Key_1),	this, SLOT(songUp()) );
	acc->connectItem( acc->insertItem(Key_2),	this, SLOT(songDown()) );
	acc->connectItem( acc->insertItem(Key_3),	this, SLOT(bitsHi()) );
	acc->connectItem( acc->insertItem(Key_4),	this, SLOT(bitsLo()) );
	acc->connectItem( acc->insertItem(Key_5),	this, SLOT(freqUp()) );
 	acc->connectItem( acc->insertItem(Key_6),	this, SLOT(freqDown()) );

 	acc->connectItem( acc->insertItem(Key_T),	this, SLOT(toggleCheckTip()) );

	acc->connectItem( acc->insertItem(Key_8),	this, SLOT(setStereo()) );
	acc->connectItem( acc->insertItem(Key_9),	this, SLOT(setHeadphones()) );
	acc->connectItem( acc->insertItem(Key_0),	this, SLOT(setMono()) );
 	
	acc->connectItem( acc->insertItem(Key_V),	this,	SLOT(toggleOsampButton())  );
	
	// these are all KDE standard accelerators "scroll up/down" is
	// here interpreted as "previous/next subsong"
	acc->connectItem( acc->insertItem(Key_F1), this, SLOT(help()) );
	acc->connectItem( acc->insertItem(CTRL+Key_O),	this, SLOT(openTfx()) );
	acc->connectItem( acc->insertItem(CTRL+Key_Q),	this, SLOT(quitTfx()) );
	acc->connectItem( acc->insertItem(Key_Next),	this, SLOT(songUp()) );
	acc->connectItem( acc->insertItem(Key_Prior),	this, SLOT(songDown()) );
}

// ################# set all defaults ########################

void KTfxWidget::initParanoia()
{
	bits=16;					// 8 or 16 bit
	freq=44;					// 44=44100 Hz, 32=32000 Hz,  22=22050 Hz, 16=16000 Hz, 11=10025 Hz
	song=0;						// subsong number
	open=0;						// song open?
	playing=0;				// song playing?
	browseDir=0;			// start browsing in current dir
	preloadSong=0;		// song to preload
	preloadSubsong=0;	// subsong to preselect
	tfmxFile=0;				// mdat song filename
	qtarch_ToolTipCheck->setChecked(FALSE);	// no tooltips, so we uncheck this button and keep 'em off
	qtarch_OverSample->setChecked(FALSE);	// no oversampling
}

// ### return path of sample file for given mdat.-file, return 0 if it does not exist ###

QString KTfxWidget::samplePath(QString mdatPath){
			QFileInfo fi3( mdatPath );
			
			QString smplFile=fi3.fileName();
			// mdat.somefile
			QString smplPath=mdatPath;
			// /where/ever/it/is/mdat.somefile
			smplPath=smplPath.left(smplPath.length()-smplFile.length());
			// /where/ever/it/is/
			smplFile=smplFile.remove(0,5);
			// somefile
			smplFile="smpl."+smplFile;
			// smpl.somefile
			smplPath=smplPath+smplFile;
			// /where/ever/it/is/smpl.somefile
			
			QFileInfo fi4( smplPath );
			if ((fi4.exists())&&(fi4.isFile())&&(fi4.isReadable())&&(fi4.fileName().left(5)=="smpl.")) {
				return smplPath;
			}
			return 0;	// sorry, the file does not exist
}

// ############# evaluate command line ###############

void KTfxWidget::evalComm()
{
	if (mykapp->argc()>1) { 								// get filename from command-line
		QString commFile=mykapp->argv()[1];		// get first argument
		QFileInfo fi3( commFile );						// check for given file...
		if ((fi3.exists())&&(fi3.isFile())&&(fi3.isReadable())&&(fi3.fileName().left(5)=="mdat.")) {
			// now check if smpl. file also exists...
			if (samplePath(commFile)!=0) {
				preloadSong=fi3.absFilePath();		// override preloaded song from config file
				browseDir = fi3.dirPath(TRUE);		// set dir for browser accordingly
				song=0;														// reset subsong
				if (mykapp->argc()>2) {							// get subsong from command-line
					int mySub=((QString)mykapp->argv()[2]).toInt();
					if ((mySub>=0)&&(mySub<=31))		// check valid range
						song=mySub;										// override subsong
				}
			}
		}
	}
}

// ######## update display with preloaded song et al., start player ###########

void KTfxWidget::initPreload()
{
	if ((preloadSong!=0)&&(preloadSong!="")) {					// show preloaded songfile
		tfmxFile=preloadSong;
		open=1;
		qtarch_FileBar->setText( tfmxFile );	
		qtarch_SongLcd->display(song);
	}
	qtarch_FreqLcd->display(freq);// sound settings
	qtarch_BitLcd->display(bits);

	if ((tfmxFile!=0)&&(tfmxFile!="")) {						// if a file has been loaded, play it
		playTfx();
	}
}

// ################## cleanup the player process ##############
void KTfxWidget::done(KProcess*){
	// remove KProcess instance
	delete p;
	p=0;
	// make sure the frontend really knows that the player is gone
	// (this is needed when /dev/dsp is busy, for example, or when
	// the player is killed from outside)
	qtarch_StatusBar->setText(i18n("stopped"));
	playing=0;
	if (qtarch_ToolTipCheck->isChecked()) {	// update tooltip, if active
			QToolTip::remove( qtarch_StatusBar );
			QToolTip::add( qtarch_StatusBar, tipStatusBar[playing] );
	}
}

// ############# core stuff to stop the player #################

void KTfxWidget::stopCore()
{	
	if (playing!=0) {
	// kill player process
	if (p) {
		if (p->isRunning()) {
			p->kill();
		}
	}
		
	qtarch_StatusBar->setText(i18n("stopped"));
	playing=0;
	if (qtarch_ToolTipCheck->isChecked()) {	// update tooltip, if active
			QToolTip::remove( qtarch_StatusBar );
			QToolTip::add( qtarch_StatusBar, tipStatusBar[playing] );
		}
	}
}

// ########### core stuff to start the player ############

void KTfxWidget::playCore()
{
	QString songStr;
	songStr.setNum(song);
	
	QString freqStr;
	switch(freq) {
		case 44:
			freqStr=" -f44100 ";break;
		case 32:
			freqStr=" -f32000 ";break;
		case 22:
			freqStr=" -f22050 ";break;
		case 16:
			freqStr=" -f16000 ";break;
		case 11:
			freqStr=" -f11050 ";break;
	}
	
	QString bitStr;
	switch(bits) {
		case 16:
			bitStr="";break;
		case 8:
			bitStr=" -8 ";break;
	}
	
	QString sepStr;
	sepStr.setNum(separation);
		
	updateLcd();
		
	qtarch_FileBar->setText( tfmxFile );	

	if (p) {
		delete p;
		p=0;
	}
	if (!p) {
		p=new KShellProcess;
	}
	if (p) {
		// clear all arguments
		p->clearArguments();
		
		*p << "tfmx-play";	// set executable name first
		*p << tfmxFile;
		*p << "-S";
		*p << "-p" << songStr << bitStr << freqStr;
		*p << "-b" << sepStr;
		
		// turn oversampling off, if box is not checked
		if (!qtarch_OverSample->isChecked()) {
			*p << "-v";
		}
		
		// player output MUST NOT be sent to /dev/null for KShellProcess to work correctly!
	}
	// connect "done"-slot to KProcess instance
	QApplication::connect(p, SIGNAL(processExited(KProcess *)), this, SLOT(done(KProcess*)));
		
	// try to start player
	if (p->start(KShellProcess::NotifyOnExit,KShellProcess::NoCommunication)) {
		qtarch_StatusBar->setText(i18n("playing"));
		playing=1;
	}
	else {
		qtarch_StatusBar->setText(i18n("stopped"));
		playing=0;
	}
		
	if (qtarch_ToolTipCheck->isChecked()) {	// update tooltips, if active
		QToolTip::remove( qtarch_StatusBar );
		QToolTip::add( qtarch_StatusBar, tipStatusBar[playing] );
	}

}

void KTfxWidget::updateLcd()
{
	// show separation (no LCD, but who cares)
	qtarch_SeparationBar->setText(showSeparation[separation]);
	if (qtarch_ToolTipCheck->isChecked()) {	// update tooltips, if active
		QToolTip::remove( qtarch_SeparationBar );
		QToolTip::add( qtarch_SeparationBar, tipSeparation[separation] );
	}
	// the real LCDs
  qtarch_FreqLcd->display(freq);	
	qtarch_BitLcd->display(bits);		
	qtarch_SongLcd->display(song);
}

void KTfxWidget::setupDropzone()
{
	dropzone = new KDNDDropZone(this, DndURL);
	
	connect(dropzone,SIGNAL(dropAction(KDNDDropZone*)),SLOT(dropAction(KDNDDropZone*)));
}

void KTfxWidget::dropAction(KDNDDropZone *dz) // something has been dropped
{
	QStrList &list = dz->getURLList();// list of dropped URLs
	QString first=list.first();				// get first item in URL list, others are not used
  KURL theUrl(first);
	
	if (theUrl.isLocalFile()) {
		QString thePath=(QString)theUrl.directory()+(QString)theUrl.filename();	
		openTfx(thePath); // try to open this file
	}
	else {
		cerr << "Drag-and-Drop for remote files not supported, yet." << endl;
		// file is remote, do nothing, maybe later support for remote files
		// will be added here...
		
		// NOTE: remote files always have to be downloaded in pairs (the smpl. file
		// is needed as well!), and should be placed into /tmp/.tfmxcess.songs/,
		// temp files can be erased when we quit...
	}
}

void KTfxWidget::i18nInitBulk()
{
	// initialize translated tooltips
	tipFileBar=i18n("Current songfile");
	tipSongLcd=i18n("Selected subsong");
	tipFreqLcd=i18n("Selected frequency");
	tipBitLcd=i18n("Selected bits per sample");
	tipStatusBar[0]=i18n("Status: stopped");
	tipStatusBar[1]=i18n("Status: playing");
	tipPlayButton=i18n("Start playing");
	tipStopButton=i18n("Stop playing");
	tipOpenButton=i18n("Open TFMX songfile");
	tipQuitButton=i18n("Leave this program");
	tipUpButton=i18n("Next subsong");
	tipDownButton=i18n("Previous subsong");
	tipEightButton=i18n("8 bit sound");
	tipSixteenButton=i18n("16 bit sound");
	tipHiButton=i18n("Higher frequency");
	tipLoButton=i18n("Lower frequency");
	tipHelpButton=i18n("Call HTML help");
	tipAboutButton=i18n("Show credits");
	tipToolTipCheck=i18n("Toggle tooltips on/off");
	tipSeparation[0]=i18n("Channel separation: Mono");
	tipSeparation[1]=i18n("Channel separation: Headphones");
	tipSeparation[2]=i18n("Channel separation: Stereo");	
	tipMonoButton=i18n("Mono mix");
	tipStereoButton=i18n("Stereo mix");
	tipHeadphonesButton=i18n("Headphones mix");
	tipOversampling=i18n("Toggle oversampling on/off");
	// initialize "about"-box translation	
	aboutStr[0]=i18n("TFMXcess Version ");
	aboutStr[1]=i18n("KDE-based frontend for TFMX-PLAY");
	aboutStr[2]=i18n("Author: David Banz");
	aboutStr[3]=i18n("neo@sakura-audio.cx");
	// initialize translations for the buttons
	qtarch_EightButton->setText( i18n("8 bit") );
	qtarch_SixteenButton->setText( i18n("16 bit") );
	qtarch_HiButton->setText( i18n("Freq+") );
	qtarch_LoButton->setText( i18n("Freq-") );
	qtarch_ToolTipCheck->setText( i18n("Tooltips") );
	qtarch_OverSample->setText( i18n("Oversampling") );
	// initialize translation for the channel separation display
	showSeparation[0]=i18n("Mono");
	showSeparation[1]=i18n("Headphones");
	showSeparation[2]=i18n("Stereo");
	qtarch_SeparationBar->setText( showSeparation[1] );

	// ######### that's it for most of the translation... ########
}

// ######################### THE END ############################
