summaryrefslogtreecommitdiffstats
path: root/kmid
diff options
context:
space:
mode:
Diffstat (limited to 'kmid')
-rw-r--r--kmid/ChangeLog104
-rw-r--r--kmid/Makefile.am74
-rw-r--r--kmid/PEOPLE4
-rw-r--r--kmid/README123
-rw-r--r--kmid/audiomidi.desktop3
-rw-r--r--kmid/button1.xpm22
-rw-r--r--kmid/button2.xpm22
-rw-r--r--kmid/channel.cpp233
-rw-r--r--kmid/channel.h104
-rw-r--r--kmid/channel3d.cpp149
-rw-r--r--kmid/channel3d.h52
-rw-r--r--kmid/channel4d.cpp232
-rw-r--r--kmid/channel4d.h58
-rw-r--r--kmid/channelcfgdlg.cpp39
-rw-r--r--kmid/channelcfgdlg.h51
-rw-r--r--kmid/channelview.cpp165
-rw-r--r--kmid/channelview.h76
-rw-r--r--kmid/collectdlg.cpp307
-rw-r--r--kmid/collectdlg.h83
-rw-r--r--kmid/configure.in.in5
-rw-r--r--kmid/drums.o3bin0 -> 7680 bytes
-rw-r--r--kmid/drums.sbbin0 -> 6656 bytes
-rw-r--r--kmid/examples/DiesIrae.karbin0 -> 45515 bytes
-rw-r--r--kmid/examples/Guantanamera.karbin0 -> 37539 bytes
-rw-r--r--kmid/examples/Makefile.am6
-rw-r--r--kmid/examples/MariaDeLasMercedes.karbin0 -> 29440 bytes
-rw-r--r--kmid/examples/OFortuna.karbin0 -> 51276 bytes
-rw-r--r--kmid/hi16-app-kmid.pngbin0 -> 870 bytes
-rw-r--r--kmid/hi32-app-kmid.pngbin0 -> 2425 bytes
-rw-r--r--kmid/hi48-app-kmid.pngbin0 -> 4307 bytes
-rw-r--r--kmid/history.txt567
-rw-r--r--kmid/instrfilter.awk2
-rw-r--r--kmid/instrname.cpp132
-rw-r--r--kmid/instrname.h6
-rw-r--r--kmid/instrname.i18n133
-rw-r--r--kmid/kdisptext.cpp640
-rw-r--r--kmid/kdisptext.h125
-rw-r--r--kmid/keyboard.xpm50
-rw-r--r--kmid/klcdnumber.cpp339
-rw-r--r--kmid/klcdnumber.h153
-rw-r--r--kmid/kmid.desktop88
-rw-r--r--kmid/kmid.lsm22
-rw-r--r--kmid/kmid.spec62
-rw-r--r--kmid/kmidIface.h46
-rw-r--r--kmid/kmid_part.cpp144
-rw-r--r--kmid/kmid_part.h63
-rw-r--r--kmid/kmid_partui.rc17
-rw-r--r--kmid/kmidbutton.h32
-rw-r--r--kmid/kmidclient.cpp1606
-rw-r--r--kmid/kmidclient.h240
-rw-r--r--kmid/kmidframe.cpp728
-rw-r--r--kmid/kmidframe.h133
-rw-r--r--kmid/kmidui.rc44
-rw-r--r--kmid/ktrianglebutton.cpp164
-rw-r--r--kmid/ktrianglebutton.h73
-rw-r--r--kmid/main.cpp101
-rw-r--r--kmid/maps/Makefile.am5
-rw-r--r--kmid/maps/YamahaPSR500.map293
-rw-r--r--kmid/maps/YamahaPSS790.map299
-rw-r--r--kmid/maps/YamahaQY10.map305
-rw-r--r--kmid/maps/gm.map290
-rw-r--r--kmid/midicfgdlg.cpp138
-rw-r--r--kmid/midicfgdlg.h60
-rw-r--r--kmid/pics/Makefile.am3
-rw-r--r--kmid/pics/cr16-action-piano.pngbin0 -> 248 bytes
-rw-r--r--kmid/pics/cr16-action-volume.pngbin0 -> 180 bytes
-rw-r--r--kmid/pics/cr22-action-piano.pngbin0 -> 272 bytes
-rw-r--r--kmid/pics/cr22-action-volume.pngbin0 -> 377 bytes
-rw-r--r--kmid/pics/cr32-action-piano.pngbin0 -> 361 bytes
-rw-r--r--kmid/pics/cr32-action-volume.pngbin0 -> 447 bytes
-rw-r--r--kmid/qslidertime.cpp120
-rw-r--r--kmid/qslidertime.h56
-rw-r--r--kmid/randomlist.cpp103
-rw-r--r--kmid/randomlist.h34
-rw-r--r--kmid/rhythmview.cpp108
-rw-r--r--kmid/rhythmview.h54
-rw-r--r--kmid/slman.cpp320
-rw-r--r--kmid/slman.h74
-rw-r--r--kmid/songlist.cpp247
-rw-r--r--kmid/songlist.h84
-rw-r--r--kmid/std.o3bin0 -> 7680 bytes
-rw-r--r--kmid/std.sbbin0 -> 6656 bytes
-rw-r--r--kmid/version.h48
-rw-r--r--kmid/x-karaoke.desktop61
84 files changed, 10324 insertions, 0 deletions
diff --git a/kmid/ChangeLog b/kmid/ChangeLog
new file mode 100644
index 00000000..6914c1d0
--- /dev/null
+++ b/kmid/ChangeLog
@@ -0,0 +1,104 @@
+0.1 30-10-97
+----- --------
+First version
+
+0.2 9-11-97
+----- -------
+Better syncronization between lyrics and music.
+Drag&Drop, better installation, icons, Customizable fonts.
+
+0.3 16-11-97
+----- --------
+The lyrics handler is very improved.
+Option to automagically select lyrics or text.
+Better handling for broken files.
+Few bug fixes.
+Real Session Management.
+First rpm version.
+
+0.4 30-12-97
+----- --------
+Fixed the pthread bug (sorry to everyone that suffered it ;-))
+Added support for AWE and GUS cards
+Can modify the midi device without recompiling.
+Can play gzipped files
+
+0.41 22-2-98
+----- -------
+Fixed a problem with GUS cards
+Improved midi mapper
+Fixed a non-feature :-) related to FM
+New icon and toolbar pixmaps which use fewer colors
+
+0.5 15-3-98
+----- -------
+FM support
+Playlists (Collections)
+Some small improvements here and there
+
+0.5.1 15-3-98
+----- -------
+A very small bug fix
+
+0.5.2 5-4-98
+----- ------
+Save Lyrics
+Some bug fixes
+More keys binded to functions (arrows, space, backspace, etc.)
+
+0.5.3 24-4-98
+----- -------
+Improved Synchronization between gui and player
+Some bug fixes:
+ - One which caused kmid to freeze when playing a collection with only 1 song
+ in aleatory mode and changing to next song
+ (reported by Jose Luis Sanchez)
+ - It was not possible to play a gzipped file that have spaces in its name
+ - There were some songs that played at a lower volume when moving the
+ slider, but not if playing from the beginning.
+Better support for shuffle mode (now it doesn't repeat songs :-))
+
+0.6 7-5-98
+----- ------
+Just thought that everything worked fine and did a major release to
+put it in my homepage
+
+1.0 22-6-98
+----- -------
+Well, I should be studying, but KDE 1.0 good deserves a few minutes
+to change the version number everywhere, remove debug printfs, and
+clean the latest bugs, isn't it ? :-)
+
+1.2 14-9-98
+----- -------
+This version includes a new ChannelView to see notes played by each
+instrument and a volume bar.
+It also has some bug fixes and support for really broken midi files.
+
+1.6 27-11-98
+----- --------
+This version fix a bug that made kmid totally unusable to many users
+because it played music at different tempos (sometimes faster and
+sometimes slower), without any rhythm. Anyway, this isn't a public
+version yet, it's only available from CVS.
+
+1.7 2-4-99
+----- -------
+Modified KMid to work with Linux kernels from the 2.2.x series which
+work very different than the ones in 2.0.x . That problem made KMid
+continue playing music for a while (up to a few minutes !) after the
+user had pressed the stop button.
+Fixed a problem with AWE cards that made it play files with the pitch
+bender raised.
+Fixed a problem that made kmid not to play the last few milliseconds of
+some songs (sometimes up to half a second)
+Another usual fixes (better support for kernel modules, workarounds for
+compiler bugs, etc.)
+
+2.0 1-10-2000
+----- ---------
+KMid has been ported to KDE 2.0
+Now has a separated ui and engine, it also has native ALSA support
+It's a part now, so you can embed KMid in Konqueror and other apps.
+Ah, and the scroll is smooth now :)
+
diff --git a/kmid/Makefile.am b/kmid/Makefile.am
new file mode 100644
index 00000000..6dd4acb7
--- /dev/null
+++ b/kmid/Makefile.am
@@ -0,0 +1,74 @@
+INCLUDES = $(all_includes)
+
+kde_module_LTLIBRARIES = libkmidpart.la
+lib_LTLIBRARIES = libkmidlib.la
+
+libkmidlib_la_LDFLAGS = $(all_libraries)
+libkmidlib_la_LIBADD = $(LIB_KFILE) $(LIB_KPARTS) $(LIB_KIO) -lkmid
+
+libkmidpart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module
+libkmidpart_la_LIBADD = libkmidlib.la
+
+libkmidlib_la_SOURCES = kmidframe.cpp kmidclient.cpp kdisptext.cpp \
+ qslidertime.cpp klcdnumber.cpp ktrianglebutton.cpp \
+ midicfgdlg.cpp collectdlg.cpp randomlist.cpp \
+ channelview.cpp channel.cpp channel3d.cpp channel4d.cpp \
+ channelcfgdlg.cpp instrname.cpp rhythmview.cpp \
+ songlist.cpp slman.cpp kmid_part.cpp kmidIface.skel
+
+libkmidpart_la_SOURCES = part_dummy.cpp
+
+part_dummy.cpp:
+ touch part_dummy.cpp
+
+noinst_HEADERS = kmidframe.h kmidclient.h kdisptext.h \
+ qslidertime.h klcdnumber.h ktrianglebutton.h \
+ midicfgdlg.h collectdlg.h randomlist.h \
+ channelview.h channel.h channel3d.h channel4d.h \
+ channelcfgdlg.h instrname.h rhythmview.h \
+ songlist.h slman.h kmid_part.h
+
+kmid_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kmid_SOURCES = main.cpp
+kmid_LDADD = libkmidlib.la
+
+bin_PROGRAMS = kmid
+METASOURCES = AUTO
+
+servicetype_DATA = audiomidi.desktop
+servicetypedir = $(kde_servicetypesdir)
+
+SUBDIRS = maps examples pics
+
+xdg_apps_DATA = kmid.desktop
+
+mime_DATA = x-karaoke.desktop
+mimedir = $(kde_mimedir)/audio
+
+rc_DATA = kmidui.rc
+rcdir = $(kde_datadir)/kmid
+
+KDE_ICON = kmid
+
+fmpatches_DATA = std.sb drums.sb std.o3 drums.o3
+fmpatchesdir = $(kde_datadir)/kmid/fm
+
+partdir = $(kde_datadir)/kmid
+part_DATA = kmid_partui.rc
+
+channelview_DATA = keyboard.xpm button1.xpm button2.xpm
+channelviewdir = $(kde_datadir)/kmid/icons
+
+EXTRA_DIST = $(xdg_apps_DATA) $(mime_DATA) $(fmpatches_DATA) $(part_DATA)
+
+instrname.i18n: instrname.cpp
+ echo "/* This is an automatically generated file" > instrname.i18n
+ echo " * DO NOT EDIT !!!" >> instrname.i18n
+ echo " * To create this file run : ""make instrname.i18n"" " >> instrname.i18n
+ echo " */" >> instrname.i18n
+ echo "" >> instrname.i18n
+ awk -f instrfilter.awk instrname.cpp >> instrname.i18n
+
+
+messages: instrname.i18n rc.cpp
+ $(XGETTEXT) *.cpp instrname.i18n -o $(podir)/kmid.pot
diff --git a/kmid/PEOPLE b/kmid/PEOPLE
new file mode 100644
index 00000000..4cd777c2
--- /dev/null
+++ b/kmid/PEOPLE
@@ -0,0 +1,4 @@
+Please take a look at the online help for a list of people who have helped
+me in the development of KMid (emotionally or with patches :-) ).
+
+ - Antonio Larrosa
diff --git a/kmid/README b/kmid/README
new file mode 100644
index 00000000..52c5f759
--- /dev/null
+++ b/kmid/README
@@ -0,0 +1,123 @@
+**********************************************************************
+ KKK KK MMM MMM IIIIII DDDDD
+ KKK KK MMMMMMMMMM IIII DDDDDDD
+ KKKKK MMMMMMMMMM II DDD DD
+ Console KKKKKK MMM MM MMM IIII DDDDDDD
+ KKK KKK MMM MMM IIIIII DDDDD
+
+ ConsoleKMID
+
+
+ This info is up to date if you have KMid version 1.7
+
+________________________________________________
+If you are looking for a KMid README file, then this is NOT the one you are
+looking for. Please look the online documentation, that is, the html help
+
+I've left this file only for help on the small cousin of KMid, ConsoleKMid.
+
+ - Antonio Larrosa
+------------------------------------------------
+
+Index
+-------
+ 1. What is ConsoleKMid ?
+ 2. Requirements of consoleKMid
+ 3. Compiling consoleKMid
+ 4. Installing
+ 5. Running
+ 6. How do I use a Midi Mapper ?
+ 7. Where can I download KMid and consoleKMid from ?
+ 8. To do list
+
+1. What is ConsoleKMid ?
+------------------------
+ ConsoleKMid is a small program for Unix in console mode, which uses the same
+ player engine of KMid. Of course it doesn't have the same friendly
+ interface of KMid but it works to play midi files.
+
+ If you have the rpm distribution, you will not find the consolekmid program
+ unless you have compiled it from the src.rpm distribution
+
+
+2. Requirements of consoleKMid
+-------------------------------
+
+ A UNIX machine, a soundcard and a /dev/sequencer device well installed.
+ If you have a GUS, you need a properly installed driver from the Linux
+ Ultrasound Project, AWE cards are also supported, but you will probably
+ need to compile consoleKMid in order to get an AWE card to work.
+ FM devices are also supported.
+ I have only tested KMid in Linux, but I have had sucessful reports getting
+ KMid to work on FreeBSD
+ If you sucessfully run KMid in other unices, please tell me !
+
+ Currently GUS cards make a little sound when using the oss driver, but are
+ not supported officially, I'm looking to find people with GUS cards that
+ want to help me to provide such support (either programming or testing),
+ as I think that if nobody has worried about it it's because there's no
+ need for it ;-)
+
+3. Compiling consoleKMid
+-----------------
+ Do a configure from the parent directory, then go to the player directory,
+ and do a 'make' . Simple , isn't it ?
+
+ By default it will use the external midi device, if you want to use another
+ one (fm, awe, or anything else), edit the file main.cc and change the value
+ of DEFAULT_DEVICE to the one you want, or specify the -d option as in :
+
+ consolekmid -d 1 mymidifile.mid
+
+4. Installing
+-----------------
+ No installing of consoleKMid is actually done, just copy the consoleKMid file
+ yourself to where you want (usually /usr/local/bin ). To use the fm device,
+ you should specify in fmout.cc the path to where the fm patches are installed
+ ( /etc by default)
+
+5. Running
+--------------
+ Well, it's quite easy, just type "consolekmid" and it should run :-)
+
+6. How do I use a Midi Mapper ?
+-------------------------------
+ A Midi Mapper is the feature you have been waiting for in Linux for years,
+ (at least I have been :-) it makes a non General Midi synth, appear to the
+ computer as General Midi compliant. Thus, a GM synth is emulated with a
+ nonGM.
+ Look the KMid docs for more info on creating/using a midi map.
+ If you want to use one with consolekmid, you can use the -M option,
+ use it like this example :
+
+ consolekmid -M /opt/kde/share/apps/kmid/maps/YamahaPSS790.map mymidifile
+
+ You can also edit main.cc in the player directory and change the value of
+ DEFAULT_MAP to whatever you want, so that you don't need to specify the
+ -M option each time you run consolekmid.
+
+ If you want to define a new map for your midi keyboard, I recommend you to
+ start by copying the file yamaha790.map and modifying it. And remember to
+ send it to me so that it will be included in future revisions and other
+ people can use it !
+
+7. Where can I download KMid and consoleKMid from ?
+---------------------------------------------------
+
+ KMid's homepage is at :
+ http://developer.kde.org/~larrosa/kmid.html
+
+ From there you can download latest versions as well as know the latest
+ changes and improvements of KMid and consoleKMid
+
+8. To do list
+---------------
+ GUS support is nearly done (and also SoftOSS) but still need little
+ improvements. It should mostly work now.
+ Better AWE support and use Soundfonts
+ The KMidServer and make KMid use it.
+
+-------
+30-4-2001
+Antonio Larrosa Jimenez
+larrosa@kde.org
diff --git a/kmid/audiomidi.desktop b/kmid/audiomidi.desktop
new file mode 100644
index 00000000..420045bf
--- /dev/null
+++ b/kmid/audiomidi.desktop
@@ -0,0 +1,3 @@
+# This file used to define audio/x-midi, which is already defined as a mime type!
+[Desktop Entry]
+Hidden=true
diff --git a/kmid/button1.xpm b/kmid/button1.xpm
new file mode 100644
index 00000000..93d38a73
--- /dev/null
+++ b/kmid/button1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * button1_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #000000000000",
+"X c #FFFF00000000",
+" ",
+" .... ",
+" ........ ",
+" .......... ",
+" .....XX..... ",
+" ...XXXXXX... ",
+" ....XXXXXX.... ",
+" ...XXXXXXXX... ",
+" ...XXXXXXXX... ",
+" ....XXXXXX.... ",
+" ...XXXXXX... ",
+" .....XX..... ",
+" .......... ",
+" ........ ",
+" .... ",
+" "};
diff --git a/kmid/button2.xpm b/kmid/button2.xpm
new file mode 100644
index 00000000..8c8922df
--- /dev/null
+++ b/kmid/button2.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * button2_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #000000000000",
+"X c #0000FFFF0000",
+" ",
+" .... ",
+" ........ ",
+" .......... ",
+" .....XX..... ",
+" ...XXXXXX... ",
+" ....XXXXXX.... ",
+" ...XXXXXXXX... ",
+" ...XXXXXXXX... ",
+" ....XXXXXX.... ",
+" ...XXXXXX... ",
+" .....XX..... ",
+" .......... ",
+" ........ ",
+" .... ",
+" "};
diff --git a/kmid/channel.cpp b/kmid/channel.cpp
new file mode 100644
index 00000000..14dd95a9
--- /dev/null
+++ b/kmid/channel.cpp
@@ -0,0 +1,233 @@
+/**************************************************************************
+
+ channel.cpp - The KMidChannel widget (with pure virtual members)
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <qpainter.h>
+#include <qcombobox.h>
+
+#include <kglobal.h>
+#include <kinstance.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include "kmidbutton.h"
+
+#include "channel.h"
+#include "instrname.h"
+#include <kiconloader.h>
+
+KMidChannel::KMidChannel(int chn,QWidget *parent) : QWidget (parent)
+{
+ channel=chn;
+ replay=TRUE;
+ int i;
+ for (i=0;i<128;i++) pressed[i]=0;
+ keyboard = QPixmap(locate("appdata","icons/keyboard.xpm"));
+ penB = new QPen (black);
+ penW = new QPen (white);
+ penT = new QPen (colorGroup().background());
+
+ KConfig *kcfg=KGlobal::instance()->config();
+ kcfg->setGroup("KMid");
+ QFont *qtextfontdefault=new QFont("lucida",18,QFont::Bold,TRUE);
+ qcvfont=new QFont(kcfg->readFontEntry("ChannelViewFont",qtextfontdefault));
+ delete qtextfontdefault;
+
+ instrumentCombo = new QComboBox(FALSE,this,"instr");
+ instrumentCombo->setGeometry(160,2,200,20);
+
+ for (i=0;i<128;i++)
+ instrumentCombo->insertItem(i18n(instrumentName[i]),i);
+
+ connect(instrumentCombo,SIGNAL(activated(int)),this,SLOT(pgmChanged(int)));
+
+ forcepgm=new KMidButton(this,"forcepgm");
+ forcepgm->setGeometry(135,4,16,16);
+ forcepgm->setToggleButton(TRUE);
+ button1 = QPixmap(locate("appdata","icons/button1.xpm"));
+ button2 = QPixmap(locate("appdata","icons/button2.xpm"));
+ forcepgm->setPixmaps(button1,button2);
+ forcepgm->show();
+ connect(forcepgm,SIGNAL(toggled(bool)),this,SLOT(changeForcedState(bool)));
+
+}
+
+KMidChannel::~KMidChannel()
+{
+ delete penB;
+ delete penW;
+ delete penT;
+}
+
+void KMidChannel::paintEvent( QPaintEvent * )
+{
+
+ QPainter *qpaint=new QPainter(this);
+
+ QString tmp = i18n("Channel %1").arg(channel);
+ qpaint->setFont(*qcvfont);
+ qpaint->setPen(*penB);
+ qpaint->drawText(2,20,tmp);
+ qpaint->setPen(*penW);
+ qpaint->drawText(0,18,tmp);
+
+ drawKeyboard(qpaint);
+ drawPressedKeys(qpaint);
+
+ delete qpaint;
+}
+
+void KMidChannel::drawKeyboard(QPainter *qpaint)
+{
+ int x=1;
+ for (int i=0;(i<12) && (x<width());i++,x+=63)
+ {
+ qpaint->drawPixmap(x,KEYBOARDY,keyboard);
+ };
+ qpaint->setPen(*penB);
+ qpaint->drawLine(0,KEYBOARDY,0,KEYBOARDY+44);
+
+ qpaint->setPen(*penT);
+ qpaint->drawLine(0,KEYBOARDY+45,x+63,KEYBOARDY+45);
+
+
+}
+
+void KMidChannel::drawPressedKeys(QPainter *qpaint)
+{
+ for (int i=0;i<128;i++)
+ if (pressed[i]) drawKey(qpaint,i);
+}
+
+void KMidChannel::drawKey(QPainter *qpaint,int key)
+{
+ int octave=key/12;
+ int note=key%12;
+ int x=octave*63+1;
+
+ switch (note)
+ {
+ case (0) : drawDo (qpaint,x,pressed[key]);break;
+ case (1) : drawDo__ (qpaint,x,pressed[key]);break;
+ case (2) : drawRe (qpaint,x,pressed[key]);break;
+ case (3) : drawRe__ (qpaint,x,pressed[key]);break;
+ case (4) : drawMi (qpaint,x,pressed[key]);break;
+ case (5) : drawFa (qpaint,x,pressed[key]);break;
+ case (6) : drawFa__ (qpaint,x,pressed[key]);break;
+ case (7) : drawSol (qpaint,x,pressed[key]);break;
+ case (8) : drawSol__(qpaint,x,pressed[key]);break;
+ case (9) : drawLa (qpaint,x,pressed[key]);break;
+ case (10) : drawLa__ (qpaint,x,pressed[key]);break;
+ case (11) : drawSi (qpaint,x,pressed[key]);break;
+ };
+// qpaint->flush();
+}
+
+void KMidChannel::noteOn(int key)
+{
+ pressed[key]=1;
+ QPainter *qpaint=new QPainter(this);
+ drawKey(qpaint,key);
+ delete qpaint;
+}
+
+void KMidChannel::noteOff(int key)
+{
+ pressed[key]=0;
+ QPainter *qpaint=new QPainter(this);
+ drawKey(qpaint,key);
+ delete qpaint;
+}
+
+void KMidChannel::changeInstrument(int pgm)
+{
+ instrumentCombo->setCurrentItem(pgm);
+}
+
+void KMidChannel::changeForceState(bool i)
+{
+ replay=FALSE;
+ forcepgm->setOn(i);
+ replay=TRUE;
+}
+
+void KMidChannel::reset(int level)
+{
+ for (int i=0;i<128;i++) pressed[i]=0;
+ if (level>=1)
+ {
+ instrumentCombo->setCurrentItem(0);
+ replay=FALSE;
+ forcepgm->setOn(FALSE);
+ replay=TRUE;
+ };
+
+ repaint(FALSE);
+}
+
+void KMidChannel::saveState(bool *p,int *pgm)
+{
+ for (int i=0;i<128;i++) p[i]=pressed[i];
+ *pgm=instrumentCombo->currentItem();
+}
+
+void KMidChannel::loadState(bool *p,int *pgm)
+{
+ for (int i=0;i<128;i++) pressed[i]=p[i];
+ instrumentCombo->setCurrentItem(*pgm);
+ repaint(FALSE);
+}
+
+void KMidChannel::pgmChanged(int i)
+{
+ int data[4];
+ data[0]=CHN_CHANGE_PGM;
+ data[1]=channel;
+ data[2]=i;
+ data[3]=0;
+
+ replay=FALSE;
+ forcepgm->setOn(TRUE);
+ replay=TRUE;
+
+ emit signalToKMidClient(data);
+
+
+}
+
+
+void KMidChannel::changeForcedState(bool i)
+{
+ int data[4];
+ data[0]=CHN_CHANGE_FORCED_STATE;
+ data[1]=channel;
+ data[2]=i;
+ data[3]=(replay)? 1 : 0;
+
+ emit signalToKMidClient(data);
+
+}
+#include "channel.moc"
diff --git a/kmid/channel.h b/kmid/channel.h
new file mode 100644
index 00000000..29ddfcd2
--- /dev/null
+++ b/kmid/channel.h
@@ -0,0 +1,104 @@
+/**************************************************************************
+
+ channel.h - The KMidChannel widget (with pure virtual members)
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#ifndef KMIDCHANNEL_H
+#define KMIDCHANNEL_H
+#include <qwidget.h>
+#include <qpixmap.h>
+
+#define CHANNELHEIGHT 71
+#define KEYBOARDY CHANNELHEIGHT-46
+
+#define CHN_CHANGE_PGM 1
+#define CHN_CHANGE_FORCED_STATE 2
+
+class QFont;
+class QComboBox;
+class KMidButton;
+class KMidChannel : public QWidget
+{
+ Q_OBJECT
+
+private:
+ bool pressed[128]; // The 128 keys
+ int channel;
+ bool replay; // Indicates if music should restart playing after
+ // changing the force state
+
+protected:
+ QPixmap keyboard;
+ QPixmap button1;
+ QPixmap button2;
+
+ QComboBox *instrumentCombo;
+
+ KMidButton *forcepgm;
+ QFont *qcvfont;
+
+ QPen *penB; // Black
+ QPen *penW; // White
+ QPen *penT; // "Transparent" for Background
+
+ void paintEvent( QPaintEvent * );
+public:
+ KMidChannel(int i,QWidget *Parent);
+ virtual ~KMidChannel();
+
+ void drawKeyboard(QPainter *qpaint);
+ void drawPressedKeys(QPainter *qpaint);
+ void drawKey(QPainter *qpaint,int key);
+
+ virtual void drawDo (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawDo__ (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawRe (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawRe__ (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawMi (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawFa (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawFa__ (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawSol (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawSol__(QPainter *qpaint,int x,int p) = 0;
+ virtual void drawLa (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawLa__ (QPainter *qpaint,int x,int p) = 0;
+ virtual void drawSi (QPainter *qpaint,int x,int p) = 0;
+
+ void noteOn(int key);
+ void noteOff(int key);
+ void changeInstrument(int pgm);
+ void changeForceState(bool i);
+
+ void reset(int level=1); // 0 only release notes, 1 also set instr to 0 ...
+
+ void saveState(bool *p,int *pgm);
+ void loadState(bool *p,int *pgm);
+
+public slots:
+ void pgmChanged(int i);
+ void changeForcedState(bool);
+
+signals:
+ void signalToKMidClient(int *data);
+
+};
+
+#endif
diff --git a/kmid/channel3d.cpp b/kmid/channel3d.cpp
new file mode 100644
index 00000000..2a2451c6
--- /dev/null
+++ b/kmid/channel3d.cpp
@@ -0,0 +1,149 @@
+/**************************************************************************
+
+ channel3d.cpp - KMidChannel3D widget, a Channel widget with 3D look
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#include "channel3d.h"
+#include <qpainter.h>
+
+KMidChannel3D::KMidChannel3D (int chn,QWidget *parent) : KMidChannel(chn,parent)
+{
+}
+
+void KMidChannel3D::drawDo(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x,KEYBOARDY+43,x+6,KEYBOARDY+43);
+ qpaint->drawLine(x,KEYBOARDY+44,x+6,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x-1,KEYBOARDY+45,x+8,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+7,KEYBOARDY+28,x+7,KEYBOARDY+42);
+}
+void KMidChannel3D::drawDo__(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+6,KEYBOARDY+2,x+6,KEYBOARDY+25);
+ qpaint->drawLine(x+7,KEYBOARDY+25,x+11,KEYBOARDY+25);
+
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+11,KEYBOARDY+1,x+11,KEYBOARDY+27);
+ qpaint->drawPoint(x+10,KEYBOARDY+27);
+
+}
+void KMidChannel3D::drawRe(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+9,KEYBOARDY+43,x+15,KEYBOARDY+43);
+ qpaint->drawLine(x+9,KEYBOARDY+44,x+15,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+8,KEYBOARDY+45,x+17,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+16,KEYBOARDY+28,x+16,KEYBOARDY+42);
+}
+void KMidChannel3D::drawRe__(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+15,KEYBOARDY+2,x+15,KEYBOARDY+25);
+ qpaint->drawLine(x+16,KEYBOARDY+25,x+20,KEYBOARDY+25);
+
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+20,KEYBOARDY+1,x+20,KEYBOARDY+27);
+ qpaint->drawPoint(x+19,KEYBOARDY+27);
+}
+void KMidChannel3D::drawMi(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+18,KEYBOARDY+43,x+24,KEYBOARDY+43);
+ qpaint->drawLine(x+18,KEYBOARDY+44,x+24,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+17,KEYBOARDY+45,x+26,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+25,KEYBOARDY+1,x+25,KEYBOARDY+42);
+}
+void KMidChannel3D::drawFa(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+27,KEYBOARDY+43,x+33,KEYBOARDY+43);
+ qpaint->drawLine(x+27,KEYBOARDY+44,x+33,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+26,KEYBOARDY+45,x+35,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+34,KEYBOARDY+28,x+34,KEYBOARDY+42);
+}
+void KMidChannel3D::drawFa__(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+33,KEYBOARDY+2,x+33,KEYBOARDY+25);
+ qpaint->drawLine(x+34,KEYBOARDY+25,x+38,KEYBOARDY+25);
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+38,KEYBOARDY+1,x+38,KEYBOARDY+27);
+ qpaint->drawPoint(x+37,KEYBOARDY+27);
+}
+void KMidChannel3D::drawSol(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+36,KEYBOARDY+43,x+42,KEYBOARDY+43);
+ qpaint->drawLine(x+36,KEYBOARDY+44,x+42,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+35,KEYBOARDY+45,x+44,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+43,KEYBOARDY+28,x+43,KEYBOARDY+42);
+}
+void KMidChannel3D::drawSol__(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+42,KEYBOARDY+2,x+42,KEYBOARDY+25);
+ qpaint->drawLine(x+43,KEYBOARDY+25,x+47,KEYBOARDY+25);
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+47,KEYBOARDY+1,x+47,KEYBOARDY+27);
+ qpaint->drawPoint(x+46,KEYBOARDY+27);
+}
+void KMidChannel3D::drawLa(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+45,KEYBOARDY+43,x+51,KEYBOARDY+43);
+ qpaint->drawLine(x+45,KEYBOARDY+44,x+51,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+44,KEYBOARDY+45,x+53,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+52,KEYBOARDY+28,x+52,KEYBOARDY+42);
+}
+void KMidChannel3D::drawLa__(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+51,KEYBOARDY+2,x+51,KEYBOARDY+25);
+ qpaint->drawLine(x+52,KEYBOARDY+25,x+56,KEYBOARDY+25);
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+56,KEYBOARDY+1,x+56,KEYBOARDY+27);
+ qpaint->drawPoint(x+55,KEYBOARDY+27);
+}
+void KMidChannel3D::drawSi(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+54,KEYBOARDY+43,x+60,KEYBOARDY+43);
+ qpaint->drawLine(x+54,KEYBOARDY+44,x+60,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+53,KEYBOARDY+45,x+62,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+61,KEYBOARDY+1,x+61,KEYBOARDY+42);
+}
diff --git a/kmid/channel3d.h b/kmid/channel3d.h
new file mode 100644
index 00000000..e0bfcc67
--- /dev/null
+++ b/kmid/channel3d.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+
+ channel3d.h - KMidChannel3D widget, a Channel widget with 3D look
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#ifndef KMIDCHANNEL3D_H
+#define KMIDCHANNEL3D_H
+
+#include "channel.h"
+
+class KMidChannel3D : public KMidChannel
+{
+public:
+ KMidChannel3D(int chn,QWidget *parent);
+
+
+ virtual void drawDo (QPainter *qpaint,int x,int p);
+ virtual void drawDo__ (QPainter *qpaint,int x,int p);
+ virtual void drawRe (QPainter *qpaint,int x,int p);
+ virtual void drawRe__ (QPainter *qpaint,int x,int p);
+ virtual void drawMi (QPainter *qpaint,int x,int p);
+ virtual void drawFa (QPainter *qpaint,int x,int p);
+ virtual void drawFa__ (QPainter *qpaint,int x,int p);
+ virtual void drawSol (QPainter *qpaint,int x,int p);
+ virtual void drawSol__(QPainter *qpaint,int x,int p);
+ virtual void drawLa (QPainter *qpaint,int x,int p);
+ virtual void drawLa__ (QPainter *qpaint,int x,int p);
+ virtual void drawSi (QPainter *qpaint,int x,int p);
+
+
+};
+
+#endif
diff --git a/kmid/channel4d.cpp b/kmid/channel4d.cpp
new file mode 100644
index 00000000..a05cc5df
--- /dev/null
+++ b/kmid/channel4d.cpp
@@ -0,0 +1,232 @@
+/**************************************************************************
+
+ channel4d.cpp - KMidChannel4D widget, with 3D look and filled
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#include "channel4d.h"
+#include <qpainter.h>
+
+KMidChannel4D::KMidChannel4D (int chn,QWidget *parent) : KMidChannel(chn,parent)
+{
+ brushR = new QBrush (red);
+ brushW = new QBrush (white);
+ brushB = new QBrush (black);
+ penR = new QPen (red);
+}
+
+
+void KMidChannel4D::drawDo(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penR):(*penB));
+
+ qpaint->drawLine(x,KEYBOARDY+43,x+6,KEYBOARDY+43);
+ qpaint->drawLine(x,KEYBOARDY+44,x+6,KEYBOARDY+44);
+
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x-1,KEYBOARDY+45,x+8,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+7,KEYBOARDY+28,x+7,KEYBOARDY+42);
+
+ qpaint->fillRect(x,KEYBOARDY+28,7,15,((p)?*brushR:*brushW));
+ qpaint->fillRect(x,KEYBOARDY+1,5,27,((p)?*brushR:*brushW));
+ qpaint->setPen(p?(*penR):(*penW));
+ qpaint->drawPoint(x+5,KEYBOARDY+27);
+}
+void KMidChannel4D::drawDo__(QPainter *qpaint,int x,int p)
+{
+ qpaint->fillRect(x+6,KEYBOARDY+1,5,26,((p)?*brushR:*brushB));
+
+ if (!p)
+ {
+ qpaint->setPen(*penW);
+ qpaint->drawLine(x+6,KEYBOARDY+2,x+6,KEYBOARDY+25);
+ qpaint->drawLine(x+7,KEYBOARDY+25,x+11,KEYBOARDY+25);
+ };
+
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+11,KEYBOARDY+1,x+11,KEYBOARDY+27);
+ qpaint->drawPoint(x+10,KEYBOARDY+27);
+
+
+}
+void KMidChannel4D::drawRe(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penR):(*penB));
+ qpaint->drawLine(x+9,KEYBOARDY+43,x+15,KEYBOARDY+43);
+ qpaint->drawLine(x+9,KEYBOARDY+44,x+15,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+8,KEYBOARDY+45,x+17,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+16,KEYBOARDY+28,x+16,KEYBOARDY+42);
+
+ qpaint->fillRect(x+9,KEYBOARDY+28,7,15,((p)?*brushR:*brushW));
+ qpaint->fillRect(x+12,KEYBOARDY+1,2,27,((p)?*brushR:*brushW));
+ qpaint->setPen(p?(*penR):(*penW));
+ qpaint->drawPoint(x+11,KEYBOARDY+27);
+ qpaint->drawPoint(x+14,KEYBOARDY+27);
+
+}
+
+void KMidChannel4D::drawRe__(QPainter *qpaint,int x,int p)
+{
+ qpaint->fillRect(x+15,KEYBOARDY+1,5,26,((p)?*brushR:*brushB));
+
+ if (!p)
+ {
+ qpaint->setPen(*penW);
+ qpaint->drawLine(x+15,KEYBOARDY+2,x+15,KEYBOARDY+25);
+ qpaint->drawLine(x+16,KEYBOARDY+25,x+20,KEYBOARDY+25);
+ };
+
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+20,KEYBOARDY+1,x+20,KEYBOARDY+27);
+ qpaint->drawPoint(x+19,KEYBOARDY+27);
+
+
+}
+void KMidChannel4D::drawMi(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penR):(*penB));
+ qpaint->drawLine(x+18,KEYBOARDY+43,x+24,KEYBOARDY+43);
+ qpaint->drawLine(x+18,KEYBOARDY+44,x+24,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+17,KEYBOARDY+45,x+26,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+25,KEYBOARDY+1,x+25,KEYBOARDY+42);
+
+ qpaint->fillRect(x+18,KEYBOARDY+28,7,15,((p)?*brushR:*brushW));
+ qpaint->fillRect(x+21,KEYBOARDY+1,4,27,((p)?*brushR:*brushW));
+ qpaint->setPen(p?(*penR):(*penW));
+ qpaint->drawPoint(x+20,KEYBOARDY+27);
+
+}
+void KMidChannel4D::drawFa(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penR):(*penB));
+ qpaint->drawLine(x+27,KEYBOARDY+43,x+33,KEYBOARDY+43);
+ qpaint->drawLine(x+27,KEYBOARDY+44,x+33,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+26,KEYBOARDY+45,x+35,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+34,KEYBOARDY+28,x+34,KEYBOARDY+42);
+
+ qpaint->fillRect(x+27,KEYBOARDY+28,7,15,((p)?*brushR:*brushW));
+ qpaint->fillRect(x+27,KEYBOARDY+1,5,27,((p)?*brushR:*brushW));
+ qpaint->setPen(p?(*penR):(*penW));
+ qpaint->drawPoint(x+32,KEYBOARDY+27);
+
+}
+void KMidChannel4D::drawFa__(QPainter *qpaint,int x,int p)
+{
+ qpaint->fillRect(x+33,KEYBOARDY+1,5,26,((p)?*brushR:*brushB));
+ if (!p)
+ {
+ qpaint->setPen(*penW);
+ qpaint->drawLine(x+33,KEYBOARDY+2,x+33,KEYBOARDY+25);
+ qpaint->drawLine(x+34,KEYBOARDY+25,x+38,KEYBOARDY+25);
+ };
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+38,KEYBOARDY+1,x+38,KEYBOARDY+27);
+ qpaint->drawPoint(x+37,KEYBOARDY+27);
+
+}
+
+void KMidChannel4D::drawSol(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penR):(*penB));
+ qpaint->drawLine(x+36,KEYBOARDY+43,x+42,KEYBOARDY+43);
+ qpaint->drawLine(x+36,KEYBOARDY+44,x+42,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+35,KEYBOARDY+45,x+44,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+43,KEYBOARDY+28,x+43,KEYBOARDY+42);
+
+ qpaint->fillRect(x+36,KEYBOARDY+28,7,15,((p)?*brushR:*brushW));
+ qpaint->fillRect(x+39,KEYBOARDY+1,2,27,((p)?*brushR:*brushW));
+ qpaint->setPen(p?(*penR):(*penW));
+ qpaint->drawPoint(x+38,KEYBOARDY+27);
+ qpaint->drawPoint(x+41,KEYBOARDY+27);
+
+}
+
+void KMidChannel4D::drawSol__(QPainter *qpaint,int x,int p)
+{
+ qpaint->fillRect(x+42,KEYBOARDY+1,5,26,((p)?*brushR:*brushB));
+
+ if (!p)
+ {
+ qpaint->setPen(*penW);
+ qpaint->drawLine(x+42,KEYBOARDY+2,x+42,KEYBOARDY+25);
+ qpaint->drawLine(x+43,KEYBOARDY+25,x+47,KEYBOARDY+25);
+ };
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+47,KEYBOARDY+1,x+47,KEYBOARDY+27);
+ qpaint->drawPoint(x+46,KEYBOARDY+27);
+
+
+}
+void KMidChannel4D::drawLa(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penR):(*penB));
+ qpaint->drawLine(x+45,KEYBOARDY+43,x+51,KEYBOARDY+43);
+ qpaint->drawLine(x+45,KEYBOARDY+44,x+51,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+44,KEYBOARDY+45,x+53,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+52,KEYBOARDY+28,x+52,KEYBOARDY+42);
+
+ qpaint->fillRect(x+45,KEYBOARDY+28,7,15,((p)?*brushR:*brushW));
+ qpaint->fillRect(x+48,KEYBOARDY+1,2,27,((p)?*brushR:*brushW));
+ qpaint->setPen(p?(*penR):(*penW));
+ qpaint->drawPoint(x+47,KEYBOARDY+27);
+ qpaint->drawPoint(x+50,KEYBOARDY+27);
+}
+void KMidChannel4D::drawLa__(QPainter *qpaint,int x,int p)
+{
+ qpaint->fillRect(x+51,KEYBOARDY+1,5,26,((p)?*brushR:*brushB));
+
+ if (!p)
+ {
+ qpaint->setPen(*penW);
+ qpaint->drawLine(x+51,KEYBOARDY+2,x+51,KEYBOARDY+25);
+ qpaint->drawLine(x+52,KEYBOARDY+25,x+56,KEYBOARDY+25);
+ };
+ qpaint->setPen(p?(*penW):(*penB));
+ qpaint->drawLine(x+56,KEYBOARDY+1,x+56,KEYBOARDY+27);
+ qpaint->drawPoint(x+55,KEYBOARDY+27);
+
+}
+void KMidChannel4D::drawSi(QPainter *qpaint,int x,int p)
+{
+ qpaint->setPen(p?(*penR):(*penB));
+ qpaint->drawLine(x+54,KEYBOARDY+43,x+60,KEYBOARDY+43);
+ qpaint->drawLine(x+54,KEYBOARDY+44,x+60,KEYBOARDY+44);
+ qpaint->setPen(p?(*penB):(*penT));
+ qpaint->drawLine(x+53,KEYBOARDY+45,x+62,KEYBOARDY+45);
+ qpaint->setPen(p?(*penB):(*penW));
+ qpaint->drawLine(x+61,KEYBOARDY+1,x+61,KEYBOARDY+42);
+
+ qpaint->fillRect(x+54,KEYBOARDY+28,7,15,((p)?*brushR:*brushW));
+ qpaint->fillRect(x+57,KEYBOARDY+1,4,27,((p)?*brushR:*brushW));
+ qpaint->setPen(p?(*penR):(*penW));
+ qpaint->drawPoint(x+56,KEYBOARDY+27);
+}
diff --git a/kmid/channel4d.h b/kmid/channel4d.h
new file mode 100644
index 00000000..b97dc0e1
--- /dev/null
+++ b/kmid/channel4d.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+
+ channel4d.h - KMidChannel4D widget, with 3D look and filled
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#ifndef KMIDCHANNEL4D_H
+#define KMIDCHANNEL4D_H
+
+#include "channel.h"
+
+class KMidChannel4D : public KMidChannel
+{
+private:
+ QBrush *brushR;
+ QBrush *brushW;
+ QBrush *brushB;
+ QPen *penR;
+
+public:
+ KMidChannel4D(int chn,QWidget *parent);
+
+
+ virtual void drawDo (QPainter *qpaint,int x,int p);
+ virtual void drawDo__ (QPainter *qpaint,int x,int p);
+ virtual void drawRe (QPainter *qpaint,int x,int p);
+ virtual void drawRe__ (QPainter *qpaint,int x,int p);
+ virtual void drawMi (QPainter *qpaint,int x,int p);
+ virtual void drawFa (QPainter *qpaint,int x,int p);
+ virtual void drawFa__ (QPainter *qpaint,int x,int p);
+ virtual void drawSol (QPainter *qpaint,int x,int p);
+ virtual void drawSol__(QPainter *qpaint,int x,int p);
+ virtual void drawLa (QPainter *qpaint,int x,int p);
+ virtual void drawLa__ (QPainter *qpaint,int x,int p);
+ virtual void drawSi (QPainter *qpaint,int x,int p);
+
+
+};
+
+#endif
diff --git a/kmid/channelcfgdlg.cpp b/kmid/channelcfgdlg.cpp
new file mode 100644
index 00000000..8ed5ee66
--- /dev/null
+++ b/kmid/channelcfgdlg.cpp
@@ -0,0 +1,39 @@
+#include <qpushbutton.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <kdialogbase.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+
+#include "channelview.h"
+#include "channelcfgdlg.h"
+#include "version.h"
+#include <qlayout.h>
+#include <qvbuttongroup.h>
+
+ChannelViewConfigDialog::ChannelViewConfigDialog(QWidget *parent,const char *name) : KDialogBase(parent,name,TRUE,i18n("Configure Channel View"),Ok|Cancel, Ok)
+{
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+ qbg = new QVButtonGroup(i18n("Choose Look Mode"),page,"qbg");
+
+ rb0=new QRadioButton(i18n("3D look"),qbg,"3d");
+ rb1=new QRadioButton(i18n("3D - filled"),qbg,"4d");
+
+ qbg->setExclusive(TRUE);
+
+ topLayout->addWidget( qbg );
+ ((ChannelView::lookMode()==0)?rb0:rb1)->setChecked(TRUE);
+
+ connect (qbg, SIGNAL(pressed(int)),this,SLOT(modeselected(int)));
+}
+
+void ChannelViewConfigDialog::modeselected(int idx)
+{
+selectedmode=idx;
+}
+
+int ChannelViewConfigDialog::selectedmode;
+#include "channelcfgdlg.moc"
diff --git a/kmid/channelcfgdlg.h b/kmid/channelcfgdlg.h
new file mode 100644
index 00000000..da7b7f82
--- /dev/null
+++ b/kmid/channelcfgdlg.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+
+ channelcfgdlg.h - The channel view config dialog
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _channelcfgdlg_h_
+#define _channelcfgdlg_h_
+
+#include <kdialogbase.h>
+
+class QVButtonGroup;
+class QRadioButton;
+class ChannelViewConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ ChannelViewConfigDialog(QWidget *parent,const char *name);
+
+private:
+ QVButtonGroup *qbg;
+ QRadioButton *rb0;
+ QRadioButton *rb1;
+
+public slots:
+ void modeselected(int idx);
+
+public:
+ static int selectedmode;
+};
+
+#endif
diff --git a/kmid/channelview.cpp b/kmid/channelview.cpp
new file mode 100644
index 00000000..e40857dc
--- /dev/null
+++ b/kmid/channelview.cpp
@@ -0,0 +1,165 @@
+/**************************************************************************
+
+ channelview.cpp - The ChannelView dialog
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#include <kapplication.h>
+#include <klocale.h>
+
+#include "channelview.h"
+#include "channel3d.h"
+#include "channel4d.h"
+#include <kconfig.h>
+
+
+ChannelView::ChannelView(void) : KMainWindow(0, "ChannelView")
+{
+ setCaption(i18n("Channel View"));
+ for (int i=0;i<16;i++)
+ {
+ if (lookMode()==0)
+ Channel[i]=new KMidChannel3D(i+1,this);
+ else
+ Channel[i]=new KMidChannel4D(i+1,this);
+ connect(Channel[i],SIGNAL(signalToKMidClient(int *)),this,SLOT(slottokmidclient(int *)));
+ Channel[i]->setGeometry(5,5+i*CHANNELHEIGHT,width()-20,CHANNELHEIGHT);
+ Channel[i]->show();
+ }
+ scrollbar=new QScrollBar(1,16,1,1,1,QScrollBar::Vertical,this,"Channelscrollbar");
+ connect(scrollbar,SIGNAL(valueChanged(int)),this,SLOT(ScrollChn(int)));
+ setScrollBarRange();
+}
+
+ChannelView::~ChannelView()
+{
+
+}
+
+void ChannelView::closeEvent(QCloseEvent *e)
+{
+ emit destroyMe();
+ e->accept();
+}
+
+void ChannelView::resizeEvent(QResizeEvent *)
+{
+ scrollbar->setGeometry(width()-16,0,16,height());
+ for (int i=0;i<16;i++)
+ {
+ Channel[i]->setGeometry(5,5+(i-(scrollbar->value()-1))*CHANNELHEIGHT,width()-20,CHANNELHEIGHT);
+ }
+ setScrollBarRange();
+
+}
+
+void ChannelView::setScrollBarRange(void)
+{
+ nvisiblechannels=height()/CHANNELHEIGHT;
+ if (nvisiblechannels<16)
+ scrollbar->setRange(1,16-nvisiblechannels+1);
+ else
+ scrollbar->setRange(1,1);
+}
+
+void ChannelView::ScrollChn(int v)
+{
+ for (int i=0;i<16;i++)
+ {
+ Channel[i]->move(5,5+(i-(v-1))*CHANNELHEIGHT);
+ }
+}
+
+void ChannelView::noteOn(int chn,int note)
+{
+ Channel[chn]->noteOn(note);
+}
+
+void ChannelView::noteOff(int chn,int note)
+{
+ Channel[chn]->noteOff(note);
+}
+
+void ChannelView::changeInstrument(int chn,int pgm)
+{
+ Channel[chn]->changeInstrument(pgm);
+}
+
+void ChannelView::changeForceState(int chn,bool i)
+{
+ Channel[chn]->changeForceState(i);
+}
+
+
+void ChannelView::reset(int level)
+{
+ for (int i=0;i<16;i++)
+ {
+ Channel[i]->reset(level);
+ }
+}
+
+int ChannelView::lookmode=0;
+
+int ChannelView::lookMode(void)
+{
+ KConfig *kcfg=(KApplication::kApplication())->config();
+
+ kcfg->setGroup("KMid");
+ lookmode=kcfg->readNumEntry("ChannelViewLookMode",0);
+
+ return lookmode;
+}
+
+void ChannelView::lookMode(int i)
+{
+ KConfig *kcfg=(KApplication::kApplication())->config();
+
+ lookmode=i;
+
+ kcfg->setGroup("KMid");
+ kcfg->writeEntry("ChannelViewLookMode",lookmode);
+
+ bool tmp[128];
+ int pgm;
+ for (int i=0;i<16;i++)
+ {
+ Channel[i]->saveState(tmp,&pgm);
+ delete Channel[i];
+
+ if (lookmode==0)
+ Channel[i]=new KMidChannel3D(i+1,this);
+ else
+ Channel[i]=new KMidChannel4D(i+1,this);
+
+ connect(Channel[i],SIGNAL(signalToKMidClient(int *)),this,SLOT(slottokmidclient(int *)));
+ Channel[i]->setGeometry(5,5+(i-(scrollbar->value()-1))*CHANNELHEIGHT,width()-20,CHANNELHEIGHT);
+ Channel[i]->loadState(tmp,&pgm);
+ Channel[i]->show();
+ }
+
+}
+
+void ChannelView::slottokmidclient(int *data)
+{
+ emit signalToKMidClient(data);
+}
+#include "channelview.moc"
diff --git a/kmid/channelview.h b/kmid/channelview.h
new file mode 100644
index 00000000..9534e73a
--- /dev/null
+++ b/kmid/channelview.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+
+ channelview.h - The ChannelView dialog
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#ifndef CHANNELVIEW_H
+#define CHANNELVIEW_H
+
+#include <kmainwindow.h>
+#include <qscrollbar.h>
+#include "channel.h"
+
+
+class ChannelView : public KMainWindow
+{
+ Q_OBJECT
+private:
+ KMidChannel *Channel[16];
+ int nvisiblechannels;
+
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void closeEvent(QCloseEvent *e);
+
+public:
+ ChannelView(void);
+ virtual ~ChannelView();
+
+ void setScrollBarRange(void);
+
+ void noteOn(int chn,int note);
+ void noteOff(int chn,int note);
+ void changeInstrument(int chn,int pgm);
+ void changeForceState(int chn,bool i);
+
+ void reset(int level=1);
+
+ static int lookMode(void);
+
+ void lookMode(int i);
+
+public slots:
+ void ScrollChn(int i);
+ void slottokmidclient(int *data);
+
+signals:
+ void destroyMe();
+ void signalToKMidClient(int *data);
+
+private:
+ QScrollBar *scrollbar;
+
+
+ static int lookmode;
+
+
+};
+#endif
diff --git a/kmid/collectdlg.cpp b/kmid/collectdlg.cpp
new file mode 100644
index 00000000..fb79667b
--- /dev/null
+++ b/kmid/collectdlg.cpp
@@ -0,0 +1,307 @@
+/**************************************************************************
+
+ collectdlg.cpp - The collections manager dialog
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include <qpushbutton.h>
+#include <qlistbox.h>
+#include <qlabel.h>
+
+#include <kapplication.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+#include "collectdlg.h"
+#include "version.h"
+#include "songlist.h"
+#include "slman.h"
+
+CollectionDialog::CollectionDialog(SLManager *slm,int selC,QWidget *parent,const char *name) : QDialog(parent,name,TRUE)
+{
+setCaption(i18n("Collections Manager"));
+ok=new KPushButton(KStdGuiItem::ok(),this);
+ok->setGeometry(140,200,100,30);
+connect(ok,SIGNAL(clicked()),SLOT(accept()) );
+cancel=new KPushButton(KStdGuiItem::cancel(),this);
+cancel->setGeometry(250,200,100,30);
+connect(cancel,SIGNAL(clicked()),SLOT(reject()) );
+
+label=new QLabel(i18n("Available collections:"),this);
+label->adjustSize();
+label->move(10,10);
+collections=new QListBox(this,"collectionlist");
+collections->setGeometry(10,20+label->height(),340,90);
+connect(collections,SIGNAL(highlighted(int)),SLOT(collectionselected(int)));
+connect(collections,SIGNAL(selected(int)),SLOT(changeCollectionName(int)));
+slman=slm;
+for (int i=0;i<=slman->numberOfCollections();i++)
+ {
+ collections->insertItem(i18n( slman->getCollectionName(i) ),i);
+#ifdef COLLECTDLGDEBUG
+ printf("Name : %s\n",slman->getCollectionName(i));
+#endif
+ };
+selectedC=selC;
+#ifdef COLLECTDLGDEBUG
+printf("selectedC : %d\n",selectedC);
+#endif
+
+label2=new QLabel(i18n("Songs in selected collection:"),this);
+label2->adjustSize();
+label2->move(10,collections->y()+collections->height()+10);
+
+songs=new QListBox(this,"songlist");
+songs->setGeometry(10,label2->y()+label2->height()+10,340,120);
+connect(songs,SIGNAL(highlighted(int)),SLOT(songselected(int)));
+currentsl=slman->getCollection(selectedC);
+if (slman->numberOfCollections()>0)
+ {
+ collections->setCurrentItem(selectedC);
+ collections->centerCurrentItem();
+ };
+//fillInSongList();
+newC=new QPushButton(i18n("&New..."),this);
+newC->adjustSize();
+newC->move(360,collections->y()+5);
+connect(newC,SIGNAL(clicked()),SLOT(newCollection()) );
+copyC=new QPushButton(i18n("&Copy..."),this);
+copyC->adjustSize();
+copyC->move(360,newC->y()+newC->height()+5);
+connect(copyC,SIGNAL(clicked()),SLOT(copyCollection()) );
+deleteC=new QPushButton(i18n("Delete"),this);
+deleteC->adjustSize();
+deleteC->move(360,copyC->y()+copyC->height()+5);
+connect(deleteC,SIGNAL(clicked()),SLOT(deleteCollection()) );
+
+addS=new QPushButton(i18n("&Add..."),this);
+addS->adjustSize();
+addS->move(360,songs->y()+5);
+connect(addS,SIGNAL(clicked()),SLOT(addSong()) );
+delS=new QPushButton(i18n("&Remove"),this);
+delS->adjustSize();
+delS->move(360,addS->y()+addS->height()+5);
+connect(delS,SIGNAL(clicked()),SLOT(removeSong()) );
+
+ok->move(ok->x(),songs->y()+songs->height()+10);
+cancel->move(ok->x()+ok->width()+5,ok->y());
+
+setMinimumSize(400,ok->y()+ok->height()+5);
+//setMaximumSize(360,240);
+}
+
+void CollectionDialog::collectionselected(int idx)
+{
+selectedC=idx;
+#ifdef COLLECTDLGDEBUG
+printf("Selected collection: %d\n",selectedC);
+#endif
+currentsl=slman->getCollection(selectedC);
+fillInSongList();
+}
+
+void CollectionDialog::fillInSongList(void)
+{
+QString qs;
+songs->clear();
+if (currentsl!=NULL)
+ {
+ currentsl->iteratorStart();
+ int i=0;
+ while (!currentsl->iteratorAtEnd())
+ {
+ qs=QString(currentsl->getIteratorName());
+ //KURL::decode(qs);
+ songs->insertItem(qs,i);
+ currentsl->iteratorNext();
+ i++;
+ };
+ songs->setCurrentItem(currentsl->getActiveSongID()-1);
+ songs->centerCurrentItem();
+ };
+}
+
+void CollectionDialog::songselected(int idx)
+{
+selectedS=idx;
+currentsl->setActiveSong(idx+1);
+
+#ifdef COLLECTDLGDEBUG
+printf("Selected song: %d\n",selectedS);
+#endif
+}
+
+void CollectionDialog::newCollection()
+{
+ bool ok;
+ QString name = KInputDialog::getText( i18n( "New Collection" ),
+ i18n( "Enter the name of the new collection:" ), QString::null,
+ &ok, this );
+
+ if (ok)
+ {
+ int i=slman->createCollection(name.ascii());
+ if (i==-1)
+ {
+ QString s = i18n("The name '%1' is already used").arg(name);
+ KMessageBox::sorry(this, s);
+ }
+ else
+ {
+ collections->insertItem(name,i);
+ collections->setCurrentItem(i);
+ collections->centerCurrentItem();
+ };
+ };
+}
+
+void CollectionDialog::copyCollection()
+{
+SongList *src=currentsl;
+int i;
+ bool ok;
+ QString name = KInputDialog::getText( i18n( "Copy Collection" ),
+ i18n( "Enter the name of the copy collection:" ), QString::null,
+ &ok, this );
+
+ if (ok)
+ {
+ i=slman->createCollection(name.ascii());
+ if (i==-1)
+ {
+ QString s = i18n("The name '%1' is already used").arg(name);
+ KMessageBox::sorry(this, s);
+ }
+ else
+ {
+ collections->insertItem(name,i);
+ SongList *tgt=slman->getCollection(i);
+ src->iteratorStart();
+ while (!src->iteratorAtEnd())
+ {
+ tgt->AddSong(src->getIteratorName());
+ src->iteratorNext();
+ };
+ collections->setCurrentItem(i);
+ collections->centerCurrentItem();
+ };
+ };
+}
+
+void CollectionDialog::deleteCollection()
+{
+if (selectedC==0) return;
+slman->deleteCollection(selectedC);
+int i=selectedC;
+collections->removeItem(selectedC);
+collections->setCurrentItem(i);
+collections->centerCurrentItem();
+}
+
+void CollectionDialog::changeCollectionName(int idx)
+{
+if (idx==0) return;
+ bool ok;
+
+ QString name = KInputDialog::getText( i18n( "Change Collection Name" ),
+ i18n( "Enter the name of the selected collection:" ), QString::null,
+ &ok, this );
+
+ if (ok)
+ {
+ if (slman->getCollection(name.ascii())!=NULL)
+ {
+ QString s = i18n("The name '%1' is already used").arg(name);
+ KMessageBox::sorry(this, s);
+ }
+ else
+ {
+ slman->changeCollectionName(idx,name.ascii());
+ collections->changeItem(name,idx);
+ };
+ };
+}
+
+void CollectionDialog::addSong(const KURL &url)
+{
+ if (currentsl==NULL) return;
+ if( url.isEmpty()) return;
+
+ int id=currentsl->AddSong(QFile::encodeName(url.path()));
+
+ if (id==-1)
+ {
+ printf("Couldn't add song to collection\n");
+ return;
+ };
+
+ songs->insertItem(url.fileName(),id-1);
+}
+
+
+void CollectionDialog::addSong()
+{
+ KURL::List urls = KFileDialog::getOpenURLs(":MidiFiles",
+ "*.kar *.mid *.kar.gz *.mid.gz\n*.kar *.kar.gz\n*.mid *.mid.gz\n*",this);
+
+ KURL::List::Iterator it;
+ for( it = urls.begin(); it != urls.end(); ++it )
+ addSong(*it);
+
+}
+
+void CollectionDialog::removeSong()
+{
+if (currentsl==NULL) return;
+currentsl->DelSong(selectedS+1);
+int i=selectedS;
+songs->removeItem(selectedS);
+songs->setCurrentItem(i);
+}
+
+void CollectionDialog::resizeEvent(QResizeEvent *)
+{
+int maxw=newC->width();
+if (copyC->width()>maxw) maxw=copyC->width();
+if (deleteC->width()>maxw) maxw=deleteC->width();
+if (addS->width()>maxw) maxw=addS->width();
+if (delS->width()>maxw) maxw=delS->width();
+
+newC->setGeometry(width()-maxw-5,newC->y(),maxw,newC->height());
+copyC->setGeometry(width()-maxw-5,copyC->y(),maxw,copyC->height());
+deleteC->setGeometry(width()-maxw-5,deleteC->y(),maxw,deleteC->height());
+
+collections->resize(width()-maxw-20,(height()*35)/100);
+label2->move(10,collections->y()+collections->height()+10);
+songs->setGeometry(10,label2->y()+label2->height()+10,width()-maxw-20,height()-(label2->y()+label2->height()+10+ok->height()+10));
+addS->setGeometry(width()-maxw-5,songs->y()+5,maxw,addS->height());
+delS->setGeometry(width()-maxw-5,addS->y()+addS->height()+5,maxw,delS->height());
+
+cancel->move(width()-cancel->width()-5,height()-cancel->height()-5);
+ok->move(cancel->x()-5-ok->width(),height()-ok->height()-5);
+}
+
+int CollectionDialog::selectedC=0;
+int CollectionDialog::selectedS=0;
+#include "collectdlg.moc"
diff --git a/kmid/collectdlg.h b/kmid/collectdlg.h
new file mode 100644
index 00000000..46f96ea4
--- /dev/null
+++ b/kmid/collectdlg.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+
+ collectdlg.h - The collection manager dialog
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _collectdlg_h_
+#define _collectdlg_h_
+
+#include <qdialog.h>
+#include "songlist.h"
+#include "slman.h"
+
+class QLabel;
+class KPushButton;
+class QPushButton;
+class QListBox;
+class KURL;
+class CollectionDialog : public QDialog
+{
+ Q_OBJECT
+private:
+ SLManager *slman;
+ SongList *currentsl;
+
+protected:
+
+ virtual void resizeEvent(QResizeEvent *qre);
+ void fillInSongList(void); //clear the songs list and insert in it
+ // the songs in currentsl
+ void addSong(const KURL &);
+public:
+
+ CollectionDialog(SLManager *slm,int selc,QWidget *parent,const char *name);
+
+public slots:
+ void collectionselected(int idx);
+ void songselected(int idx);
+ void newCollection();
+ void copyCollection();
+ void deleteCollection();
+ void changeCollectionName(int idx);
+ void addSong();
+ void removeSong();
+
+private:
+QLabel *label;
+QLabel *label2;
+KPushButton *ok;
+KPushButton *cancel;
+QListBox *collections;
+QListBox *songs;
+QPushButton *newC;
+QPushButton *copyC;
+QPushButton *deleteC;
+QPushButton *addS;
+QPushButton *delS;
+
+
+public:
+static int selectedC;
+static int selectedS;
+
+};
+
+#endif
diff --git a/kmid/configure.in.in b/kmid/configure.in.in
new file mode 100644
index 00000000..f1e1d100
--- /dev/null
+++ b/kmid/configure.in.in
@@ -0,0 +1,5 @@
+KDE_CHECK_HEADER([libkmid/libkmid.h], [kde_mid_compiles=yes], [kde_mid_compiles=no])
+if test $kde_mid_compiles = no; then
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kmid"
+fi
+
diff --git a/kmid/drums.o3 b/kmid/drums.o3
new file mode 100644
index 00000000..01d9b9c5
--- /dev/null
+++ b/kmid/drums.o3
Binary files differ
diff --git a/kmid/drums.sb b/kmid/drums.sb
new file mode 100644
index 00000000..4bfaf8a3
--- /dev/null
+++ b/kmid/drums.sb
Binary files differ
diff --git a/kmid/examples/DiesIrae.kar b/kmid/examples/DiesIrae.kar
new file mode 100644
index 00000000..c54c6fb6
--- /dev/null
+++ b/kmid/examples/DiesIrae.kar
Binary files differ
diff --git a/kmid/examples/Guantanamera.kar b/kmid/examples/Guantanamera.kar
new file mode 100644
index 00000000..7fee4b1a
--- /dev/null
+++ b/kmid/examples/Guantanamera.kar
Binary files differ
diff --git a/kmid/examples/Makefile.am b/kmid/examples/Makefile.am
new file mode 100644
index 00000000..b53f7c54
--- /dev/null
+++ b/kmid/examples/Makefile.am
@@ -0,0 +1,6 @@
+
+example_DATA = OFortuna.kar DiesIrae.kar Guantanamera.kar \
+ MariaDeLasMercedes.kar
+exampledir = $(kde_datadir)/kmid
+
+EXTRA_DIST = $(example_DATA)
diff --git a/kmid/examples/MariaDeLasMercedes.kar b/kmid/examples/MariaDeLasMercedes.kar
new file mode 100644
index 00000000..7a2e305e
--- /dev/null
+++ b/kmid/examples/MariaDeLasMercedes.kar
Binary files differ
diff --git a/kmid/examples/OFortuna.kar b/kmid/examples/OFortuna.kar
new file mode 100644
index 00000000..cc59960e
--- /dev/null
+++ b/kmid/examples/OFortuna.kar
Binary files differ
diff --git a/kmid/hi16-app-kmid.png b/kmid/hi16-app-kmid.png
new file mode 100644
index 00000000..dcad9f23
--- /dev/null
+++ b/kmid/hi16-app-kmid.png
Binary files differ
diff --git a/kmid/hi32-app-kmid.png b/kmid/hi32-app-kmid.png
new file mode 100644
index 00000000..4538ad78
--- /dev/null
+++ b/kmid/hi32-app-kmid.png
Binary files differ
diff --git a/kmid/hi48-app-kmid.png b/kmid/hi48-app-kmid.png
new file mode 100644
index 00000000..928cebca
--- /dev/null
+++ b/kmid/hi48-app-kmid.png
Binary files differ
diff --git a/kmid/history.txt b/kmid/history.txt
new file mode 100644
index 00000000..c436db0b
--- /dev/null
+++ b/kmid/history.txt
@@ -0,0 +1,567 @@
+Thursday 11-9-97
+- I have started with some tries to make the midi work and due to the
+ success I have even made an object to manage the midi : midiOut
+
+Friday 12-9-97
+- Waking up at 7:00am, working from 8:20 to 11:20 and doing some fixes
+ at 14:20, I have been able to play a midi file through the /dev/sequencer
+ using the class midiOut and writing some new classes like : midfile
+ track and some more.
+
+Saturday 13-9-97
+- Today I have made a midi mapper (object mapper) which read a map config file
+ and is used to support older synths without general midi compliance.
+
+Sunday 14-9-97
+- I have made a window, with a KMenuBar, and a KSilder, which reads a mid file
+ and play it (using a fork)
+
+Monday 15-9-97
+- fork copy the memory and thus, I cannot tell the player to pause, I have read
+ much about the subject, and about threads
+
+Tuesday 16-9-97
+- I have made a small program to test the threads and forks, threads apparently
+are faster, but it seems to have a problem with libqt or anyone, and I get
+core dumpes what I run kmid even if I only link libpthread but don't use it.
+So I've decided to make a fork, in the other way, I've learned to share memory
+
+Wednesday 17-9-97
+- Christian Esken has told me to use mediatool, but I don't have the
+documentation, so I cannot continue work until I get it.
+
+Thursday 18-9-97
+- Well, I'll continue even without the docs, and when I have them, I will
+make the neccesary changes to the code. I have made a few details in windows
+
+Friday 19-9-97
+- Today I have made the Pause and Stop buttons work. Also, I have made the
+slide bar move. And also, I have made a parser of the midi file, which tells
+how long the song is, in seconds. If this was little, I have made the interface
+between the ui and the player.
+
+Saturday 20-9-97
+- The interface between the ui and the player doesn't work well, I have to
+redesign it because it's difficult to be accurate writing the karaoke at the same that the note plays
+
+Sunday 21-9-97
+- I have redesigned twice the interface between ui and player and it still
+doesn't work well, the first method was creating a list of the karaoke events
+and using a timer to process the next event at the right time, but that doesn't
+work perfectly, because the text appears a moment after or before the note is
+played. The second method is a while loop, which calls processEvents, but
+that isn't a very good option, because, though text appears just at the same
+time of the note is played, top tells me that kmid is consuming up to 98% of
+CPU time, and I don't want to make such a monster.
+
+Monday 22-9-97
+- Another failed method, and another passed day
+
+Tuesday 23-9-97
+- Some small changes beautifying the monster to send it to Christian
+
+Wednesday 24-9-97
+- More debugging and no result. I have uploaded current version to arrakis for
+Christian to see it.
+
+Thursday 25-9-97
+- Eureka ! , at last, I have made the player and the ui run at the same time
+with PERFECT syncronisation :-) (at 10:30 pm)
+
+Friday,Saturday,Sunday 26,27,28-9-97
+- I've been looking at the birds flying freely from tree to tree in all this
+weekend, also, I've studied for the test drive.
+
+Monday 29-9-97
+- I have passed the exam and also, I have (almost) done the karaoke widget
+and it works very well !
+
+Tuesday 30-9-97
+- The karaoke widget is finished, it also have a scrollbar to see all the
+lyrics. By the way, StarTrek : First Contact is a very recommended film
+
+Wednesday 1-10-97
+- I have fixed pause and stop, which were broken during the karaoke syncro
+By the way, kmid consumes 0.0% CPU and 00:00 time while playing a 6 minute song
+(and I think that even in longer songs !)
+
+Thursday 2-10-97
+- I have started classes, so I think I will have less time :-(
+
+Wednesday 8-10-97
+- The player now recognizes the SETPOS message, but the ui is not syncronized
+yet
+
+Thursday 9-10-97
+- S. R. has "show"ed me the way to initialize the menu, toolbar and client of a
+KTopLevelWidget, without the need to resize the window.
+
+Sunday 12-10-97
+- I have made that all time variables are expressed in milliseconds, so no
+more change units !!
+
+Sunday 19-10-97
+- I have programmed very little this week, but today I have kill a big bug,
+now all the songs play well. Some songs were played with some parts faster and
+some parts slower than they should (thanks to Christian Esken for reporting
+ the bug!)
+
+Tuesday 21-10-97
+- WOE, KDE-Beta-ONE is even better than before. But now kmid doesn't compile (?)
+
+Wednesday 22-10-97
+- After compiling the kde libs, kmid compiles ok. KSlider has changed and its
+behaviour (Arrrgh!), so I have trickered a little the code.
+
+Thursday 23-10-97
+- I have cleaned a little the code.
+
+Friday 24-10-97
+- I started to "rewrite" the track class to make the slider work well
+
+Saturday 25-10-97
+- I have passed the day working in the time.
+
+Sunday 26-10-97
+- Eureka !!!, KMid works great! with good timings and syncronization between
+ O ~ music and lyrics.
+ U
+ \_/
+
+Monday 27-10-97
+- After 10 hours in the university, I have made the final touches to send
+kmid 0.1 to the internet.
+
+??? 7-11-97
+- Finally, there's an impossible-better syncro between the program
+and the user !!!. I mean, that when you press the pause button, the music
+is inmediatly paused !!!
+
+Saturday 8-11-97
+- So I suppose yesterday was Friday, but I should demostrate it :-)
+I have added drag & drop support in kmid to load files by dropping them from kfm
+Also made the slider show the time played at resizeable steps
+
+Sunday 9-11-97
+- Today I have made possible to change the font and I have made an icon.
+Prepare a version to upload tomorrow to the internet.
+
+Thursday 13-11-97
+- I have nearly rewritten (made lots of changes to) the lyrics display widget
+Also fixed that old "bug" that let in black the last word of a phrase in some
+songs.
+
+Friday 14-11-97
+- Automatic text event chooser is done !
+- Fixed a bug that could freeze kmid under very rare circunstances.
+- Added more support for incomplete/broken files
+
+Saturday 15-11-97
+- I have changed the exit-behaviour for a messagebox-behaviour
+- Fixed a bug that could leave the children running when closing kmid
+
+Sunday 16-11-97
+- KMid adds a mime entry for karaoke files in audio/x-karaoke
+- Real Session Management.
+- Made the first rpm of kmid.
+
+Monday 17-11-97
+- Release version 0.3 in tgz and rpm
+
+Friday 28-11-97
+- I've been quite busy this week, but I have had reports and patches :-) on
+how to make kmid to work with an AWE, a GUS, and in FreeBSD :-))))
+
+Monday 8-12-97
+- I have fixed a small bug with which the time that a song longs was not well
+reported.
+- Also a tiny bug in consolekmid
+
+Tuesday 9-12-97
+- I've made the first feature that I've been asked for. Another thing to map
+with the midi mapper for Dietmar's PSR500
+
+Friday 12-12-97
+- Nearly done the map chooser so that there will no be needed to edit the kmidrc
+for anything.
+Now when you choose a new map or change GM/MT32 mode, the music is automatically
+changed while playing !.
+
+...... **-12-97
+- I have been the rest of the month implementing a midi server that I will
+call KMidServer and that will provide any application with easy control over
+midi functions.
+
+30-12-97
+- KMid now can play gzipped midi files just as any other normal file.
+
+.... **-1-98
+- I have improved the midi mapper by allowing to factor the pitch bender.
+ Now pitch benders works OK !! (at last I have improved the windows mapper :-)
+ I have also added support to convert expression events to volume events.
+* I have been doing the kfourier this month and studying (little time to do more)
+
+
+Thursday 5-2-98
+- After doing my first exam this year, I have decided to calm things a little
+ by programming something. I have made the options added to the mapper available
+through the config map file.
+
+Monday 9-2-98
+- 2nd exam done and a bug that I introduced last thrusday fixed.
+
+Friday 20-2-98
+- I've finished exams, have installed the yesterday snapshots and have
+updated the configure scripts to add rpath and all that stuff to my copy
+of kmid (thanks to Kulow, who added it to kmid in kdemultimedia)
+
+Saturday 21-2-98
+- Fixed the not-a-feature problem with FM, next time I will not let the
+option for the user to select something that doesn't work.
+Final touches to release kmid 0.41 tomorrow morning.
+
+Monday 23-2-98
+- I've started working on FM support (and it goes very fast)
+
+Tuesday 24-2-98
+- fm already works, but notes are shifted to a higher key !!!
+Also pitch bender seems not to be accurate.
+
+Wednesday 25-2-98
+- pitch bender is now fixed, and also the shift of notes, now the problem
+ is that some notes are lost (always from the same track/channel/patch?!?!)
+
+Friday 27-2-98
+- The problem with the lost notes is fixed :-/, the problem was that some
+notes are played through the left speaker and some thru the right speaker,
+and my wires for the right speaker were broken, but it wasn't noted with
+the surround activated :-))))))) (Sometimes I feel real shame). Three days
+lost in that !!
+
+Saturday 28-2-98
+- I've gone to the country and I've done the internals of the playlists in a
+486/50 without linux, so I'll compile the Monday.
+
+Sunday 1-3-98
+- Some test with multiple toolbars.
+
+Monday 2-3-98
+- Started to do the collections manager dialog
+
+Tuesday 3-3-98
+- The collections manager dialog is done.
+
+Wednesday 4-3-98
+- KKeyConfig is a really good class, easy to use to make the karaoke scroll
+when arrow keys are pressed.
+
+Thursday 5-3-98
+- I've done the playlist hardest part, now it works and there's only left
+ some final touches to do
+
+Tuesday 10-3-98
+- Playlists are finally working ok.
+
+Wednesday 11-3-98
+- Fixed the session management (in fact, I've changed it a little to support
+collections)
+
+Thursday 12-3-98
+- Fixed some small bugs.
+
+Friday 13-3-98
+- I have replaced my new Makefiles.am (just two days old) with the one
+of Stephan Kulow which look much better.
+
+Saturday 14-3-98
+- Finished deleting printf's to upload kmid tomorrow :-)
+
+Sunday 15-3-98
+- Upload it, but as I forgot to delete some printf messages :-( , I had
+to quickly do a fix and send also 0.5.1
+
+**** **-3-98
+- I've passed many days configuring the modem, the internet connection,
+sendmail, kppp, cvs and all those programs :-)
+
+Monday 30-3-98
+- I've implemented the save-Lyrics feature that Adrian Knoth suggested (thanks!)
+
+Tuesday 31-3-98
+- I've done some changes to support the new KFileDialog and the new
+changes in kdelibs done by Matthias.
+
+Thursday 2-4-98
+- Some bug fixes
+
+Monday 6-4-98
+- I've found and fixed a memory leakage bug, I forgot to delete the
+SpecialEvents from each song, so kmid was using more and more memory with
+each opened song.
+
+Tuesday 7-4-98
+- Aaaargh !, I have to remove the changes that I did last tuesday because it
+seems that the changes in the kdelibs have been removed.
+
+Monday 13-4-98
+- Added support for midi files with strange headers not related to midi files.
+ (suggested by Adrian Knoth, thanks !)
+
+Friday 24-4-98
+- At last, I have had some free time and have done some things:
+ 1. Finally fixed the synchronization between gui and player (hopefully forever)
+ 2. Fixed a problem openning a gzipped file with spaces in its name
+ 3. Fixed a bug which caused kmid to freeze if collection has only 1 song, and
+ trying to play next song in aleatory mode.
+ 4. Fixed the problem which made some songs to play at a lower volume when
+ moving the slider, but no if playing from the beginning
+ That's all for now :-) , there have been so many changes that I've call
+ this version 0.5.3
+
+Thursday 7-5-98
+- Released version 0.6 to update my homepage which was getting very outdated
+
+Saturday 9-5-98
+- After fixing my midi cable, I've noticed that fm is (as Gyula Kerekes
+ reported), playing in mono, and I've fixed it.
+
+Sunday 10-5-98
+- I've fixed a small bug with which midi files without text events (nor lyrics)
+got the time slider very desynchronized after pausing for a long time.
+
+Monday 25-5-98
+- Applied a patch submitted by Kevin Street, to compile kmid on FreeBSD 3.0
+systems with awe support (directory settings has changed since 2.2)
+
+Saturday 20-6-98
+- I'm on exams, but just to relax a few minutes I've been hunting for bugs :-)
+
+Sunday 21-6-98
+- Wow, KDE-1.0 is finally here, and it is REAL, so I will prepare very quickly
+KMid 1.0 before the freeze of kdemultimedia.
+
+Saturday 4-7-98
+- Just finished exams :-), and I've implemented the (long awaited feature of a)
+volume bar.
+
+Sunday 5-7-98
+- I'm doing a channel view in which you can see the keys being pressed
+and released, it's very nice :-)
+
+Monday 6-7-98
+- Using the (still hot) shutDown signal (the most awaited thing for
+kmid)
+
+Monday 13-7-98
+- I've restructured the Channel view, it's much nicer and allows for easier
+expansion. It also shows the used instrument
+
+Saturday 15-8-98
+- Wow, I haven't updated this file for so long ...
+ I've finished the changing instrument feature and so the channel view.
+ I've also improved speed a little by supressing some parses to the midi file.
+ I have improved consolekmid, now it is much more usuable.
+ Finally, I've changed the sources to use the KAccel class.
+
+Monday 31-8-98
+- I've fixed some bugs, the most important one being that kmid left its player
+ processes as zombies after stopping playing (it worked ok, but now it doesn't,
+ dunno why). That problem made to appear some weird dialogs telling "song is already
+ playing" at each moment
+- I left a color hardcoded in button*.xpm when it should be Transparent (not
+ everybody has a window background color of #5D5D8F8FA0A0 :-) )
+- I created a Motif 1.0 combo box in the channelview, but it should be Motif 2.0
+ because 1.0 has a "feature" for large como boxes (as this one)
+
+
+Wednesday 9-9-98
+- Fixed the last bug for leaving zombies around.
+
+Monday 14-9-98
+- Released Version 1.2
+
+Tuesday 15-9-98
+- Added the change tempo widget and the KTriangleButton widget
+
+Wednesday 16-9-98
+- It's possible now to change the tempo of a song.
+
+Thursday 1-10-98
+- Fixed some problems
+
+Thursday 15-10-98
+- FIXED !!!
+ The long awaited fix has arrived for songs keeping playing after X11' logout
+ when channelview was actived.
+ Now also the ChannelView change its colors when the user change the
+ global colors, kdisptext paints a frame over the karaoke text,
+ KLCDNumber only accepts a range of values (from 3 to 999)
+
+Friday 16-10-98
+- Improved support for really broken files.
+- Added some translations to Spanish
+
+Friday 23-10-98
+- I've started writing the internals of a rhythm view
+
+Saturday 24-10-98
+- Now KMid shows a new widget to make easier follow the rhythm of songs.
+ I've also fixed a small bug by which the tempo (and rhythm) changed its
+ state before the event actually happening if you moved the timebar near
+ before the event time. The problem was caused by volatile shared variables.
+
+Sunday 25-10-98
+- Fixed a serious bug I introduced in the previous commitment
+
+Monday 2-11-98
+- Fixed some problems
+
+Sunday 8-11-98
+- Some small changes
+
+Wednesday 25-11-98
+- I've finally fixed the bug that made kmid play music sometimes
+faster and sometimes slower on some machines (i.e. mine, since I installed
+kernel 2.0.36)
+This bug was there since the real beginning, and now, it is FIXED.
+This deserves a new 2.0 version, probably next week.
+
+Friday 27-11-98
+- Fixed a broken link in the .kdelnk file (DocPath) and raised version
+number to 1.6
+
+Thursday 10-12-98
+- Added new sgml documentation, updated up to KMid 1.6
+
+Friday 11-12-98
+- Fixed a shared memory leackage bug (hopefully the last bug in KMid :) ).
+
+Thursday 17-12-98
+- Initial support for SoftOSS (this is making some sound now :))
+- Indentified the player directory sources and beautified them a little
+
+Friday 18-12-98
+- Fixed a geometry layout bug
+
+Sunday 20-12-98
+- Fixed a problem when [un]installing midi devices (not such a mad idea if you
+use kernel modules) that made kmid segfault because it couldn't found
+the device.
+
+Saturday 16-1-99
+- Decode URL before showing it on the screen.
+
+Thursday 21-1-99
+- Fixed a null pointer access while generating beats, because I didn't
+checked for songs which didn't contain any spev (songs which use absolute 0 spev
+are extremely rare to find, as any song must include at least a tempo event)
+
+Tuesday 26-1-99
+- Removed ; after QOBJECT and fixed default midi map in consolekmid (not kmid)
+
+Sunday 21-2-99
+- Made a quick hack (no more than 15 lines) and kmid uses KIOJob to be
+net transparent (now it can download files using an http or ftp protocol just
+using dnd from a kfm window or using the open file dialog)
+
+Saturday 6-3-99
+- The sound driver in Linux kernels from the 2.2.x series work very different
+than the ones in 2.0.x so kmid was severely damaged. After several days of
+hacking (and after getting from A.Cox that this wasn't going to be fixed in the
+kernel) I've found a fix that even works in the 2.0.x kernels.
+
+Sunday 21-3-99
+- Fixed the high pitch of AWE cards (thanks to Joseph H. Buehler and Takashi Iwai for
+ the indications)
+- Raised version number to 1.7
+
+Friday 2-4-99
+- Did a workaround for a bug in egcs which doesn't seem to optimize simple
+return-a-value function as an inline function when using -O2 and it made kmid
+freeze under certain conditions when parsing some midi files.
+
+- Removed a comparison of double variables which is very dangerous (_even_ after
+storing in one of them the value of the other one)
+- Fixed a problem by which kmid didn't play the last half second or so of some songs.
+
+Thursday 8-4-99
+- Fixed a problem that made Kmid consume 99% of CPU since a month ago. Now it's back
+to the usual 0.00% of CPU use :-)
+
+Monday 12-4-99
+- Fixed a bug that made KMid freeze when trying to open a directory
+
+Thursday 15-4-99
+- Better support for broken karaoke files which has duplicated lyrics
+
+Thursday 11-11-99
+- Fixed a problem with corrupt files that suddenly doesn't work (but KMid
+ from the 1.1 branch works ok (?) ). Anyway, I've got it to work even
+ better with broken files
+- Fixed the KLed usage, which was broken since the KLedLamp -> KLed transition.
+- Fixed a repaint bug with the time tags that has been here for too long.
+
+Friday 12-11-99
+- Instead of using manual layout, let's use QLayouts (there are still some
+ problems with this )
+- Added xdnd support (finally !)
+
+Thursday 25-11-99
+- Changed a lot of code to look much better
+- Fixed many problems when painting lyrics in different colors
+
+Friday 26-11-99
+- The lyrics display doesn't flicker anymore (finally :-) )
+- Reworked the scrolling code, it's smooth now instead of line-by-line (but also
+ makes consumes a bit of CPU, so I'll make it configurable for people who don't
+ want to waste resources)
+- note: don't call resizeContents from drawContents, or you'll have some
+ problems (QScrollView bug ?, anyway, this note should be on the docs)
+
+Tuesday 11-1-2000
+- SoftOSS is working now !
+- Added LOTS of documentation to the MIDI library. Anyway, there's a lot more
+to come.
+- Also fixed a few problems in the lyrics display, and added a new option
+to consolekmid
+
+Sunday 27-2-2000
+- Ported KMid to use the "official" LibKMid and KXMLGUI, with the following
+ result :
+ # wc kmidframe.cpp
+ Before: 769 1450 24820 kmidframe.cpp
+ After : 622 1171 19045 kmidframe.cpp
+
+Monday 28-2-2000
+- Added ALSA support to libkmid
+
+Tuesday 29-2-2000
+- I'm making KMid a part
+
+It took me : exactly 13 minutes to port the app
+ 30 seconds to do /LD/LIB/ in Makefile.am
+ 5:14 to compile it and see that kbrowser.h doesn't exist now :(
+
+Sunday 5-3-2000
+- Now libkmid does build and run on systems where OSS is not installed.
+- Updated the code to simplify it a bit due to libkmid changes.
+- I still have to search for a bug that makes KMid (and the part!) to crash
+ when destroying KDisplayText (the curious thing is that it crashes on
+ QScrollView)
+
+Sunday 2-4-2000
+- Now Libkmid links with kdecore and qt in order to use a KConfig object to
+read the default settings as saved by the user with the midi kcontrol module.
+- It creates a "dummy" KInstance in case of the application being a non-KDE
+application.
+- Fixed compilation of KMid, as 1) someone renamed klinedit.h to klineedit.h
+and 2) now we have to include qiconset.h when creating an action with pictures
+as in kmid_part.cpp
+- Now I just have to find why KMid doesn't show any interface except the
+standard actions
+
+Saturday 30-9-2000
+- Hmm, it's been a long time since I don't update this file. In summer
+ I've fixed ALSA support and many related bugs.
+- Today, I've finally added the accelerators.
+- Raised version to 2.0
diff --git a/kmid/instrfilter.awk b/kmid/instrfilter.awk
new file mode 100644
index 00000000..078169aa
--- /dev/null
+++ b/kmid/instrfilter.awk
@@ -0,0 +1,2 @@
+{ match ($0,"\".*\"") }
+{ if (RSTART>0) print "i18n("substr($0,RSTART,RLENGTH)");" };
diff --git a/kmid/instrname.cpp b/kmid/instrname.cpp
new file mode 100644
index 00000000..551b85c9
--- /dev/null
+++ b/kmid/instrname.cpp
@@ -0,0 +1,132 @@
+const char *instrumentName[128]={
+ "Acoustic Grand Piano",
+ "Bright Acoustic Piano",
+ "Electric Grand Piano",
+ "Honky-Tonk",
+ "Rhodes Piano",
+ "Chorused Piano",
+ "Harpsichord",
+ "Clavinet",
+ "Celesta",
+ "Glockenspiel",
+ "Music Box",
+ "Vibraphone",
+ "Marimba",
+ "Xylophone",
+ "Tubular Bells",
+ "Dulcimer",
+ "Hammond Organ",
+ "Percussive Organ",
+ "Rock Organ",
+ "Church Organ",
+ "Reed Organ",
+ "Accordion",
+ "Harmonica",
+ "Tango Accordion",
+ "Acoustic Guitar (Nylon)",
+ "Acoustic Guitar (Steel)",
+ "Electric Guitar (Jazz)",
+ "Electric Guitar (Clean)",
+ "Electric Guitar (Muted)",
+ "Overdriven Guitar",
+ "Distortion Guitar",
+ "Guitar Harmonics",
+ "Acoustic Bass",
+ "Electric Bass (Finger)",
+ "Electric Bass (Pick)",
+ "Fretless Bass",
+ "Slap Bass 1",
+ "Slap Bass 2",
+ "Synth Bass 1",
+ "Synth Bass 2",
+ "Violin",
+ "Viola",
+ "Cello",
+ "Contrabass",
+ "Tremolo Strings",
+ "Pizzicato Strings",
+ "Orchestral Harp",
+ "Timpani",
+ "String Ensemble 1",
+ "String Ensemble 2",
+ "Synth Strings 1",
+ "Synth Strings 2",
+ "Choir Aahs",
+ "Voice Oohs",
+ "Synth Voice",
+ "Orchestra Hit",
+ "Trumpet",
+ "Trombone",
+ "Tuba",
+ "Muted Trumpet",
+ "French Horn",
+ "Brass Section",
+ "Synth Brass 1",
+ "Synth Brass 2",
+ "Soprano Sax",
+ "Alto Sax",
+ "Tenor Sax",
+ "Baritone Sax",
+ "Oboe",
+ "English Horn",
+ "Bassoon",
+ "Clarinet",
+ "Piccolo",
+ "Flute",
+ "Recorder",
+ "Pan Flute",
+ "Blown Bottle",
+ "Shakuhachi",
+ "Whistle",
+ "Ocarina",
+ "Lead 1 - Square Wave",
+ "Lead 2 - Saw Tooth",
+ "Lead 3 - Calliope",
+ "Lead 4 - Chiflead",
+ "Lead 5 - Charang",
+ "Lead 6 - Voice",
+ "Lead 7 - Fifths",
+ "Lead 8 - Bass+Lead",
+ "Pad 1 - New Age",
+ "Pad 2 - Warm",
+ "Pad 3 - Polysynth",
+ "Pad 4 - Choir",
+ "Pad 5 - Bow",
+ "Pad 6 - Metallic",
+ "Pad 7 - Halo",
+ "Pad 8 - Sweep",
+ "FX 1 - Rain",
+ "FX 2 - Soundtrack",
+ "FX 3 - Crystal",
+ "FX 4 - Atmosphere",
+ "FX 5 - Brightness",
+ "FX 6 - Goblins",
+ "FX 7 - Echoes",
+ "FX 8 - Sci-fi",
+ "Sitar",
+ "Banjo",
+ "Shamisen",
+ "Koto",
+ "Kalimba",
+ "Bagpipe",
+ "Fiddle",
+ "Shannai",
+ "Tinkle Bell",
+ "Agogo",
+ "Steel Drum",
+ "Wook Block",
+ "Taiko Drum",
+ "Melodic Tom",
+ "Synth Drum",
+ "Reverse Cymbal",
+ "Guitar Fret Noise",
+ "Breath Noise",
+ "Seashore",
+ "Bird Tweet",
+ "Telephone",
+ "Helicopter",
+ "Applause",
+ "Gunshot"
+};
+
+
diff --git a/kmid/instrname.h b/kmid/instrname.h
new file mode 100644
index 00000000..80e199c4
--- /dev/null
+++ b/kmid/instrname.h
@@ -0,0 +1,6 @@
+#ifndef _INSTRNAME_H
+#define _INSTRNAME_H
+
+extern const char *instrumentName[128];
+
+#endif
diff --git a/kmid/instrname.i18n b/kmid/instrname.i18n
new file mode 100644
index 00000000..08ec0938
--- /dev/null
+++ b/kmid/instrname.i18n
@@ -0,0 +1,133 @@
+/* This is an automatically generated file
+ * DO NOT EDIT !!!
+ * To create this file run : make instrname.i18n
+ */
+
+i18n("Acoustic Grand Piano");
+i18n("Bright Acoustic Piano");
+i18n("Electric Grand Piano");
+i18n("Honky-Tonk");
+i18n("Rhodes Piano");
+i18n("Chorused Piano");
+i18n("Harpsichord");
+i18n("Clavinet");
+i18n("Celesta");
+i18n("Glockenspiel");
+i18n("Music Box");
+i18n("Vibraphone");
+i18n("Marimba");
+i18n("Xylophone");
+i18n("Tubular Bells");
+i18n("Dulcimer");
+i18n("Hammond Organ");
+i18n("Percussive Organ");
+i18n("Rock Organ");
+i18n("Church Organ");
+i18n("Reed Organ");
+i18n("Accordion");
+i18n("Harmonica");
+i18n("Tango Accordion");
+i18n("Acoustic Guitar (Nylon)");
+i18n("Acoustic Guitar (Steel)");
+i18n("Electric Guitar (Jazz)");
+i18n("Electric Guitar (Clean)");
+i18n("Electric Guitar (Muted)");
+i18n("Overdriven Guitar");
+i18n("Distortion Guitar");
+i18n("Guitar Harmonics");
+i18n("Acoustic Bass");
+i18n("Electric Bass (Finger)");
+i18n("Electric Bass (Pick)");
+i18n("Fretless Bass");
+i18n("Slap Bass 1");
+i18n("Slap Bass 2");
+i18n("Synth Bass 1");
+i18n("Synth Bass 2");
+i18n("Violin");
+i18n("Viola");
+i18n("Cello");
+i18n("Contrabass");
+i18n("Tremolo Strings");
+i18n("Pizzicato Strings");
+i18n("Orchestral Harp");
+i18n("Timpani");
+i18n("String Ensemble 1");
+i18n("String Ensemble 2");
+i18n("Synth Strings 1");
+i18n("Synth Strings 2");
+i18n("Choir Aahs");
+i18n("Voice Oohs");
+i18n("Synth Voice");
+i18n("Orchestra Hit");
+i18n("Trumpet");
+i18n("Trombone");
+i18n("Tuba");
+i18n("Muted Trumpet");
+i18n("French Horn");
+i18n("Brass Section");
+i18n("Synth Brass 1");
+i18n("Synth Brass 2");
+i18n("Soprano Sax");
+i18n("Alto Sax");
+i18n("Tenor Sax");
+i18n("Baritone Sax");
+i18n("Oboe");
+i18n("English Horn");
+i18n("Bassoon");
+i18n("Clarinet");
+i18n("Piccolo");
+i18n("Flute");
+i18n("Recorder");
+i18n("Pan Flute");
+i18n("Blown Bottle");
+i18n("Shakuhachi");
+i18n("Whistle");
+i18n("Ocarina");
+i18n("Lead 1 - Square Wave");
+i18n("Lead 2 - Saw Tooth");
+i18n("Lead 3 - Calliope");
+i18n("Lead 4 - Chiflead");
+i18n("Lead 5 - Charang");
+i18n("Lead 6 - Voice");
+i18n("Lead 7 - Fifths");
+i18n("Lead 8 - Bass+Lead");
+i18n("Pad 1 - New Age");
+i18n("Pad 2 - Warm");
+i18n("Pad 3 - Polysynth");
+i18n("Pad 4 - Choir");
+i18n("Pad 5 - Bow");
+i18n("Pad 6 - Metallic");
+i18n("Pad 7 - Halo");
+i18n("Pad 8 - Sweep");
+i18n("FX 1 - Rain");
+i18n("FX 2 - Soundtrack");
+i18n("FX 3 - Crystal");
+i18n("FX 4 - Atmosphere");
+i18n("FX 5 - Brightness");
+i18n("FX 6 - Goblins");
+i18n("FX 7 - Echoes");
+i18n("FX 8 - Sci-fi");
+i18n("Sitar");
+i18n("Banjo");
+i18n("Shamisen");
+i18n("Koto");
+i18n("Kalimba");
+i18n("Bagpipe");
+i18n("Fiddle");
+i18n("Shannai");
+i18n("Tinkle Bell");
+i18n("Agogo");
+i18n("Steel Drum");
+i18n("Wook Block");
+i18n("Taiko Drum");
+i18n("Melodic Tom");
+i18n("Synth Drum");
+i18n("Reverse Cymbal");
+i18n("Guitar Fret Noise");
+i18n("Breath Noise");
+i18n("Seashore");
+i18n("Bird Tweet");
+i18n("Telephone");
+i18n("Helicopter");
+i18n("Applause");
+i18n("Gunshot");
diff --git a/kmid/kdisptext.cpp b/kmid/kdisptext.cpp
new file mode 100644
index 00000000..c871e55a
--- /dev/null
+++ b/kmid/kdisptext.cpp
@@ -0,0 +1,640 @@
+/**************************************************************************
+
+ kdisptext.cpp - The widget that displays the karaoke/lyrics text
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include "kdisptext.h"
+#include <qpainter.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qrect.h>
+#include <qtextcodec.h>
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kinstance.h>
+#include <klocale.h>
+#include "version.h"
+
+
+#define NUMPREVLINES 2
+//#define DRAW_BOUNDING_RECTS
+
+
+KDisplayText::KDisplayText(QWidget *parent,const char *name) : QScrollView(parent,name)
+{
+ first_line_[0]=first_line_[1]=NULL;
+ linked_list_[0]=linked_list_[1]=NULL;
+ cursor_line_[0]=cursor_line_[1]=NULL;
+ cursor_[0]=cursor_[1]=NULL;
+ nlines_[0]=nlines_[1]=0;
+ linked_list=NULL;
+ cursor_line=NULL;
+ first_line=NULL;
+ cursor=NULL;
+ nlines=0;
+ lyrics_codec=KGlobal::locale()->codecForEncoding();
+
+ viewport()->setBackgroundColor(QColor (110,110,110));
+// setBackgroundMode(NoBackground);
+ KConfig *kcfg=KGlobal::instance()->config();
+ kcfg->setGroup("KMid");
+ typeoftextevents=kcfg->readNumEntry("TypeOfTextEvents",1);
+ QFont *qtextfontdefault=new QFont(KGlobalSettings::fixedFont().family(),22);
+ qtextfont=new QFont(kcfg->readFontEntry("KaraokeFont",qtextfontdefault));
+ delete qtextfontdefault;
+ qfmetr=new QFontMetrics(*qtextfont);
+ nvisiblelines=height()/qfmetr->lineSpacing();
+ autoscrollv=0;
+}
+
+KDisplayText::~KDisplayText()
+{
+ RemoveLinkedList();
+}
+
+/*void KDisplayText::PreDestroyer(void)
+{
+ delete qfmetr;
+ delete qtextfont;
+}
+*/
+
+void KDisplayText::RemoveLine(kdispt_line *tmpl)
+{
+ kdispt_ev *tmpe;
+ while (tmpl->ev!=NULL)
+ {
+ tmpe=tmpl->ev;
+ tmpl->ev=tmpe->next;
+ // delete tmpe->spev; Remember that the Special Events that this pointer
+ // points to is the same that the Player object has instantiated
+ delete tmpe;
+ }
+}
+
+void KDisplayText::RemoveLinkedList(void)
+{
+ cursor=NULL;
+ cursor_line=NULL;
+ first_line=NULL;
+ linked_list=NULL;
+ nlines=0;
+ nlines_[0]=nlines_[1]=0;
+ first_line_[0]=first_line_[1]=NULL;
+ cursor_line_[0]=cursor_line_[1]=NULL;
+ cursor_[0]=cursor_[1]=NULL;
+
+ kdispt_line *tmpl;
+ for (int i=0;i<2;i++)
+ {
+ while (linked_list_[i]!=NULL)
+ {
+ RemoveLine(linked_list_[i]);
+ tmpl=linked_list_[i];
+ linked_list_[i]=linked_list_[i]->next;
+ delete tmpl;
+ }
+ }
+}
+
+void KDisplayText::ClearEv(bool totally)
+{
+ RemoveLinkedList();
+ if (totally)
+ {
+ killTimers();
+ autoscrollv=0;
+ resizeContents(0,0);
+ viewport()->repaint(TRUE);
+ }
+}
+
+int KDisplayText::IsLineFeed(char c,int type)
+{
+ switch (type)
+ {
+ case (1) : if (/*(c==0)||*/(c=='\\')||(c=='/')||(c=='@')) return 1;break;
+ case (5) : if (/*(c==0)||*/(c==10)||(c==13)) return 1;break;
+ default : if ((c==0)||(c==10)||(c==13)||(c=='\\')||(c=='/')||(c=='@')) return 1;break;
+ }
+ return 0;
+}
+
+void KDisplayText::AddEv(SpecialEvent *ev)
+{
+ if ((ev->type==1) || (ev->type==5))
+ {
+ int idx=(ev->type==1)? 0 : 1;
+ if (linked_list_[idx]==NULL)
+ {
+ linked_list_[idx]=new kdispt_line;
+ linked_list_[idx]->next=NULL;
+ linked_list_[idx]->num=1;
+ linked_list_[idx]->ev=new kdispt_ev;
+ cursor_line_[idx]=linked_list_[idx];
+ cursor_[idx]=cursor_line_[idx]->ev;
+ cursor_[idx]->spev=ev;
+ cursor_[idx]->next=NULL;
+ first_line_[idx]=linked_list_[idx];
+ first_line=first_line_[idx];
+ nlines_[idx]=1;
+ }
+ else
+ {
+ if (IsLineFeed(ev->text[0],ev->type))
+ {
+ nlines_[idx]++;
+ cursor_line_[idx]->next=new kdispt_line;
+ cursor_line_[idx]=cursor_line_[idx]->next;
+ cursor_line_[idx]->num=nlines_[idx];
+ cursor_line_[idx]->ev=new kdispt_ev;
+ cursor_line_[idx]->next=NULL;
+ cursor_[idx]=cursor_line_[idx]->ev;
+ }
+ else
+ {
+ cursor_[idx]->next=new kdispt_ev;
+ cursor_[idx]=cursor_[idx]->next;
+ }
+ cursor_[idx]->spev=ev;
+ cursor_[idx]->next=NULL;
+ }
+ }
+}
+
+void KDisplayText::calculatePositions(void)
+{
+ int typeoftextevents=1;
+ int fin=0;
+ kdispt_line *tmpl;
+ kdispt_ev *tmp;
+ int tmpx=0;
+ int tmpy=0;
+ int tmpw=0;
+ int maxx=0;
+ nlines=nlines_[(typeoftextevents==1)? 0:1];
+ int lineSpacing=qfmetr->lineSpacing();
+ int descent=qfmetr->descent();
+ while (!fin)
+ {
+ tmpl=linked_list_[(typeoftextevents==1)?0:1];
+ tmpy=lineSpacing;
+ maxx=0;
+ while (tmpl!=NULL)
+ {
+ tmp=tmpl->ev;
+ tmpx=5;
+ while (tmp!=NULL)
+ {
+ if (tmp->spev->type==typeoftextevents)
+ {
+ if (IsLineFeed(tmp->spev->text[0],typeoftextevents))
+ {
+ tmpy+=lineSpacing;
+ tmpx=5;
+
+ tmp->xpos=tmpx;
+ if (tmp->spev->text[0]!=0) tmpw=qfmetr->width(lyrics_codec->toUnicode(&tmp->spev->text[1]));
+ else tmpw=0;
+ tmp->r=qfmetr->boundingRect(lyrics_codec->toUnicode(&tmp->spev->text[1]));
+ }
+ else
+ {
+ tmp->xpos=tmpx;
+ tmpw=qfmetr->width(lyrics_codec->toUnicode(tmp->spev->text));
+ tmp->r=qfmetr->boundingRect(lyrics_codec->toUnicode(tmp->spev->text));
+ }
+ // We add 5 pixels above, below and to the right because of a
+ // problem with latest released Xft
+ tmp->r.moveBy(tmpx,tmpy-tmp->r.height()-tmp->r.y()-5);
+ tmp->r.setHeight(tmp->r.height()+descent+10);
+ tmp->r.setWidth(tmp->r.width()+5);
+ tmpx+=tmpw;
+ if (tmpx>maxx) maxx=tmpx;
+ }
+ tmp=tmp->next;
+ }
+ tmpl->ypos=tmpl->num*lineSpacing;
+ tmpy=tmpl->ypos;
+ tmpl=tmpl->next;
+ }
+ maxX[(typeoftextevents==1)?0:1]=maxx+10;
+ maxY[(typeoftextevents==1)?0:1]=
+ nlines_[(typeoftextevents==1)?0:1]*lineSpacing+descent+10;
+
+ if (typeoftextevents==1) typeoftextevents=5;
+ else fin=1;
+ }
+
+}
+
+kdispt_line *KDisplayText::searchYOffset(int y, kdispt_line *start)
+{
+kdispt_line *t=start;
+while (t!=NULL)
+ {
+// if (t->ypos+qfmetr->descent()>y) return start;
+ if (t->ypos+qfmetr->descent()+20>y) return start;
+ start=t;
+ t=t->next;
+ };
+return start;
+}
+
+void KDisplayText::drawContents(QPainter *p, int /*clipx*/, int clipy, int /*clipw*/, int cliph)
+{
+ p->setFont(*qtextfont);
+ if (linked_list==NULL) return;
+ int i=0;
+ p->setPen(yellow);
+ int colorplayed=1;
+ if (cursor==NULL) colorplayed=0; // Thus, the program doesn't change the color
+ kdispt_line *tmpl=linked_list;
+ kdispt_ev *tmp;
+
+#ifdef KDISPTEXTDEBUG
+ printf("events displayed %d\n",typeoftextevents);
+#endif
+
+ tmpl=searchYOffset(clipy,linked_list);
+ int nlinestodraw=1;
+ kdispt_line *t=tmpl;
+ while ((t!=NULL)&&(t->ypos+qfmetr->descent()<clipy+cliph))
+ {
+ nlinestodraw++;
+ t=t->next;
+ }
+
+ i=0;
+ while ((i<nlinestodraw)&&(tmpl!=NULL))
+ {
+ tmp=tmpl->ev;
+ while ((tmp!=NULL)&&(tmp->spev->type!=typeoftextevents)) tmp=tmp->next;
+ while (tmp!=NULL)
+ {
+ if ( colorplayed &&
+ // (tmp->spev->absmilliseconds>=cursor->spev->absmilliseconds))
+ (tmp->spev->id>=cursor->spev->id))
+ {
+ p->setPen(black);
+ colorplayed=0;
+ }
+
+ if (IsLineFeed(tmp->spev->text[0],tmp->spev->type))
+ p->drawText(tmp->xpos,tmpl->ypos,lyrics_codec->toUnicode(&tmp->spev->text[1]));
+ else
+ p->drawText(tmp->xpos,tmpl->ypos,lyrics_codec->toUnicode(tmp->spev->text));
+
+#ifdef DRAW_BOUNDING_RECTS
+ p->setPen(red);
+ p->drawRect(tmp->r);
+ p->setPen((colorplayed)?yellow:black);
+#endif
+ tmp=tmp->next;
+ while ((tmp!=NULL)&&(tmp->spev->type!=typeoftextevents)) tmp=tmp->next;
+ }
+ i++;
+ tmpl=tmpl->next;
+ }
+
+}
+
+
+void KDisplayText::resizeEvent(QResizeEvent *e)
+{
+ QScrollView::resizeEvent(e);
+ nvisiblelines=visibleHeight()/qfmetr->lineSpacing();
+ if ( (nlines>nvisiblelines) || (nvisiblelines==0) )
+ resizeContents(maxX[(typeoftextevents==1)?0:1],maxY[(typeoftextevents==1)?0:1]);
+ else
+ resizeContents(0,0);
+
+}
+
+void KDisplayText::CursorToHome(void)
+{
+/* KConfig *kcfg=KGlobal::instance()->config();
+ kcfg->setGroup("KMid");
+ typeoftextevents=kcfg->readNumEntry("TypeOfTextEvents",1);
+*/
+ linked_list=linked_list_[(typeoftextevents==1)? 0:1];
+ nlines=nlines_[(typeoftextevents==1)? 0:1];
+ cursor_line_[0]=linked_list_[0];
+ first_line_[0]=cursor_line_[0];
+ if (cursor_line_[0]!=NULL) cursor_[0]=cursor_line_[0]->ev;
+ cursor_line_[1]=linked_list_[1];
+ first_line_[1]=cursor_line_[1];
+ if (cursor_line_[1]!=NULL) cursor_[1]=cursor_line_[1]->ev;
+
+ if (linked_list==NULL)
+ {
+ cursor_line=NULL;
+ cursor=NULL;
+ first_line=NULL;
+ }
+ else
+ {
+ cursor_line=linked_list;
+ cursor=cursor_line->ev;
+ first_line=linked_list;
+ }
+
+ nvisiblelines=visibleHeight()/qfmetr->lineSpacing();
+ if (nlines>nvisiblelines)
+ resizeContents(maxX[(typeoftextevents==1)?0:1],maxY[(typeoftextevents==1)?0:1]);
+ else
+ resizeContents(0,0);
+
+
+ setContentsPos(0,0);
+ viewport()->repaint(true);
+}
+
+void KDisplayText::PaintIn(int type)
+{
+ bool paint=false;
+ if (type!=typeoftextevents)
+ {
+ int idx=(type==1)?0:1;
+ if (cursor_[idx]==NULL) return;
+ cursor_[idx]=cursor_[idx]->next;
+ while ((cursor_[idx]==NULL)&&(cursor_line_[idx]!=NULL))
+ {
+ cursor_line_[idx]=cursor_line_[idx]->next;
+ if (cursor_line_[idx]!=NULL)
+ {
+ cursor_[idx]=cursor_line_[idx]->ev;
+ if ((cursor_line_[idx]->num>first_line_[idx]->num+NUMPREVLINES)
+ &&(cursor_line_[idx]->num<first_line_[idx]->num+nvisiblelines+1))
+ if ((first_line_[idx]!=NULL)&&(first_line_[idx]->num+nvisiblelines<=nlines_[idx])) first_line_[idx]=first_line_[idx]->next;
+ }
+ }
+ return;
+ }
+
+ if ((cursor==NULL)||(cursor_line==NULL))
+ {
+ printf("KDispT : cursor == NULL !!!\n");
+ return;
+ }
+
+ kdispt_ev *tmp=cursor;
+ if (cursor->spev->type==typeoftextevents)
+ {
+// int x,y;
+// contentsToViewport(cursor->xpos,cursor_line->ypos,x,y);
+
+ cursor=cursor->next;
+ paint=true;
+
+ }
+ else
+ cursor=cursor->next;
+
+
+ while ((cursor==NULL)&&(cursor_line!=NULL))
+ {
+ cursor_line=cursor_line->next;
+ if (cursor_line!=NULL)
+ {
+ cursor=cursor_line->ev;
+ if ((cursor_line->ypos>contentsY()+(visibleHeight()*5/8))&&
+ (cursor_line->ypos<contentsY()+visibleHeight()+autoscrollv))
+ {
+ bool b=(autoscrollv==0);
+ autoscrollv+=qfmetr->lineSpacing();
+ if (b) startTimer(100);
+ else {
+ killTimers();
+ startTimer(100/(autoscrollv/qfmetr->lineSpacing()+1));
+ }
+ }
+// scrollBy(0,qfmetr->lineSpacing());
+ }
+ }
+ if (paint) repaintContents(tmp->r);
+}
+
+void KDisplayText::gotomsec(ulong i)
+{
+ int notidx=(typeoftextevents==1)?1:0;
+
+ if (linked_list_[notidx]!=NULL)
+ {
+ cursor_line_[notidx]=linked_list_[notidx];
+ first_line_[notidx]=cursor_line_[notidx];
+ cursor_[notidx]=cursor_line_[notidx]->ev;
+ while ((cursor_line_[notidx]!=NULL)&&(cursor_[notidx]->spev->absmilliseconds<i))
+ {
+ cursor_[notidx]=cursor_[notidx]->next;
+ while ((cursor_[notidx]==NULL)&&(cursor_line_[notidx]!=NULL))
+ {
+ cursor_line_[notidx]=cursor_line_[notidx]->next;
+ if (cursor_line_[notidx]!=NULL)
+ {
+ cursor_[notidx]=cursor_line_[notidx]->ev;
+ if ((cursor_line_[notidx]->num>first_line_[notidx]->num+NUMPREVLINES)
+ &&(cursor_line_[notidx]->num<first_line_[notidx]->num+nvisiblelines+1))
+ if ((first_line_[notidx]!=NULL)&&(first_line_[notidx]->num+nvisiblelines<=nlines_[notidx])) first_line_[notidx]=first_line_[notidx]->next;
+ }
+ }
+ }
+ }
+
+ if (linked_list!=NULL)
+ {
+ cursor_line=linked_list;
+ cursor=cursor_line->ev;
+ first_line=linked_list;
+ while ((cursor_line!=NULL)&&(cursor->spev->absmilliseconds<i))
+ {
+ cursor=cursor->next;
+ while ((cursor==NULL)&&(cursor_line!=NULL))
+ {
+ cursor_line=cursor_line->next;
+ if (cursor_line!=NULL)
+ {
+ cursor=cursor_line->ev;
+ if ((cursor_line->num>first_line->num+NUMPREVLINES)
+ &&(cursor_line->num<first_line->num+nvisiblelines+1))
+ if ((first_line!=NULL)&&(first_line->num+nvisiblelines<=nlines)) first_line=first_line->next;
+ }
+ }
+
+
+ }
+
+ killTimers();
+ autoscrollv=0;
+ setContentsPos(0,first_line->ypos);
+ viewport()->repaint();
+
+ }
+}
+
+QFont *KDisplayText::getFont(void)
+{
+ return qtextfont;
+}
+
+void KDisplayText::fontChanged(void)
+{
+ KConfig *kcfg=KGlobal::instance()->config();
+ kcfg->setGroup("KMid");
+ QFont *qtextfontdefault=new QFont(*qtextfont);
+ delete qtextfont;
+ qtextfont=new QFont(kcfg->readFontEntry("KaraokeFont",qtextfontdefault));
+ delete qtextfontdefault;
+ qfmetr=new QFontMetrics(*qtextfont);
+ calculatePositions();
+ nvisiblelines=height()/qfmetr->lineSpacing();
+ viewport()->repaint(TRUE);
+}
+
+void KDisplayText::ChangeTypeOfTextEvents(int type)
+{
+ int idxold=(typeoftextevents==1)?0:1;
+ int idxnew=(type==1)?0:1;
+ cursor_line_[idxold]=cursor_line;
+ first_line_[idxold]=first_line;
+ cursor_[idxold]=cursor;
+ linked_list=linked_list_[idxnew];
+ cursor_line=cursor_line_[idxnew];
+ first_line=first_line_[idxnew];
+ cursor=cursor_[idxnew];
+ nlines=nlines_[idxnew];
+ typeoftextevents=type;
+ if (first_line!=NULL)
+ {
+ nvisiblelines=height()/qfmetr->lineSpacing();
+ if (nlines>nvisiblelines)
+ resizeContents(maxX[(typeoftextevents==1)?0:1],maxY[(typeoftextevents==1)?0:1]);
+ else
+ resizeContents(0,0);
+
+ setContentsPos(0,first_line->ypos);
+ }
+ viewport()->repaint(TRUE);
+}
+
+int KDisplayText::ChooseTypeOfTextEvents(void)
+{
+ return (nlines_[0]>nlines_[1])? 1 : 5;
+}
+
+void KDisplayText::ScrollDown()
+{
+ scrollBy(0,2/**qfmetr->lineSpacing()*/);
+}
+
+void KDisplayText::ScrollUp()
+{
+ scrollBy(0,-2/**qfmetr->lineSpacing()*/);
+}
+
+void KDisplayText::ScrollPageDown()
+{
+ scrollBy(0,nvisiblelines*qfmetr->lineSpacing());
+}
+
+void KDisplayText::ScrollPageUp()
+{
+ scrollBy(0,-nvisiblelines*qfmetr->lineSpacing());
+}
+
+void KDisplayText::saveLyrics(FILE *fh)
+{
+ kdispt_line *Lptr=linked_list_[(typeoftextevents==1)? 0:1];
+ while (Lptr!=NULL)
+ {
+ kdispt_ev *Cptr=Lptr->ev;
+ if (Cptr!=NULL)
+ {
+ if (strcmp(Cptr->spev->text,"")!=0)
+ if (IsLineFeed(Cptr->spev->text[0],Cptr->spev->type))
+ fputs(&Cptr->spev->text[1],fh);
+ else
+ fputs(Cptr->spev->text,fh);
+ Cptr=Cptr->next;
+ }
+ while (Cptr!=NULL)
+ {
+ fputs(Cptr->spev->text,fh);
+ Cptr=Cptr->next;
+ }
+ fputs("\n",fh);
+ Lptr=Lptr->next;
+ }
+}
+
+void KDisplayText::timerEvent(QTimerEvent *e)
+{
+ int dy;
+ if (autoscrollv>0)
+ {
+ dy=2+autoscrollv/50;
+ scrollBy(0,dy);
+ autoscrollv-=dy;
+ if (autoscrollv<0)
+ {
+ killTimer(e->timerId());
+ autoscrollv=0;
+ }
+ }
+ else
+ if (autoscrollv<0)
+ {
+// dy=(autoscrollv<-2*qfmetr->lineSpacing())?-7:-2;
+ dy=-2+autoscrollv/50;
+ scrollBy(0,dy);
+ autoscrollv-=dy;
+ if (autoscrollv>0)
+ {
+ killTimer(e->timerId());
+ autoscrollv=0;
+ }
+ }
+ else
+ killTimer(e->timerId());
+
+}
+
+void KDisplayText::setLyricsEncoding(const QString &enc)
+{
+ QTextCodec *newcodec;
+ if (enc.isEmpty())
+ newcodec=KGlobal::locale()->codecForEncoding();
+ else
+ newcodec=QTextCodec::codecForName(enc.latin1());
+
+ if (newcodec!=lyrics_codec)
+ {
+ if (newcodec)
+ {
+ lyrics_codec=newcodec;
+ fontChanged();
+ }
+ }
+}
+
+#include "kdisptext.moc"
diff --git a/kmid/kdisptext.h b/kmid/kdisptext.h
new file mode 100644
index 00000000..e47026c6
--- /dev/null
+++ b/kmid/kdisptext.h
@@ -0,0 +1,125 @@
+/**************************************************************************
+
+ kdisptext.h - The widget that displays the karaoke/lyrics text
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _kdisptext_h_
+#define _kdisptext_h_
+
+#include <qwidget.h>
+#include <qscrollview.h>
+#include <libkmid/player.h>
+
+struct kdispt_ev
+{
+ SpecialEvent *spev;
+ int xpos;
+ class QRect r;
+ kdispt_ev *next;
+};
+
+struct kdispt_line
+{
+ kdispt_ev *ev;
+ int num;
+ int ypos;
+ kdispt_line *next;
+};
+
+class QFont;
+class QFontMetrics;
+class QScrollBar;
+
+class KDisplayText : public QScrollView
+{
+ Q_OBJECT
+private:
+ QTextCodec *lyrics_codec;
+
+ QFontMetrics *qfmetr;
+ QFont *qtextfont;
+
+ int typeoftextevents;
+
+ kdispt_line *linked_list_[2];
+ int nlines_[2];
+ kdispt_line *first_line_[2];
+ kdispt_line *cursor_line_[2];
+ kdispt_ev *cursor_[2];
+
+ kdispt_line *linked_list;
+ kdispt_line *cursor_line;
+ kdispt_ev *cursor;
+
+ kdispt_line *first_line; // Pointer to first text at first visible line
+
+ int nlines; // Total number of lines
+ int nvisiblelines; // Number of visible lines
+
+ void RemoveLine(kdispt_line *tmpl);
+ void RemoveLinkedList(void);
+
+ int IsLineFeed(char c,int type=0);
+ virtual void drawContents(QPainter *qpaint,int clipx,int clipy,int clipw,int cliph);
+
+ kdispt_line * searchYOffset(int y, kdispt_line *start);
+
+ int maxX[2];
+ int maxY[2];
+ int autoscrollv;
+
+protected:
+ virtual void resizeEvent(QResizeEvent *qre);
+ virtual void timerEvent(QTimerEvent *e);
+
+public:
+ KDisplayText(QWidget *parent,const char *name);
+ virtual ~KDisplayText();
+
+ void ClearEv(bool totally=true);
+ void AddEv(SpecialEvent *ev);
+ void calculatePositions(void);
+
+ void CursorToHome(void);
+
+ void ChangeTypeOfTextEvents(int type);
+ int ChooseTypeOfTextEvents(void);
+ void PaintIn(int type);
+ void gotomsec(ulong i);
+
+ QFont *getFont(void);
+ void fontChanged(void);
+
+ void saveLyrics(FILE *fh);
+
+ void setLyricsEncoding(const QString &enc);
+
+// QSize sizeHint();
+
+public slots:
+ void ScrollDown();
+ void ScrollUp();
+ void ScrollPageDown();
+ void ScrollPageUp();
+
+};
+
+#endif
diff --git a/kmid/keyboard.xpm b/kmid/keyboard.xpm
new file mode 100644
index 00000000..9859e3a7
--- /dev/null
+++ b/kmid/keyboard.xpm
@@ -0,0 +1,50 @@
+/* XPM */
+static char * keyboard_xpm[] = {
+"63 45 2 1",
+" c #000000000000",
+". c #FFFFFFFFFFFF",
+" ",
+"..... .. ..... ..... .. .. ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... . .. . ..... ..... . .. . .. . ..... ",
+"..... .... .. .... ..... ..... .... .. .... .. .... ..... ",
+"..... .. ..... ..... .. .. ..... ",
+"...... .... ...... ...... .... .... ...... ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+"........ ........ ........ ........ ........ ........ ........ ",
+" ",
+" "};
diff --git a/kmid/klcdnumber.cpp b/kmid/klcdnumber.cpp
new file mode 100644
index 00000000..190d8da4
--- /dev/null
+++ b/kmid/klcdnumber.cpp
@@ -0,0 +1,339 @@
+/**************************************************************************
+
+ klcdnumber.cpp - The KLCDNumber widget (displays a lcd number)
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include "klcdnumber.h"
+#include <qpainter.h>
+#include <stdio.h>
+#include "ktrianglebutton.h"
+
+#define BUTTONWIDTH 9
+
+KLCDNumber::KLCDNumber(int _numDigits,QWidget *parent,const char *name)
+ : QWidget(parent,name)
+{
+ initDigits();
+ setUserChangeValue=false;
+ numDigits=_numDigits;
+ value=0;
+ minValue=0;
+ maxValue=1000;
+ oldvalue=-1;
+ // setPalette( QPalette (QColor(0,0,0)));
+ upBtn=NULL;
+ downBtn=NULL;
+ setUserDefaultValue=false;
+ doubleclicked=false;
+ setLCDBackgroundColor(0,0,0);
+ setLCDColor(100,255,100);
+}
+
+KLCDNumber::KLCDNumber(bool _setUserChangeValue,int _numDigits,QWidget *parent,const char *name)
+ : QWidget(parent,name)
+{
+ initDigits();
+ setUserChangeValue=_setUserChangeValue;
+ numDigits=_numDigits;
+ value=0;
+ minValue=0;
+ maxValue=1000;
+ oldvalue=-1;
+// setBackgroundColor(QColor(0,0,0));
+// setPalette( QPalette (QColor(0,0,0)));
+ upBtn=NULL;
+ downBtn=NULL;
+ setUserDefaultValue=false;
+ doubleclicked=false;
+ setLCDBackgroundColor(0,0,0);
+ setLCDColor(100,255,100);
+ if (setUserChangeValue)
+ {
+ upBtn=new KTriangleButton(KTriangleButton::Right,this,"Up");
+ downBtn=new KTriangleButton(KTriangleButton::Left,this,"Down");
+ upBtn->setGeometry(width()-BUTTONWIDTH,0,BUTTONWIDTH,height());
+ downBtn->setGeometry(0,0,BUTTONWIDTH,height());
+ connect(upBtn,SIGNAL(clicked()),this,SLOT(increaseValue()));
+ connect(downBtn,SIGNAL(clicked()),this,SLOT(decreaseValue()));
+ connect(upBtn,SIGNAL(clickedQuickly()),this,SLOT(increaseValueFast()));
+ connect(downBtn,SIGNAL(clickedQuickly()),this,SLOT(decreaseValueFast()));
+ };
+}
+
+void KLCDNumber::initDigits (void)
+{
+Digit[0] = digit(true,true,true,false,true,true,true);
+Digit[1] = digit(false,false,true,false,false,true,false);
+Digit[2] = digit(true,false,true,true,true,false,true);
+Digit[3] = digit(true,false,true,true,false,true,true);
+Digit[4] = digit(false,true,true,true,false,true,false);
+Digit[5] = digit(true,true,false,true,false,true,true);
+Digit[6] = digit(true,true,false,true,true,true,true);
+Digit[7] = digit(true,false,true,false,false,true,false);
+Digit[8] = digit(true,true,true,true,true,true,true);
+Digit[9] = digit(true,true,true,true,false,true,true);
+Digit[10] = digit(false,false,false,false,false,false,false);
+}
+
+void KLCDNumber::resizeEvent ( QResizeEvent *)
+{
+ if (setUserChangeValue)
+ {
+ upBtn->setGeometry(width()-BUTTONWIDTH,0,BUTTONWIDTH,height());
+ downBtn->setGeometry(0,0,BUTTONWIDTH,height());
+ }
+}
+
+void KLCDNumber::drawVerticalBar(QPainter *qpaint,int x,int y,int w,int h,int d)
+{
+ /* If d is 0 it means that it is a bar on the left and if 1 it is on the right */
+ /*
+ |\ /|
+ | | | |
+ | | = 0 1 = | |
+ | | | |
+ |/ \|
+ */
+
+ y++;
+ h-=2;
+ if (d==0)
+ {
+ for (int i=x;i<x+w;i++)
+ {
+ qpaint->drawLine(i,y,i,y+h);
+ y++;
+ h-=2;
+ }
+ } else {
+ for (int i=x+w;i>x;i--)
+ {
+ qpaint->drawLine(i,y,i,y+h);
+ y++;
+ h-=2;
+ }
+ }
+}
+
+void KLCDNumber::drawHorizBar(QPainter *qpaint,int x,int y,int w,int h,int d)
+{
+ // 0 is upper, 1 is bottom and 2 is the middle bar.
+ x++;
+ w-=3;
+ if (d==0)
+ {
+ for (int i=y;i<y+h;i++)
+ {
+ qpaint->drawLine(x,i,x+w,i);
+ x++;
+ w-=2;
+ }
+ }
+ else if (d==1)
+ {
+ for (int i=y+h;i>y;i--)
+ {
+ qpaint->drawLine(x,i,x+w,i);
+ x++;
+ w-=2;
+ }
+ }
+ else
+ {
+ for (int i=0;i<=h/2;i++)
+ {
+ qpaint->drawLine(x,y-i,x+w,y-i);
+ qpaint->drawLine(x,y+i,x+w,y+i);
+ x++;
+ w-=2;
+ }
+
+ };
+
+}
+
+void KLCDNumber::drawDigit(QPainter *qpaint,int x,int y,int w,int h,digit d)
+{
+if (d.nw) drawVerticalBar(qpaint,x,y,w/5,h/2,0);
+if (d.ne) drawVerticalBar(qpaint,x+w*4/5,y,w/5,h/2,1);
+if (d.sw) drawVerticalBar(qpaint,x,y+h/2,w/5,h/2,0);
+if (d.se) drawVerticalBar(qpaint,x+w*4/5,y+h/2,w/5,h/2,1);
+if (d.up) drawHorizBar (qpaint,x,y,w,w/5,0);
+if (d.bt) drawHorizBar (qpaint,x,y+h-w/5,w,w/5,1);
+if (d.md) drawHorizBar (qpaint,x,y+h/2,w,w/5,2);
+}
+
+
+void KLCDNumber::setValue(double v)
+{
+ oldvalue=value;
+ if (v<minValue)
+ value=minValue;
+ else if (v>maxValue)
+ value=maxValue;
+ else
+ value=v;
+
+}
+
+void KLCDNumber::display (double v)
+{
+ setValue(v);
+ repaint(FALSE);
+}
+
+void KLCDNumber::display (int v)
+{
+ display((double)v);
+}
+
+
+void KLCDNumber::paintEvent ( QPaintEvent * )
+{
+ QPainter qpaint(this);
+ qpaint.fillRect(0,0,width(),height(),backgcolor);
+ qpaint.setPen(LCDcolor);
+
+ QString numStr;
+ numStr.setNum((int) value);
+ numStr = numStr.rightJustify( numDigits, ' ', true);
+
+ int dx,dy,dw,dh;
+ if (setUserChangeValue)
+ {
+ dx=BUTTONWIDTH;
+ dy=height()/10;
+ dh=height()-dy*2;
+ dw=(width()-(BUTTONWIDTH*2))/numDigits;
+ } else
+ {
+ dx=0;
+ dy=height()/10;
+ dh=height()-dy*2;
+ dw=width()/numDigits;
+ };
+ int sep=dw/10;
+
+ for(int i=0; i < numDigits; i++)
+ {
+ char dig = numStr[i].latin1();
+ if ((dig>='0')&&(dig<='9'))
+ drawDigit(&qpaint,dx+sep,dy,dw-sep*2,dh,Digit[dig-'0']);
+ else
+ drawDigit(&qpaint,dx+sep,dy,dw-sep*2,dh,KLCDNumber::Digit[10]);
+ dx+=dw;
+ };
+}
+
+void KLCDNumber::setUserSetDefaultValue(bool _userSetDefaultValue)
+{
+ if (setUserDefaultValue!=_userSetDefaultValue)
+ {
+ setUserDefaultValue=_userSetDefaultValue;
+ /* if (setUserDefaultValue)
+ connect();
+ else
+ disconnect();
+ */
+ }
+
+}
+
+void KLCDNumber::setDefaultValue(double v)
+{
+ defaultValue=v;
+}
+
+
+void KLCDNumber::decreaseValue()
+{
+ display( value-1 );
+ emit valueChanged( value );
+}
+
+void KLCDNumber::increaseValue()
+{
+ display( value+1 );
+ emit valueChanged( value );
+}
+
+void KLCDNumber::decreaseValueFast()
+{
+ display( value-1 );
+}
+
+void KLCDNumber::increaseValueFast()
+{
+ display( value+1 );
+}
+
+void KLCDNumber::mouseDoubleClickEvent (QMouseEvent *)
+{
+ doubleclicked=true;
+ defaultValueClicked();
+}
+
+void KLCDNumber::mousePressEvent (QMouseEvent *e)
+{
+ startTimer(200);
+ QWidget::mousePressEvent(e);
+}
+
+void KLCDNumber::timerEvent(QTimerEvent *)
+{
+ killTimers();
+ doubleclicked=false;
+
+}
+
+
+void KLCDNumber::defaultValueClicked()
+{
+ if (setUserDefaultValue)
+ {
+ display( defaultValue );
+ emit valueChanged( value );
+ }
+}
+
+void KLCDNumber::setLCDBackgroundColor(int r,int g,int b)
+{
+ backgcolor=QColor(r,g,b);
+ repaint(FALSE);
+}
+
+void KLCDNumber::setLCDColor(int r,int g,int b)
+{
+ LCDcolor=QColor(r,g,b);
+ repaint(FALSE);
+}
+
+void KLCDNumber::setRange(double min, double max)
+{
+ minValue=min;
+ maxValue=max;
+}
+
+QSize KLCDNumber::sizeHint()
+{
+ return QSize(83,28);
+}
+#include "klcdnumber.moc"
diff --git a/kmid/klcdnumber.h b/kmid/klcdnumber.h
new file mode 100644
index 00000000..0359e472
--- /dev/null
+++ b/kmid/klcdnumber.h
@@ -0,0 +1,153 @@
+/**************************************************************************
+
+ klcdnumber.h - The KLCDNumber widget (displays a lcd number)
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _klcdnumber_h_
+#define _klcdnumber_h_
+
+#include <qwidget.h>
+
+class QPainter;
+class KTriangleButton;
+class QColor;
+
+class KLCDNumber : public QWidget
+{
+ Q_OBJECT
+protected:
+ class digit {
+public:
+ digit()
+ : up(false), nw(false), ne(false), md(false),
+ sw(false), se(false), bt(false) { }
+ digit( bool _up, bool _nw, bool _ne,
+ bool _md, bool _sw, bool _se, bool _bt)
+ : up(_up), nw(_nw), ne(_ne), md(_md),
+ sw(_sw), se(_se), bt(_bt) { }
+ bool up;
+ bool nw;
+ bool ne;
+ bool md;
+ bool sw;
+ bool se;
+ bool bt;
+ };
+ /*
+ up
+ ---
+ nw| |ne
+ |___|<------ md
+ | |
+ sw|___|se
+ bt
+ */
+
+
+ KLCDNumber::digit Digit[11];
+/*
+={
+ / 0 / {true,true,true,false,true,true,true},
+ / 1 / {false,false,true,false,false,true,false},
+ / 2 / {true,false,true,true,true,false,true},
+ / 3 / {true,false,true,true,false,true,true},
+ / 4 / {false,true,true,true,false,true,false},
+ / 5 / {true,true,false,true,false,true,true},
+ / 6 / {true,true,false,true,true,true,true},
+ / 7 / {true,false,true,false,false,true,false},
+ / 8 / {true,true,true,true,true,true,true},
+ / 9 / {true,true,true,true,false,true,true},
+ / / {false,false,false,false,false,false,false}
+ };*/
+
+ int numDigits;
+ bool setUserChangeValue;
+ bool setUserDefaultValue;
+ bool doubleclicked;
+
+ QColor backgcolor;
+ QColor LCDcolor;
+
+ double value;
+ double oldvalue;
+ double defaultValue;
+
+ double minValue;
+ double maxValue;
+
+ void drawVerticalBar(QPainter *qpaint,int x,int y,int w,int h,int d);
+ void drawHorizBar(QPainter *qpaint,int x,int y,int w,int h,int d);
+ void drawDigit(QPainter *qpaint,int x,int y,int w,int h,digit d);
+
+ void initDigits(void);
+
+public:
+ KLCDNumber(int _numDigits,QWidget *parent,const char *name);
+ KLCDNumber(bool _setUserChangeValue,int _numDigits,QWidget *parent,const char *name);
+
+ void setUserSetDefaultValue(bool _userSetDefaultValue);
+ void setDefaultValue(double v);
+
+ void setValue(double v);
+ double getValue(void) { return value; };
+ double getOldValue(void) { return oldvalue; };
+
+ double getMinValue(void) { return minValue;};
+ double getMaxValue(void) { return maxValue;};
+ void setRange(double min, double max);
+
+ void setLCDBackgroundColor (int r,int g,int b);
+ void setLCDColor (int r,int g,int b);
+
+ void display (int v);
+ void display (double v);
+
+ QSize sizeHint ();
+// QSizePolicy sizePolicy();
+
+protected:
+
+ virtual void paintEvent ( QPaintEvent *e );
+ virtual void resizeEvent ( QResizeEvent *e);
+ virtual void mouseDoubleClickEvent (QMouseEvent *e);
+ virtual void mousePressEvent (QMouseEvent *e);
+ virtual void timerEvent(QTimerEvent *e);
+ void defaultValueClicked();
+
+ KTriangleButton *downBtn;
+ KTriangleButton *upBtn;
+
+
+
+public slots:
+
+ void decreaseValue();
+ void increaseValue();
+ void decreaseValueFast();
+ void increaseValueFast();
+
+signals:
+
+ void valueChanged(double v);
+
+};
+
+#endif
diff --git a/kmid/kmid.desktop b/kmid/kmid.desktop
new file mode 100644
index 00000000..3920b855
--- /dev/null
+++ b/kmid/kmid.desktop
@@ -0,0 +1,88 @@
+[Desktop Entry]
+Name=KMid
+Name[af]=Kmid
+Name[bn]=কে-মিড
+Name[eo]=MIDI-ludilo
+Name[hi]=के-मिड
+Name[ne]=केडीई मिड
+Name[sv]=Kmid
+Name[tr]=Kmid
+Name[zh_HK]=KMidi
+Name[zh_TW]=KMid 播放器
+Name[zu]=KMidi
+MimeType=audio/x-karaoke;audio/x-midi;audio/midi;
+GenericName=Midi/Karaoke Player
+GenericName[af]=Midi/Kareokie Speler
+GenericName[ar]=مشغل Midi/Karaoke
+GenericName[bg]=Midi/Karaoke плеър
+GenericName[br]=C'hoarier Midi/Karaoke
+GenericName[bs]=Preglednik Midi/Karaoke datoteka
+GenericName[ca]=Reproductor Midi/Karaoke
+GenericName[cs]=Přehrávač Midi/Karaoke
+GenericName[cy]=Chwaraewr Midi/Karaoke
+GenericName[da]=Midi/Karaoke-afspiller
+GenericName[de]=Midi/Karaoke-Programm
+GenericName[el]=Αναπαραγωγέας Midi/Karaoke
+GenericName[eo]=Ludilo por Midi/Karaoko-dosieroj
+GenericName[es]=Un reproductor MIDI/Karaoke
+GenericName[et]=Midi/karaoke mängija
+GenericName[eu]=Midi/Karaoke erreproduzigailua
+GenericName[fa]=پخش‌کنندۀ Midi/Karaoke
+GenericName[fi]=Midi/Karaokesoitin
+GenericName[fr]=Platine MIDI / Karaoké
+GenericName[ga]=Seinnteoir Midi/Karaoke
+GenericName[gl]=Reproductor de Midi/Karaoke
+GenericName[he]=נגן MIDI/קריוקי
+GenericName[hi]=मिडी/कराओके प्लेयर
+GenericName[hr]=Midi/Karaoke player
+GenericName[hu]=MIDI/Karaoke-lejátszó
+GenericName[is]=Midi / Karaoke spilari
+GenericName[it]=Lettore MIDI/Karaoke
+GenericName[ja]=Midi/カラオケプレーヤ
+GenericName[kk]=Midi/Караоке ойнатқышы
+GenericName[km]=កម្មវិធី​ចាក់ Midi/ខារ៉ាអូខេ
+GenericName[ko]=미디/노래방 재생기
+GenericName[lt]=Midi/Karaoke grotuvas
+GenericName[lv]=Midi/Karaoke Atskaņotājs
+GenericName[mk]=Midi/Karaoke изведувач
+GenericName[ms]=Pemain Midi/Karaoke
+GenericName[nb]=Midi-/karaokespiller
+GenericName[nds]=Midi-/Karaoke-Afspeler
+GenericName[ne]=मिडि/कारावके प्लेयर
+GenericName[nl]=Midi/karaokespeler
+GenericName[nn]=Midi-/karaoke-spelar
+GenericName[pl]=Odtwarzacz Midi/Karaoke
+GenericName[pt]=Leitor de MIDI/Karaoke
+GenericName[pt_BR]=Reprodutor de Midi/Karaokê
+GenericName[ro]=Program de redare MIDI/Karaoke
+GenericName[ru]=Проигрыватель midi/караоке
+GenericName[se]=Midi-/karaoke-čuojaheaddji
+GenericName[sk]=Prehrávač Midi/Karaoke
+GenericName[sl]=Predvajalnik datotek MIDI/Karaoke
+GenericName[sr]=MIDI/караока плејер
+GenericName[sr@Latn]=MIDI/karaoka plejer
+GenericName[sv]=Midi/Karaoke-spelare
+GenericName[ta]=ஒரு மிடி/கரயோக்கே இயக்கி
+GenericName[tg]=Бозингари Midi/Karaoke
+GenericName[th]=โปรแกรมเล่นแฟ้มมิดี้/คาราโอเกะ
+GenericName[tr]=Midi ve Karaoke Yürütücü
+GenericName[uk]=Програвач Midi/Karaoke
+GenericName[uz]=Midi/Karaoki pleyer
+GenericName[uz@cyrillic]=Midi/Караоки плейер
+GenericName[ven]=Midi/Tshitambi tsha Karaoke
+GenericName[xh]=Umdlali we Midi/Karaoke
+GenericName[zh_CN]=Midi/卡拉 OK 播放器
+GenericName[zh_HK]=Midi/卡拉OK 播放器
+GenericName[zh_TW]=Midi/卡拉OK播放器
+GenericName[zu]=Umdlali weMidi/Karaoke
+Exec=kmid %u
+Icon=kmid
+Path=
+DocPath=kmid/index.html
+Type=Application
+Terminal=false
+ServiceTypes=Browser/View
+X-KDE-Library=libkmidpart
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;AudioVideo;X-KDE-More;
diff --git a/kmid/kmid.lsm b/kmid/kmid.lsm
new file mode 100644
index 00000000..bfae2aa6
--- /dev/null
+++ b/kmid/kmid.lsm
@@ -0,0 +1,22 @@
+Begin3
+Title: kmid
+Version: 2.0
+Entered-date: 30/04/2001
+Description: A midi/karaoke player with a very friendly interface.
+ Main features of kmid :
+ - Shows the text of karaoke files changing its color synchronized with music
+ - Use external synths, fm, awe or gus cards
+ - Has midi maps to allow using old keyboards with GM midi/karaoke files
+ - Stores an unlimited number of collections (also called playlists)
+ - Shows in a keyboard the notes played by each instrument (at realtime).
+ - Allows to change the tempo
+Keywords: mid kar player midi karaoke KDE X11 Qt kmid fm awe gus synth
+Author: larrosa@kde.org (Antonio Larrosa Jimenez)
+Maintained-by: larrosa@kde.org (Antonio Larrosa Jimenez)
+Primary-site: http://perso.wanadoo.es/antlarr/kmid.html
+Original-site: http://perso.wanadoo.es/antlarr/kmid.html
+Alternate-site: ftp://ftp.kde.org/pub/kde/apps/multimedia
+Platform: Linux, BSD and every OS in which OSS works, needs Qt 1.3,
+ X11 and the KDE libs
+Copying-policy: GPL
+End
diff --git a/kmid/kmid.spec b/kmid/kmid.spec
new file mode 100644
index 00000000..959ce342
--- /dev/null
+++ b/kmid/kmid.spec
@@ -0,0 +1,62 @@
+Summary: Play midi/karaoke files and show lyrics. Support External synths, AWE, GUS, and FM devices. For X11/KDE
+Name: kmid
+Version: 1.2
+Release: 1
+Copyright: GPL
+Group: X11/K Desktop Environment/Multimedia
+Source: kmid-1.2.tar.gz
+Requires: qt >= 1.3 , kdelibs
+
+%description
+KMid is a midi/karaoke file player, with configurable midi mapper,
+real Session Management, drag & drop, customizable fonts, etc.
+It has a very nice interface which let you easily follow the tune while
+changing the color of the lyrics.
+It supports output through external synthesizers, AWE, FM and GUS cards.
+It also has a keyboard view to see the notes played by each instrument
+
+%prep
+%setup
+
+%build
+export KDEDIR=/opt/kde
+./configure
+make all
+
+%install
+export KDEDIR=/opt/kde
+make install
+
+%files
+%doc kmid/README kmid/COPYING kmid/PEOPLE kmid/kmid.lsm kmid/ChangeLog
+
+/opt/kde/bin/kmid
+/opt/kde/share/doc/HTML/en/kmid
+/opt/kde/share/doc/HTML/es/kmid
+/opt/kde/share/icons/kmid.xpm
+/opt/kde/share/icons/mini/kmid.xpm
+/opt/kde/share/applnk/Multimedia/kmid.kdelnk
+/opt/kde/share/mimelnk/audio/x-karaoke.kdelnk
+/opt/kde/share/apps/kmid/toolbar
+/opt/kde/share/apps/kmid/fm
+/opt/kde/share/apps/kmid/maps/gm.map
+/opt/kde/share/apps/kmid/maps/YamahaPSS790.map
+/opt/kde/share/apps/kmid/maps/YamahaPSR500.map
+/opt/kde/share/apps/kmid/OFortuna.kar
+/opt/kde/share/apps/kmid/StopInTheNameOfLove.kar
+/opt/kde/share/apps/kmid/TheGirlFromIpanema.kar
+/opt/kde/share/apps/kmid/AnotherGlitchInTheCall.kar
+/opt/kde/share/locale/es/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/cs/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/de/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/fi/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/hr/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/pl/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/pt/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/sk/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/eo/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/no/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/sv/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/pt_BR/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/zh_CN.GB2312/LC_MESSAGES/kmid.mo
+/opt/kde/share/locale/zh_TW.Big5/LC_MESSAGES/kmid.mo
diff --git a/kmid/kmidIface.h b/kmid/kmidIface.h
new file mode 100644
index 00000000..75f2ca72
--- /dev/null
+++ b/kmid/kmidIface.h
@@ -0,0 +1,46 @@
+#ifndef _KMIDIFACE_H_
+#define _KMIDIFACE_H_
+
+#include <dcopobject.h>
+
+class KMidIface : virtual public DCOPObject
+{
+ K_DCOP
+
+k_dcop:
+// File
+
+ virtual int openURL( const QString s )=0;
+
+ // Song
+ virtual void play()=0;
+ virtual void pause()=0;
+ virtual void stop()=0;
+ virtual void rewind()=0;
+ virtual void forward()=0;
+ virtual void seek(int ms)=0;
+ virtual void prevSong()=0;
+ virtual void nextSong()=0;
+
+ virtual void setSongLoop(int i)=0;
+ virtual void setVolume(int i)=0;
+ virtual void setTempo(int i)=0;
+// GUI
+
+
+ virtual void setSongEncoding( int i )=0;
+ virtual void setLyricEvents( int i )=0;
+
+// Collections
+ virtual void setCurrentSong(int i)=0;
+
+ virtual void setActiveCollection( int i )=0;
+ virtual void setCollectionPlayMode(int i)=0;
+
+// Midi device
+
+ virtual void setMidiDevice(int i)=0;
+
+};
+#endif
+
diff --git a/kmid/kmid_part.cpp b/kmid/kmid_part.cpp
new file mode 100644
index 00000000..98241ac1
--- /dev/null
+++ b/kmid/kmid_part.cpp
@@ -0,0 +1,144 @@
+#include "kmid_part.h"
+
+#include <kinstance.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <kaction.h>
+#include <qiconset.h>
+
+#include <kparts/partmanager.h>
+
+#include "kmidclient.h"
+#include <qtimer.h>
+#include <kdelibs_export.h>
+
+K_EXPORT_COMPONENT_FACTORY( libkmidpart, KMidFactory )
+
+/**
+ * We need one static instance of the factory for our C 'main'
+ * function
+ */
+KInstance *KMidFactory::s_instance = 0L;
+
+KMidFactory::KMidFactory()
+{
+ s_instance=0L;
+}
+
+KMidFactory::~KMidFactory()
+{
+ if (s_instance)
+ {
+ delete s_instance->aboutData();
+ delete s_instance;
+ }
+
+ s_instance = 0;
+}
+
+KParts::Part *KMidFactory::createPartObject(QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name, const char*,
+ const QStringList& )
+{
+ KParts::Part *obj = new KMidPart(parentWidget, widgetName, parent, name);
+ return obj;
+}
+
+KAboutData *KMidFactory::aboutData()
+{
+ KAboutData *aboutdata = new KAboutData("kmid", "KMid", "2.0",
+ I18N_NOOP("MIDI/Karaoke file player"), KAboutData::License_GPL,
+ I18N_NOOP("(c) 1997,98,99,2000, Antonio Larrosa Jimenez"),"",
+ "http://perso.wanadoo.es/antlarr/kmid.html");
+ aboutdata->addAuthor("Antonio Larrosa Jimenez",
+ I18N_NOOP("Original Developer/Maintainer"),"larrosa@kde.org",
+ "http://perso.wanadoo.es/antlarr/index.html");
+ return aboutdata;
+}
+
+KInstance *KMidFactory::instance()
+{
+ if ( !s_instance )
+ s_instance = new KInstance( aboutData() );
+
+ return s_instance;
+}
+
+ KMidPart::KMidPart(QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name)
+: KParts::ReadOnlyPart(parent, name)
+{
+ setInstance(KMidFactory::instance());
+
+ widget = new kmidClient(parentWidget, actionCollection());
+ widget->show();
+ widget->setFocusPolicy(QWidget::ClickFocus);
+ setWidget(widget);
+
+ // create and connect our actions
+ (void)new KAction(i18n("Play"), "player_play", 0, this,
+ SLOT(slotPlay()), actionCollection(),
+ "play");
+
+ (void)new KAction(i18n("Stop"), "player_stop", 0, this,
+ SLOT(slotStop()), actionCollection(),
+ "stop");
+
+ (void)new KAction(i18n("Backward"),
+ "2leftarrow", 0, this,
+ SLOT(slotBackward()), actionCollection(),
+ "backward");
+
+ (void)new KAction(i18n("Forward"),
+ "2rightarrow", 0, this,
+ SLOT(slotForward()), actionCollection(),
+ "forward");
+
+ m_extension = new KMidBrowserExtension(this);
+
+ setXMLFile("kmid_partui.rc");
+
+
+}
+
+KMidPart::~KMidPart()
+{
+}
+
+bool KMidPart::openFile()
+{
+ widget->openURL(m_file);
+ widget->stop();
+ widget->show();
+ QTimer::singleShot(2000, this, SLOT(slotPlay()));
+
+ return true;
+}
+
+bool KMidPart::closeURL()
+{
+ slotStop();
+ return true;
+}
+
+void KMidPart::slotPlay()
+{
+ widget->stop();
+ widget->play();
+}
+
+
+void KMidPart::slotStop()
+{
+ widget->stop();
+}
+KMidBrowserExtension::KMidBrowserExtension(KMidPart *parent)
+ : KParts::BrowserExtension(parent, "KMidBrowserExtension")
+{
+}
+
+KMidBrowserExtension::~KMidBrowserExtension()
+{
+}
+#include "kmid_part.moc"
diff --git a/kmid/kmid_part.h b/kmid/kmid_part.h
new file mode 100644
index 00000000..4b02e099
--- /dev/null
+++ b/kmid/kmid_part.h
@@ -0,0 +1,63 @@
+#ifndef __KMIDPART_H__
+#define __KMIDPART_H__
+
+#include <kparts/browserextension.h>
+#include <kparts/factory.h>
+#include <kdelibs_export.h>
+class KAboutData;
+class KInstance;
+class KMidBrowserExtension;
+class kmidClient;
+
+class KDE_EXPORT KMidFactory : public KParts::Factory
+{
+ Q_OBJECT
+ public:
+ KMidFactory();
+ virtual ~KMidFactory();
+
+ virtual KParts::Part* createPartObject(QWidget *parentWidget, const char *widgetName,
+ QObject* parent = 0, const char* name = 0,
+ const char* classname = "QObject",
+ const QStringList &args = QStringList());
+
+ static KInstance *instance();
+
+ static KAboutData *aboutData();
+ private:
+ static KInstance *s_instance;
+};
+
+class KMidPart: public KParts::ReadOnlyPart
+{
+ Q_OBJECT
+ public:
+ KMidPart(QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name);
+ virtual ~KMidPart();
+
+
+ virtual bool closeURL();
+
+ protected:
+ virtual bool openFile();
+
+ protected slots:
+ void slotPlay();
+ void slotStop();
+
+ private:
+ kmidClient *widget;
+ KMidBrowserExtension *m_extension;
+};
+
+class KMidBrowserExtension : public KParts::BrowserExtension
+{
+ Q_OBJECT
+ friend class KMidPart;
+ public:
+ KMidBrowserExtension(KMidPart *parent);
+ virtual ~KMidBrowserExtension();
+};
+
+#endif
diff --git a/kmid/kmid_partui.rc b/kmid/kmid_partui.rc
new file mode 100644
index 00000000..aad5c6b2
--- /dev/null
+++ b/kmid/kmid_partui.rc
@@ -0,0 +1,17 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kmid" version="2">
+<MenuBar>
+ <Menu name="view">
+ <Action name="play"/>
+ <Action name="stop"/>
+ <Action name="backward"/>
+ <Action name="forward"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="KMid-ToolBar">
+ <Action name="play"/>
+ <Action name="stop"/>
+ <Action name="backward"/>
+ <Action name="forward"/>
+</ToolBar>
+</kpartgui>
diff --git a/kmid/kmidbutton.h b/kmid/kmidbutton.h
new file mode 100644
index 00000000..cda01f59
--- /dev/null
+++ b/kmid/kmidbutton.h
@@ -0,0 +1,32 @@
+#include <qpushbutton.h>
+#include <qpainter.h>
+
+class KMidButton : public QPushButton
+{
+protected:
+
+ QPixmap pixmap1,pixmap2;
+
+ virtual void drawButton(QPainter *paint)
+ {
+ if ((isOn())&&(!pixmap1.isNull())) paint->drawPixmap(0,0,pixmap1);
+ else if ((!isOn())&&(!pixmap2.isNull())) paint->drawPixmap(0,0,pixmap2);
+ };
+
+public:
+
+ KMidButton (QWidget *parent,const char *name) : QPushButton (parent,name)
+ {
+ };
+
+ ~KMidButton()
+ {
+ };
+
+ void setPixmaps(const QPixmap& p1, const QPixmap& p2)
+ {
+ pixmap1=p1;
+ pixmap2=p2;
+ };
+
+};
diff --git a/kmid/kmidclient.cpp b/kmid/kmidclient.cpp
new file mode 100644
index 00000000..c7dcd009
--- /dev/null
+++ b/kmid/kmidclient.cpp
@@ -0,0 +1,1606 @@
+/**************************************************************************
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <qkeycode.h>
+#include <qfiledialog.h>
+#include <qstring.h>
+#include <qlabel.h>
+#include <qfile.h>
+#include <qcombobox.h>
+#include <qlayout.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(QWidget *parent, KActionCollection *ac, const char *name)
+ : DCOPObject("KMidIface"), QWidget(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");
+ QString tmp2 = locateLocal("appdata", "collections");
+ collectionsfile=kconf->readPathEntry("CollectionsFile",tmp2);
+ slman=new SLManager();
+ slman->loadConfig(QFile::encodeName(collectionsfile));
+ currentsl=NULL;
+ // currentsl=slman->getCollection(activecollection);
+ itsme=0;
+ m_kMid.pid=0;
+ timebar = new QSlider(0,240000,30000,60000,QSlider::Horizontal, this);
+ timebar->setSteps(30000,60000);
+ timebar->setValue(0);
+ connect (timebar,SIGNAL(valueChanged(int)),this,SLOT(slotSeek(int)));
+
+ timetags = new QSliderTime(timebar,this);
+ timetags->setMinimumSize(timetags->sizeHint());
+
+ qlabelTempo= new QLabel(i18n("Tempo:"), this,"tempolabel",
+ QLabel::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,SIGNAL(valueChanged(double)),this,SLOT(slotSetTempo(double)));
+
+ comboSongs = new QComboBox(FALSE, this,"Songs");
+ connect (comboSongs,SIGNAL(activated(int)),this,SLOT(slotSelectSong(int)));
+ comboSongs->setMinimumWidth(200);
+
+ comboEncodings = new QComboBox(FALSE, this, "Encodings");
+ connect (comboEncodings,SIGNAL(activated(int)),this,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 QSlider(0,200,10,100,QSlider::Vertical, this );
+ volumebar->setSteps(10,20);
+ volumebar->setValue(100);
+ volumebar->setTickmarks(QSlider::NoMarks);
+ volumebar->setTickInterval(50);
+ connect (volumebar,SIGNAL(valueChanged(int)),this,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 QTimer(this);
+ connect (timer4timebar,SIGNAL(timeout()),this,SLOT(timebarUpdate()));
+ timer4events=new QTimer(this);
+ connect (timer4events,SIGNAL(timeout()),this,SLOT(processSpecialEvent()));
+
+ QString samplefile =
+ KGlobal::dirs()->findAllResources("appdata", "fm/*.o3").last();
+ samplefile.truncate(samplefile.findRev('/'));
+ FMOut::setFMPatchesDirectory(QFile::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");
+ QCString qs=QFile::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;
+
+ QVBoxLayout *lv=new QVBoxLayout( this );
+ lv->addWidget( timebar );
+ lv->addWidget( timetags );
+ lv->addSpacing(5);
+ QHBoxLayout *lh=new QHBoxLayout( 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);
+ QHBoxLayout *lh2=new QHBoxLayout( lv );
+ lh2->addWidget( volumebar );
+ lh2->addWidget( kdispt );
+}
+
+/*void kmidClient::resizeEvent(QResizeEvent *)
+{
+ //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)
+ {
+ QString 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 QString _url)
+{
+ KURL u(_url);
+ if (!u.isValid()) {printf("Malformed URL\n");return -1;};
+
+ QString filename;
+ bool deleteFile=false;
+ if (!u.isLocalFile())
+ {
+ filename = QString("/tmp/") + u.filename();
+ KIO::Job *iojob = KIO::copy( u, KURL::fromPathOrURL( filename ) );
+ downloaded=false;
+ connect( iojob, SIGNAL( result( KIO::Job *) ), this, SLOT(downloadFinished( KIO::Job * ) ) );
+
+ if (!downloaded)
+ kapp->enter_loop();
+ deleteFile=true;
+
+ }
+ else
+ {
+ filename=u.path();
+ }
+
+ QCString filename_8bit = QFile::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();
+
+ QApplication::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;
+
+ QApplication::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;
+
+ QApplication::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();
+ }
+
+}
+
+
+QFont * 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)
+ {
+ QString tmp = locate("appdata", QString("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];
+ QString 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(QFile::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,SIGNAL(signalToKMidClient(int *)),this,SLOT(communicationFromChannelView(int *)));
+ connect(kapp,SIGNAL(shutDown()),parentWidget(),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();
+}
+
+QSize kmidClient::sizeHint() const
+{
+ QSize sh = QWidget::sizeHint();
+ return sh.expandedTo(QSize(560,420));
+}
+
+QSizePolicy kmidClient::sizePolicy()
+{
+ return QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::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(QString::null); // Default
+ else
+ kdispt->setLyricsEncoding(KGlobal::charsets()->encodingForName(comboEncodings->text(i)));
+}
+#include "kmidclient.moc"
diff --git a/kmid/kmidclient.h b/kmid/kmidclient.h
new file mode 100644
index 00000000..18d33d66
--- /dev/null
+++ b/kmid/kmidclient.h
@@ -0,0 +1,240 @@
+/**************************************************************************
+
+ kmidclient.h - 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _KMIDCLIENT_H
+#define _KMIDCLIENT_H
+
+#include "qslidertime.h"
+#include <libkmid/player.h>
+#include <libkmid/track.h>
+#include <libkmid/notearray.h>
+#include <libkmid/libkmid.h>
+#include <qtimer.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include "kdisptext.h"
+#include "slman.h"
+#include "version.h"
+#include "kmidIface.h"
+
+#include <kio/job.h>
+
+class DeviceManager;
+
+
+class KApplication;
+class KConfig;
+class KLCDNumber;
+class QLabel;
+class QComboBox;
+class RhythmView;
+class ChannelView;
+class QString;
+
+class kmidClient : public QWidget, virtual public KMidIface
+{
+ Q_OBJECT
+private:
+#ifdef KMidDEBUG
+ long passcount;
+#endif
+
+ DeviceManager *midi;
+ MidiPlayer *player;
+
+ struct kMidData m_kMid;
+
+ QTimer *timer4timebar;
+ QTimer *timer4events;
+
+ ulong beginmillisec;
+ ulong pausedatmillisec;
+ double currentTempo;
+ SpecialEvent *spev;
+ NoteArray *noteArray;
+
+ bool downloaded;
+
+ int itsme;
+ bool shuttingdown;
+ int visiblevolumebar;
+
+ char *midifile_opened;
+ int hasbeenopened;
+
+ int typeoftextevents;
+
+ SLManager *slman;
+ int activecollection;
+ QString collectionsfile;
+ SongList *currentsl;
+ int initializing_songs;
+ int loopsong;
+ int collectionplaymode;
+ int *collectionplaylist; // the list of songs ordered in the
+ // user selected mode
+
+ class KActionCollection *actionCollection;
+
+ void generateCPL(void);
+ int searchInCPL(int song); // Returns the index of song
+
+ void fillInComboSongs(void);
+
+ int openFile(const char *filename);
+ void allNotesOff(void);
+public:
+ kmidClient(QWidget *parent, KActionCollection *ac, const char *name=0);
+ ~kmidClient();
+
+ char *midiFileName(void) {return midifile_opened;};
+ // If it returns NULL then there isn't any file opened
+
+ int isPlaying(void) {return m_kMid.pctl->playing;};
+ int isPaused(void) {return (m_kMid.pctl->playing)&&(m_kMid.pctl->paused);};
+
+ int openURL(const QString s);
+
+ void repaintText(int typeoftextevents);
+ static void kmidOutput(void);
+
+ int ChooseTypeOfTextEvents(void);
+
+ QFont *getFont(void);
+ void fontChanged(void); // The new font is already in KConfig
+
+ SLManager *getSLManager(void) {return slman;};
+ void setSLManager(SLManager *slm);
+ // setSLManager only change the pointer, so DO NOT DELETE
+ // the objectr you pass to it
+ int getActiveCollection(void) {return activecollection;};
+ void setActiveCollection(int i);
+ int getSelectedSong(void);
+ void saveCollections(void);
+
+ void setSongType(int i);
+ void setSongLoop(int i);
+ void setCollectionPlayMode(int i);
+
+ void visibleVolumeBar(int i); // 1 shows it, and 0 hides it
+ // int isVisibleVolumeBar(void) {return visiblevolumebar;};
+ void visibleChannelView(int i);
+
+ void shuttingDown(void);
+
+ ulong timeOfNextEvent(int *type=NULL);
+ void rethinkNextEvent(void);
+ // Recalculates time of next event and updates the timer4events according to it
+
+
+ void moveEventPointersTo(ulong ms);
+
+protected:
+// void resizeEvent(QResizeEvent *qre);
+
+
+public slots:
+// void help_Help();
+// void help_About();
+ void slotPlay();
+ void slotPause();
+ void slotStop();
+ void slotRewind();
+ void slotForward();
+ void slotPrevSong();
+ void slotNextSong();
+
+ void timebarUpdate();
+ void slotSeek(int i);
+ void slotSetVolume(int i);
+ void slotSelectSong(int i);
+ void slotSelectEncoding(int i);
+
+ void downloadFinished( KIO::Job * );
+
+ void processSpecialEvent();
+
+ void channelViewDestroyed();
+
+ void communicationFromChannelView(int *);
+
+ void slotSetTempo(double value);
+
+signals:
+ void mustRechooseTextEvent();
+ void stopPause();
+// void channelView_Destroyed();
+
+public:
+ void saveLyrics(FILE *fh);
+
+ DeviceManager *devman(void) {return midi;};
+ void setMidiDevice(int i);
+ void setMidiMapFilename(const char *mapfilename);
+
+ ChannelView *getChannelView(void) { return channelView; };
+ KDisplayText *getKDisplayText(void) { return kdispt; };
+
+ QSizePolicy sizePolicy();
+
+ QComboBox *getComboSongs() { return comboSongs; };
+
+
+ void play();
+ void pause();
+ void stop();
+ void rewind();
+ void forward();
+ void seek(int ms);
+ void prevSong();
+ void nextSong();
+ void setVolume(int i);
+ void setTempo(int i);
+ void setSongEncoding( int i );
+ void setLyricEvents( int i );
+ void setCurrentSong(int i);
+ void setPlayListMode(int i);
+
+ QSize sizeHint() const;
+private:
+ QSlider *timebar;
+ QSliderTime *timetags;
+ QSlider *volumebar;
+
+ KLCDNumber *tempoLCD;
+ KDisplayText *kdispt;
+ QLabel *qlabelTempo;
+ QComboBox *comboSongs;
+ QComboBox *comboEncodings;
+ RhythmView *rhythmview;
+
+
+ ChannelView *channelView;
+
+};
+
+char *extractFilename(const char *in,char *out); // returns a pointer to out
+
+#endif
+
diff --git a/kmid/kmidframe.cpp b/kmid/kmidframe.cpp
new file mode 100644
index 00000000..007f0b82
--- /dev/null
+++ b/kmid/kmidframe.cpp
@@ -0,0 +1,728 @@
+/**************************************************************************
+
+ kmidframe.cpp - The main 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., 59 Temple
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+#include <qkeycode.h>
+#include <qstring.h>
+
+#include <kaccel.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcmdlineargs.h>
+#include <kfiledialog.h>
+#include <kfontdialog.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktoolbar.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kurldrag.h>
+#include <kedittoolbar.h>
+#include <dcopclient.h>
+
+#include "kmidframe.h"
+#include "kmidclient.h"
+#include "midicfgdlg.h"
+#include "collectdlg.h"
+#include "channelcfgdlg.h"
+#include "channelview.h"
+#include "version.h"
+
+kmidFrame::kmidFrame(const char *name)
+ :KMainWindow(0, name)
+{
+ kmidclient=new kmidClient(this,actionCollection(), "KMidClient");
+ kmidclient->setSongType(1);
+ kmidclient->show();
+ setCentralWidget( kmidclient );
+/*
+ kKeysAccel=new KAccel(this);
+ kKeysAccel->insertItem(i18n("Play/Pause"),"Play/Pause", Key_Space);
+ kKeysAccel->connectItem("Play/Pause", this, SLOT(spacePressed()));
+ kKeysAccel->insertItem(i18n("Stop"),"Stop", Key_Backspace);
+ kKeysAccel->connectItem("Stop",kmidclient,SLOT(song_Stop()));
+ kKeysAccel->insertItem(i18n("Previous Song"),"Previous Song", Key_Left);
+ kKeysAccel->connectItem("Previous Song",kmidclient,SLOT(song_PlayPrevSong()));
+ kKeysAccel->insertItem(i18n("Next Song"),"Next Song", Key_Right);
+ kKeysAccel->connectItem("Next Song",kmidclient,SLOT(song_PlayNextSong()));
+ kKeysAccel->insertItem(i18n("Scroll Down Karaoke"),"Scroll down karaoke",Key_Down);
+ kKeysAccel->connectItem("Scroll Down karaoke",kmidclient->getKDisplayText(),SLOT(ScrollDown()));
+ kKeysAccel->insertItem(i18n("Scroll Up Karaoke"),"Scroll up karaoke",Key_Up);
+ kKeysAccel->connectItem("Scroll Up Karaoke",kmidclient->getKDisplayText(),SLOT(ScrollUp()));
+ kKeysAccel->insertItem(i18n("Scroll Page Down Karaoke"),"Scroll page down karaoke",Key_PageDown);
+ kKeysAccel->connectItem("Scroll Page Down Karaoke",kmidclient->getKDisplayText(),SLOT(ScrollPageDown()));
+ kKeysAccel->insertItem(i18n("Scroll Page Up Karaoke"),"Scroll page up karaoke",Key_PageUp);
+ kKeysAccel->connectItem("Scroll Page Up Karaoke",kmidclient->getKDisplayText(),SLOT(ScrollPageUp()));
+
+ kKeysAccel->readSettings();
+*/
+ KStdAction::open(this, SLOT(file_Open()), actionCollection());
+ (void)new KAction(i18n("&Save Lyrics..."), 0, this,
+ SLOT(file_SaveLyrics()), actionCollection(), "file_save_lyrics");
+ KStdAction::quit(kapp, SLOT(quit()), actionCollection());
+
+ (void)new KAction(i18n("&Play"), "player_play", Qt::Key_Space,
+ kmidclient, SLOT(slotPlay()), actionCollection(), "song_play");
+ (void)new KAction(i18n("P&ause"), "player_pause", Qt::Key_P, kmidclient,
+ SLOT(slotPause()), actionCollection(), "song_pause");
+ (void)new KAction(i18n("&Stop"), "player_stop", Qt::Key_Backspace,
+ kmidclient, SLOT(slotStop()), actionCollection(), "song_stop");
+
+ (void)new KAction(i18n("P&revious Song"), "player_start", Key_Left,
+ kmidclient, SLOT(slotPrevSong()), actionCollection(),
+ "song_previous");
+ (void)new KAction(i18n("&Next Song"), "player_end", Key_Right,
+ kmidclient, SLOT(slotNextSong()), actionCollection(),
+ "song_next");
+ (void)new KToggleAction(i18n("&Loop"), 0, this, SLOT(song_Loop()),
+ actionCollection(), "song_loop");
+
+ (void)new KAction(i18n("Rewind"), "2leftarrow", 0, kmidclient,
+ SLOT(slotRewind()), actionCollection(), "song_rewind");
+
+ (void)new KAction(i18n("Forward"), "2rightarrow", 0, kmidclient,
+ SLOT(slotForward()), actionCollection(), "song_forward");
+
+ (void)new KAction(i18n("&Organize..."), 0, this, SLOT(collect_organize()),
+ actionCollection(), "collect_organize");
+
+ QStringList playmodes;
+ playmodes.append(i18n("In Order"));
+ playmodes.append(i18n("Shuffle"));
+
+ KSelectAction *act=new KSelectAction(i18n("Play Order"), 0, /*this, SLOT(collect_PlayOrder(int)),*/
+ actionCollection(), "play_order");
+ connect(act,SIGNAL(activated(int)),this, SLOT(collect_PlayOrder(int)));
+ act->setItems(playmodes);
+
+ (void)new KToggleAction(i18n("Auto-Add to Collection"), 0, this,
+ SLOT(collect_AutoAdd()), actionCollection(), "collect_autoadd");
+
+ playmodes.clear();
+ playmodes.append(i18n("&General MIDI"));
+ playmodes.append(i18n("&MT-32"));
+
+ act=new KSelectAction(i18n("File Type"), 0,/* this, SLOT(options_FileType(int)),*/
+ actionCollection(), "file_type");
+ connect(act,SIGNAL(activated(int)),this, SLOT(options_FileType(int)));
+ act->setItems(playmodes);
+
+ playmodes.clear();
+ playmodes.append(i18n("&Text Events"));
+ playmodes.append(i18n("&Lyric Events"));
+
+ act=new KSelectAction(i18n("Display Events"), Key_T, /*this,
+ SLOT(options_DisplayEvents(int)),*/ actionCollection(),
+ "display_events");
+ connect(act,SIGNAL(activated(int)),this, SLOT(options_DisplayEvents(int)));
+ act->setItems(playmodes);
+
+ (void)new KToggleAction(i18n("Automatic Text Chooser"), 0, this,
+ SLOT(options_AutomaticText()), actionCollection(),
+ "option_automatictext");
+
+ KToggleAction* togact = new KToggleAction(i18n("Show &Volume Bar"), "volume",
+ 0, this, SLOT(options_ShowVolumeBar()), actionCollection(),
+ "toggle_volumebar");
+ togact->setCheckedState(i18n("Hide &Volume Bar"));
+
+ togact = new KToggleAction(i18n("Show &Channel View"), "piano",
+ 0, this, SLOT(options_ShowChannelView()), actionCollection(),
+ "toggle_channelview");
+ togact->setCheckedState(i18n("Hide &Channel View"));
+
+ (void)new KAction(i18n("Channel View &Options..."), 0, this,
+ SLOT(options_ChannelViewOptions()), actionCollection(),
+ "channelview_options");
+
+ (void)new KAction(i18n("&Font Change..."), 0, this,
+ SLOT(options_FontChange()), actionCollection(),
+ "change_font");
+
+ (void)new KAction(i18n("MIDI &Setup..."), 0, this,
+ SLOT(options_MidiSetup()), actionCollection(), "midi_setup");
+
+
+ setupGUI((ToolBar | Keys | StatusBar | Save | Create ), "kmidui.rc" );
+
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ KSelectAction *tmplistaction=
+ ((KSelectAction*)actionCollection()->action("display_events"));
+
+ if (cfg->readNumEntry("TypeOfTextEvents",5)==5)
+ tmplistaction->setCurrentItem(1);
+ else
+ tmplistaction->setCurrentItem(0);
+
+ tmplistaction=((KSelectAction*)actionCollection()->action("file_type"));
+ if (cfg->readNumEntry("TypeOfMidiFile",0)==0)
+ tmplistaction->setCurrentItem(0);
+ else
+ tmplistaction->setCurrentItem(1);
+
+ if (cfg->readNumEntry("Loop",0)==1)
+ ((KToggleAction*)actionCollection()->action("song_loop"))->setChecked(true);
+
+ if (cfg->readNumEntry("ShowVolumeBar",0)==1)
+ ((KToggleAction*)actionCollection()->action("toggle_volumebar"))->setChecked(true);
+
+
+ tmplistaction=((KSelectAction*)actionCollection()->action("play_order"));
+ if (cfg->readNumEntry("CollectionPlayMode",0)==0)
+ tmplistaction->setCurrentItem(0);
+ else
+ tmplistaction->setCurrentItem(1);
+
+ if ((cfg->readNumEntry("AutoAddToCollection",0))==1)
+ ((KToggleAction*)actionCollection()->action("collect_autoadd"))->setChecked(true);
+
+ if ((cfg->readNumEntry("AutomaticTextEventChooser",1))==1)
+ ((KToggleAction*)actionCollection()->action("option_automatictext"))->setChecked(true);
+
+ setAcceptDrops(true);
+
+ connect( kmidclient, SIGNAL( mustRechooseTextEvent() ),
+ this, SLOT( rechooseTextEvent() ) );
+
+ connect( kmidclient, SIGNAL( stopPause() ),
+ this, SLOT( song_stopPause() ) );
+
+// connect( kmidclient, SIGNAL( channelView_Destroyed() ),
+// this, SLOT( channelViewDestroyed() ) );
+
+ KCmdLineArgs * args = KCmdLineArgs::parsedArgs();
+
+ if ( args->count() > 0 )
+ {
+// printf("Opening command line file...\n");
+ int backautoadd=cfg->readNumEntry("AutoAddToCollection",0);
+ cfg->writeEntry("AutoAddToCollection",0);
+
+ char ttt[40];
+ sprintf(ttt,"%d",kapp->argc());
+ int i=0;
+ int c=autoAddSongToCollection( args->url( 0 ).path() , 1 );
+ i++;
+ while (i<args->count())
+ {
+ autoAddSongToCollection( args->url( i ).path() , 0 );
+ i++;
+ }
+
+ kmidclient->setActiveCollection(c);
+
+ /// kmidclient->openURL((kapp->argv())[1]);
+ /* if ((cfg->readNumEntry("AutomaticTextEventChooser",1))==1)
+ {
+ if (kmidclient->ChooseTypeOfTextEvents()==1)
+ options_Text();
+ else
+ options_Lyrics();
+ }*/
+ if (kmidclient->midiFileName()!=NULL) kmidclient->play();
+ cfg->writeEntry("AutoAddToCollection",backautoadd);
+ }
+
+ args->clear();
+ /*
+ kKeys->addKey("Play/Pause",Key_Space);
+ kKeys->registerWidget("KMidFrame",this);
+ kKeys->connectFunction("KMidFrame","Play/Pause",this,SLOT(spacePressed()));
+ */
+// kKeysAccel->writeSettings(cfg);
+
+ DCOPClient *client = kapp->dcopClient();
+ if (!client->isRegistered()) // just in case we're embeeded
+ {
+ client->attach();
+ client->registerAs("kmid");
+ }
+}
+
+kmidFrame::~kmidFrame()
+{
+}
+
+void kmidFrame::file_Open()
+{
+ KURL url = KFileDialog::getOpenURL(QString::null, "*.kar *.mid *.kar.gz *.mid.gz\n*.kar *.kar.gz\n*.mid *.mid.gz\n*",this);
+
+ if( url.isEmpty() )
+ return;
+
+ if( !url.isLocalFile() )
+ {
+ KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) );
+ return;
+ }
+
+ openURL(url.path());
+}
+
+
+
+void kmidFrame::song_stopPause()
+{
+ if (kmidclient->isPaused())
+ {
+ // song_Pause();
+ ((KToggleAction*)actionCollection()->action("song_pause"))->setChecked(false);
+ kmidclient->pause();
+ }
+}
+
+void kmidFrame::options_FileType(int i)
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ cfg->writeEntry("TypeOfMidiFile",i);
+ kmidclient->setSongType(1-i);
+}
+
+void kmidFrame::options_DisplayEvents(int i)
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ cfg->writeEntry("TypeOfTextEvents",(i==0)?1:5);
+ cfg->sync();
+ kmidclient->repaintText((i==0)?1:5);
+}
+
+void kmidFrame::options_AutomaticText()
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ cfg->writeEntry("AutomaticTextEventChooser",1-cfg->readNumEntry("AutomaticTextEventChooser",1));
+}
+
+void kmidFrame::options_FontChange()
+{
+ KFontDialog *kfd=new KFontDialog(this);
+ QFont font;
+ font=*kmidclient->getFont();
+ kfd->getFont(font);
+ delete kfd;
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ cfg->writeEntry("KaraokeFont",font);
+ cfg->sync();
+ kmidclient->fontChanged();
+}
+
+int kmidFrame::autoAddSongToCollection(const QString& filename,int setactive)
+{
+ int r;
+ SLManager *slman;
+ SongList *sl;
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ if (cfg->readNumEntry("AutoAddToCollection",0)==0)
+ {
+ r=0;
+ slman=kmidclient->getSLManager();
+ if (setactive) slman->createTemporaryCollection();
+ sl=slman->getCollection(0);
+ if (filename==NULL) sl->AddSong(kmidclient->midiFileName());
+ else sl->AddSong(QFile::encodeName(filename));
+ }
+ else
+ {
+ slman=kmidclient->getSLManager();
+ sl=slman->getCollection(kmidclient->getActiveCollection());
+ r=kmidclient->getActiveCollection();
+ if (sl==NULL) return 0;
+ int id;
+ if (filename==NULL) id=sl->AddSong(kmidclient->midiFileName());
+ else id=sl->AddSong(QFile::encodeName(filename));
+ if (setactive)
+ {
+ sl->setActiveSong(id);
+ }
+ }
+ return r;
+}
+
+void kmidFrame::urlDrop_slot(QDropEvent* e)
+{
+ dropEvent(e);
+}
+
+void kmidFrame::dragEnterEvent(QDragEnterEvent* e)
+{
+ e->accept(KURLDrag::canDecode(e));
+}
+
+void kmidFrame::dropEvent( QDropEvent * event )
+{
+ KURL::List list;
+ KURLDrag::decode(event, list);
+
+ if (list.count()==0) return;
+
+ bool first = true;
+ int c = true;
+
+ for (KURL::List::ConstIterator it = list.begin();
+ it != list.end(); ++it)
+ {
+ if (!(*it).isLocalFile())
+ continue;
+
+ if (first)
+ {
+ c = autoAddSongToCollection((*it).path(),1);
+ first = false;
+ }
+ else
+ {
+ autoAddSongToCollection((*it).path(),0);
+ }
+ }
+
+ if (!first)
+ {
+ kmidclient->setActiveCollection(c);
+
+ if ((!kmidclient->isPlaying())&&(kmidclient->midiFileName()!=NULL))
+ kmidclient->play();
+ }
+}
+
+void kmidFrame::shuttingDown()
+{
+ if (kmidclient->isPlaying()==1)
+ {
+// kmidclient->stop();
+ kmidclient->shuttingDown();
+ }
+ kmidclient->saveCollections();
+}
+
+void kmidFrame::saveProperties(KConfig *cfg)
+{
+ kmidclient->saveCollections();
+ int play=kmidclient->isPlaying();
+ cfg->writeEntry("File",kmidclient->midiFileName());
+ cfg->writeEntry("ActiveCollection",kmidclient->getActiveCollection());
+ cfg->writeEntry("ActiveSong",kmidclient->getSelectedSong());
+ cfg->writeEntry("Playing",play);
+}
+
+void kmidFrame::readProperties(KConfig *cfg)
+{
+ int activecol=cfg->readNumEntry("ActiveCollection",0);
+ int activesong=cfg->readNumEntry("ActiveSong",0);
+ int wasplaying=cfg->readNumEntry("Playing",0);
+ SLManager *slman=kmidclient->getSLManager();
+ SongList *sl=slman->getCollection(activecol);
+ sl->setActiveSong(activesong);
+ kmidclient->setActiveCollection(activecol);
+ kmidclient->slotSelectSong(activesong-1);
+
+ if ((activecol==0)&&(wasplaying)) // It was the temporary collection,
+ { // surely the user would like to continue
+ // hearing the song
+ QString s = cfg->readPathEntry("File");
+ int c=autoAddSongToCollection(s,1);
+ kmidclient->setActiveCollection(c);
+ }
+
+ if ((wasplaying)&&(kmidclient->midiFileName()!=NULL)) kmidclient->play();
+}
+
+void kmidFrame::options_MidiSetup()
+{
+ if (kmidclient->devman()->checkInit()<0)
+ {
+ KMessageBox::error(this,
+ i18n("Could not open /dev/sequencer to get some info.\nProbably there is another program using it."));
+ return;
+ }
+ MidiConfigDialog *dlg;
+
+ dlg=new MidiConfigDialog(kmidclient->devman(),NULL,"MidiDialog");
+ if (dlg->exec() == QDialog::Accepted)
+ {
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ cfg->writeEntry("MidiPortNumber",MidiConfigDialog::selecteddevice);
+ kmidclient->setMidiDevice(MidiConfigDialog::selecteddevice);
+ cfg->setGroup("Midimapper");
+ cfg->writePathEntry("LoadFile",
+ (MidiConfigDialog::selectedmap==NULL)? QString::null:MidiConfigDialog::selectedmap);
+ kmidclient->setMidiMapFilename(MidiConfigDialog::selectedmap);
+ }
+ delete dlg;
+}
+
+void kmidFrame::collect_organize()
+{
+ CollectionDialog *dlg;
+ SLManager *slman=new SLManager(*kmidclient->getSLManager());
+ int idx=kmidclient->getActiveCollection();
+
+ dlg=new CollectionDialog(slman,idx,NULL,"MidiDialog");
+ if (dlg->exec() == QDialog::Accepted)
+ {
+ kmidclient->setSLManager(slman);
+ kmidclient->setActiveCollection(CollectionDialog::selectedC);
+ kmidclient->slotSelectSong(
+ (slman->getCollection(CollectionDialog::selectedC))->getActiveSongID()-1);
+ }
+ else
+ {
+ delete slman;
+ }
+delete dlg;
+}
+
+void kmidFrame::rechooseTextEvent()
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ if ((cfg->readNumEntry("AutomaticTextEventChooser",1))==1)
+ {
+ int t=kmidclient->ChooseTypeOfTextEvents();
+ kmidclient->repaintText(t);
+ if (t==1)
+ ((KSelectAction*)actionCollection()->action("display_events"))->setCurrentItem(0);
+ else
+ ((KSelectAction*)actionCollection()->action("display_events"))->setCurrentItem(1);
+ }
+}
+
+void kmidFrame::song_Loop()
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ int i=1-cfg->readNumEntry("Loop",0);
+ cfg->writeEntry("Loop",i);
+ cfg->sync();
+ kmidclient->setSongLoop(i);
+}
+
+void kmidFrame::collect_PlayOrder(int i)
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ cfg->writeEntry("CollectionPlayMode", i);
+ cfg->sync();
+ kmidclient->setCollectionPlayMode(i);
+}
+
+void kmidFrame::collect_AutoAdd()
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ cfg->writeEntry("AutoAddToCollection",1-cfg->readNumEntry("AutoAddToCollection",0));
+ cfg->sync();
+}
+
+void kmidFrame::file_SaveLyrics()
+{
+ KURL url = KFileDialog::getSaveURL(QString::null,"*",this);
+
+ if( url.isEmpty() )
+ return;
+
+ if( !url.isLocalFile() )
+ {
+ KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) );
+ return;
+ }
+
+ QString filename = url.path();
+ struct stat statbuf;
+
+ if (stat(QFile::encodeName(filename), &statbuf)!=-1)
+ {
+ QString s = i18n("File %1 already exists\nDo you want to overwrite it?").arg(filename);
+ if (KMessageBox::warningYesNo(this,s,QString::null,i18n("Overwrite"),KStdGuiItem::cancel())==1)
+ return;
+ }
+
+ FILE *fh=fopen(QFile::encodeName(filename),"wt");
+ kmidclient->saveLyrics(fh);
+ fclose(fh);
+}
+
+void kmidFrame::spacePressed()
+{
+ if (!kmidclient->isPlaying()) kmidclient->play();
+ else pause();
+}
+void kmidFrame::options_ShowVolumeBar()
+{
+ KConfig *cfg=kapp->config();
+ cfg->setGroup("KMid");
+ int i=1-cfg->readNumEntry("ShowVolumeBar",0);
+ cfg->writeEntry("ShowVolumeBar",i);
+ kmidclient->visibleVolumeBar(i);
+}
+
+void kmidFrame::options_ShowChannelView()
+{
+ if (!((KToggleAction*)actionCollection()->action("toggle_channelview"))->isChecked())
+ {
+ kmidclient->visibleChannelView(0);
+ } else
+ {
+ kmidclient->visibleChannelView(1);
+ connect (kmidclient->getChannelView(),SIGNAL(destroyMe()),this,SLOT(channelViewDestroyed()));
+ }
+
+}
+
+void kmidFrame::channelViewDestroyed()
+{
+ kmidclient->channelViewDestroyed();
+ ((KToggleAction*)actionCollection()->action("toggle_channelview"))->setChecked(false);
+}
+
+void kmidFrame::options_ChannelViewOptions()
+{
+ ChannelViewConfigDialog *dlg;
+
+ dlg=new ChannelViewConfigDialog(NULL,"ChannelViewConfigDialog");
+ if (dlg->exec() == QDialog::Accepted)
+ {
+ if (kmidclient->getChannelView())
+ kmidclient->getChannelView()->lookMode(
+ ChannelViewConfigDialog::selectedmode );
+ }
+ delete dlg;
+}
+
+void kmidFrame::openURL( const QString url )
+{
+ int c=autoAddSongToCollection(url,1);
+ kmidclient->setActiveCollection(c);
+}
+
+/*void kmidFrame::play()
+{
+ kmidclient->play();
+}
+
+void kmidFrame::pause()
+{
+// kmidclient->pause();
+ ((KAction*)actionCollection()->action("pause"))->activate();
+}
+
+void kmidFrame::stop()
+{
+ kmidclient->stop();
+}
+
+void kmidFrame::rewind()
+{
+ kmidclient->rewind();
+}
+
+void kmidFrame::forward()
+{
+ kmidclient->forward();
+}
+
+void kmidFrame::seek(int ms)
+{
+ kmidclient->timebarChange(ms);
+}
+
+void kmidFrame::prevSong()
+{
+ kmidclient->prevSong();
+}
+
+void kmidFrame::nextSong()
+{
+ kmidclient->nextSong();
+}
+
+void kmidFrame::setSongLoop(int i)
+{
+ ((KToggleAction*)actionCollection()->action("song_loop"))->setChecked(i!=0);
+}
+
+void kmidFrame::setVolume(int i)
+{
+ kmidclient->volumebarChange(200-i);
+}
+
+void kmidFrame::setTempo(int i)
+{
+ kmidclient->changeTempo(i);
+}
+
+void kmidFrame::setSongType( int i )
+{
+ KSelectAction *tmplistaction=
+ ((KSelectAction*)actionCollection()->action("file_type"));
+
+ tmplistaction->setCurrentItem(i);
+}
+
+void kmidFrame::setLyricEvents( int i )
+{
+ KSelectAction *tmplistaction=
+ ((KSelectAction*)actionCollection()->action("display_events"));
+ tmplistaction->setCurrentItem(i);
+}
+
+void kmidFrame::selectSong(int i)
+{
+ kmidclient->getComboSongs()->setCurrentItem(i-1);
+ kmidclient->selectSong(i-1);
+}
+
+void kmidFrame::setActiveCollection( int i )
+{
+ kmidclient->setActiveCollection(i);
+}
+
+void kmidFrame::setCollectionPlayMode(int i)
+{
+ ((KSelectAction*)actionCollection()->action("play_order"))->setCurrentItem(i);
+}
+
+void kmidFrame::setMidiDevice(int i)
+{
+
+
+}
+*/
+
+
+#include "kmidframe.moc"
diff --git a/kmid/kmidframe.h b/kmid/kmidframe.h
new file mode 100644
index 00000000..e88c902a
--- /dev/null
+++ b/kmid/kmidframe.h
@@ -0,0 +1,133 @@
+/**************************************************************************
+
+ kmidframe.h - The main 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _KMIDFRAME_H
+#define _KMIDFRAME_H
+
+#include <kmainwindow.h>
+#include <kmenubar.h>
+#include <libkmid/midiout.h>
+#include <libkmid/player.h>
+#include <libkmid/track.h>
+#include <qtimer.h>
+#include <kdelibs_export.h>
+
+class KApplication;
+class KConfig;
+class kmidClient;
+class KToolBar;
+class QDragEvent;
+class KAccel;
+
+class KDE_EXPORT kmidFrame : public KMainWindow
+{
+ Q_OBJECT
+private:
+#ifdef KMidDEBUG
+ long passcount;
+#endif
+
+ MidiOut *Midi;
+ MidiPlayer *Player;
+/*
+ int playerProcessID;
+ PlayerController *pctl;
+
+ int donttoggle;
+
+ QPopupMenu *m_file;
+ QPopupMenu *m_song;
+ QPopupMenu *m_collections;
+ QPopupMenu *m_options;
+ QPopupMenu *m_help;
+*/
+ KAccel *kKeysAccel;
+protected:
+ int autoAddSongToCollection(const QString& filename=QString::null,int setactive=1);
+
+
+ virtual void saveProperties(KConfig *kcfg);
+ virtual void readProperties(KConfig *kcfg);
+
+// virtual void closeEvent(QCloseEvent *e);
+
+ void dragEnterEvent(QDragEnterEvent* e);
+ void dropEvent ( QDropEvent * event );
+
+
+public:
+ kmidFrame(const char *name=0);
+ virtual ~kmidFrame();
+
+public slots:
+
+ void file_Open();
+ void file_SaveLyrics();
+ void song_stopPause(); // release the pause button and quit the pause mode
+ void song_Loop();
+ void collect_organize();
+ void collect_PlayOrder(int i);
+ void collect_AutoAdd();
+ void options_FileType(int i);
+ void options_DisplayEvents(int i);
+ void options_AutomaticText();
+ void options_ShowVolumeBar();
+ void options_ShowChannelView();
+ void options_ChannelViewOptions();
+ void options_FontChange();
+
+ void options_MidiSetup();
+ void spacePressed();
+
+
+ virtual void openURL( const QString s );
+/* virtual void play();
+ virtual void pause();
+ virtual void stop();
+ virtual void rewind();
+ virtual void forward();
+ virtual void seek(int ms);
+ virtual void prevSong();
+ virtual void nextSong();
+ virtual void setSongLoop(int i);
+ virtual void setVolume(int i);
+ virtual void setTempo(int i);
+ virtual void setSongType( int i );
+ virtual void setLyricEvents( int i );
+ virtual void selectSong(int i);
+ virtual void setActiveCollection( int i );
+ virtual void setCollectionPlayMode(int i);
+ virtual void setMidiDevice(int i);
+*/
+ void urlDrop_slot(class QDropEvent *);
+
+ void rechooseTextEvent();
+
+ void channelViewDestroyed();
+ void shuttingDown();
+
+private:
+ kmidClient *kmidclient;
+};
+
+#endif
diff --git a/kmid/kmidui.rc b/kmid/kmidui.rc
new file mode 100644
index 00000000..8553ad2e
--- /dev/null
+++ b/kmid/kmidui.rc
@@ -0,0 +1,44 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kmid" version="3">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="file_save_lyrics"/>
+ </Menu>
+ <Menu name="song"><text>&amp;Song</text>
+ <Action name="song_play"/>
+ <Action name="song_pause"/>
+ <Action name="song_stop"/>
+ <Action name="song_previous"/>
+ <Action name="song_next"/>
+ <Action name="song_loop"/>
+ </Menu>
+ <Menu name="collections"><text>&amp;Collections</text>
+ <Action name="collect_organize"/>
+ <Action name="play_order"/>
+ <Action name="collect_autoadd"/>
+ </Menu>
+ <Menu name="settings">
+ <Action name="toggle_volumebar" append="show_merge"/>
+ <Action name="toggle_channelview" append="show_merge"/>
+ <Action name="file_type" append="save_merge"/>
+ <Action name="display_events" append="save_merge"/>
+ <Action name="option_automatictext" append="save_merge"/>
+ <Separator append="save_merge"/>
+ <Action name="channelview_options" append="save_merge"/>
+ <Action name="change_font" append="save_merge"/>
+ <Action name="midi_setup" append="save_merge"/>
+ </Menu>
+</MenuBar>
+<ToolBar fullWidth="true" name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="song_previous"/>
+ <Action name="song_rewind"/>
+ <Action name="song_stop"/>
+ <Action name="song_pause"/>
+ <Action name="song_play"/>
+ <Action name="song_forward"/>
+ <Action name="song_next"/>
+ <Separator/>
+ <Action name="toggle_volumebar"/>
+ <Action name="toggle_channelview"/>
+</ToolBar>
+</kpartgui>
diff --git a/kmid/ktrianglebutton.cpp b/kmid/ktrianglebutton.cpp
new file mode 100644
index 00000000..61e1af96
--- /dev/null
+++ b/kmid/ktrianglebutton.cpp
@@ -0,0 +1,164 @@
+/**************************************************************************
+
+ ktrianglebutton.cpp - The KTriangleButton widget (button with an arrow)
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+ Note: This widget was based on KButton as found in the kdelibs/kdeui
+ KButton was originally copyrighted by Torben Weis (weis@kde.org)
+ and Matthias Ettrich (ettrich@kde.org) on 1997
+
+***************************************************************************/
+#include "ktrianglebutton.h"
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qstyle.h>
+
+KTriangleButton::KTriangleButton( Direction d,QWidget *_parent, const char *name )
+ : QButton( _parent , name)
+{
+ dir=d;
+ raised = FALSE;
+ setFocusPolicy( NoFocus );
+}
+
+KTriangleButton::~KTriangleButton()
+{
+}
+
+void KTriangleButton::enterEvent( QEvent* )
+{
+ if ( isEnabled() )
+ {
+ raised = TRUE;
+ repaint(FALSE);
+ }
+}
+
+void KTriangleButton::leaveEvent( QEvent * )
+{
+ if( raised != FALSE )
+ {
+ raised = FALSE;
+ repaint();
+ }
+}
+
+
+void KTriangleButton::drawButton( QPainter *_painter )
+{
+ paint( _painter );
+}
+
+void KTriangleButton::drawButtonLabel( QPainter *_painter )
+{
+ paint( _painter );
+}
+
+void KTriangleButton::paint( QPainter *painter )
+{
+ if ( isDown() || isOn() )
+ {
+ if ( style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ qDrawWinButton( painter, 0, 0, width(),
+ height(), colorGroup(), TRUE );
+ else
+ qDrawShadePanel( painter, 0, 0, width(),
+ height(), colorGroup(), TRUE, 2, 0L );
+ }
+ else if ( raised )
+ {
+ if ( style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ qDrawWinButton( painter, 0, 0, width(), height(),
+ colorGroup(), FALSE );
+ else
+ qDrawShadePanel( painter, 0, 0, width(), height(),
+ colorGroup(), FALSE, 2, 0L );
+ }
+
+ if (dir==Right)
+ {
+ int x=width()/4;
+ int y=height()/6;
+ int l=height()-y*2;
+ int i=0;
+ int maxi=width()-2*x;
+ double m=(double)(l/2)/maxi;
+ while (i<=maxi)
+ {
+ painter->drawLine(x,y+(int)(i*m),x,y+l-(int)(i*m));
+ x++;
+ i++;
+ };
+ }
+ else if (dir==Left)
+ {
+ int x=width()/4;
+ int y=height()/6;
+ int l=height()-y*2;
+ int i=0;
+ int maxi=width()-2*x;
+ x=width()-x;
+ double m=(double)(l/2)/maxi;
+ while (i<=maxi)
+ {
+ painter->drawLine(x,y+(int)(i*m),x,y+l-(int)(i*m));
+ x--;
+ i++;
+ };
+
+ };
+
+}
+
+void KTriangleButton::mousePressEvent(QMouseEvent *e)
+{
+ QButton::mousePressEvent(e);
+ usingTimer=true;
+ startTimer(500);
+ timeCount=0;
+
+}
+
+void KTriangleButton::mouseReleaseEvent(QMouseEvent *e)
+{
+ usingTimer=false;
+ QButton::mouseReleaseEvent(e);
+}
+
+void KTriangleButton::timerEvent(QTimerEvent *)
+{
+ if (!usingTimer) {killTimers();return;};
+ if (timeCount==0)
+ {
+ timeCount++;
+ killTimers();
+ startTimer(120);
+ } else
+ if (timeCount==30)
+ {
+ timeCount=-1;
+ killTimers();
+ startTimer(80);
+ }
+ else if (timeCount>0) timeCount++;
+ emit clickedQuickly();
+
+}
+#include "ktrianglebutton.moc"
diff --git a/kmid/ktrianglebutton.h b/kmid/ktrianglebutton.h
new file mode 100644
index 00000000..f7bad7fd
--- /dev/null
+++ b/kmid/ktrianglebutton.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+
+ ktrianglebutton.h - The KTriangleButton widget (button with an arrow)
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+ Note: This widget was copied from KButton as found in the kdelibs/kdeui
+ KButton was originally copyrighted by Torben Weis (weis@kde.org)
+ and Matthias Ettrich (ettrich@kde.org) on 1997
+
+***************************************************************************/
+#ifndef _ktrianglebutton_h_
+#define _ktrianglebutton_h_
+
+#include <qbutton.h>
+
+class KTriangleButton : public QButton
+{
+ Q_OBJECT
+
+public:
+ enum Direction {Left , Right, Up, Down};
+ /*
+ Up and Down are not implemented, feel free to implement them yourself
+ if you need them :-)
+ */
+protected:
+
+ Direction dir;
+ bool usingTimer;
+ int timeCount;
+
+public:
+ KTriangleButton( Direction d,QWidget *_parent = 0L, const char *name = 0L );
+ ~KTriangleButton();
+
+ virtual void leaveEvent( QEvent *_ev );
+ virtual void enterEvent( QEvent *_ev );
+
+ virtual void drawButton( QPainter *_painter );
+ virtual void drawButtonLabel( QPainter *_painter );
+
+ void paint( QPainter *_painter );
+
+signals:
+ void clickedQuickly();
+
+protected:
+ bool raised;
+
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+ virtual void timerEvent(QTimerEvent *);
+
+};
+
+#endif
diff --git a/kmid/main.cpp b/kmid/main.cpp
new file mode 100644
index 00000000..bb991d74
--- /dev/null
+++ b/kmid/main.cpp
@@ -0,0 +1,101 @@
+/**************************************************************************
+
+ main.cpp - The main function for 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include <qwidget.h>
+#include <qtextcodec.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kio/job.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+
+#include "kmidframe.h"
+#include "kmid_part.h"
+#include "version.h"
+
+int main(int argc, char **argv)
+{
+ printf("%s Copyright (C) 1997,98,99,2000,01 Antonio Larrosa Jimenez. Malaga (Spain)\n",VERSION_TXT);
+ printf("KMid comes with ABSOLUTELY NO WARRANTY; for details view file COPYING\n");
+ printf("This is free software, and you are welcome to redistribute it\n");
+ printf("under certain conditions\n\n");
+
+ QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
+/*
+ struct sigaction act;
+ act.sa_handler = SIG_DFL;
+ sigemptyset(&(act.sa_mask));
+ act.sa_flags=0;
+
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+*/
+
+ KCmdLineArgs::init(argc, argv, KMidFactory::aboutData() );
+
+ static KCmdLineOptions options[] =
+ {
+ { "+file", I18N_NOOP("File to open"), 0 },
+ KCmdLineLastOption
+ };
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KApplication app;
+
+ kmidFrame *kmidframe=new kmidFrame("KMid");
+
+ app.setMainWidget ( kmidframe );
+
+ QObject::connect(&app,SIGNAL(shutDown()),kmidframe,SLOT(shuttingDown()));
+
+ if (app.isRestored())
+ {
+ if (kmidframe->canBeRestored(1)) kmidframe->restore(1);
+ }
+
+ kmidframe->show();
+
+ //CT KIOJob::initStatic();
+
+/*
+ if (app->isRestored())
+ {
+ RESTORE(kmidFrame);
+ }
+ else
+ {
+ kmidFrame *kmidframe=new kmidFrame("KMid");
+ kmidframe->show();
+ };
+*/
+
+
+
+ return app.exec();
+}
+
diff --git a/kmid/maps/Makefile.am b/kmid/maps/Makefile.am
new file mode 100644
index 00000000..d276e13e
--- /dev/null
+++ b/kmid/maps/Makefile.am
@@ -0,0 +1,5 @@
+
+maps_DATA = gm.map YamahaPSS790.map YamahaPSR500.map YamahaQY10.map
+mapsdir = $(kde_datadir)/kmid/maps
+
+EXTRA_DIST = $(maps_DATA)
diff --git a/kmid/maps/YamahaPSR500.map b/kmid/maps/YamahaPSR500.map
new file mode 100644
index 00000000..16068c21
--- /dev/null
+++ b/kmid/maps/YamahaPSR500.map
@@ -0,0 +1,293 @@
+# Blank lines and lines beginning with # are ignored
+# This is a map for a Yamaha PSR-500 keyboard
+# This file was done by Dietmar Schnabel (thanks !)
+
+# If you make a new map, please send it to Antonio, so future releases
+# will include them.
+# Antonio Larrosa Jimenez, larrosa@kde.org
+
+# General Midi Map File
+
+DEFINE PATCHMAP
+AcusticPiano =0
+BrightPiano =0
+SynthPiano =3
+HonkyTonky =2
+ElectricPiano1=4
+ElectricPiano2=5
+Harpsichord =6
+Clavinet =8
+Celeste =9
+Glockenspiel =40
+Musicbox =41
+Vibes =40
+Marimba =41
+Xylophon =41
+TubeBell =41
+Santur =42
+HomeOrg =12
+PercussionOrg =13
+RockOrg =14
+ChurchOrg =10
+ReedOrg =11
+Accordion =16
+Harmonica =17
+Concrtna =17
+NylonGuitar =29
+AcusticGuitar =31
+JazzGuitar =24
+CleanGuitar =19
+MuteGuitar =26
+OdGuitar =18
+DistortionGuit=23
+GtrHarm =20
+AcusticBass =88
+FingerBass =89
+PickBass =87
+FretlessBass =84
+SlapBass1 =87
+SlapBass2 =87
+SynthBass1 =90
+SynthBass2 =91
+Violin =32
+Viola =33
+Cello =34
+Contrabajo =33
+Marcato =34
+Pizzicato =38
+Harp =38
+Timpani =33
+Marcato =34
+SlowStrings =35
+SynthStrings1 =36
+SynthStrings2 =75
+Choir =72
+Doo =72
+Voices =72
+OrchestraHit =37
+Trumpet =43
+Trombone =47
+Tuba =50
+MuteTrumpet =44
+FrenchHorn =49
+HitBrass =51
+SynthBrass1 =52
+SynthBrass2 =74
+SopranoSax =60
+AltoSax =61
+TenorSax =62
+BaritoneSax =63
+Oboe =57
+EnglishHorn =58
+Bassoon =59
+Clarinet =55
+Piccolo =53
+Flute =54
+Recorder =66
+WoodFlute =65
+Bottle =55
+Shakazul =55
+Whistle =68
+Ocarina =79
+SquareWave =80
+SawWave =81
+Calliope =82
+Chiflead =83
+Charang =84
+VoxLead =85
+Lead5th =86
+BassLead =87
+Fantasia =88
+WarmPad =89
+Polysyn =90
+Ghostie =91
+BowGlass =92
+MetalPad =93
+HaloPad =94
+Sweeper =95
+Aurora =72
+SoundTrack =72
+Crystal =72
+Atmosphear =72
+FreshAir =100
+Unicorn =101
+Sweeper =102
+StarTrak =103
+Sitar =104
+Banjo =105
+Shamisen =106
+Koto =107
+Kalimba =108
+BagPipes =109
+Fiddle =110
+Shannai =111
+Carillon =112
+Agogo =113
+SteelDrm =114
+WoodBlk =115
+Taiko =116
+Toms =117
+Syntom =118
+RevCymbal =119
+Fx-Fret =120
+Fx-Blow =121
+Seashore =122
+Jungle =123
+Telephon =124
+Helicopter =125
+Applause =126
+Gunshot =127
+END
+
+DEFINE KEYMAP "Drumset"
+C 0 =0
+C#0 =1
+D 0 =2
+D#0 =3
+E 0 =4
+F 0 =5
+F#0 =6
+G 0 =7
+G#0 =8
+A 0 =9
+A#0 =10
+B 0 =11
+C 1 =12
+C#1 =13
+D 1 =14
+D#1 =15
+E 1 =16
+F 1 =17
+F#1 =18
+G 1 =19
+G#1 =20
+A 1 =21
+A#1 =22
+B 1 =23
+C 2 =24
+C#2 =25
+D 2 =26
+D#2 27 Highq =27
+E 2 28 Slap =54
+F 2 29 Scratch1 =62
+F#2 30 Scratch2 =63
+G 2 31 Sticks =22
+G#2 32 SqrClick =87
+A 2 33 MetaClick=57
+A#2 34 MetBell =55
+B 2 35 Kick1 =44
+C 3 36 Kick2 =45
+C#3 37 StickRim =27
+D 3 38 Snare1 =28
+D#3 39 Claps =30
+E 3 40 snare2 =25
+F 3 41 tomlo2 =24
+F#3 42 Hihatclos=72
+G 3 43 Tomlo1 =17
+G#3 44 HihatPd =56
+A 3 45 Tommid2 =26
+A#3 46 Hihatop =35
+B 3 47 Tommid1 =18
+C 4 48 Tomhi2 =29
+C#4 49 Cymbalcrsh1 =36
+D 4 50 Tomhi1 =19
+D#4 51 Cymbalride1 =38
+E 4 52 Cymbalchina =38
+F 4 53 Cymbell =38
+F#4 54 Tamborin =47
+G 4 55 CymbalSplash=37
+G#4 56 Cowbell =31
+A 4 57 Cymbalcrash2=36
+A#4 58 Vibslap =39
+B 4 59 Cymbalride2 =39
+C 5 60 Bongohi =44
+C#5 61 Bongolo =43
+D 5 62 Congahi1 =41
+D#5 63 congahi2 =42
+E 5 64 Congalo =40
+F 5 65 Timbalehi=46
+F#5 66 Timbalelo=45
+G 5 67 Agogohi =51
+G#5 68 Agogolo =50
+A 5 69 Cabasa =32
+A#5 70 Maracas =65
+B 5 71 whistle1 =52
+C 6 72 whistle2 =53
+C#6 73 Guiro1 =74
+D 6 74 Guiro2 =74
+D#6 75 Clave =29
+E 6 76 Woodblock1=73
+F 6 77 Woodblock2=72
+F#6 78 Cuica1 =76
+G 6 79 Cuica2 =77
+G#6 80 Triangle1=13
+A 6 81 Triangle2=15
+A#6 82 Shaker =56
+B 6 83 Jingles =75
+C 7 84 Belltree =71
+C#7 85 Canstinet=85
+D 7 86 Surdo1 =86
+D#7 87 Surdo2 =87
+E 7 =88
+F 7 =89
+F#7 =90
+G 7 =91
+G#7 =92
+A 7 =93
+A#7 =94
+B 7 =95
+C 8 =96
+C#8 =97
+D 8 =98
+D#8 =99
+E 8 =100
+F 8 =101
+F#8 =102
+G 8 =103
+G#8 =104
+A 8 =105
+A#8 =106
+B 8 =107
+C 9 =108
+C#9 =109
+D 9 =110
+D#9 =111
+E 9 =112
+F 9 =113
+F#9 =114
+G 9 =115
+G#9 =116
+A 9 =117
+A#9 =118
+B 9 =119
+C 10=120
+C#10=121
+D 10=122
+D#10=123
+E 10=124
+F 10=125
+F#10=126
+G 10=127
+# This line should be ignored
+END
+
+
+DEFINE CHANNELMAP
+0 = 0
+1 = 1
+2 = 2
+3 = 3
+4 = 4
+5 = 5
+6 = 6
+7 = 7
+8 = 8
+9 = 9 Keymap "Drumset" ForcePatch 99
+10 = 10
+11 = 11
+12 = 12
+13 = 13
+14 = 14
+15 = 15
+END
+
diff --git a/kmid/maps/YamahaPSS790.map b/kmid/maps/YamahaPSS790.map
new file mode 100644
index 00000000..5017832e
--- /dev/null
+++ b/kmid/maps/YamahaPSS790.map
@@ -0,0 +1,299 @@
+# Blank lines and lines beginning with # are ignored
+# This is my a map for the Yamaha PSS-790 keyboard
+# it can be used as a template to make any new map for any
+# other keyboard.
+# If you make a new map, please send it to me, so future releases
+# will include it.
+# Antonio Larrosa Jimenez, larrosa@kde.org
+
+# Yamaha PSS-790 Map File
+
+DEFINE PATCHMAP
+AcusticPiano =3
+BrightPiano =3
+SynthPiano =54
+HonkyTonky =25
+ElectricPiano1=25
+ElectricPiano2=25
+Harpsichord =53
+Clavinet =30
+Celeste =6
+Glockenspiel =64
+Musicbox =24
+Vibes =28
+Marimba =8
+Xylophon =24
+TubeBell =95
+Santur =30
+HomeOrg =1
+PercussionOrg =2
+RockOrg =11
+ChurchOrg =29
+ReedOrg =49
+Accordion =31
+Harmonica =22
+Concrtna =3
+NylonGuitar =36
+AcusticGuitar =68
+JazzGuitar =122
+CleanGuitar =68
+MuteGuitar =12
+OdGuitar =123
+DistortionGuit=13
+GtrHarm =72
+AcusticBass =38
+FingerBass =39
+PickBass =79
+FretlessBass =80
+SlapBass1 =14
+SlapBass2 =81
+SynthBass1 =58
+SynthBass2 =86
+Violin =10
+Viola =67
+Cello =67
+Contrabajo =41
+Marcato =41
+Pizzicato =78
+Harp =37
+Timpani =66
+Marcato =41
+SlowStrings =50
+SynthStrings1 =41
+SynthStrings2 =50
+Choir =96
+Doo =94
+Voices =96
+OrchestraHit =90
+Trumpet =15
+Trombone =16
+Tuba =84
+MuteTrumpet =44
+FrenchHorn =17
+HitBrass =92
+SynthBrass1 =0
+SynthBrass2 =82
+SopranoSax =101
+AltoSax =18
+TenorSax =102
+BaritoneSax =101
+Oboe =19
+EnglishHorn =87
+Bassoon =87
+Clarinet =19
+Piccolo =103
+Flute =20
+Recorder =88
+WoodFlute =111
+Bottle =111
+Shakazul =110
+Whistle =88
+Ocarina =93
+SquareWave =54
+SawWave =54
+Calliope =22
+Chiflead =9
+Charang =19
+VoxLead =96
+Lead5th =41
+BassLead =95
+Fantasia =111
+WarmPad =51
+Polysyn =60
+Ghostie =94
+BowGlass =33
+MetalPad =9
+HaloPad =111
+Sweeper =78
+Aurora =60
+SoundTrack =84
+Crystal =60
+Atmosphear =51
+FreshAir =60
+Unicorn =93
+Sweeper =112
+StarTrak =117
+Sitar =73
+Banjo =34
+Shamisen =73
+Koto =70
+Kalimba =73
+BagPipes =11
+Fiddle =67
+Shannai =11
+Carillon =64
+Agogo =91
+SteelDrm =9
+WoodBlk =35
+Taiko =100 AllKeysTo 60
+Toms =66
+Syntom =85
+RevCymbal =100 AllKeysTo 60
+Fx-Fret =121
+Fx-Blow =94
+Seashore =100 AllKeysTo 79
+Jungle =70
+Telephon =91
+Helicopter =111
+Applause =100 AllKeysTo 79
+Gunshot =100 AllKeysTo 38
+
+END
+
+DEFINE KEYMAP "Drumset"
+C 0 =0
+C#0 =1
+D 0 =2
+D#0 =3
+E 0 =4
+F 0 =5
+F#0 =6
+G 0 =7
+G#0 =8
+A 0 =9
+A#0 =10
+B 0 =11
+C 1 =12
+C#1 =13
+D 1 =14
+D#1 =15
+E 1 =16
+F 1 =17
+F#1 =18
+G 1 =19
+G#1 =20
+A 1 =21
+A#1 =22
+B 1 =23
+C 2 =24
+C#2 =25
+D 2 =26
+D#2 27 Highq =27
+E 2 28 Slap =54
+F 2 29 Scratch1 =29
+F#2 30 Scratch2 =30
+G 2 31 Sticks =46
+G#2 32 SqrClick =87
+A 2 33 MetaClick=57
+A#2 34 MetBell =55
+B 2 35 AcousticBassDrum=44
+C 3 36 BassDrum1=47
+C#3 37 StickRim =46
+D 3 38 AcSnare =47
+D#3 39 Claps =63
+E 3 40 ElectSnare =49
+F 3 41 LowFloorTom =48
+F#3 42 Hihatclos =57
+G 3 43 HighFloorTom=50
+G#3 44 PedalHihat =80
+A 3 45 LowTom =47
+A#3 46 OpenHihat =59
+B 3 47 LowMidTom =48
+C 4 48 HiMidTom =50
+C#4 49 Cymbalcrsh1 =60
+D 4 50 HiTom =53
+D#4 51 Cymbalride1 =63
+E 4 52 Cymbalchina =60
+F 4 53 RideBell =62
+F#4 54 Tambourin =71
+G 4 55 CymbalSplash=61
+G#4 56 Cowbell =55
+A 4 57 Cymbalcrash2=60
+A#4 58 Vibraslap =79
+B 4 59 Cymbalride2 =62
+C 5 60 Bongohi =68
+C#5 61 Bongolo =67
+D 5 62 MuteHiConga =66
+D#5 63 OpenHiConga =65
+E 5 64 LowConga =64
+F 5 65 HiTimbale =70
+F#5 66 LoTimbale =69
+G 5 67 HiAgogo =75
+G#5 68 LoAgogo =74
+A 5 69 Cabasa =56
+A#5 70 Maracas =56
+B 5 71 ShortWhistle=78
+C 6 72 LongWhistle =78
+C#6 73 ShortGuiro =79
+D 6 74 LongGuiro =71
+D#6 75 Clave =72
+E 6 76 HiWoodBlock =73
+F 6 77 LoWoodBlock =72
+F#6 78 MuteCuica =77
+G 6 79 OpenCuica =76
+G#6 80 MuteTriangle=37
+A 6 81 OpenTriangle=39
+A#6 82 Shaker =56
+B 6 83 Jingles =75
+C 7 84 Belltree =63
+C#7 85 Canstinet=85
+D 7 86 Surdo1 =86
+D#7 87 Surdo2 =87
+E 7 =88
+F 7 =89
+F#7 =90
+G 7 =91
+G#7 =92
+A 7 =93
+A#7 =94
+B 7 =95
+C 8 =96
+C#8 =97
+D 8 =98
+D#8 =99
+E 8 =100
+F 8 =101
+F#8 =102
+G 8 =103
+G#8 =104
+A 8 =105
+A#8 =106
+B 8 =107
+C 9 =108
+C#9 =109
+D 9 =110
+D#9 =111
+E 9 =112
+F 9 =113
+F#9 =114
+G 9 =115
+G#9 =116
+A 9 =117
+A#9 =118
+B 9 =119
+C 10=120
+C#10=121
+D 10=122
+D#10=123
+E 10=124
+F 10=125
+F#10=126
+G 10=127
+# This line should be ignored
+END
+
+
+DEFINE CHANNELMAP
+0 = 0
+1 = 1
+2 = 2
+3 = 3
+4 = 4
+5 = 5
+6 = 6
+7 = 7
+8 = 8
+9 = 15 Keymap "Drumset" ForcePatch 100
+10 = 10
+11 = 11
+12 = 12
+13 = 13
+14 = 14
+15 = 9
+END
+
+OPTIONS
+PitchBenderRatio = 672
+MapExpressionToVolumeEvents
+END
+
diff --git a/kmid/maps/YamahaQY10.map b/kmid/maps/YamahaQY10.map
new file mode 100644
index 00000000..1a4914b4
--- /dev/null
+++ b/kmid/maps/YamahaQY10.map
@@ -0,0 +1,305 @@
+# Midi map file for the Yamaha QY10 "walkstation", a basic sequencer / tone
+# module.
+
+# Provided by Malcolm Tyrrell. If there is a problem with this file, please
+# e-mail tyrrelmr@cs.tcd.ie
+
+# If you make a new map, please send it to Antonio, so future releases
+# will include them.
+# Antonio Larrosa Jimenez, larrosa@kde.org
+
+# Yamaha QY10 Map File
+
+DEFINE PATCHMAP
+AcusticPiano =0
+BrightPiano =0
+SynthPiano =1
+HonkyTonky =0
+ElectricPiano1=1
+ElectricPiano2=2
+Harpsichord =3
+Clavinet =3
+Celeste =18
+Glockenspiel =18
+Musicbox =20
+Vibes =19
+Marimba =18
+Xylophon =20
+TubeBell =19
+Santur =12
+HomeOrg =4
+PercussionOrg =4
+RockOrg =4
+ChurchOrg =5
+ReedOrg =5
+Accordion =5
+Harmonica =23
+Concrtna =23
+NylonGuitar =12
+AcusticGuitar =12
+JazzGuitar =9
+CleanGuitar =9
+MuteGuitar =11
+OdGuitar =9
+DistortionGuit=10
+GtrHarm =25
+AcusticBass =13
+FingerBass =14
+PickBass =14
+FretlessBass =13
+SlapBass1 =15
+SlapBass2 =15
+SynthBass1 =16
+SynthBass2 =16
+Violin =23
+Viola =23
+Cello =23
+Contrabajo =23
+Marcato =6
+Pizzicato =16
+Harp =12
+Timpani =20
+Marcato =6
+SlowStrings =6
+SynthStrings1 =22
+SynthStrings2 =22
+Choir =27
+Doo =21
+Voices =21
+OrchestraHit =8
+Trumpet =26
+Trombone =26
+Tuba =21
+MuteTrumpet =8
+FrenchHorn =26
+HitBrass =8
+SynthBrass1 =21
+SynthBrass2 =21
+SopranoSax =26
+AltoSax =26
+TenorSax =26
+BaritoneSax =26
+Oboe =27
+EnglishHorn =26
+Bassoon =27
+Clarinet =27
+Piccolo =27
+Flute =27
+Recorder =27
+WoodFlute =27
+Bottle =27
+Shakazul =27
+Whistle =27
+Ocarina =27
+SquareWave =28
+SawWave =28
+Calliope =29
+Chiflead =29
+Charang =24
+VoxLead =21
+Lead5th =21
+BassLead =21
+Fantasia =24
+WarmPad =21
+Polysyn =22
+Ghostie =27
+BowGlass =26
+MetalPad =21
+HaloPad =27
+Sweeper =24
+Aurora =31
+SoundTrack =21
+Crystal =19
+Atmosphear =24
+FreshAir =21
+Unicorn =24
+Sweeper =24
+StarTrak =21
+Sitar =9
+Banjo =9
+Shamisen =12
+Koto =12
+Kalimba =18
+BagPipes =28
+Fiddle =28
+Shannai =23
+Carillon =19
+Agogo =20
+SteelDrm =18
+WoodBlk =20
+Taiko =20
+Toms =18
+Syntom =18
+RevCymbal =31
+Fx-Fret =31
+Fx-Blow =31
+Seashore =31
+Jungle =31
+Telephon =5
+Helicopter =31
+Applause =31
+Gunshot =31
+END
+
+DEFINE KEYMAP "Drumset"
+C 0 =0
+C#0 =1
+D 0 =2
+D#0 =3
+E 0 =4
+F 0 =5
+F#0 =6
+G 0 =7
+G#0 =8
+A 0 =9
+A#0 =10
+B 0 =11
+C 1 =12
+C#1 =13
+D 1 =14
+D#1 =15
+E 1 =16
+F 1 =17
+F#1 =18
+G 1 =19
+G#1 =20
+A 1 =21
+A#1 =22
+B 1 =23
+C 2 =24
+C#2 =25
+D 2 =26
+# What is a high q?
+D#2 27 Highq =40
+E 2 28 Slap =37
+F 2 29 Scratch1 =23
+F#2 30 Scratch2 =48
+G 2 31 Sticks =21
+G#2 32 SqrClick =42
+A 2 33 MetaClick=42
+A#2 34 MetBell =43
+B 2 35 Kick1 =36
+C 3 36 Kick2 =12
+C#3 37 StickRim =21
+D 3 38 Snare1 =15
+D#3 39 Claps =19
+E 3 40 snare2 =14
+F 3 41 tomlo2 =16
+F#3 42 Hihatclos=23
+G 3 43 Tomlo1 =16
+G#3 44 HihatPd =23
+A 3 45 Tommid2 =17
+A#3 46 Hihatop =24
+B 3 47 Tommid1 =17
+C 4 48 Tomhi2 =18
+C#4 49 Cymbalcrsh1 =20
+D 4 50 Tomhi1 =18
+D#4 51 Cymbalride1 =22
+E 4 52 Cymbalchina =22
+F 4 53 Cymbell =22
+F#4 54 Tamborin =21
+G 4 55 CymbalSplash=20
+G#4 56 Cowbell =37
+A 4 57 Cymbalcrash2=20
+A#4 58 Vibslap =0
+B 4 59 Cymbalride2 =22
+C 5 60 Bongohi =41
+C#5 61 Bongolo =40
+D 5 62 Congahi1 =41
+D#5 63 congahi2 =41
+E 5 64 Congalo =40
+F 5 65 Timbalehi=46
+F#5 66 Timbalelo=45
+G 5 67 Agogohi =44
+G#5 68 Agogolo =43
+A 5 69 Cabasa =48
+A#5 70 Maracas =48
+B 5 71 whistle1 =0
+C 6 72 whistle2 =0
+C#6 73 Guiro1 =0
+D 6 74 Guiro2 =0
+D#6 75 Clave =44
+E 6 76 Woodblock1=40
+F 6 77 Woodblock2=41
+# Don't know about the following two
+F#6 78 Cuica1 =0
+G 6 79 Cuica2 =0
+G#6 80 Triangle1=44
+A 6 81 Triangle2=44
+A#6 82 Shaker =48
+B 6 83 Jingles =23
+C 7 84 Belltree =0
+C#7 85 Canstinet=21
+D 7 86 Surdo1 =16
+D#7 87 Surdo2 =17
+E 7 =88
+F 7 =89
+F#7 =90
+G 7 =91
+G#7 =92
+A 7 =93
+A#7 =94
+B 7 =95
+C 8 =96
+C#8 =97
+D 8 =98
+D#8 =99
+E 8 =100
+F 8 =101
+F#8 =102
+G 8 =103
+G#8 =104
+A 8 =105
+A#8 =106
+B 8 =107
+C 9 =108
+C#9 =109
+D 9 =110
+D#9 =111
+E 9 =112
+F 9 =113
+F#9 =114
+G 9 =115
+G#9 =116
+A 9 =117
+A#9 =118
+B 9 =119
+C 10=120
+C#10=121
+D 10=122
+D#10=123
+E 10=124
+F 10=125
+F#10=126
+G 10=127
+END
+
+
+DEFINE CHANNELMAP
+# The information on channels 7-8 and 11-15 is ignored since the QY10 is only
+# 8 part multi-timbral. The polyphony should be okay.
+0 = 0
+1 = 1
+2 = 2
+3 = 3
+4 = 4
+5 = 5
+6 = 6
+# The next two channels are ignored
+7 = 9
+8 = 8
+# Play GM channel 9 (drums) on QY10 track 7 (rhythm track)
+9 = 7 Keymap "Drumset" ForcePatch 30
+# All the following channels are ignored.
+10 = 10
+11 = 11
+12 = 12
+13 = 13
+14 = 14
+15 = 15
+END
+
+# I don't think the QY10 responds to Expression Events, so...
+OPTIONS
+MapExpressionToVolumeEvents
+END
diff --git a/kmid/maps/gm.map b/kmid/maps/gm.map
new file mode 100644
index 00000000..fd188ec0
--- /dev/null
+++ b/kmid/maps/gm.map
@@ -0,0 +1,290 @@
+# Blank lines and lines beginning with # are ignored
+# This is a map for any General Midi synthesizer
+# If you make a new map, please send it to me, so future releases
+# will include them.
+# Antonio Larrosa Jimenez, larrosa@kde.org
+
+# General Midi Map File
+
+DEFINE PATCHMAP
+AcusticPiano =0
+BrightPiano =1
+SynthPiano =2
+HonkyTonky =3
+ElectricPiano1=4
+ElectricPiano2=5
+Harpsichord =6
+Clavinet =7
+Celeste =8
+Glockenspiel =9
+Musicbox =10
+Vibes =11
+Marimba =12
+Xylophon =13
+TubeBell =14
+Santur =15
+HomeOrg =16
+PercussionOrg =17
+RockOrg =18
+ChurchOrg =19
+ReedOrg =20
+Accordion =21
+Harmonica =22
+Concrtna =23
+NylonGuitar =24
+AcusticGuitar =25
+JazzGuitar =26
+CleanGuitar =27
+MuteGuitar =28
+OdGuitar =29
+DistortionGuit=30
+GtrHarm =31
+AcusticBass =32
+FingerBass =33
+PickBass =34
+FretlessBass =35
+SlapBass1 =36
+SlapBass2 =37
+SynthBass1 =38
+SynthBass2 =39
+Violin =40
+Viola =41
+Cello =42
+Contrabajo =43
+Marcato =44
+Pizzicato =45
+Harp =46
+Timpani =47
+Marcato =48
+SlowStrings =49
+SynthStrings1 =50
+SynthStrings2 =51
+Choir =52
+Doo =53
+Voices =54
+OrchestraHit =55
+Trumpet =56
+Trombone =57
+Tuba =58
+MuteTrumpet =59
+FrenchHorn =60
+HitBrass =61
+SynthBrass1 =62
+SynthBrass2 =63
+SopranoSax =64
+AltoSax =65
+TenorSax =66
+BaritoneSax =67
+Oboe =68
+EnglishHorn =69
+Bassoon =70
+Clarinet =71
+Piccolo =72
+Flute =73
+Recorder =74
+WoodFlute =75
+Bottle =76
+Shakazul =77
+Whistle =78
+Ocarina =79
+SquareWave =80
+SawWave =81
+Calliope =82
+Chiflead =83
+Charang =84
+VoxLead =85
+Lead5th =86
+BassLead =87
+Fantasia =88
+WarmPad =89
+Polysyn =90
+Ghostie =91
+BowGlass =92
+MetalPad =93
+HaloPad =94
+Sweeper =95
+Aurora =96
+SoundTrack =97
+Crystal =98
+Atmosphear =99
+FreshAir =100
+Unicorn =101
+Sweeper =102
+StarTrak =103
+Sitar =104
+Banjo =105
+Shamisen =106
+Koto =107
+Kalimba =108
+BagPipes =109
+Fiddle =110
+Shannai =111
+Carillon =112
+Agogo =113
+SteelDrm =114
+WoodBlk =115
+Taiko =116
+Toms =117
+Syntom =118
+RevCymbal =119
+Fx-Fret =120
+Fx-Blow =121
+Seashore =122
+Jungle =123
+Telephon =124
+Helicopter =125
+Applause =126
+Gunshot =127
+END
+
+DEFINE KEYMAP "Drumset"
+C 0 =0
+C#0 =1
+D 0 =2
+D#0 =3
+E 0 =4
+F 0 =5
+F#0 =6
+G 0 =7
+G#0 =8
+A 0 =9
+A#0 =10
+B 0 =11
+C 1 =12
+C#1 =13
+D 1 =14
+D#1 =15
+E 1 =16
+F 1 =17
+F#1 =18
+G 1 =19
+G#1 =20
+A 1 =21
+A#1 =22
+B 1 =23
+C 2 =24
+C#2 =25
+D 2 =26
+D#2 27 Highq =27
+E 2 28 Slap =28
+F 2 29 Scratch1 =29
+F#2 30 Scratch2 =30
+G 2 31 Sticks =31
+G#2 32 SqrClick =32
+A 2 33 MetaClick=33
+A#2 34 MetBell =34
+B 2 35 Kick1 =35
+C 3 36 Kick2 =36
+C#3 37 StickRim =37
+D 3 38 Snare1 =38
+D#3 39 Claps =39
+E 3 40 snare2 =40
+F 3 41 tomlo2 =41
+F#3 42 Hihatclos=42
+G 3 43 Tomlo1 =43
+G#3 44 HihatPd =44
+A 3 45 Tommid2 =45
+A#3 46 Hihatop =46
+B 3 47 Tommid1 =47
+C 4 48 Tomhi2 =48
+C#4 49 Cymbalcrsh1 =49
+D 4 50 Tomhi1 =50
+D#4 51 Cymbalride1 =51
+E 4 52 Cymbalchina =52
+F 4 53 Cymbell =53
+F#4 54 Tamborin =54
+G 4 55 CymbalSplash=55
+G#4 56 Cowbell =56
+A 4 57 Cymbalcrash2=57
+A#4 58 Vibslap =58
+B 4 59 Cymbalride2 =59
+C 5 60 Bongohi =60
+C#5 61 Bongolo =61
+D 5 62 Congahi1 =62
+D#5 63 congahi2 =63
+E 5 64 Congalo =64
+F 5 65 Timbalehi=65
+F#5 66 Timbalelo=66
+G 5 67 Agogohi =67
+G#5 68 Agogolo =68
+A 5 69 Cabasa =69
+A#5 70 Maracas =70
+B 5 71 whistle1 =71
+C 6 72 whistle2 =72
+C#6 73 Guiro1 =73
+D 6 74 Guiro2 =74
+D#6 75 Clave =75
+E 6 76 Woodblock1=76
+F 6 77 Woodblock2=77
+F#6 78 Cuica1 =78
+G 6 79 Cuica2 =79
+G#6 80 Triangle1=80
+A 6 81 Triangle2=81
+A#6 82 Shaker =82
+B 6 83 Jingles =83
+C 7 84 Belltree =84
+C#7 85 Canstinet=85
+D 7 86 Surdo1 =86
+D#7 87 Surdo2 =87
+E 7 =88
+F 7 =89
+F#7 =90
+G 7 =91
+G#7 =92
+A 7 =93
+A#7 =94
+B 7 =95
+C 8 =96
+C#8 =97
+D 8 =98
+D#8 =99
+E 8 =100
+F 8 =101
+F#8 =102
+G 8 =103
+G#8 =104
+A 8 =105
+A#8 =106
+B 8 =107
+C 9 =108
+C#9 =109
+D 9 =110
+D#9 =111
+E 9 =112
+F 9 =113
+F#9 =114
+G 9 =115
+G#9 =116
+A 9 =117
+A#9 =118
+B 9 =119
+C 10=120
+C#10=121
+D 10=122
+D#10=123
+E 10=124
+F 10=125
+F#10=126
+G 10=127
+END
+
+
+DEFINE CHANNELMAP
+0 = 0
+1 = 1
+2 = 2
+3 = 3
+4 = 4
+5 = 5
+6 = 6
+7 = 7
+8 = 8
+9 = 9
+10 = 10
+11 = 11
+12 = 12
+13 = 13
+14 = 14
+15 = 15
+END
+
diff --git a/kmid/midicfgdlg.cpp b/kmid/midicfgdlg.cpp
new file mode 100644
index 00000000..c33b5043
--- /dev/null
+++ b/kmid/midicfgdlg.cpp
@@ -0,0 +1,138 @@
+/**************************************************************************
+
+ midicfgdlg.cpp - The midi config dialog
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include <qpushbutton.h>
+#include <qlistbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kapplication.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <libkmid/deviceman.h>
+
+#include "midicfgdlg.h"
+#include "version.h"
+#include <kglobal.h>
+#include <kstandarddirs.h>
+
+MidiConfigDialog::MidiConfigDialog(DeviceManager *dm,
+ QWidget *parent,const char *name) : KDialogBase(parent,name,TRUE,
+ i18n("Configure MIDI Devices"), KDialogBase::Ok|KDialogBase::Cancel)
+{
+ setMinimumSize(360,240);
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+
+ QVBoxLayout *topLayout=new QVBoxLayout(page, 0, spacingHint());
+ QLabel *label=new QLabel(i18n("Select the MIDI device you want to use:"),page);
+ topLayout->addWidget(label);
+ mididevices=new QListBox(page,"midideviceslist");
+ topLayout->addWidget(mididevices,3);
+ connect(mididevices,SIGNAL(highlighted(int)),SLOT(deviceselected(int)));
+ devman=dm;
+ QString temp;
+ for (int i=0;i<devman->midiPorts()+devman->synthDevices();i++)
+ {
+ if (strcmp(devman->type(i),"")!=0)
+ temp = QString("%1 - %2").arg(devman->name(i)).arg(devman->type(i));
+ else
+ temp = devman->name(i);
+
+ mididevices->insertItem(temp,i);
+ };
+ selecteddevice=devman->defaultDevice();
+ mididevices->setCurrentItem(selecteddevice);
+
+ QLabel *label2=new QLabel(i18n("Use the MIDI map:"),page);
+ topLayout->addWidget(label2);
+
+
+ if (selectedmap!=NULL) delete selectedmap;
+ if (strcmp(devman->midiMapFilename(),"")==0)
+ selectedmap=NULL;
+ else
+ {
+ selectedmap=new char[strlen(devman->midiMapFilename())+1];
+ strcpy(selectedmap,devman->midiMapFilename());
+ }
+
+ if (selectedmap!=NULL) maplabel=new QLabel(selectedmap,page);
+ else maplabel=new QLabel(i18n("None"),page);
+
+ topLayout->addWidget(maplabel);
+
+ QHBoxLayout *hbox=new QHBoxLayout(topLayout);
+ hbox->addStretch(1);
+ mapbrowse=new QPushButton(i18n("Browse..."),page);
+ hbox->addWidget(mapbrowse);
+ connect(mapbrowse,SIGNAL(clicked()),SLOT(browseMap()) );
+
+ mapnone=new QPushButton(i18n("None"),page);
+ hbox->addWidget(mapnone);
+ connect(mapnone,SIGNAL(clicked()),SLOT(noMap()) );
+
+ topLayout->addStretch(1);
+
+}
+
+void MidiConfigDialog::deviceselected(int idx)
+{
+ selecteddevice=idx;
+}
+
+void MidiConfigDialog::browseMap()
+{
+ QString path = KGlobal::dirs()->findAllResources("appdata", "maps/*.map").last();
+ path.truncate(path.findRev('/'));
+
+ KURL url = KFileDialog::getOpenURL(path,"*.map",this);
+
+ if( url.isEmpty() )
+ return;
+
+ if( !url.isLocalFile() )
+ {
+ KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) );
+ return;
+ }
+
+ QString filename = url.path();
+
+ delete selectedmap;
+ selectedmap=new char[filename.length()+1];
+ strcpy(selectedmap,QFile::encodeName(filename));
+ maplabel->setText(selectedmap);
+}
+
+void MidiConfigDialog::noMap()
+{
+ if (selectedmap!=NULL) {delete selectedmap;selectedmap=NULL;};
+ maplabel->setText(i18n("None"));
+}
+
+int MidiConfigDialog::selecteddevice=0;
+char *MidiConfigDialog::selectedmap=NULL;
+
+#include "midicfgdlg.moc"
diff --git a/kmid/midicfgdlg.h b/kmid/midicfgdlg.h
new file mode 100644
index 00000000..37417b36
--- /dev/null
+++ b/kmid/midicfgdlg.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+
+ midicfgdlg.h - The midi config dialog
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _midicfgdlg_h_
+#define _midicfgdlg_h_
+
+#include <kdialogbase.h>
+
+class DeviceManager;
+
+class QLabel;
+class QPushButton;
+class QListBox;
+class MidiConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ MidiConfigDialog(DeviceManager *dm,QWidget *parent,const char *name);
+
+public slots:
+ void deviceselected(int idx);
+ void browseMap();
+ void noMap();
+
+private:
+ QLabel *maplabel;
+ QListBox *mididevices;
+ QPushButton *mapbrowse;
+ QPushButton *mapnone;
+
+ DeviceManager *devman;
+
+public:
+ static int selecteddevice;
+ static char *selectedmap;
+};
+
+#endif
diff --git a/kmid/pics/Makefile.am b/kmid/pics/Makefile.am
new file mode 100644
index 00000000..4bf75950
--- /dev/null
+++ b/kmid/pics/Makefile.am
@@ -0,0 +1,3 @@
+kmidicondir = $(kde_datadir)/kmid/icons
+kmidicon_ICON = AUTO
+
diff --git a/kmid/pics/cr16-action-piano.png b/kmid/pics/cr16-action-piano.png
new file mode 100644
index 00000000..29536a0a
--- /dev/null
+++ b/kmid/pics/cr16-action-piano.png
Binary files differ
diff --git a/kmid/pics/cr16-action-volume.png b/kmid/pics/cr16-action-volume.png
new file mode 100644
index 00000000..3b75a38c
--- /dev/null
+++ b/kmid/pics/cr16-action-volume.png
Binary files differ
diff --git a/kmid/pics/cr22-action-piano.png b/kmid/pics/cr22-action-piano.png
new file mode 100644
index 00000000..226e4444
--- /dev/null
+++ b/kmid/pics/cr22-action-piano.png
Binary files differ
diff --git a/kmid/pics/cr22-action-volume.png b/kmid/pics/cr22-action-volume.png
new file mode 100644
index 00000000..e87c5147
--- /dev/null
+++ b/kmid/pics/cr22-action-volume.png
Binary files differ
diff --git a/kmid/pics/cr32-action-piano.png b/kmid/pics/cr32-action-piano.png
new file mode 100644
index 00000000..9d75a570
--- /dev/null
+++ b/kmid/pics/cr32-action-piano.png
Binary files differ
diff --git a/kmid/pics/cr32-action-volume.png b/kmid/pics/cr32-action-volume.png
new file mode 100644
index 00000000..0e1f3dec
--- /dev/null
+++ b/kmid/pics/cr32-action-volume.png
Binary files differ
diff --git a/kmid/qslidertime.cpp b/kmid/qslidertime.cpp
new file mode 100644
index 00000000..be5fdab2
--- /dev/null
+++ b/kmid/qslidertime.cpp
@@ -0,0 +1,120 @@
+/**************************************************************************
+
+ kslidertime.cpp - A widget that displays time tags under a KSlider
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include "qslidertime.h"
+#include <qwidget.h>
+#include <qpainter.h>
+#include <stdio.h>
+
+#define ARROW_LENGTH 13
+
+QSliderTime::QSliderTime( QSlider *ksl, QWidget *parent, const char *name)
+ : QWidget (parent,name)
+{
+kslider=ksl;
+
+QPainter painter;
+QFontMetrics qfmt(painter.font());
+fontheight=qfmt.height();
+
+}
+
+char *QSliderTime::formatMillisecs(int ms,char *tmp)
+{
+ if (ms<60000)
+ {
+ sprintf(tmp,"0:%02d",ms/1000);
+ }
+ else
+ sprintf(tmp,"%d:%02d",ms/60000,(ms%60000)/1000);
+return tmp;
+}
+
+void QSliderTime::paintEvent( QPaintEvent * )
+{
+ QPainter painter(this);
+
+// erase();
+ drawTimeMarks(&painter);
+}
+
+int quantizeTimeStep(int t)
+{
+if (t<=2000) t=2000;
+ else if (t<=5000) t=5000;
+ else if (t<=10000) t=10000;
+ else if (t<=15000) t=15000;
+ else if (t<=30000) t=30000;
+ else if (t<=60000) t=60000;
+ else if (t<=120000) t=120000;
+return t;
+}
+
+void QSliderTime::drawTimeMarks(QPainter *painter)
+{
+if (kslider==NULL) return;
+ int i;
+ int maxV = kslider->maxValue();
+ QFontMetrics qfmt(painter->font());
+ fontheight=qfmt.height();
+ int ntimetags = width()/(qfmt.width("-88:88-"));
+ int timestep;
+ if (ntimetags>1) timestep = maxV/(ntimetags);
+ else timestep=maxV;
+ timestep = quantizeTimeStep(timestep);
+ ntimetags = maxV/timestep;
+
+ // draw time tags (only in horizontal !!)
+ int posy=qfmt.height();
+ char *tmp=new char[100];
+ int pos=0;
+ int deltapos=0;
+ formatMillisecs(0,tmp);
+ painter->drawText( 0, posy,tmp);
+ for ( i = timestep; i <= maxV - timestep; i += timestep )
+ {
+ pos = (width()-10) * i / maxV + 5;
+ formatMillisecs(i,tmp);
+ deltapos=qfmt.width(tmp)/2;
+ painter->drawText( pos-deltapos, posy,tmp);
+ }
+
+ pos = width()- 5;
+ formatMillisecs(maxV,tmp);
+ deltapos=qfmt.width(tmp);
+
+ painter->drawText( pos-deltapos, posy,tmp);
+
+}
+
+
+QSize QSliderTime::sizeHint()
+{
+ return QSize(10,fontheight+2);
+}
+
+QSizePolicy QSliderTime::sizePolicy()
+{
+ return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
+}
+#include "qslidertime.moc"
diff --git a/kmid/qslidertime.h b/kmid/qslidertime.h
new file mode 100644
index 00000000..4b42d7d9
--- /dev/null
+++ b/kmid/qslidertime.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+
+ kslidertime.h - A widget that displays time tags under a KSlider
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _kslidertime_h_
+#define _kslidertime_h_
+
+#include <qslider.h>
+
+class QWidget;
+
+class QSliderTime : public QWidget
+{
+ Q_OBJECT
+private:
+
+ QSlider *kslider;
+
+int fontheight;
+public:
+
+ QSliderTime( QSlider *ksl, QWidget *parent = NULL, const char *name = NULL );
+
+ int getFontHeight(void) {return fontheight;};
+
+ QSize sizeHint();
+ QSizePolicy sizePolicy();
+
+private:
+
+ virtual void paintEvent( QPaintEvent * );
+ void drawTimeMarks(QPainter *painter);
+
+ char *formatMillisecs(int ms,char *tmp);
+};
+
+#endif
diff --git a/kmid/randomlist.cpp b/kmid/randomlist.cpp
new file mode 100644
index 00000000..5ac736a9
--- /dev/null
+++ b/kmid/randomlist.cpp
@@ -0,0 +1,103 @@
+/**************************************************************************
+
+ randomlist.cpp - Some "random functions" :-)
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include "randomlist.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#define RAND_UNIFORM (double)rand()/(double)RAND_MAX
+
+int random_discrete(double *distrib,int n)
+{
+ int i=0;
+ double g=0.0;
+ double z=0.0;
+ while ((z==0.0)||(z==1.0)) z=RAND_UNIFORM;
+ while ((g<z)&&(i<n))
+ {
+ g+=distrib[i];
+ i++;
+ };
+ return i-1;
+}
+
+double *generate_discrete_uniform_distrib(int n)
+{
+ double *distrib=new double[n];
+
+ for (int i=0;i<n;i++)
+ distrib[i]=1.0/(double)n;
+
+ return distrib;
+}
+
+void remove_lmn_from_discrete_distrib(int k,double *distrib,int n,int used=0)
+{
+ int i;
+ if (used==0) //guess how many values of the v.a. are strictly positive
+ {
+ for (i=0;i<n;i++) if (distrib[i]>0) used++;
+ };
+ used--; // k will no longer be used :-)
+ if (used==0) return;
+ double piece=distrib[k]/(double)used;
+ distrib[k]=0.0;
+ for (i=0;i<n;i++) if (distrib[i]>0) distrib[i]+=piece;
+}
+
+void show_distrib(double *distrib,int n)
+{
+ printf("(");
+ for (int j=0;j<n;j++) printf("%g,",distrib[j]);
+ printf(")\n");
+}
+
+int *generate_random_list(int n)
+{
+ if (n==0) return NULL;
+ int *list=new int[n];
+ double *distrib=generate_discrete_uniform_distrib(n);
+ int used=n;
+ int x;
+ int i=1;
+ while (used>0)
+ {
+ x=random_discrete(distrib,n);
+ list[x]=i;
+ i++;
+ remove_lmn_from_discrete_distrib(x,distrib,n,used);
+ used--;
+ };
+ delete distrib;
+
+ return list;
+}
+
+int *generate_list(int n)
+{
+ int *list=new int[n];
+ for (int i=0;i<n;i++)
+ list[i]=i+1;
+
+ return list;
+}
diff --git a/kmid/randomlist.h b/kmid/randomlist.h
new file mode 100644
index 00000000..e351aaad
--- /dev/null
+++ b/kmid/randomlist.h
@@ -0,0 +1,34 @@
+/**************************************************************************
+
+ randomlist.h - Some "random functions" :-)
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+
+#ifndef _RANDOMLIST_H
+#define _RANDOMLIST_H
+
+// Returns a list (created with new) of num elements, filled with 1,2,..., num
+// at random places.
+int *generate_random_list(int num);
+
+int *generate_list(int num);
+
+#endif
diff --git a/kmid/rhythmview.cpp b/kmid/rhythmview.cpp
new file mode 100644
index 00000000..2b9136aa
--- /dev/null
+++ b/kmid/rhythmview.cpp
@@ -0,0 +1,108 @@
+/**************************************************************************
+
+ rhythmview.cpp - The RhythmView widget
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include "rhythmview.h"
+
+RhythmView::RhythmView (QWidget *parent, const char *name) : QWidget (parent,name)
+{
+ lamps=NULL;
+ setRhythm(4,4);
+}
+
+RhythmView::~RhythmView()
+{
+ if (lamps!=NULL)
+ {
+ for (int i=0;i<num;i++) delete lamps[i];
+ delete [] lamps;
+ lamps=NULL;
+ }
+}
+
+void RhythmView::setRhythm(int numerator,int denominator)
+{
+ int i;
+ if (lamps!=NULL)
+ {
+ for (i=0;i<num;i++) delete lamps[i];
+ delete [] lamps;
+ lamps=NULL;
+ }
+ num=numerator;
+ den=denominator;
+
+ lamps=new KLed *[num];
+ int w=width()/num;
+ int x=0;
+
+ for (i=0;i<num;i++)
+ {
+ lamps[i]=new KLed(Qt::yellow, KLed::Off, KLed::Sunken, KLed::Rectangular, this);
+// lamps[i]->setState(KLed::Off);
+ lamps[i]->setGeometry(x+2,0,w-4,height());
+ lamps[i]->show();
+ x+=w;
+ }
+// lamps[0]->setState(KLed::On);
+
+}
+
+void RhythmView::Beat(int j)
+{
+ if (j>num) setRhythm(j,4); // This is a preventive case
+
+ for (int i=0;i<num;i++)
+ {
+ lamps[i]->off();
+ }
+ lamps[j-1]->on();
+}
+
+void RhythmView::Beat(void)
+{
+
+}
+
+void RhythmView::resizeEvent(QResizeEvent *)
+{
+ int w=width()/num;
+ int x=0;
+
+ for (int i=0;i<num;i++)
+ {
+ lamps[i]->setGeometry(x+2,0,w-4,height());
+ x+=w;
+ }
+}
+
+QSize RhythmView::sizeHint()
+{
+ return QSize(10,10);
+}
+
+QSizePolicy RhythmView::sizePolicy()
+{
+// return QWidget::sizePolicy();
+ return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
+}
+
diff --git a/kmid/rhythmview.h b/kmid/rhythmview.h
new file mode 100644
index 00000000..80402fad
--- /dev/null
+++ b/kmid/rhythmview.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+
+ rhythmview.h - The RhythmView widget
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef _rhythmview_h_
+#define _rhythmview_h_
+
+#include <qwidget.h>
+#include <kled.h>
+
+class RhythmView : public QWidget
+{
+ int num,den;
+
+ KLed **lamps;
+
+public:
+ RhythmView (QWidget *parent, const char *name);
+ ~RhythmView();
+
+ void setRhythm(int numerator,int denominator);
+
+ void Beat(int i); // Sets the beat number
+
+ void Beat(void); // Just increase the beat
+
+ QSize sizeHint();
+ QSizePolicy sizePolicy();
+
+private:
+ void resizeEvent(QResizeEvent *);
+
+};
+
+#endif
diff --git a/kmid/slman.cpp b/kmid/slman.cpp
new file mode 100644
index 00000000..62acdd2b
--- /dev/null
+++ b/kmid/slman.cpp
@@ -0,0 +1,320 @@
+/**************************************************************************
+
+ slman.cc - SongList Manager, which holds a set of collections (SongLists)
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include "slman.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "version.h"
+#include <klocale.h>
+
+SLManager::SLManager()
+{
+ list=NULL;
+ ntotal=0;
+ tempsl=NULL;
+ createTemporaryCollection();
+}
+
+SLManager::SLManager(SLManager &src)
+{
+ list=NULL;
+ ntotal=0;
+ tempsl=NULL;
+ SongListNode *srcSL=src.list;
+ SongList *tmpSL;
+ int i;
+ while (srcSL!=NULL)
+ {
+ i=createCollection(srcSL->name);
+ tmpSL=getCollection(i);
+ if (tmpSL!=NULL)
+ tmpSL->copy(*srcSL->SL);
+ srcSL=srcSL->next;
+ }
+ if (src.tempsl!=NULL) tempsl=new SongList(*src.tempsl);
+ else tempsl=NULL;
+}
+
+SLManager::~SLManager()
+{
+ SongListNode *ptr;
+ ptr=list;
+ while (ptr!=NULL)
+ {
+ list=ptr->next;
+ if (ptr->SL!=NULL) delete ptr->SL;
+ if (ptr->name!=NULL) delete ptr->name;
+ delete ptr;
+ ptr=list;
+ }
+ if (tempsl!=NULL) delete tempsl;
+ ntotal=0;
+}
+
+int SLManager::createCollection(const char *name)
+{
+ SongListNode *ptr;
+ if (nameUsed(name))
+ {
+ printf("Name '%s' is already used\n",name);
+ return -1;
+ }
+ if (list==NULL)
+ {
+ list=new SongListNode;
+ list->id=1;
+ ntotal=1;
+ ptr=list;
+ }
+ else
+ {
+ ptr=list;
+ while (ptr->next!=NULL) ptr=ptr->next;
+ ptr->next=new SongListNode;
+ ptr=ptr->next;
+
+ ptr->id= ++ntotal;
+ }
+ ptr->SL=new SongList;
+ ptr->next=NULL;
+ if (name!=NULL)
+ {
+ ptr->name=new char[strlen(name)+1];
+ strcpy(ptr->name,name);
+ }
+ else
+ {
+ ptr->name=getNotUsedName();
+ }
+return ptr->id;
+}
+
+char *SLManager::getNotUsedName(void)
+{
+ char *trythis;
+ trythis=new char[100];
+ strcpy(trythis,"No Name");
+ int tries=1;
+ int success=0;
+ while (!success)
+ {
+ if (nameUsed(trythis)) sprintf(trythis,"No Name - %d",++tries);
+ else
+ success=1;
+ }
+ return trythis;
+}
+
+int SLManager::nameUsed(const char *name)
+{
+ /*
+ SongListNode *ptr=list;
+ int used=0;
+ while ((!used)&&(ptr!=NULL))
+ {
+ if (strcmp(ptr->name,name)==0) used=1;
+ ptr=ptr->next;
+ };
+ return used;
+ */
+ if (getCollection(name)==NULL) return 0;
+ return 1;
+}
+
+void SLManager::deleteCollection(int id)
+{
+ if (list==NULL) return;
+ SongListNode *ptr=list;
+ SongListNode *ptr2;
+ if (id==1) list=list->next;
+ else
+ {
+ ptr2=list;
+ while ((ptr!=NULL)&&(ptr->id!=id))
+ {
+ ptr2=ptr;
+ ptr=ptr->next;
+ }
+ if (ptr==NULL)
+ {
+ printf("Trying to delete a not used id\n");
+ return;
+ }
+ ptr2->next=ptr->next;
+ }
+ ptr2=ptr->next;
+ delete ptr->SL;
+ delete ptr->name;
+ delete ptr;
+ regenerateid(ptr2,id);
+
+}
+
+void SLManager::regenerateid(SongListNode *sl,int id)
+{
+ SongListNode *tmp=sl;
+ int i=id;
+ while (tmp!=NULL)
+ {
+ tmp->id=i++;
+ tmp=tmp->next;
+ }
+ ntotal=i-1;
+}
+
+void SLManager::changeCollectionName(int id,const char *newname)
+{
+ if (id<1) return;
+ if (nameUsed(newname))
+ {
+ printf("Cannot change name, '%s' is already used\n",newname);
+ return;
+ }
+ SongListNode *ptr=list;
+ while ((ptr!=NULL)&&(ptr->id!=id)) ptr=ptr->next;
+ if (ptr==NULL) return;
+
+ delete ptr->name;
+ ptr->name=new char[strlen(newname)+1];
+ strcpy(ptr->name,newname);
+}
+
+SongList *SLManager::getCollection(int id)
+{
+ if (id==0) return tempsl;
+
+ SongListNode *ptr=list;
+ while ((ptr!=NULL)&&(ptr->id!=id)) ptr=ptr->next;
+
+ if (ptr==NULL) return NULL;
+ return ptr->SL;
+}
+
+SongList *SLManager::getCollection(const char *name)
+{
+ SongListNode *ptr=list;
+ while ((ptr!=NULL)&&(strcmp(ptr->name,name)!=0)) ptr=ptr->next;
+
+ if (ptr==NULL) return NULL;
+ return ptr->SL;
+}
+
+const char *SLManager::getCollectionName(int id)
+{
+ if (id==0) return I18N_NOOP("Temporary Collection");
+ SongListNode *ptr=list;
+ while ((ptr!=NULL)&&(ptr->id!=id)) ptr=ptr->next;
+
+ if (ptr==NULL) return NULL;
+ return ptr->name;
+}
+
+void SLManager::loadConfig(const char *filename)
+{
+#ifdef GENERAL_DEBUG_MESSAGES
+ printf("Loading collections\n");
+#endif
+ FILE *fh=fopen(filename,"rt");
+ if (fh==NULL)
+ {
+ printf("Collections cannot be loaded\n(File %s doesn't exist or can't be opened)\n",filename);
+ return;
+ }
+ char s[300];
+ SongList *sl=NULL;
+ int activeid=0;
+ while (!feof(fh))
+ {
+ s[0] = 0;
+ fgets(s,299,fh);
+ if ((strlen(s)>0)&&(s[strlen(s)-1]==10)) s[strlen(s)-1]=0;
+ switch (s[0])
+ {
+ case (0) : break;
+ case (10) : break;
+ case ('=') :
+ {
+ if (sl!=NULL) sl->setActiveSong(activeid);
+ int id=createCollection(&s[1]);
+ sl=getCollection(id);
+ fgets(s,299,fh);
+ activeid=atoi(s);
+ }
+ break;
+ default :
+ {
+ if (sl!=NULL) sl->AddSong((const char *)s);
+ }
+ }
+ }
+ if (sl!=NULL) sl->setActiveSong(activeid);
+
+ fclose(fh);
+}
+
+void SLManager::saveConfig(const char *filename)
+{
+ SongListNode *ptr=list;
+ FILE *fh=fopen(filename,"wt");
+ if (fh==NULL)
+ {
+ printf("Collections couldn't be saved\n");
+ return;
+ }
+ char s[FILENAME_MAX];
+ SongList *sl;
+ while (ptr!=NULL)
+ {
+ sprintf(s,"=%s\n",ptr->name);
+ fputs(s,fh);
+
+ sl=ptr->SL;
+ sprintf(s,"%d\n",sl->getActiveSongID());
+ fputs(s,fh);
+
+ sl->iteratorStart();
+ while (!sl->iteratorAtEnd())
+ {
+ sprintf(s,"%s\n",sl->getIteratorName());
+ fputs(s,fh);
+ sl->iteratorNext();
+ }
+ // ptr->SL->saveList(fh);
+ fputs("\n",fh);
+
+ ptr=ptr->next;
+ }
+ fclose(fh);
+
+}
+
+SongList *SLManager::createTemporaryCollection(void)
+{
+ if (tempsl==NULL)
+ tempsl=new SongList();
+ else
+ tempsl->clean();
+
+ return tempsl;
+}
diff --git a/kmid/slman.h b/kmid/slman.h
new file mode 100644
index 00000000..3013f242
--- /dev/null
+++ b/kmid/slman.h
@@ -0,0 +1,74 @@
+/* slman.h - SongList Manager, which holds a set of collections (SongLists)
+ Copyright (C) 1997,98,99,2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef SLMAN_H
+#define SLMAN_H
+
+#include "songlist.h"
+
+class SLManager
+{
+protected:
+int ntotal;
+
+struct SongListNode
+ {
+ int id;
+ char *name;
+ SongList *SL;
+
+ SongListNode *next;
+ };
+SongListNode *list;
+SongList *tempsl;
+
+char *getNotUsedName(void);
+int nameUsed(const char *name);
+void regenerateid(SongListNode *sl,int id);
+
+public:
+SLManager();
+SLManager(SLManager &src); // Copy constructor
+~SLManager();
+
+int createCollection(const char *name=NULL); // Returns the id associated to the
+ // new collection
+ // -1 if name already is used and Collection was
+ // not created
+
+void deleteCollection(int id);
+void changeCollectionName(int id, const char *newname);
+
+SongList *getCollection(int id);
+SongList *getCollection(const char *name);
+const char *getCollectionName(int id);
+
+int numberOfCollections(void) {return ntotal;};
+
+void loadConfig(const char *filename);
+void saveConfig(const char *filename);
+
+SongList *createTemporaryCollection(void);
+SongList *getTemporaryCollection(void) {return tempsl;};
+
+};
+
+#endif
diff --git a/kmid/songlist.cpp b/kmid/songlist.cpp
new file mode 100644
index 00000000..8d98600c
--- /dev/null
+++ b/kmid/songlist.cpp
@@ -0,0 +1,247 @@
+/**************************************************************************
+
+ songlist.cc - class SongList, which holds a list of songs (collection)
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#include "songlist.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+SongList::SongList(void)
+{
+ list=NULL;
+ last=NULL;
+ active=NULL;
+ ntotal=0;
+}
+
+SongList::SongList(SongList &src)
+{
+ list=last=active=NULL;
+ ntotal=0;
+ src.iteratorStart();
+ while (!src.iteratorAtEnd())
+ {
+ AddSong(src.getIteratorName());
+ src.iteratorNext();
+ }
+ if (src.active!=NULL) active=getSongid(src.active->id);
+}
+
+SongList::~SongList()
+{
+ clean();
+ Song *ptr=list;
+ active=last=NULL;
+ ntotal=0;
+
+ while (ptr!=NULL)
+ {
+ list=ptr->next;
+ delete ptr->name;
+ delete ptr;
+ ptr=list;
+ }
+
+}
+
+SongList::Song *SongList::getSongid(int id)
+{
+ Song *ptr=list;
+ while ((ptr!=NULL)&&(ptr->id!=id))
+ ptr=ptr->next;
+
+ return ptr;
+}
+
+int SongList::AddSong(const char *song)
+{
+ if (!song) return 0;
+
+ if (last==NULL)
+ {
+ last=new Song;
+ list=last;
+ }
+ else
+ {
+ last->next=new Song;
+ last=last->next;
+ }
+ last->name=new char[strlen(song)+1];
+ strcpy(last->name,song);
+ last->id= ++ntotal;
+ last->next=NULL;
+ if (active==NULL) active=last;
+ return last->id;
+}
+
+void SongList::DelSong(int id)
+{
+ Song *ptr;
+
+ if (list==NULL) return;
+ if (id==1)
+ {
+ if (last->id==1)
+ {
+ list=last=active=NULL;
+ ntotal=0;
+ }
+ else
+ {
+ ptr=list;
+ if (active->id==1) active=list->next;
+ list=list->next;
+ delete ptr->name;
+ delete ptr;
+ ntotal--;
+
+ regenerateid(list,1);
+ }
+ return;
+ }
+ Song *ptr_prev=getSongid(id-1);
+ ptr=ptr_prev->next;
+ if (last->id==id) last=ptr_prev;
+ if (active->id==id)
+ if (active->next!=NULL) active=active->next;
+ else active=ptr_prev;
+
+ ntotal--;
+ ptr_prev->next=ptr->next;
+ delete ptr->name;
+ delete ptr;
+ regenerateid(ptr_prev->next,id);
+
+}
+
+void SongList::regenerateid(Song *song,int id)
+{
+ Song *tmp=song;
+ int i=id;
+ while (tmp!=NULL)
+ {
+ tmp->id=i++;
+ tmp=tmp->next;
+ }
+ ntotal=i-1;
+}
+
+void SongList::setActiveSong(int id)
+{
+ Song *tmp=getSongid(id);
+ if (tmp!=NULL) active=tmp;
+}
+
+char *SongList::getName(int id)
+{
+ Song *tmp=getSongid(id);
+ if (tmp!=NULL) return tmp->name;
+ return NULL;
+}
+
+/*
+void SongList::saveList(FILE *fh)
+{
+ Song *ptr=list;
+ while (ptr!=NULL)
+ {
+ fputs(fh,ptr->name);
+ ptr=ptr->next;
+ }
+}
+*/
+
+void SongList::iteratorStart(void)
+{
+ it=list;
+}
+
+void SongList::iteratorNext(void)
+{
+ if (it!=NULL) it=it->next;
+}
+
+int SongList::getIteratorID(void)
+{
+ if (it==NULL) return -1;
+ return it->id;
+}
+
+char *SongList::getIteratorName(void)
+{
+ if (it==NULL) return NULL;
+ return it->name;
+}
+
+
+void SongList::clean(void)
+{
+ Song *tmp=list;
+ active=last=NULL;
+ ntotal=0;
+
+ while (tmp!=NULL)
+ {
+ list=tmp->next;
+ delete [] tmp->name;
+ delete tmp;
+ tmp=list;
+ }
+}
+
+void SongList::copy(SongList &src)
+{
+ clean();
+ src.iteratorStart();
+ while (!src.iteratorAtEnd())
+ {
+ AddSong(src.getIteratorName());
+ src.iteratorNext();
+ }
+ if (src.active!=NULL) active=getSongid(src.active->id);
+}
+
+int SongList::next(void)
+{
+ if (list==NULL) {active=NULL;return 0;};
+ if (active!=NULL) active=active->next;
+ if (active==NULL)
+ {
+ Song *tmp=list;
+ while (tmp->next!=NULL) tmp=tmp->next;
+ active=tmp;
+ return 0;
+ }
+ return 1;
+}
+
+
+void SongList::previous(void)
+{
+ if (list==NULL) {active=NULL;return;};
+ Song *tmp=list;
+ while ((tmp->next!=NULL)&&(tmp->next->id!=active->id)) tmp=tmp->next;
+ if (tmp->next==NULL) {active=list;return;};
+ active=tmp;
+}
diff --git a/kmid/songlist.h b/kmid/songlist.h
new file mode 100644
index 00000000..85203c46
--- /dev/null
+++ b/kmid/songlist.h
@@ -0,0 +1,84 @@
+/* songlist.h - class SongList, which holds a list of songs (collection)
+ Copyright (C) 1997,98,99,2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Send comments and bug fixes to larrosa@kde.org
+ or to Antonio Larrosa, Rio Arnoya, 10 5B, 29006 Malaga, Spain
+
+***************************************************************************/
+#ifndef SONGLIST_H
+#define SONGLIST_H
+
+#include <stdio.h>
+
+class SongList
+{
+protected:
+int ntotal;
+
+struct Song
+{
+ int id;
+ char *name; // complete path and file name
+
+ Song *next;
+};
+
+Song *list;
+Song *last;
+Song *active;
+
+Song *it; // Iterator, just a helper variable to make easy (and fast) reading
+ // all the list
+
+Song *getSongid(int id);
+
+void regenerateid(Song *song,int id);
+
+public:
+SongList(void);
+SongList(SongList &src); // Copy constructor
+~SongList();
+
+int AddSong(const char *song); // Returns the id number assigned to the song
+void DelSong(int id);
+
+int NumberOfSongs(void) { return ntotal; };
+
+void setActiveSong(int id);
+int getActiveSongID(void) {return ((active!=NULL)? (active->id ):(-1)); };
+char *getActiveSongName(void)
+ {
+ return ((active!=NULL)? (active->name):((char *)NULL));
+ };
+
+char *getName(int id); // Returns the name of the song with id id
+
+void previous(void);
+int next(void); // returns 1 if evrything is ok, and 0 if it was the last element
+ // (but leaves active the last element instead of NULL)
+
+void iteratorStart(void);
+void iteratorNext(void);
+int iteratorAtEnd (void) {return (it==NULL);};
+int getIteratorID(void);
+char *getIteratorName(void);
+
+void clean(void); // Clean this list
+void copy(SongList &src); // Makes this object a copy of src (really copied)
+};
+
+#endif
diff --git a/kmid/std.o3 b/kmid/std.o3
new file mode 100644
index 00000000..e58311da
--- /dev/null
+++ b/kmid/std.o3
Binary files differ
diff --git a/kmid/std.sb b/kmid/std.sb
new file mode 100644
index 00000000..4fe2d0be
--- /dev/null
+++ b/kmid/std.sb
Binary files differ
diff --git a/kmid/version.h b/kmid/version.h
new file mode 100644
index 00000000..be282fff
--- /dev/null
+++ b/kmid/version.h
@@ -0,0 +1,48 @@
+#ifndef _VERSION_H
+
+
+#define VERSION_NUM 2.0
+#define VERSION_SHORTTXT "2.0"
+#define VERSION_TXT "KMid 2.0"
+
+// Undefine WORKING for release versions
+//#define WORKING
+
+// I want to keep some special variables defined at home for personal
+// adjustments
+//#define AT_HOME
+
+
+// The next definition makes kmid display some general debug messages
+// that may be helpful to locate any bug, but without making lots of
+// messages. Please when reporting a bug, be sure that this is set and
+// send me the output.
+//#define GENERAL_DEBUG_MESSAGES
+
+// Define MODE_DEMO_ONLYVISUAL for kmid to work on systems with no soundcard,
+// or when it is not well configured. You will only get visual feedback, that
+// is, you will see the letter changing of colors, but no music. Really, you
+// would get music if it is possible, but by defining this, many synchronization
+// routines will be turned off.
+//#define MODE_DEMO_ONLYVISUAL
+
+
+// And now, DEBUG messages :
+#ifdef WORKING
+#define KMidDEBUG
+//#define KDISPTEXTDEBUG
+//#define COLLECTDLGDEBUG
+//#define DEVICEMANDEBUG
+//#define FMOUTDEBUG
+//#define GUSOUTDEBUG
+//#define MIDFILEDEBUG
+//#define MIDIOUTDEBUG
+//#define MIDISTATDEBUG
+//#define MIDIMAPPERDEBUG
+//#define SYNTHOUTDEBUG
+//#define VOICEMANDEBUG
+//#define PLAYERDEBUG
+//#define TRACKDEBUG
+#endif
+
+#endif
diff --git a/kmid/x-karaoke.desktop b/kmid/x-karaoke.desktop
new file mode 100644
index 00000000..2784f27a
--- /dev/null
+++ b/kmid/x-karaoke.desktop
@@ -0,0 +1,61 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=audio/x-karaoke
+Icon=sound
+Patterns=*.kar;*.KAR;
+Comment=Karaoke File
+Comment[ar]=ملف Karaoke
+Comment[bg]=Файл на Karaoke
+Comment[bn]=কারাওকে ফাইল
+Comment[br]=Restr Karaoke
+Comment[bs]=Karaoke datoteka
+Comment[ca]=Fitxer karaoke
+Comment[cs]=Karaoke soubor
+Comment[cy]=Ffeil Karaoke
+Comment[da]=Karaoke-fil
+Comment[de]=Karaoke-Datei
+Comment[el]=Αρχείο Karaoke
+Comment[eo]=Karaoko-dosiero
+Comment[es]=Archivo Karaoke
+Comment[et]=Karaoke fail
+Comment[eu]=Karaoke fitxategia
+Comment[fa]=پروندۀ Karaoke
+Comment[fi]=Karaoketiedosto
+Comment[fr]=Fichier de karaoké
+Comment[ga]=Comhad Karaoke
+Comment[gl]=Ficheiro Karaoke
+Comment[he]=קובץ קריוקי
+Comment[hi]=कराओके फ़ाइल
+Comment[hu]=Karaoke-fájl
+Comment[is]=Karaoke skrá
+Comment[ja]=カラオケファイル
+Comment[kk]=Караоке файлы
+Comment[km]=ឯកសារ​ខារ៉ាអូខេ
+Comment[ko]=노래방 파일
+Comment[lt]=Karaoke byla
+Comment[mk]=Karaoke датотека
+Comment[nb]=Karaokefil
+Comment[nds]=Karaoke-Datei
+Comment[ne]=कारावके फाइल
+Comment[nl]=Karaoke-bestand
+Comment[nn]=Karaokefil
+Comment[pl]=Plik Karaoke
+Comment[pt]=Ficheiro de Karaoke
+Comment[pt_BR]=Arquivo Karaokê
+Comment[ro]=Fişier karaoke
+Comment[ru]=Файл караоке
+Comment[sk]=Karaoke súbor
+Comment[sl]=Datoteka Karaoke
+Comment[sr]=Караоке фајл
+Comment[sr@Latn]=Karaoke fajl
+Comment[sv]=Karaoke-fil
+Comment[ta]=கரோக்கி கோப்பு
+Comment[tg]=Файли Karaoke
+Comment[th]=แฟ้มคาราโอเกะ
+Comment[tr]=Karaoke Dosyası
+Comment[uk]=Файл Karaoke
+Comment[uz]=Karaoki fayli
+Comment[uz@cyrillic]=Караоки файли
+Comment[zh_CN]=卡拉 OK 文件
+Comment[zh_HK]=卡拉OK 檔案
+Comment[zh_TW]=卡拉OK檔案