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.
1607 lines
40 KiB
1607 lines
40 KiB
/**************************************************************************
|
|
|
|
kmidclient.cpp - The main client widget of KMid
|
|
Copyright (C) 1997,98 Antonio Larrosa Jimenez
|
|
|
|
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.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
Send comments and bug fixes to larrosa@kde.org
|
|
or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
|
|
|
|
***************************************************************************/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/wait.h>
|
|
#include <signal.h> // kill is declared on signal.h on bsd, not sys/signal.h
|
|
#include <sys/signal.h>
|
|
|
|
#include <tqkeycode.h>
|
|
#include <tqfiledialog.h>
|
|
#include <tqstring.h>
|
|
#include <tqlabel.h>
|
|
#include <tqfile.h>
|
|
#include <tqcombobox.h>
|
|
#include <tqlayout.h>
|
|
|
|
#include <kapplication.h>
|
|
#include <kcharsets.h>
|
|
#include <kconfig.h>
|
|
#include <kglobal.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kurl.h>
|
|
#include <kaction.h>
|
|
#include <kdebug.h>
|
|
|
|
#include <libkmid/midimapper.h>
|
|
#include <libkmid/fmout.h>
|
|
#include <libkmid/track.h>
|
|
#include <libkmid/midispec.h>
|
|
#include <libkmid/deviceman.h>
|
|
#include <libkmid/mt32togm.h>
|
|
#include "kmidclient.h"
|
|
#include "klcdnumber.h"
|
|
#include "randomlist.h"
|
|
#include "channelview.h"
|
|
#include "channel.h"
|
|
#include "version.h"
|
|
#include "rhythmview.h"
|
|
|
|
//#define TEMPHACK
|
|
|
|
|
|
kmidClient::kmidClient(TQWidget *parent, KActionCollection *ac, const char *name)
|
|
: DCOPObject("KMidIface"), TQWidget(parent,name)
|
|
{
|
|
actionCollection=ac;
|
|
KConfig *cfg=kapp->config();
|
|
cfg->setGroup("KMid");
|
|
midifile_opened=0L;
|
|
loopsong=cfg->readNumEntry("Loop",0);
|
|
collectionplaymode=0;
|
|
collectionplaylist=0L;
|
|
channelView=0L;
|
|
noteArray=0L;
|
|
shuttingdown=false;
|
|
|
|
KConfig *kconf=KGlobal::instance()->config();
|
|
|
|
kconf->setGroup("KMid");
|
|
TQString tmp2 = locateLocal("appdata", "collections");
|
|
collectionsfile=kconf->readPathEntry("CollectionsFile",tmp2);
|
|
slman=new SLManager();
|
|
slman->loadConfig(TQFile::encodeName(collectionsfile));
|
|
currentsl=NULL;
|
|
// currentsl=slman->getCollection(activecollection);
|
|
itsme=0;
|
|
m_kMid.pid=0;
|
|
timebar = new TQSlider(0,240000,30000,60000,TQSlider::Horizontal, this);
|
|
timebar->setSteps(30000,60000);
|
|
timebar->setValue(0);
|
|
connect (timebar,TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(slotSeek(int)));
|
|
|
|
timetags = new QSliderTime(timebar,this);
|
|
timetags->setMinimumSize(timetags->sizeHint());
|
|
|
|
qlabelTempo= new TQLabel(i18n("Tempo:"), this,"tempolabel",
|
|
TQLabel::NoFrame);
|
|
|
|
tempoLCD = new KLCDNumber( true, 3, this, "TempoLCD");
|
|
tempoLCD->setValue(120);
|
|
tempoLCD->display(120);
|
|
currentTempo=120;
|
|
tempoLCD->setRange(3,999);
|
|
tempoLCD->setDefaultValue(120);
|
|
tempoLCD->setUserSetDefaultValue(true);
|
|
tempoLCD->setMinimumSize(tempoLCD->sizeHint());
|
|
connect(tempoLCD,TQT_SIGNAL(valueChanged(double)),this,TQT_SLOT(slotSetTempo(double)));
|
|
|
|
comboSongs = new TQComboBox(FALSE, this,"Songs");
|
|
connect (comboSongs,TQT_SIGNAL(activated(int)),this,TQT_SLOT(slotSelectSong(int)));
|
|
comboSongs->setMinimumWidth(200);
|
|
|
|
comboEncodings = new TQComboBox(FALSE, this, "Encodings");
|
|
connect (comboEncodings,TQT_SIGNAL(activated(int)),this,TQT_SLOT(slotSelectEncoding(int)));
|
|
comboEncodings->insertItem(i18n("Default"));
|
|
comboEncodings->insertStringList( KGlobal::charsets()->descriptiveEncodingNames() );
|
|
comboEncodings->setCurrentItem(0);
|
|
|
|
rhythmview= new RhythmView( this, "RhythmView");
|
|
rhythmview->setMaximumHeight(7);
|
|
rhythmview->setMinimumHeight(7);
|
|
|
|
volumebar = new TQSlider(0,200,10,100,TQSlider::Vertical, this );
|
|
volumebar->setSteps(10,20);
|
|
volumebar->setValue(100);
|
|
volumebar->setTickmarks(TQSlider::NoMarks);
|
|
volumebar->setTickInterval(50);
|
|
connect (volumebar,TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(slotSetVolume(int)));
|
|
|
|
visiblevolumebar=cfg->readNumEntry("ShowVolumeBar",0);
|
|
if (visiblevolumebar) volumebar->show();
|
|
else volumebar->hide();
|
|
|
|
typeoftextevents=1;
|
|
kdispt=new KDisplayText( this, "KaraokeWindow");
|
|
kdispt->show();
|
|
|
|
timer4timebar=new TQTimer(this);
|
|
connect (timer4timebar,TQT_SIGNAL(timeout()),this,TQT_SLOT(timebarUpdate()));
|
|
timer4events=new TQTimer(this);
|
|
connect (timer4events,TQT_SIGNAL(timeout()),this,TQT_SLOT(processSpecialEvent()));
|
|
|
|
TQString samplefile =
|
|
KGlobal::dirs()->findAllResources("appdata", "fm/*.o3").last();
|
|
samplefile.truncate(samplefile.findRev('/'));
|
|
FMOut::setFMPatchesDirectory(TQFile::encodeName(samplefile));
|
|
|
|
m_kMid.pctlsmID=shmget(IPC_PRIVATE,sizeof(PlayerController),0666 | IPC_CREAT );
|
|
if (m_kMid.pctlsmID==-1)
|
|
{
|
|
printf("ERROR: Cannot allocate shared memory !!!\n"
|
|
"Please report to larrosa@kde.org\n");
|
|
exit(1);
|
|
}
|
|
|
|
m_kMid.pctl=(PlayerController *)shmat(m_kMid.pctlsmID,0L,0);
|
|
if (!m_kMid.pctl)
|
|
printf("ERROR: Cannot get shared memory !!! "
|
|
"Please report to larrosa@kde.org\n");
|
|
m_kMid.pctl->playing=0;
|
|
m_kMid.pctl->gm=1;
|
|
m_kMid.pctl->volumepercentage=100;
|
|
m_kMid.pctl->tempo=500000;
|
|
m_kMid.pctl->ratioTempo=1.0;
|
|
for (int i=0;i<16;i++)
|
|
{
|
|
m_kMid.pctl->forcepgm[i]=0;
|
|
m_kMid.pctl->pgm[i]=0;
|
|
}
|
|
|
|
|
|
kconf->setGroup("KMid");
|
|
int mididev=kconf->readNumEntry("MidiPortNumber",-1);
|
|
|
|
midi = new DeviceManager(mididev);
|
|
midi->initManager();
|
|
m_kMid.midi=midi;
|
|
player= new MidiPlayer(midi,m_kMid.pctl);
|
|
|
|
kconf->setGroup("Midimapper");
|
|
TQCString qs=TQFile::encodeName(kconf->readPathEntry("Loadfile","gm.map"));
|
|
|
|
#ifdef KMidDEBUG
|
|
printf("Read Config file: %s\n",qs.data());
|
|
#endif
|
|
setMidiMapFilename(qs.data());
|
|
|
|
initializing_songs=1;
|
|
kconf->setGroup("KMid");
|
|
setActiveCollection(kconf->readNumEntry("ActiveCollection",0));
|
|
initializing_songs=0;
|
|
|
|
TQVBoxLayout *lv=new TQVBoxLayout( this );
|
|
lv->addWidget( timebar );
|
|
lv->addWidget( timetags );
|
|
lv->addSpacing(5);
|
|
TQHBoxLayout *lh=new TQHBoxLayout( lv );
|
|
lh->addWidget( qlabelTempo );
|
|
lh->addWidget( tempoLCD );
|
|
lh->addWidget( comboSongs, 6 );
|
|
lv->addSpacing(5);
|
|
lh->addWidget( comboEncodings, 1 );
|
|
lv->addSpacing(5);
|
|
lv->addWidget( rhythmview );
|
|
lv->addSpacing(2);
|
|
TQHBoxLayout *lh2=new TQHBoxLayout( lv );
|
|
lh2->addWidget( volumebar );
|
|
lh2->addWidget( kdispt );
|
|
}
|
|
|
|
/*void kmidClient::resizeEvent(TQResizeEvent *)
|
|
{
|
|
//timebar->resize(width()-5,timebar->height());
|
|
timebar->setGeometry(5,10,width()-5,timebar->height());
|
|
timetags->setGeometry(5,10+timebar->height(),width()-5,timetags->getFontHeight());
|
|
comboSongs->setGeometry(tempoLCD->x()+tempoLCD->width()+15,tempoLCD->y(),width()-(tempoLCD->x()+tempoLCD->width()+25),tempoLCD->height());
|
|
rhythmview->setGeometry(5,10+timebar->height()+timetags->height()+5+tempoLCD->height()+2,width()-10,7);
|
|
volumebar->setGeometry(5,10+timebar->height()+timetags->height()+5+tempoLCD->height()+10,15,height()-(10+timebar->height()+timetags->height()+5+tempoLCD->height()+15));
|
|
kdispt->setGeometry(((visiblevolumebar)?25:5),10+timebar->height()+timetags->height()+5+tempoLCD->height()+10,width()-(5+((visiblevolumebar)?25:5)),height()-(10+timebar->height()+timetags->height()+5+tempoLCD->height()+10));
|
|
}
|
|
*/
|
|
|
|
kmidClient::~kmidClient()
|
|
{
|
|
if (m_kMid.pctl->playing==1)
|
|
{
|
|
stop();
|
|
// sleep(1);
|
|
}
|
|
|
|
if (m_kMid.pid!=0)
|
|
{
|
|
kill(m_kMid.pid,SIGTERM);
|
|
waitpid(m_kMid.pid, 0L, 0);
|
|
m_kMid.midi->closeDev();
|
|
m_kMid.pid=0;
|
|
}
|
|
|
|
allNotesOff();
|
|
|
|
delete midifile_opened;
|
|
delete player;
|
|
delete midi;
|
|
delete [] collectionplaylist;
|
|
|
|
saveCollections();
|
|
delete slman;
|
|
|
|
// Let's detach and delete shared memory
|
|
shmdt((char *)m_kMid.pctl);
|
|
shmctl(m_kMid.pctlsmID, IPC_RMID, 0L);
|
|
m_kMid.pctl=0L;
|
|
}
|
|
|
|
// Use KURL::filename ! (David)
|
|
char *extractFilename(const char *in,char *out)
|
|
{
|
|
char *p=(char *)in;
|
|
char *result=out;
|
|
char *filename=(char *)in;
|
|
while (*p!=0)
|
|
{
|
|
if (*p=='/') filename=p+1;
|
|
p++;
|
|
}
|
|
while (*filename!=0)
|
|
{
|
|
*out=*filename;
|
|
out++;
|
|
filename++;
|
|
}
|
|
*out=0;
|
|
return result;
|
|
}
|
|
|
|
int kmidClient::openFile(const char *filename)
|
|
{
|
|
m_kMid.pctl->message|=PLAYER_HALT;
|
|
stop();
|
|
int r;
|
|
player->setGenerateBeats(true);
|
|
if ((r=player->loadSong(filename))!=0)
|
|
{
|
|
TQString errormsg;
|
|
switch (r)
|
|
{
|
|
case (-1) : errormsg =
|
|
i18n("The file %1 does not exist or cannot be opened.").arg(filename);
|
|
break;
|
|
case (-2) : errormsg =
|
|
i18n("The file %1 is not a MIDI file.").arg(filename);break;
|
|
case (-3) : errormsg =
|
|
i18n("Ticks per quarter note is negative. Please send this file to larrosa@kde.org");break;
|
|
case (-4) : errormsg =
|
|
i18n("Not enough memory.");break;
|
|
case (-5) : errormsg =
|
|
i18n("This file is corrupted or not well built.");break;
|
|
case (-6) : errormsg =
|
|
i18n("%1 is not a regular file.").arg(filename);break;
|
|
default : errormsg = i18n("Unknown error message");break;
|
|
}
|
|
KMessageBox::error(this, errormsg);
|
|
// player->loadSong(midifile_opened);
|
|
if (midifile_opened) delete midifile_opened;
|
|
midifile_opened=0L;
|
|
timebar->setRange(0,240000);
|
|
timebar->setValue(0);
|
|
timetags->repaint(TRUE);
|
|
kdispt->ClearEv();
|
|
kdispt->repaint(TRUE);
|
|
topLevelWidget()->setCaption("KMid");
|
|
|
|
return -1;
|
|
}
|
|
|
|
if (midifile_opened) delete midifile_opened;
|
|
midifile_opened=new char[strlen(filename)+1];
|
|
strcpy(midifile_opened,filename);
|
|
#ifdef KMidDEBUG
|
|
printf("TOTAL TIME: %g milliseconds\n",player->information()->millisecsTotal);
|
|
#endif
|
|
// noteArray=player->parseNotes();
|
|
noteArray=player->noteArray();
|
|
timebar->setRange(0,(int)(player->information()->millisecsTotal));
|
|
timetags->repaint(TRUE);
|
|
kdispt->ClearEv();
|
|
spev=player->specialEvents();
|
|
while (spev)
|
|
{
|
|
if ((spev->type==1) || (spev->type==5))
|
|
{
|
|
kdispt->AddEv(spev);
|
|
}
|
|
spev=spev->next;
|
|
}
|
|
|
|
kdispt->calculatePositions();
|
|
kdispt->CursorToHome();
|
|
// kdispt->updateScrollBars();
|
|
emit mustRechooseTextEvent();
|
|
kdispt->repaint(TRUE);
|
|
tempoLCD->display(tempoToMetronomeTempo(m_kMid.pctl->tempo));
|
|
currentTempo=tempoLCD->getValue();
|
|
tempoLCD->setDefaultValue(tempoToMetronomeTempo(m_kMid.pctl->tempo)*m_kMid.pctl->ratioTempo);
|
|
|
|
char *fn=new char[strlen(filename)+20];
|
|
extractFilename(filename,fn);
|
|
char *capt=new char[strlen(fn)+20];
|
|
sprintf(capt,"KMid - %s",fn);
|
|
delete fn;
|
|
topLevelWidget()->setCaption(capt);
|
|
delete capt;
|
|
|
|
timebar->setValue(0);
|
|
return 0;
|
|
}
|
|
|
|
int kmidClient::openURL(const TQString _url)
|
|
{
|
|
KURL u(_url);
|
|
if (!u.isValid()) {printf("Malformed URL\n");return -1;};
|
|
|
|
TQString filename;
|
|
bool deleteFile=false;
|
|
if (!u.isLocalFile())
|
|
{
|
|
filename = TQString("/tmp/") + u.filename();
|
|
KIO::Job *iojob = KIO::copy( u, KURL::fromPathOrURL( filename ) );
|
|
downloaded=false;
|
|
connect( iojob, TQT_SIGNAL( result( KIO::Job *) ), this, TQT_SLOT(downloadFinished( KIO::Job * ) ) );
|
|
|
|
if (!downloaded)
|
|
kapp->enter_loop();
|
|
deleteFile=true;
|
|
|
|
}
|
|
else
|
|
{
|
|
filename=u.path();
|
|
}
|
|
|
|
TQCString filename_8bit = TQFile::encodeName(filename);
|
|
int r=-1;
|
|
if (!filename_8bit.isEmpty())
|
|
{
|
|
r=openFile(filename_8bit.data());
|
|
|
|
KConfig *cfg=KGlobal::instance()->config();
|
|
if (cfg->readBoolEntry("deleteTmpNonLocalFiles",false))
|
|
{
|
|
unlink(filename_8bit.data());
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
ulong kmidClient::timeOfNextEvent(int *type)
|
|
{
|
|
int t=0;
|
|
ulong x=0;
|
|
|
|
|
|
if (!channelView)
|
|
{
|
|
if ((spev)&&(spev->type!=0))
|
|
{
|
|
t=1;
|
|
x=spev->absmilliseconds;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (noteArray)
|
|
{
|
|
NoteArray::noteCmd *ncmd=noteArray->get();
|
|
if (!ncmd)
|
|
{
|
|
if ((spev)&&(spev->type!=0))
|
|
{
|
|
t=1;
|
|
x=spev->absmilliseconds;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((!spev)||(spev->type==0))
|
|
{
|
|
t=2;
|
|
x=ncmd->ms;
|
|
}
|
|
else
|
|
{
|
|
if (spev->absmilliseconds<ncmd->ms)
|
|
{
|
|
t=1;
|
|
x=spev->absmilliseconds;
|
|
}
|
|
else
|
|
{
|
|
t=2;
|
|
x=ncmd->ms;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (type) *type=t;
|
|
return x;
|
|
/*
|
|
|
|
if (type!=NULL) *type=0;
|
|
if (channelView==NULL)
|
|
{
|
|
if ((spev!=NULL)&&(spev->type!=0))
|
|
{
|
|
if (type!=NULL) *type=1;
|
|
return spev->absmilliseconds;
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
if (noteArray==NULL) return 0;
|
|
noteCmd *ncmd=noteArray->get();
|
|
if (ncmd==NULL)
|
|
{
|
|
if ((spev!=NULL)&&(spev->type!=0))
|
|
{
|
|
if (type!=NULL) *type=1;
|
|
return spev->absmilliseconds;
|
|
}
|
|
else return 0;
|
|
}
|
|
else
|
|
{
|
|
if ((spev==NULL)||(spev->type==0))
|
|
{
|
|
if (type!=NULL) *type=2;
|
|
return ncmd->ms;
|
|
}
|
|
else
|
|
{
|
|
if (spev->absmilliseconds<ncmd->ms)
|
|
{
|
|
if (type!=NULL) *type=1;
|
|
return spev->absmilliseconds;
|
|
}
|
|
else
|
|
{
|
|
if (type!=NULL) *type=2;
|
|
return ncmd->ms;
|
|
}
|
|
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void kmidClient::slotPlay()
|
|
{
|
|
if (!player->isSongLoaded())
|
|
{
|
|
KMessageBox::sorry(this,
|
|
i18n("You must load a file before playing it."));
|
|
return;
|
|
}
|
|
if (m_kMid.pctl->playing==1)
|
|
{
|
|
KMessageBox::sorry(this,
|
|
i18n("A song is already being played."));
|
|
return;
|
|
}
|
|
if (midi->checkInit()==-1)
|
|
{
|
|
KMessageBox::error(this,
|
|
i18n("Could not open /dev/sequencer.\nProbably there is another program using it."));
|
|
return;
|
|
}
|
|
|
|
kdispt->CursorToHome();
|
|
m_kMid.pctl->message=0;
|
|
m_kMid.pctl->playing=0;
|
|
m_kMid.pctl->finished=0;
|
|
m_kMid.pctl->error=0;
|
|
m_kMid.pctl->SPEVplayed=0;
|
|
m_kMid.pctl->SPEVprocessed=0;
|
|
#ifdef KMidDEBUG
|
|
passcount=0;
|
|
#endif
|
|
noteArray->iteratorBegin();
|
|
|
|
TQApplication::flushX();
|
|
if ((m_kMid.pid=fork())==0)
|
|
{
|
|
#ifdef KMidDEBUG
|
|
printf("PlayerProcessID: %d\n",getpid());
|
|
#endif
|
|
player->play(0,(void (*)(void))kmidOutput);
|
|
#ifdef KMidDEBUG
|
|
printf("End of child process\n");
|
|
#endif
|
|
_exit(0);
|
|
}
|
|
m_kMid.pctl->millisecsPlayed=0;
|
|
|
|
|
|
spev=player->specialEvents();
|
|
#ifdef KMidDEBUG
|
|
printf("writing SPEV\n");
|
|
player->debugSpecialEvents();
|
|
printf("writing SPEV(END)\n");
|
|
#endif
|
|
|
|
while ((m_kMid.pctl->playing==0)&&(m_kMid.pctl->error==0)) ;
|
|
|
|
if (m_kMid.pctl->error==1) return;
|
|
beginmillisec=m_kMid.pctl->beginmillisec;
|
|
|
|
int type;
|
|
ulong x=timeOfNextEvent(&type);
|
|
if (type!=0)
|
|
timer4events->start(x,TRUE);
|
|
|
|
timer4timebar->start(1000);
|
|
|
|
#ifdef KMidDEBUG
|
|
printf("PlayerProcess: %d . ParentProcessID: %d\n",m_kMid.pid,getpid());
|
|
printf("******************************-\n");
|
|
#endif
|
|
}
|
|
|
|
void kmidClient::timebarUpdate()
|
|
{
|
|
itsme=1;
|
|
if (m_kMid.pctl->playing==0)
|
|
{
|
|
timer4timebar->stop();
|
|
}
|
|
|
|
timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
ulong currentmillisec=tv.tv_sec*1000+tv.tv_usec/1000;
|
|
m_kMid.pctl->millisecsPlayed=(currentmillisec-beginmillisec);
|
|
|
|
timebar->setValue((int)(m_kMid.pctl->millisecsPlayed));
|
|
itsme=0;
|
|
if ((m_kMid.pctl->playing==0)&&(m_kMid.pctl->finished==1))
|
|
{
|
|
waitpid(m_kMid.pid, NULL, 0);
|
|
if (loopsong)
|
|
{
|
|
play();
|
|
return;
|
|
}
|
|
else
|
|
nextSong();
|
|
}
|
|
}
|
|
|
|
void kmidClient::slotSeek(int i)
|
|
{
|
|
if (itsme) return;
|
|
|
|
if (m_kMid.pctl->playing==0)
|
|
{
|
|
itsme=1;
|
|
timebar->setValue(0);
|
|
itsme=0;
|
|
return;
|
|
}
|
|
|
|
if (m_kMid.pctl->paused) return;
|
|
|
|
if (m_kMid.pid!=0)
|
|
{
|
|
kill(m_kMid.pid,SIGTERM);
|
|
#ifdef KMidDEBUG
|
|
printf("Waiting for Process %d to be killed\n",m_kMid.pid);
|
|
#endif
|
|
waitpid(m_kMid.pid, NULL, 0);
|
|
m_kMid.midi->closeDev();
|
|
m_kMid.pid=0;
|
|
}
|
|
allNotesOff();
|
|
|
|
|
|
#ifdef KMidDEBUG
|
|
printf("change Time: %d\n",i);
|
|
#endif
|
|
|
|
timer4events->stop();
|
|
if (channelView!=NULL) channelView->reset(0);
|
|
|
|
moveEventPointersTo((ulong)i);
|
|
|
|
m_kMid.pctl->playing=0;
|
|
m_kMid.pctl->OK=0;
|
|
m_kMid.pctl->error=0;
|
|
m_kMid.pctl->gotomsec=i;
|
|
m_kMid.pctl->message|=PLAYER_SETPOS;
|
|
|
|
TQApplication::flushX();
|
|
if ((m_kMid.pid=fork())==0)
|
|
{
|
|
#ifdef KMidDEBUG
|
|
printf("Player_ProcessID: %d\n",getpid());
|
|
#endif
|
|
|
|
player->play(0,(void (*)(void))kmidOutput);
|
|
|
|
#ifdef KMidDEBUG
|
|
printf("End of child process\n");
|
|
#endif
|
|
_exit(0);
|
|
}
|
|
|
|
while ((m_kMid.pctl->playing==0)&&(m_kMid.pctl->error==0)) ;
|
|
|
|
if (m_kMid.pctl->error==1) return;
|
|
beginmillisec=m_kMid.pctl->beginmillisec-i;
|
|
ulong currentmillisec=m_kMid.pctl->beginmillisec;
|
|
|
|
int type;
|
|
ulong x=timeOfNextEvent(&type);
|
|
if (type!=0)
|
|
timer4events->start(x-(currentmillisec-beginmillisec),TRUE);
|
|
|
|
/*
|
|
if (spev==NULL) return;
|
|
ulong delaymillisec=spev->absmilliseconds-(currentmillisec-beginmillisec);
|
|
timer4events->start(delaymillisec,TRUE);
|
|
*/
|
|
|
|
m_kMid.pctl->OK=0;
|
|
/*
|
|
tempoLCD->display(tempoToMetronomeTempo(m_kMid.pctl->tempo));
|
|
currentTempo=tempoLCD->getValue();
|
|
tempoLCD->setDefaultValue(tempoToMetronomeTempo(m_kMid.pctl->tempo)*m_kMid.pctl->ratioTempo);
|
|
*/
|
|
}
|
|
|
|
void kmidClient::moveEventPointersTo(ulong ms)
|
|
{
|
|
#ifdef KMidDEBUG
|
|
printf("Move To: %lu\n",ms);
|
|
#endif
|
|
spev=player->specialEvents();
|
|
|
|
ulong tempo=(ulong)(500000 * m_kMid.pctl->ratioTempo);
|
|
int num=4;
|
|
int den=4;
|
|
|
|
while ((spev!=NULL)&&(spev->absmilliseconds<ms))
|
|
{
|
|
if (spev->type==3) tempo=spev->tempo;
|
|
else if (spev->type==6) {num=spev->num;den=spev->den;}
|
|
spev=spev->next;
|
|
}
|
|
tempoLCD->display(tempoToMetronomeTempo(tempo));
|
|
currentTempo=tempoLCD->getValue();
|
|
tempoLCD->setDefaultValue(tempoToMetronomeTempo(tempo)*m_kMid.pctl->ratioTempo);
|
|
|
|
rhythmview->setRhythm(num,den);
|
|
|
|
kdispt->gotomsec(ms);
|
|
// if (noteArray!=NULL) noteArray->moveIteratorTo(ms);
|
|
if (noteArray!=NULL)
|
|
{
|
|
int pgm[16];
|
|
noteArray->moveIteratorTo(ms,pgm);
|
|
if (channelView!=NULL)
|
|
{
|
|
for (int j=0;j<16;j++)
|
|
{
|
|
if (!m_kMid.pctl->forcepgm[j]) channelView->changeInstrument(j,(m_kMid.pctl->gm==1)?(pgm[j]):(MT32toGM[pgm[j]]));
|
|
else channelView->changeInstrument(j,(m_kMid.pctl->pgm[j]));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (noteArray!=NULL)
|
|
{
|
|
noteCmd *ncmd;
|
|
noteArray->iteratorBegin();
|
|
ncmd=noteArray->get();
|
|
while ((ncmd!=NULL)&&(ncmd->ms<ms))
|
|
{
|
|
noteArray->next();
|
|
ncmd=noteArray->get();
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void kmidClient::slotSetVolume(int i)
|
|
{
|
|
int autochangemap=0;
|
|
if ((m_kMid.pctl->playing==1)&&(m_kMid.pctl->paused==0)) autochangemap=1;
|
|
|
|
if (autochangemap)
|
|
{
|
|
pause();
|
|
}
|
|
i=200-i;
|
|
m_kMid.pctl->volumepercentage=i;
|
|
|
|
if (autochangemap)
|
|
{
|
|
pause();
|
|
}
|
|
}
|
|
|
|
|
|
void kmidClient::slotPrevSong()
|
|
{
|
|
if (currentsl==NULL) return;
|
|
if (collectionplaylist==NULL) generateCPL();
|
|
if (collectionplaylist==NULL) return;
|
|
/*
|
|
if (collectionplaymode==0)
|
|
{
|
|
if (currentsl->getActiveSongID()==1) return;
|
|
currentsl->previous();
|
|
}
|
|
else
|
|
{
|
|
int r;
|
|
while ((r=1+(int) ((double)(currentsl->NumberOfSongs())*rand()/(RAND_MAX+1.0)))==currentsl->getActiveSongID()) ;
|
|
|
|
currentsl->setActiveSong(r);
|
|
}
|
|
*/
|
|
int idx=searchInCPL(currentsl->getActiveSongID());
|
|
if (idx==0) return;
|
|
idx--;
|
|
currentsl->setActiveSong(collectionplaylist[idx]);
|
|
|
|
if (currentsl->getActiveSongID()==-1)
|
|
{
|
|
// comboSongs->setCurrentItem(0);
|
|
// currentsl->setActiveSong(1);
|
|
return;
|
|
}
|
|
|
|
if (m_kMid.pctl->paused) emit stopPause();
|
|
comboSongs->setCurrentItem(currentsl->getActiveSongID()-1);
|
|
if (openURL(currentsl->getActiveSongName())==-1) return;
|
|
play();
|
|
|
|
}
|
|
|
|
void kmidClient::slotNextSong()
|
|
{
|
|
if (currentsl==NULL) return;
|
|
if (collectionplaylist==NULL) generateCPL();
|
|
if (collectionplaylist==NULL) return;
|
|
|
|
/*if (collectionplaymode==0)
|
|
{
|
|
if (currentsl->getActiveSongID()==currentsl->NumberOfSongs()) return;
|
|
currentsl->next();
|
|
}
|
|
else
|
|
{
|
|
int r;
|
|
while ((r=1+(int) ((double)(currentsl->NumberOfSongs())*rand()/(RAND_MAX+1.0)))==currentsl->getActiveSongID()) ;
|
|
|
|
#ifdef KMidDEBUG
|
|
printf("random number:%d\n",r);
|
|
#endif
|
|
currentsl->setActiveSong(r);
|
|
}
|
|
*/
|
|
int idx=searchInCPL(currentsl->getActiveSongID());
|
|
idx++;
|
|
if (idx==currentsl->NumberOfSongs()) return;
|
|
currentsl->setActiveSong(collectionplaylist[idx]);
|
|
if (currentsl->getActiveSongID()==-1)
|
|
{
|
|
//// comboSongs->setCurrentItem(0);
|
|
// currentsl->setActiveSong(1);
|
|
return;
|
|
}
|
|
|
|
if (m_kMid.pctl->paused) emit stopPause();
|
|
comboSongs->setCurrentItem(currentsl->getActiveSongID()-1);
|
|
if (openURL(currentsl->getActiveSongName())==-1) return;
|
|
play();
|
|
}
|
|
|
|
void kmidClient::slotPause()
|
|
{
|
|
if (m_kMid.pctl->playing==0) return;
|
|
#ifdef KMidDEBUG
|
|
printf("song Pause\n");
|
|
#endif
|
|
if (m_kMid.pctl->paused==0)
|
|
{
|
|
if (m_kMid.pid!=0)
|
|
{
|
|
kill(m_kMid.pid,SIGTERM);
|
|
waitpid(m_kMid.pid, NULL, 0);
|
|
m_kMid.midi->closeDev();
|
|
m_kMid.pid=0;
|
|
}
|
|
pausedatmillisec=(ulong)m_kMid.pctl->millisecsPlayed;
|
|
m_kMid.pctl->paused=1;
|
|
timer4timebar->stop();
|
|
timer4events->stop();
|
|
allNotesOff();
|
|
// kill(m_kMid.pid,SIGSTOP);
|
|
// The previous line doesn't work because it stops the two processes (!?)
|
|
}
|
|
else
|
|
{
|
|
m_kMid.pctl->playing=0;
|
|
m_kMid.pctl->OK=0;
|
|
m_kMid.pctl->error=0;
|
|
m_kMid.pctl->gotomsec=pausedatmillisec;
|
|
m_kMid.pctl->message|=PLAYER_SETPOS;
|
|
|
|
TQApplication::flushX();
|
|
if ((m_kMid.pid=fork())==0)
|
|
{
|
|
#ifdef KMidDEBUG
|
|
printf("PlayerProcessID: %d\n",getpid());
|
|
#endif
|
|
player->play(0,(void (*)(void))kmidOutput);
|
|
#ifdef KMidDEBUG
|
|
printf("End of child process\n");
|
|
#endif
|
|
_exit(0);
|
|
}
|
|
|
|
while ((m_kMid.pctl->playing==0)&&(m_kMid.pctl->error==0)) ;
|
|
|
|
if (m_kMid.pctl->error) return;
|
|
|
|
m_kMid.pctl->OK=0;
|
|
m_kMid.pctl->paused=0;
|
|
|
|
beginmillisec=m_kMid.pctl->beginmillisec-pausedatmillisec;
|
|
ulong currentmillisec=m_kMid.pctl->beginmillisec;
|
|
|
|
int type;
|
|
ulong x=timeOfNextEvent(&type);
|
|
if (type!=0)
|
|
timer4events->start(x-(currentmillisec-beginmillisec),TRUE);
|
|
timer4timebar->start(1000);
|
|
|
|
if (noteArray!=NULL)
|
|
{
|
|
int pgm[16];
|
|
noteArray->moveIteratorTo(pausedatmillisec,pgm);
|
|
if (channelView!=NULL)
|
|
{
|
|
for (int j=0;j<16;j++)
|
|
{
|
|
if (!m_kMid.pctl->forcepgm[j]) channelView->changeInstrument(j,(m_kMid.pctl->gm==1)?(pgm[j]):(MT32toGM[pgm[j]]));
|
|
else channelView->changeInstrument(j,(m_kMid.pctl->pgm[j]));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void kmidClient::shuttingDown(void)
|
|
{
|
|
shuttingdown=true;
|
|
stop();
|
|
}
|
|
|
|
void kmidClient::slotStop()
|
|
{
|
|
if (!m_kMid.pctl) return;
|
|
|
|
if (!shuttingdown)
|
|
{
|
|
for (int i=0;i<16;i++) m_kMid.pctl->forcepgm[i]=FALSE;
|
|
if (channelView) channelView->reset();
|
|
if (tempoLCD)
|
|
{
|
|
tempoLCD->display(tempoToMetronomeTempo(m_kMid.pctl->tempo));
|
|
currentTempo=tempoLCD->getValue();
|
|
tempoLCD->setDefaultValue(tempoToMetronomeTempo(m_kMid.pctl->tempo)*m_kMid.pctl->ratioTempo);
|
|
}
|
|
}
|
|
|
|
if (m_kMid.pctl->playing==0) return;
|
|
|
|
if (m_kMid.pctl->paused) return;
|
|
#ifdef KMidDEBUG
|
|
printf("song Stop\n");
|
|
#endif
|
|
if (m_kMid.pid!=0)
|
|
{
|
|
kill(m_kMid.pid,SIGTERM);
|
|
#ifdef KMidDEBUG
|
|
printf("Killing\n");
|
|
#endif
|
|
waitpid(m_kMid.pid, NULL, 0);
|
|
m_kMid.midi->closeDev();
|
|
m_kMid.pid=0;
|
|
}
|
|
|
|
m_kMid.pctl->playing=0;
|
|
////////m_kMid.pctl->OK=0;
|
|
////////m_kMid.pctl->message|=PLAYER_HALT;
|
|
timer4timebar->stop();
|
|
timer4events->stop();
|
|
|
|
allNotesOff();
|
|
|
|
//m_kMid.pctl->playing=0;
|
|
//m_kMid.pctl->paused=0;
|
|
////////while (m_kMid.pctl->OK==0) ;
|
|
}
|
|
|
|
void kmidClient::slotRewind()
|
|
{
|
|
if ((m_kMid.pctl->playing)&&(!m_kMid.pctl->paused))
|
|
{
|
|
timebar->subtractPage();
|
|
slotSeek(timebar->value());
|
|
}
|
|
}
|
|
|
|
void kmidClient::slotForward()
|
|
{
|
|
if ((m_kMid.pctl->playing)&&(!m_kMid.pctl->paused))
|
|
{
|
|
timebar->addPage();
|
|
slotSeek(timebar->value());
|
|
}
|
|
}
|
|
|
|
|
|
void kmidClient::allNotesOff()
|
|
{
|
|
bool done=false;
|
|
m_kMid.pctl->isSendingAllNotesOff=true;
|
|
DeviceManager *_midi=new DeviceManager();
|
|
_midi->initManager();
|
|
_midi->openDev();
|
|
_midi->allNotesOff();
|
|
_midi->closeDev();
|
|
delete _midi;
|
|
done=true;
|
|
m_kMid.pctl->isSendingAllNotesOff=false;
|
|
}
|
|
|
|
void kmidClient::kmidOutput(void)
|
|
{
|
|
// Should do nothing
|
|
/*
|
|
Midi_event *ev=pctl->ev;
|
|
|
|
timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
ulong currentmillisec=tv.tv_sec*1000+tv.tv_usec/1000;
|
|
|
|
if ((ev->command==MIDI_SYSTEM_PREFIX)&&((ev->command|ev->chn)==META_EVENT))
|
|
{
|
|
if ((ev->d1==5)||(ev->d1==1))
|
|
{
|
|
char *text=new char[ev->length+1];
|
|
strncpy(text,(char *)ev->data,ev->length);
|
|
text[ev->length]=0;
|
|
#ifdef KMidDEBUG
|
|
printf("%s , played at: %ld\n",text,currentmillisec-beginmillisec);
|
|
#endif
|
|
}
|
|
else if (ev->d1==ME_SET_TEMPO)
|
|
{
|
|
int tempo=(ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]);
|
|
// printf("Change tempo: %d , %g, played at:%ld\n",tempo,tempoToMetronomeTempo(tempo),currentmillisec-beginmillisec);
|
|
}
|
|
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
void kmidClient::processSpecialEvent()
|
|
{
|
|
/*
|
|
if (spev==NULL)
|
|
{
|
|
printf("SPEV == NULL !!!!!\n");
|
|
return;
|
|
}
|
|
*/
|
|
|
|
//#ifdef KMidDEBUG
|
|
// printf(":::: %ld",passcount++);
|
|
// printf("%d %s %ld",spev->type,spev->text,spev->absmilliseconds);
|
|
//#endif
|
|
|
|
int processNext=1;
|
|
int type;
|
|
ulong x;
|
|
|
|
long delaymillisec=~0;
|
|
|
|
while (processNext)
|
|
{
|
|
/*
|
|
timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
ulong currentmillisec=tv.tv_sec*1000+tv.tv_usec/1000;
|
|
*/
|
|
|
|
x=timeOfNextEvent(&type);
|
|
|
|
if (type==0) return;
|
|
if (type==1)
|
|
{
|
|
if ((spev->type==1) || (spev->type==5))
|
|
{
|
|
kdispt->PaintIn(spev->type);
|
|
}
|
|
else if (spev->type==3)
|
|
{
|
|
tempoLCD->display(tempoToMetronomeTempo(spev->tempo));
|
|
#ifdef KMidDEBUG
|
|
printf("Changing lcd tempo: spev->tempo: %d , ratio: %.9g\n",spev->tempo,m_kMid.pctl->ratioTempo);
|
|
printf("Result: %g %.9g %d\n",tempoToMetronomeTempo(spev->tempo),tempoToMetronomeTempo(spev->tempo),(int)tempoToMetronomeTempo(spev->tempo));
|
|
#endif
|
|
currentTempo=tempoLCD->getValue();
|
|
tempoLCD->setDefaultValue(tempoToMetronomeTempo(spev->tempo)*m_kMid.pctl->ratioTempo);
|
|
}
|
|
else if (spev->type==6)
|
|
{
|
|
rhythmview->setRhythm(spev->num,spev->den);
|
|
}
|
|
else if (spev->type==7)
|
|
{
|
|
#ifdef KMidDEBUG
|
|
printf("Beat: %d/%d\n",spev->num,spev->den);
|
|
#endif
|
|
rhythmview->Beat(spev->num);
|
|
}
|
|
m_kMid.pctl->SPEVprocessed++;
|
|
spev=spev->next;
|
|
}
|
|
if (type==2)
|
|
{
|
|
NoteArray::noteCmd *ncmd=noteArray->get();
|
|
if (ncmd==NULL) {printf("ncmd is NULL !!!");return;}
|
|
if (channelView!=NULL)
|
|
{
|
|
if (ncmd->cmd==1) channelView->noteOn(ncmd->chn,ncmd->note);
|
|
else if (ncmd->cmd==0) channelView->noteOff(ncmd->chn,ncmd->note);
|
|
else if (ncmd->cmd==2)
|
|
if (!m_kMid.pctl->forcepgm[ncmd->chn]) channelView->changeInstrument(ncmd->chn,(m_kMid.pctl->gm==1)?(ncmd->note):(MT32toGM[ncmd->note]));
|
|
else channelView->changeInstrument(ncmd->chn,(m_kMid.pctl->pgm[ncmd->chn]));
|
|
|
|
noteArray->next();
|
|
}
|
|
}
|
|
processNext=0;
|
|
|
|
x=timeOfNextEvent(&type);
|
|
|
|
if (type==0) return;
|
|
|
|
timeval tv;
|
|
ulong currentmillisec;
|
|
gettimeofday(&tv, NULL);
|
|
currentmillisec=tv.tv_sec*1000+tv.tv_usec/1000;
|
|
delaymillisec=x-(currentmillisec-beginmillisec);
|
|
if (delaymillisec<10) processNext=1;
|
|
}
|
|
|
|
if (delaymillisec!=~(long)0) timer4events->start(delaymillisec,TRUE);
|
|
|
|
}
|
|
|
|
void kmidClient::repaintText(int type)
|
|
{
|
|
kdispt->ChangeTypeOfTextEvents(type);
|
|
typeoftextevents=type;
|
|
kdispt->repaint(TRUE);
|
|
}
|
|
|
|
int kmidClient::ChooseTypeOfTextEvents(void)
|
|
{
|
|
return kdispt->ChooseTypeOfTextEvents();
|
|
}
|
|
|
|
void kmidClient::setSongType(int i)
|
|
{
|
|
int autochangetype=0;
|
|
if ((m_kMid.pctl->playing==1)&&(m_kMid.pctl->paused==0)) autochangetype=1;
|
|
|
|
if (autochangetype)
|
|
{
|
|
pause();
|
|
}
|
|
m_kMid.pctl->gm=i;
|
|
|
|
if (autochangetype)
|
|
{
|
|
pause();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
TQFont * kmidClient::getFont(void)
|
|
{
|
|
return kdispt->getFont();
|
|
}
|
|
|
|
void kmidClient::fontChanged(void)
|
|
{
|
|
kdispt->fontChanged();
|
|
}
|
|
|
|
void kmidClient::setMidiDevice(int i)
|
|
{
|
|
midi->setDefaultDevice(i);
|
|
}
|
|
|
|
void kmidClient::setMidiMapFilename(const char *mapfilename)
|
|
{
|
|
MidiMapper *map=new MidiMapper(mapfilename);
|
|
if (map->ok()==-1)
|
|
{
|
|
TQString tmp = locate("appdata", TQString("maps/") + mapfilename);
|
|
delete map;
|
|
map=new MidiMapper(tmp.local8Bit());
|
|
if (map->ok()!=1)
|
|
{
|
|
delete map;
|
|
map=new MidiMapper(NULL);
|
|
}
|
|
}
|
|
int autochangemap=0;
|
|
if ((m_kMid.pctl->playing==1)&&(m_kMid.pctl->paused==0)) autochangemap=1;
|
|
|
|
if (autochangemap)
|
|
{
|
|
pause();
|
|
}
|
|
midi->setMidiMap(map);
|
|
if (autochangemap)
|
|
{
|
|
pause();
|
|
}
|
|
}
|
|
|
|
void kmidClient::setSLManager(SLManager *slm)
|
|
{
|
|
if (slman!=NULL) delete slman;
|
|
slman=slm;
|
|
}
|
|
|
|
void kmidClient::setActiveCollection(int i)
|
|
{
|
|
activecollection=i;
|
|
KConfig *kconf=KGlobal::instance()->config();
|
|
|
|
kconf->setGroup("KMid");
|
|
kconf->writeEntry("ActiveCollection",activecollection);
|
|
currentsl=slman->getCollection(activecollection);
|
|
generateCPL();
|
|
initializing_songs=1;
|
|
fillInComboSongs();
|
|
initializing_songs=0;
|
|
}
|
|
|
|
void kmidClient::fillInComboSongs(void)
|
|
{
|
|
//int oldselected=comboSongs->currentItem();
|
|
comboSongs->clear();
|
|
//comboSongs->setCurrentItem(-1);
|
|
if (currentsl==NULL) return;
|
|
currentsl->iteratorStart();
|
|
char temp[FILENAME_MAX];
|
|
char temp2[FILENAME_MAX];
|
|
TQString qs;
|
|
while (!currentsl->iteratorAtEnd())
|
|
{
|
|
qs=currentsl->getIteratorName();
|
|
//KURL::decode(qs);
|
|
sprintf(temp,"%d - %s",currentsl->getIteratorID(),
|
|
extractFilename(KURL::decode_string(qs).ascii(),temp2));
|
|
comboSongs->insertItem(temp);
|
|
currentsl->iteratorNext();
|
|
}
|
|
if (currentsl->getActiveSongID()==-1) return;
|
|
comboSongs->setCurrentItem(currentsl->getActiveSongID()-1);
|
|
/*
|
|
if (oldselected==currentsl->getActiveSongID()-1)
|
|
{
|
|
slotSelectSong(currentsl->getActiveSongID()-1);
|
|
}
|
|
*/
|
|
slotSelectSong(currentsl->getActiveSongID()-1);
|
|
}
|
|
|
|
void kmidClient::slotSelectSong(int i)
|
|
{
|
|
if (currentsl==NULL) return;
|
|
i++;
|
|
if ((i<=0)) // The collection may be empty, or it may be just a bug :-)
|
|
{
|
|
#ifdef KMidDEBUG
|
|
printf("Empty\n");
|
|
#endif
|
|
emit stopPause();
|
|
if (m_kMid.pctl->playing) stop();
|
|
if (midifile_opened!=NULL) delete midifile_opened;
|
|
midifile_opened=NULL;
|
|
player->removeSong();
|
|
timebar->setRange(0,240000);
|
|
timebar->setValue(0);
|
|
timetags->repaint(TRUE);
|
|
kdispt->ClearEv();
|
|
kdispt->repaint(TRUE);
|
|
comboSongs->clear();
|
|
comboSongs->repaint(TRUE);
|
|
topLevelWidget()->setCaption("KMid");
|
|
return;
|
|
}
|
|
|
|
if ((i==currentsl->getActiveSongID())&&(!initializing_songs)) return;
|
|
int pl=0;
|
|
if (m_kMid.pctl->playing==1) pl=1;
|
|
|
|
if (m_kMid.pctl->paused) emit stopPause();
|
|
if (/*(i!=currentsl->getActiveSongID())&&*/(pl==1)) stop();
|
|
currentsl->setActiveSong(i);
|
|
if (openURL(currentsl->getActiveSongName())==-1) return;
|
|
if (pl) play();
|
|
|
|
}
|
|
|
|
|
|
int kmidClient::getSelectedSong(void)
|
|
{
|
|
if (currentsl==NULL) return -1;
|
|
return currentsl->getActiveSongID();
|
|
}
|
|
|
|
|
|
void kmidClient::setSongLoop(int i)
|
|
{
|
|
loopsong=i;
|
|
}
|
|
|
|
|
|
void kmidClient::generateCPL(void)
|
|
{
|
|
delete [] collectionplaylist;
|
|
collectionplaylist=0;
|
|
|
|
if (currentsl==NULL) return;
|
|
|
|
if (collectionplaymode==0)
|
|
collectionplaylist=generate_list(currentsl->NumberOfSongs());
|
|
else
|
|
collectionplaylist=generate_random_list(currentsl->NumberOfSongs());
|
|
}
|
|
|
|
|
|
void kmidClient::setCollectionPlayMode(int i)
|
|
{
|
|
collectionplaymode=i;
|
|
generateCPL();
|
|
}
|
|
|
|
void kmidClient::saveCollections(void)
|
|
{
|
|
if (slman==NULL) return;
|
|
#ifdef KMidDEBUG
|
|
printf("Saving collections in: %s\n",collectionsfile.ascii());
|
|
#endif
|
|
slman->saveConfig(TQFile::encodeName(collectionsfile));
|
|
}
|
|
|
|
void kmidClient::saveLyrics(FILE *fh)
|
|
{
|
|
if (kdispt!=NULL) kdispt->saveLyrics(fh);
|
|
}
|
|
|
|
int kmidClient::searchInCPL(int song)
|
|
{
|
|
if (currentsl==NULL) return -1;
|
|
int i=0;
|
|
int n=currentsl->NumberOfSongs();
|
|
while ((i<n)&&(collectionplaylist[i]!=song)) i++;
|
|
if (i<n) return i;
|
|
return -1;
|
|
}
|
|
|
|
void kmidClient::visibleVolumeBar(int i)
|
|
{
|
|
#ifndef TEMPHACK
|
|
visiblevolumebar=i;
|
|
|
|
if (visiblevolumebar)
|
|
volumebar->show();
|
|
else
|
|
volumebar->hide();
|
|
#endif
|
|
}
|
|
|
|
void kmidClient::visibleChannelView(int i)
|
|
{
|
|
if ((channelView==NULL)&&(i==1))
|
|
{
|
|
channelView=new ChannelView();
|
|
if (noteArray!=NULL)
|
|
{
|
|
int pgm[16],j;
|
|
noteArray->moveIteratorTo((ulong)m_kMid.pctl->millisecsPlayed,pgm);
|
|
for (j=0;j<16;j++)
|
|
{
|
|
if (!m_kMid.pctl->forcepgm[j]) channelView->changeInstrument(j,(m_kMid.pctl->gm==1)?(pgm[j]):(MT32toGM[pgm[j]]));
|
|
else channelView->changeInstrument(j,(m_kMid.pctl->pgm[j]));
|
|
channelView->changeForceState(j,m_kMid.pctl->forcepgm[j]);
|
|
}
|
|
}
|
|
channelView->show();
|
|
connect(channelView,TQT_SIGNAL(signalToKMidClient(int *)),this,TQT_SLOT(communicationFromChannelView(int *)));
|
|
connect(kapp,TQT_SIGNAL(shutDown()),parentWidget(),TQT_SLOT(shuttingDown()));
|
|
|
|
}
|
|
else if ((channelView!=NULL)&&(i==0))
|
|
{
|
|
delete channelView;
|
|
channelView=NULL;
|
|
|
|
}
|
|
rethinkNextEvent();
|
|
}
|
|
|
|
void kmidClient::channelViewDestroyed()
|
|
{
|
|
channelView=NULL;
|
|
rethinkNextEvent();
|
|
}
|
|
|
|
|
|
void kmidClient::rethinkNextEvent(void)
|
|
{
|
|
if (m_kMid.pctl->playing==0) return;
|
|
timer4events->stop();
|
|
|
|
int type;
|
|
ulong delaymillisec;
|
|
ulong x=timeOfNextEvent(&type);
|
|
|
|
if (type==0) return;
|
|
|
|
timeval tv;
|
|
ulong currentmillisec;
|
|
gettimeofday(&tv, NULL);
|
|
currentmillisec=tv.tv_sec*1000+tv.tv_usec/1000;
|
|
delaymillisec=x-(currentmillisec-beginmillisec);
|
|
|
|
timer4events->start(delaymillisec,TRUE);
|
|
}
|
|
|
|
void kmidClient::communicationFromChannelView(int *i)
|
|
{
|
|
if (i==NULL) return;
|
|
int autocontplaying=0;
|
|
if ((i[0]==CHN_CHANGE_PGM)||((i[0]==CHN_CHANGE_FORCED_STATE)&&(i[3]==1)))
|
|
{
|
|
if ((m_kMid.pctl->playing==1)&&(m_kMid.pctl->paused==0)) autocontplaying=1;
|
|
|
|
if (autocontplaying)
|
|
{
|
|
pause();
|
|
}
|
|
}
|
|
if (i[0]==CHN_CHANGE_PGM)
|
|
m_kMid.pctl->pgm[i[1]-1]=i[2];
|
|
else if (i[0]==CHN_CHANGE_FORCED_STATE)
|
|
m_kMid.pctl->forcepgm[i[1]-1]=i[2];
|
|
if ((i[0]==CHN_CHANGE_PGM)||((i[0]==CHN_CHANGE_FORCED_STATE)&&(i[3]==1)))
|
|
{
|
|
if (autocontplaying)
|
|
{
|
|
pause();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void kmidClient::slotSetTempo(double value)
|
|
{
|
|
if (!player->isSongLoaded())
|
|
{
|
|
tempoLCD->display(120);
|
|
currentTempo=120;
|
|
tempoLCD->setDefaultValue(120);
|
|
return;
|
|
}
|
|
|
|
#ifdef KMidDEBUG
|
|
printf("Change tempo to %g\n",value);
|
|
#endif
|
|
int autocontplaying=0;
|
|
|
|
if ((m_kMid.pctl->playing==1)&&(m_kMid.pctl->paused==0)) autocontplaying=1;
|
|
|
|
|
|
if (autocontplaying)
|
|
{
|
|
pause();
|
|
}
|
|
|
|
// double ratio=(tempoToMetronomeTempo(m_kMid.pctl->tempo)*m_kMid.pctl->ratioTempo)/(value);
|
|
// double ratio=(tempoLCD->getOldValue()*m_kMid.pctl->ratioTempo)/(value);
|
|
double ratio=(currentTempo*m_kMid.pctl->ratioTempo)/value;
|
|
|
|
char s[20];
|
|
sprintf(s,"%g",ratio);
|
|
if (strcmp(s,"1")!=0) tempoLCD->setLCDColor (255,100,100);
|
|
else tempoLCD->setLCDColor (100,255,100);
|
|
#ifdef KMidDEBUG
|
|
printf("ratio: (%.9g = %g ) tempo now: %g , new tempo %g\n",ratio,ratio,tempoToMetronomeTempo(m_kMid.pctl->tempo),value);
|
|
printf("OldValue: %g , value %g\n",tempoLCD->getOldValue(),value);
|
|
#endif
|
|
|
|
if (m_kMid.pctl->paused==1)
|
|
{
|
|
pausedatmillisec=(long)(((double)pausedatmillisec/m_kMid.pctl->ratioTempo)*ratio);
|
|
#ifdef KMidDEBUG
|
|
printf("pausedat: %ld\n",pausedatmillisec);
|
|
#endif
|
|
}
|
|
player->setTempoRatio(ratio);
|
|
|
|
timebar->setRange(0,(int)(player->information()->millisecsTotal));
|
|
timebar->setValue(pausedatmillisec);
|
|
timetags->repaint(TRUE);
|
|
|
|
kdispt->ClearEv(false);
|
|
|
|
noteArray=player->noteArray();
|
|
spev=player->specialEvents();
|
|
currentTempo=value;
|
|
|
|
while (spev!=NULL)
|
|
{
|
|
if ((spev->type==1) || (spev->type==5))
|
|
{
|
|
kdispt->AddEv(spev);
|
|
}
|
|
spev=spev->next;
|
|
}
|
|
|
|
kdispt->calculatePositions();
|
|
kdispt->CursorToHome();
|
|
if (m_kMid.pctl->paused==1)
|
|
moveEventPointersTo(pausedatmillisec);
|
|
|
|
if (autocontplaying)
|
|
{
|
|
pause();
|
|
}
|
|
|
|
}
|
|
|
|
void kmidClient::downloadFinished(KIO::Job *)
|
|
{
|
|
downloaded=true;
|
|
kapp->exit_loop();
|
|
}
|
|
|
|
TQSize kmidClient::sizeHint() const
|
|
{
|
|
TQSize sh = TQWidget::sizeHint();
|
|
return sh.expandedTo(TQSize(560,420));
|
|
}
|
|
|
|
TQSizePolicy kmidClient::sizePolicy()
|
|
{
|
|
return TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding);
|
|
}
|
|
|
|
|
|
void kmidClient::play()
|
|
{
|
|
slotPlay();
|
|
}
|
|
void kmidClient::pause()
|
|
{
|
|
slotPause();
|
|
}
|
|
void kmidClient::stop()
|
|
{
|
|
slotStop();
|
|
}
|
|
void kmidClient::rewind()
|
|
{
|
|
slotRewind();
|
|
}
|
|
void kmidClient::forward()
|
|
{
|
|
slotForward();
|
|
}
|
|
void kmidClient::seek(int ms)
|
|
{
|
|
slotSeek(ms);
|
|
}
|
|
void kmidClient::prevSong()
|
|
{
|
|
slotPrevSong();
|
|
}
|
|
void kmidClient::nextSong()
|
|
{
|
|
slotNextSong();
|
|
}
|
|
void kmidClient::setVolume(int i)
|
|
{
|
|
slotSetVolume(200-i);
|
|
}
|
|
void kmidClient::setTempo(int i)
|
|
{
|
|
slotSetTempo(i);
|
|
}
|
|
void kmidClient::setSongEncoding( int i )
|
|
{
|
|
KListAction *tmplistaction=
|
|
((KListAction*)actionCollection->action("file_type"));
|
|
|
|
tmplistaction->setCurrentItem(i);
|
|
}
|
|
void kmidClient::setLyricEvents( int i )
|
|
{
|
|
KListAction *tmplistaction=
|
|
((KListAction*)actionCollection->action("display_events"));
|
|
tmplistaction->setCurrentItem(i);
|
|
}
|
|
void kmidClient::setCurrentSong(int i)
|
|
{
|
|
getComboSongs()->setCurrentItem(i-1);
|
|
slotSelectSong(i-1);
|
|
}
|
|
void kmidClient::setPlayListMode(int i)
|
|
{
|
|
((KListAction*)actionCollection->action("play_order"))->setCurrentItem(i);
|
|
}
|
|
void kmidClient::slotSelectEncoding(int i)
|
|
{
|
|
if (i == 0)
|
|
kdispt->setLyricsEncoding(TQString::null); // Default
|
|
else
|
|
kdispt->setLyricsEncoding(KGlobal::charsets()->encodingForName(comboEncodings->text(i)));
|
|
}
|
|
#include "kmidclient.moc"
|