Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Edit/MainWindow.py26
-rw-r--r--Edit/TrackInterface.py118
-rwxr-xr-xResources/Images/brush.pngbin0 -> 3544 bytes
-rwxr-xr-xResources/Images/brushDown.pngbin0 -> 4462 bytes
-rwxr-xr-xResources/Images/krecord.pngbin0 -> 1911 bytes
-rwxr-xr-xResources/Images/krecordDown.pngbin0 -> 1814 bytes
-rwxr-xr-xResources/Images/krecordOver.pngbin0 -> 1878 bytes
-rw-r--r--Resources/Images/record2.pngbin1650 -> 2248 bytes
-rwxr-xr-xResources/Images/record2Down.pngbin0 -> 2087 bytes
-rwxr-xr-xResources/Images/record2Over.pngbin0 -> 2166 bytes
-rwxr-xr-xTamTam.py12
-rw-r--r--Util/Clooper/Makefile2
-rw-r--r--Util/Clooper/aclient.cpp314
-rw-r--r--Util/Clooper/audio.cpp681
-rw-r--r--Util/Clooper/log.cpp47
-rw-r--r--Util/KeyboardWindow.py155
-rw-r--r--Util/Trackpad.py2
-rw-r--r--Welcome.py10
18 files changed, 1097 insertions, 270 deletions
diff --git a/Edit/MainWindow.py b/Edit/MainWindow.py
index 5fce403..e6d7118 100644
--- a/Edit/MainWindow.py
+++ b/Edit/MainWindow.py
@@ -256,7 +256,7 @@ class MainWindow( SubActivity ):
#self.GUI["2XYSliderYAdjustment"] = gtk.Adjustment( 650, 500, 1000, 1, 1, 1 )
#self.GUI["2XYSlider"] = XYSlider( self.GUI["2XYSliderFixed"], self.GUI["2XYSliderButton"], self.GUI["2XYSliderXAdjustment"], self.GUI["2XYSliderYAdjustment"], True, True )
#self.GUI["2rightPanel"].pack_start( self.GUI["2XYSlider"], False, False, 0 )
- self.trackInterface = TrackInterface( self.noteDB, self )
+ self.trackInterface = TrackInterface( self.noteDB, self, self.getScale )
self.noteDB.addListener( self.trackInterface, TrackInterfaceParasite, True )
self.trackInterface.set_size_request( -1, 713 )
self.GUI["2rightPanel"].pack_start( self.trackInterface, False, False, 0 )
@@ -266,17 +266,21 @@ class MainWindow( SubActivity ):
self.GUI["2toolPanel"].set_size_request( -1, toolPanelHeight )
# + + tool box
self.GUI["2toolBox"] = formatRoundBox( RoundHBox(), Config.BG_COLOR )
- self.GUI["2toolBox"].set_size_request( 144, -1 )
+ self.GUI["2toolBox"].set_size_request( 204, -1 )
self.GUI["2toolPointerButton"] = ImageRadioButton( None, Config.IMAGE_ROOT+"pointer.png", Config.IMAGE_ROOT+"pointerDown.png", backgroundFill = Config.BG_COLOR )
self.GUI["2toolPointerButton"].connect( "clicked", self.handleToolClick , "default" )
self.GUI["2toolBox"].pack_start( self.GUI["2toolPointerButton"] )
self.GUI["2toolPencilButton"] = ImageRadioButton( self.GUI["2toolPointerButton"], Config.IMAGE_ROOT+"pencil.png", Config.IMAGE_ROOT+"pencilDown.png", backgroundFill = Config.BG_COLOR )
self.GUI["2toolPencilButton"].connect( "clicked", self.handleToolClick , "draw" )
self.GUI["2toolBox"].pack_start( self.GUI["2toolPencilButton"] )
+ self.GUI["2toolPencilButton"] = ImageRadioButton( self.GUI["2toolPointerButton"], Config.IMAGE_ROOT+"brush.png", Config.IMAGE_ROOT+"brushDown.png", backgroundFill = Config.BG_COLOR )
+ self.GUI["2toolPencilButton"].connect( "clicked", self.handleToolClick , "paint" )
+ self.GUI["2toolBox"].pack_start( self.GUI["2toolPencilButton"] )
+
self.GUI["2toolPanel"].pack_start( self.GUI["2toolBox"], False, False )
self.GUI["2rightPanel"].pack_start( self.GUI["2toolPanel"], False )
# + + context box (for context sensitive buttons, nothing to do with CAIRO)
- contextWidth = 674
+ contextWidth = 594
self.GUI["2contextBox"] = formatRoundBox( RoundFixed(), Config.BG_COLOR )
self.GUI["2contextBox"].set_size_request( contextWidth, -1 )
self.GUI["2contextPrevButton"] = ImageButton( Config.IMAGE_ROOT+"arrowEditLeft.png", Config.IMAGE_ROOT+"arrowEditLeftDown.png", Config.IMAGE_ROOT+"arrowEditLeftOver.png", backgroundFill = Config.BG_COLOR )
@@ -338,9 +342,9 @@ class MainWindow( SubActivity ):
self.GUI["2toolPanel"].pack_start( self.GUI["2contextBox"], False )
# + + transport box
self.GUI["2transportBox"] = formatRoundBox( RoundHBox(), Config.BG_COLOR )
- self.GUI["2keyRecordButton"] = ImageToggleButton( Config.IMAGE_ROOT+"record2.png", Config.IMAGE_ROOT+"record2sel.png", Config.IMAGE_ROOT+"record2sel.png", backgroundFill = Config.BG_COLOR )
+ self.GUI["2keyRecordButton"] = ImageToggleButton( Config.IMAGE_ROOT+"krecord.png", Config.IMAGE_ROOT+"krecordDown.png", Config.IMAGE_ROOT+"krecordOver.png", backgroundFill = Config.BG_COLOR )
self.GUI["2keyRecordButton"].connect("clicked", self.handleKeyboardRecordButton )
- self.GUI["2recordButton"] = ImageToggleButton( Config.IMAGE_ROOT+"record.png", Config.IMAGE_ROOT+"recordsel.png", Config.IMAGE_ROOT+"recordsel.png", backgroundFill = Config.BG_COLOR )
+ self.GUI["2recordButton"] = ImageToggleButton( Config.IMAGE_ROOT+"record2.png", Config.IMAGE_ROOT+"record2Down.png", Config.IMAGE_ROOT+"record2Over.png", backgroundFill = Config.BG_COLOR )
self.GUI["2recordButton"].connect("clicked", self.handleAudioRecord )
self.GUI["2transportBox"].pack_start( self.GUI["2keyRecordButton"] )
self.GUI["2transportBox"].pack_start( self.GUI["2recordButton"] )
@@ -831,6 +835,9 @@ class MainWindow( SubActivity ):
#else:
# recordButton.hide()
+ def getScale(self):
+ return self.generationPanel.scale
+
def handleVolume( self, widget ):
self._data["volume"] = round( widget.get_value() )
self.csnd.setMasterVolume(self._data["volume"])
@@ -1648,7 +1655,8 @@ class MainWindow( SubActivity ):
return
self.noteDB.updateNote( n.page, n.track, n.id, PARAMETER.DURATION, adjustedDuration)
if onsetQuantized >= n.cs.onset and (onsetQuantized+2) <= (n.cs.onset + n.cs.duration):
- return
+ self.noteDB.deleteNote(n.page, n.track, n.id)
+ #return
csnote = CSoundNote(onset = 0,
pitch = pitch,
@@ -1709,7 +1717,8 @@ class MainWindow( SubActivity ):
for n in self.noteDB.getNotesByTrack( csId[0], csId[1] ):
if csId[3] < n.cs.onset and (csId[3] + newDuration) >= n.cs.onset:
- newDuration = n.cs.onset - csId[3]
+ self.noteDB.deleteNote(n.page, n.track, n.id)
+ #newDuration = n.cs.onset - csId[3]
break
self.noteDB.updateNote( csId[0], csId[1], csId[2], PARAMETER.DURATION, newDuration)
@@ -1727,7 +1736,8 @@ class MainWindow( SubActivity ):
for n in self.noteDB.getNotesByTrack( self.csId[0], self.csId[1] ):
if self.csId[3] < n.cs.onset and (self.csId[3] + newDuration) > n.cs.onset:
- newDuration = n.cs.onset - self.csId[3]
+ self.noteDB.deleteNote(n.page, n.track, n.id)
+ #newDuration = n.cs.onset - self.csId[3]
break
self.noteDB.updateNote( self.csId[0], self.csId[1], self.csId[2], PARAMETER.DURATION, newDuration)
diff --git a/Edit/TrackInterface.py b/Edit/TrackInterface.py
index f517b1d..5b4780e 100644
--- a/Edit/TrackInterface.py
+++ b/Edit/TrackInterface.py
@@ -14,7 +14,7 @@ from Edit.MainWindow import CONTEXT
from Util.NoteDB import PARAMETER
from Util.CSoundNote import CSoundNote
-
+from Generation.GenerationConstants import GenerationConstants
from Util.Profiler import TP
class SELECTNOTES:
@@ -30,6 +30,7 @@ class INTERFACEMODE:
DRAW = 1
PASTE_NOTES = 2
PASTE_TRACKS = 3
+ PAINT = 4
class TrackInterfaceParasite:
def __init__( self, noteDB, owner, note ):
@@ -43,11 +44,12 @@ class TrackInterfaceParasite:
class TrackInterface( gtk.EventBox ):
- def __init__( self, noteDB, owner ):
+ def __init__( self, noteDB, owner, getScaleFunction ):
gtk.EventBox.__init__( self )
self.noteDB = noteDB
self.owner = owner
+ self.getScale = getScaleFunction
self.drawingArea = gtk.DrawingArea()
self.drawingAreaDirty = False # are we waiting to draw?
@@ -62,6 +64,7 @@ class TrackInterface( gtk.EventBox ):
self.curPage = -1 # this isn't a real page at all!
self.curBeats = 4
+ self.painting = False
self.selectedNotes = [ [] for i in range(Config.NUMBER_OF_TRACKS) ]
@@ -316,6 +319,8 @@ class TrackInterface( gtk.EventBox ):
if mode == "draw":
self.interfaceMode = INTERFACEMODE.DRAW
+ elif mode == "paint":
+ self.interfaceMode = INTERFACEMODE.PAINT
elif mode == "paste_notes":
self.interfaceMode = INTERFACEMODE.PASTE_NOTES
self.setCurrentAction("paste", self)
@@ -423,6 +428,59 @@ class TrackInterface( gtk.EventBox ):
TP.ProfileEnd( "TI::handleButtonPress" )
return
+ elif self.interfaceMode == INTERFACEMODE.PAINT:
+ self.scale = self.getScale()
+ self.painting = True
+ self.paintTrack = i
+ self.GRID = 3.
+ if i == self.drumIndex:
+ pitch = min( self.pixelsToPitchDrumFloor( self.clickLoc[1] - self.trackLimits[i][1] + Config.HIT_HEIGHT//2 )//Config.PITCH_STEP_DRUM, Config.NUMBER_OF_POSSIBLE_PITCHES_DRUM-1)*Config.PITCH_STEP_DRUM + Config.MINIMUM_PITCH_DRUM
+ if pitch < 24:
+ pitch = 24
+ elif pitch > 48:
+ pitch = 48
+ else:
+ pitch = pitch
+ else:
+ pitch = min( self.pixelsToPitchFloor( self.clickLoc[1] - self.trackLimits[i][1] + Config.NOTE_HEIGHT//2 ), Config.NUMBER_OF_POSSIBLE_PITCHES-1) + Config.MINIMUM_PITCH
+ if pitch < 24:
+ pitch = 24
+ elif pitch > 48:
+ pitch = 48
+ else:
+ pitch = pitch
+
+ minDiff = 100
+ for pit in GenerationConstants.SCALES[self.scale]:
+ diff = abs(pitch-(pit+36))
+ if diff < minDiff:
+ minDiff = diff
+ nearestPit = pit
+ pitch = nearestPit+36
+
+ onset = self.pixelsToTicksFloor( self.curBeats, self.clickLoc[0] - self.trackRect[i].x )
+ onset = self.GRID * int(onset / self.GRID + 0.5)
+ self.pLastPos = onset
+ if i != self.drumIndex:
+ noteS = self.noteDB.getNotesByTrack(self.curPage, i)
+ for n in noteS:
+ if onset >= n.cs.onset and onset < (n.cs.onset + n.cs.duration):
+ self.noteDB.deleteNote(self.curPage, i, n.id)
+
+ cs = CSoundNote( onset,
+ pitch,
+ 0.75,
+ 0.5,
+ 1,
+ i,
+ instrumentId = self.owner.getTrackInstrument(i).instrumentId )
+ cs.pageId = self.curPage
+ id = self.noteDB.addNote( -1, self.curPage, i, cs )
+ self.noteDB.updateNote(self.curPage, i, id, PARAMETER.DURATION, self.GRID)
+ n = self.noteDB.getNote( self.curPage, i, id, self )
+ self.selectNotes( { i:[n] }, True )
+ n.playSampleNote( False )
+ self.curAction = True
TP.ProfileEnd( "TI::handleButtonPress" )
@@ -430,6 +488,7 @@ class TrackInterface( gtk.EventBox ):
def handleButtonRelease( self, widget, event ):
if not self.clickButton: return # we recieved this event but were never clicked! (probably a popup window was open)
self.clickButton = 0
+ self.painting = False
TP.ProfileBegin( "TI::handleButtonRelease" )
@@ -477,6 +536,61 @@ class TrackInterface( gtk.EventBox ):
event.y = float(y)
event.state = state
+ if self.painting:
+ i = self.paintTrack
+ curPos = self.pixelsToTicksFloor(self.curBeats, event.x - self.trackRect[i].x)
+ gridPos = self.GRID * int(curPos / self.GRID)
+ if gridPos >= self.curBeats * Config.TICKS_PER_BEAT:
+ return
+ if gridPos != self.pLastPos:
+ self.pLastPos = gridPos
+ if i == self.drumIndex:
+ pitch = min( self.pixelsToPitchDrumFloor( int(event.y) - self.trackLimits[i][1] + Config.HIT_HEIGHT//2 )//Config.PITCH_STEP_DRUM, Config.NUMBER_OF_POSSIBLE_PITCHES_DRUM-1)*Config.PITCH_STEP_DRUM + Config.MINIMUM_PITCH_DRUM
+ if pitch < 24:
+ pitch = 24
+ elif pitch > 48:
+ pitch = 48
+ else:
+ pitch = pitch
+ else:
+ pitch = min( self.pixelsToPitchFloor( int(event.y) - self.trackLimits[i][1] + Config.NOTE_HEIGHT//2 ), Config.NUMBER_OF_POSSIBLE_PITCHES-1) + Config.MINIMUM_PITCH
+ if pitch < 24:
+ pitch = 24
+ elif pitch > 48:
+ pitch = 48
+ else:
+ pitch = pitch
+ minDiff = 100
+ for pit in GenerationConstants.SCALES[self.scale]:
+ diff = abs(pitch-(pit+36))
+ if diff < minDiff:
+ minDiff = diff
+ nearestPit = pit
+ pitch = nearestPit+36
+
+ onset = gridPos
+ if i != self.drumIndex:
+ noteS = self.noteDB.getNotesByTrack(self.curPage, i)
+ for n in noteS:
+ if onset >= n.cs.onset and onset < (n.cs.onset + n.cs.duration):
+ self.noteDB.deleteNote(self.curPage, i, n.id)
+
+ cs = CSoundNote( onset,
+ pitch,
+ 0.75,
+ 0.5,
+ 1,
+ i,
+ instrumentId = self.owner.getTrackInstrument(i).instrumentId )
+ cs.pageId = self.curPage
+ id = self.noteDB.addNote( -1, self.curPage, i, cs )
+ self.noteDB.updateNote(self.curPage, i, id, PARAMETER.DURATION, self.GRID)
+ n = self.noteDB.getNote( self.curPage, i, id, self )
+ self.selectNotes( { i:[n] }, True )
+ n.playSampleNote( False )
+ self.curAction = True
+
+
TP.ProfileEnd( "TI::handleMotion::Common" )
if not self.clickButton and self.curAction != "paste": # we recieved this event but were never clicked! (probably a popup window was open)
diff --git a/Resources/Images/brush.png b/Resources/Images/brush.png
new file mode 100755
index 0000000..60d29a9
--- /dev/null
+++ b/Resources/Images/brush.png
Binary files differ
diff --git a/Resources/Images/brushDown.png b/Resources/Images/brushDown.png
new file mode 100755
index 0000000..ea46632
--- /dev/null
+++ b/Resources/Images/brushDown.png
Binary files differ
diff --git a/Resources/Images/krecord.png b/Resources/Images/krecord.png
new file mode 100755
index 0000000..ee40bc1
--- /dev/null
+++ b/Resources/Images/krecord.png
Binary files differ
diff --git a/Resources/Images/krecordDown.png b/Resources/Images/krecordDown.png
new file mode 100755
index 0000000..754d3f0
--- /dev/null
+++ b/Resources/Images/krecordDown.png
Binary files differ
diff --git a/Resources/Images/krecordOver.png b/Resources/Images/krecordOver.png
new file mode 100755
index 0000000..16e04de
--- /dev/null
+++ b/Resources/Images/krecordOver.png
Binary files differ
diff --git a/Resources/Images/record2.png b/Resources/Images/record2.png
index f9dd7be..f7bdc4f 100644
--- a/Resources/Images/record2.png
+++ b/Resources/Images/record2.png
Binary files differ
diff --git a/Resources/Images/record2Down.png b/Resources/Images/record2Down.png
new file mode 100755
index 0000000..0e7923c
--- /dev/null
+++ b/Resources/Images/record2Down.png
Binary files differ
diff --git a/Resources/Images/record2Over.png b/Resources/Images/record2Over.png
new file mode 100755
index 0000000..3830034
--- /dev/null
+++ b/Resources/Images/record2Over.png
Binary files differ
diff --git a/TamTam.py b/TamTam.py
index f590fc4..3571005 100755
--- a/TamTam.py
+++ b/TamTam.py
@@ -52,7 +52,8 @@ class TamTam(Activity):
self.set_resizable(False)
self.trackpad = Trackpad( self )
- self.keyboardWindow = KeyboardWindow(8)
+ self.keyboardWindow = KeyboardWindow(size = 8, popup = True)
+ self.keyboardWindow.color_piano()
self.preloadTimeout = None
@@ -62,7 +63,9 @@ class TamTam(Activity):
self.connect( "key-press-event", self.onKeyPress )
self.connect( "key-release-event", self.onKeyRelease )
self.connect( "key-press-event", self.keyboardWindow.handle_keypress)
- self.connect( "key-release-event", self.keyboardWindow.handle_keyrelease )
+ self.connect( "key-release-event", self.keyboardWindow.handle_keyrelease)
+ self.connect( "button-press-event", self.keyboardWindow.handle_mousePress)
+ self.connect( "button-release-event", self.keyboardWindow.handle_mouseRelease)
self.mode = None
self.modeList = {}
@@ -167,12 +170,13 @@ class TamTam(Activity):
return
elif key == 49:#39: S
#self.set_mode('synth')
- os.spawnlp(os.P_NOWAIT,'/usr/share/activities/TamTam.activity/cnee','/usr/share/activities/TamTam.activity/cnee', '--record', '--keyboard', '--mouse', '--stop-key', 'h', '--out-file', '/home/olpc/test.xnl')
+ self.keyboardWindow.hide_all()
+ l = os.spawnlp(os.P_NOWAIT,'/usr/share/activities/TamTam.activity/cnee','/usr/share/activities/TamTam.activity/cnee', '--record', '--keyboard', '--mouse', '--stop-key', 'h', '--out-file', '/home/olpc/test.xnl')
return
elif key == 10:#25: W
#self.set_mode('welcome')
self.keyboardWindow.show_all()
- os.spawnlp(os.P_NOWAIT,'/usr/share/activities/TamTam.activity/cnee','/usr/share/activities/TamTam.activity/cnee', '--replay', '--keyboard', '--mouse', '--file', '/home/olpc/test.xnl')
+ l = os.spawnlp(os.P_NOWAIT,'/usr/share/activities/TamTam.activity/cnee','/usr/share/activities/TamTam.activity/cnee', '--replay', '--keyboard', '--mouse', '--file', '/home/olpc/test.xnl')
return
elif key == 53: #X
self.destroy()
diff --git a/Util/Clooper/Makefile b/Util/Clooper/Makefile
index 3b585f2..a1d1870 100644
--- a/Util/Clooper/Makefile
+++ b/Util/Clooper/Makefile
@@ -13,7 +13,7 @@ LDFlAGS+=-lpython2.4
all : aclient.so
-aclient.so : aclient.cpp
+aclient.so : aclient.cpp audio.cpp
g++ $(CPPFLAGS) $(CXXFLAGS) -shared -o $@ $< $(LDFLAGS)
clean :
diff --git a/Util/Clooper/aclient.cpp b/Util/Clooper/aclient.cpp
index 0d73c7e..c84fece 100644
--- a/Util/Clooper/aclient.cpp
+++ b/Util/Clooper/aclient.cpp
@@ -14,13 +14,6 @@
#include <csound/csound.h>
#include <alsa/asoundlib.h>
-#define ERROR_HERE if (_debug && (VERBOSE > 0)) fprintf(_debug, "ERROR: %s:%i\n", __FILE__, __LINE__)
-
-#define IF_DEBUG(N) if (_debug && (VERBOSE > N))
-
-int VERBOSE = 2;
-FILE * _debug = NULL;
-
static double pytime(const struct timeval * tv)
{
struct timeval t;
@@ -31,6 +24,18 @@ static double pytime(const struct timeval * tv)
}
return (double) tv->tv_sec + (double) tv->tv_usec / 1000000.0;
}
+#include "log.cpp"
+#include "audio.cpp"
+
+#define ERROR_HERE if (_debug && (VERBOSE > 0)) fprintf(_debug, "ERROR: %s:%i\n", __FILE__, __LINE__)
+
+#define IF_DEBUG(N) if (_debug && (VERBOSE > N))
+
+#define NEWAUDIO 0
+
+int VERBOSE = 3;
+FILE * _debug = NULL;
+
struct ev_t
{
@@ -116,187 +121,6 @@ struct ev_t
csoundScoreEvent(csound, type, &param[0], param.size());
}
};
-struct SystemStuff
-{
- static void setscheduler(void)
- {
- struct sched_param sched_param;
-
- if (sched_getparam(0, &sched_param) < 0) {
- printf("Scheduler getparam failed...\n");
- return;
- }
- sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
-
- if (sched_setscheduler(0, SCHED_RR, &sched_param))
- {
- if (_debug && (VERBOSE > 2)) printf("WARNING: Scheduler set to Round Robin with priority %i failed!\n", sched_param.sched_priority);
- }
- else
- {
- if (_debug && (VERBOSE > 2)) printf("INFO: Scheduler set to Round Robin with priority %i.\n", sched_param.sched_priority);
- }
- }
-
- /** the currently opened pcm hande */
- snd_pcm_t * pcm;
- snd_pcm_uframes_t period_size;
- unsigned int frame_rate;
-
- SystemStuff() : pcm(NULL), period_size(0), frame_rate(0)
- {
- }
- ~SystemStuff()
- {
- if (pcm) close(0);
- }
-
- int open(unsigned int rate0, int upsample_max, snd_pcm_uframes_t period0, unsigned int p_per_buff)
- {
- snd_pcm_hw_params_t *hw;
-
- if (pcm)
- {
- IF_DEBUG(0) fprintf(_debug, "ERROR: open called twice! First close the sound device\n");
- return -1;
- }
-
- if ( 0 > snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0)) { ERROR_HERE; return -1; }
- if ( 0 > snd_pcm_hw_params_malloc(&hw)) { ERROR_HERE; snd_pcm_close(pcm); pcm = NULL; return -1; }
-
- //now we can be a bit flexible with the buffer size and the sample-rate...
-
- int upsample;
- for (upsample = 1; upsample < upsample_max; ++upsample)
- {
- frame_rate = rate0 * upsample;
-
- if ( 0 > snd_pcm_hw_params_any(pcm, hw)) { ERROR_HERE; goto open_error;}
-
- //first do the compulsory steps... interleaved float, 2 channel
- if ( 0 > snd_pcm_hw_params_set_rate_resample(pcm, hw, 0)) { ERROR_HERE; goto open_error;}
- if ( 0 > snd_pcm_hw_params_test_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;}
- if ( 0 > snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;}
- if ( 0 > snd_pcm_hw_params_test_format(pcm, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;}
- if ( 0 > snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;}
- if ( 0 > snd_pcm_hw_params_set_channels(pcm, hw, 2)) { ERROR_HERE; goto open_error;}
-
- IF_DEBUG(1) fprintf(_debug, "testing rate : %i\t", frame_rate);
- if ( snd_pcm_hw_params_test_rate(pcm, hw, frame_rate, 0))
- {
- fprintf(_debug, "failed.\n");
- continue;
- }
- else
- {
- IF_DEBUG(1) fprintf(_debug, "success! setting rate : %i\n", frame_rate);
- if (0 > snd_pcm_hw_params_set_rate(pcm, hw, frame_rate, 0)) { ERROR_HERE; goto open_error;}
-
- snd_pcm_uframes_t minb=0, maxb= 0;
- int mind=0, maxd=0;
- snd_pcm_hw_params_get_period_size_min(hw, &minb,&mind);
- snd_pcm_hw_params_get_period_size_max(hw, &maxb,&maxd);
- IF_DEBUG(1) fprintf(_debug, "FYI: period size range is [%li/%i,%li/%i]\n", minb,mind, maxb, maxd);
-
- assert(mind == 0); //rate_resample 0 makes this true right?
- assert(maxd == 0); //rate_resample 0 makes this true right?
-
- if (period0 < minb)
- {
- IF_DEBUG(1) fprintf(_debug, "requested period size (%li) < min (%li), adjusting to min\n", period_size, minb);
- period_size = minb;
- }
- else if (period0 > maxb)
- {
- IF_DEBUG(1) fprintf(_debug, "requested period size (%li) < max (%li), adjusting to min\n", period_size, maxb);
- period_size = maxb;
- }
- else
- {
- period_size = period0;
- }
-
- IF_DEBUG(1) fprintf(_debug, "testing period size : %li\n", period_size);
- if ( 0 > snd_pcm_hw_params_test_period_size(pcm, hw, period_size, 0)){ ERROR_HERE; goto open_error;}
-
-
- IF_DEBUG(1) fprintf(_debug, "setting period size : %li\n", period_size);
- if ( 0 > snd_pcm_hw_params_set_period_size(pcm, hw, period_size, 0)){ ERROR_HERE; goto open_error;}
-
- IF_DEBUG(1) fprintf(_debug, "setting buffer size : %i * %li = %li\n", p_per_buff, period_size, p_per_buff * period_size);
- if ( 0 > snd_pcm_hw_params_set_buffer_size(pcm, hw, p_per_buff*period_size)) { ERROR_HERE; goto open_error;}
-
- break;
- }
- }
-
- if (upsample_max == upsample) { ERROR_HERE; goto open_error; }
-
- if (0 > snd_pcm_hw_params(pcm, hw)) { ERROR_HERE; goto open_error; }
-
- snd_pcm_hw_params_free (hw);
- return 0;
-
-open_error:
- snd_pcm_hw_params_free (hw);
- snd_pcm_close(pcm);
- pcm = NULL;
- return -1;
- }
- void close(int drain = 0)
- {
- if (!pcm)
- {
- IF_DEBUG(2) fprintf(_debug, "WARNING: attempt to close already-closed pcm\n");
- return;
- }
- IF_DEBUG(1) fprintf(_debug, "INFO: closing pcm device\n");
- if (drain) snd_pcm_drain(pcm);
- snd_pcm_close(pcm);
- pcm = NULL;
- }
- void prepare()
- {
- if (!pcm)
- {
- IF_DEBUG(0) fprintf(_debug, "ERROR: attempt to prepare a closed pcm\n");
- return;
- }
- if (0 > snd_pcm_prepare(pcm)) { ERROR_HERE; }
- }
- int write(snd_pcm_uframes_t frame_count, float * frame_data)
- {
- if (!pcm)
- {
- IF_DEBUG(0) fprintf(_debug, "ERROR: attempt to write a closed pcm\n");
- return -1;
- }
- int err;
- err = snd_pcm_writei (pcm, frame_data, frame_count );
- if (err == (signed)frame_count) return 0; //success
-
- assert(err < 0);
-
- const char * msg = NULL;
- snd_pcm_state_t state = snd_pcm_state(pcm);
- switch (state)
- {
- case SND_PCM_STATE_OPEN: msg = "open"; break;
- case SND_PCM_STATE_SETUP: msg = "setup"; break;
- case SND_PCM_STATE_PREPARED:msg = "prepared"; break;
- case SND_PCM_STATE_RUNNING: msg = "running"; break;
- case SND_PCM_STATE_XRUN: msg = "xrun"; break;
- case SND_PCM_STATE_DRAINING: msg = "draining"; break;
- case SND_PCM_STATE_PAUSED: msg = "paused"; break;
- case SND_PCM_STATE_SUSPENDED: msg = "suspended"; break;
- case SND_PCM_STATE_DISCONNECTED: msg = "disconnected"; break;
- }
- if (_debug && (VERBOSE > 1)) fprintf (_debug, "WARNING: write failed (%s)\tstate = %s\ttime=%lf\n", snd_strerror (err), msg, pytime(NULL));
- if (0 > snd_pcm_recover(pcm, err, 0)) { ERROR_HERE; return err;}
- if (0 > snd_pcm_prepare(pcm)) { ERROR_HERE; return err;}
- return 1; //warning
- }
-};
struct TamTamSound
{
/** the id of an running sound-rendering thread, or NULL */
@@ -521,7 +345,12 @@ struct TamTamSound
unsigned int period_per_buffer;
int up_ratio;
- SystemStuff sys_stuff;
+ log_t * ll;
+#if NEWAUDIO
+ AlsaStuff * sys_stuff;
+#else
+ SystemStuff * sys_stuff;
+#endif
TamTamSound(char * orc, snd_pcm_uframes_t period0, unsigned int ppb)
: ThreadID(NULL), PERF_STATUS(STOP), csound(NULL),
@@ -531,17 +360,31 @@ struct TamTamSound
period0(period0),
period_per_buffer(ppb),
up_ratio(0),
- sys_stuff()
- {
- if (0 > sys_stuff.open(csound_frame_rate, 4, period0, period_per_buffer))
- {
- return;
- }
- sys_stuff.close(0);
- up_ratio = sys_stuff.frame_rate / csound_frame_rate;
- csound_period_size = (sys_stuff.period_size % up_ratio == 0)
- ? sys_stuff.period_size / up_ratio
+ ll( new log_t(_debug, VERBOSE) ),
+ sys_stuff(NULL)
+ {
+#if NEWAUDIO
+ sys_stuff = new AlsaStuff( "default", "default", SND_PCM_FORMAT_FLOAT, 2, csound_frame_rate, period0, 4, ll);
+ if (! sys_stuff->good_to_go ) return;
+ up_ratio = sys_stuff->rate / csound_frame_rate;
+ csound_period_size = (sys_stuff->period_size % up_ratio == 0)
+ ? sys_stuff->period_size / up_ratio
: csound_ksmps * 4;
+ delete sys_stuff;
+ sys_stuff=NULL;
+#else
+ sys_stuff = new SystemStuff(ll);
+ if (0 > sys_stuff->open(csound_frame_rate, 4, period0, period_per_buffer))
+ {
+ return;
+ }
+ sys_stuff->close(0);
+ up_ratio = sys_stuff->rate / csound_frame_rate;
+ csound_period_size = (sys_stuff->period_size % up_ratio == 0)
+ ? sys_stuff->period_size / up_ratio
+ : csound_ksmps * 4;
+
+#endif
csound = csoundCreate(NULL);
int argc=3;
@@ -576,6 +419,8 @@ struct TamTamSound
csoundDestroy(csound);
}
if (_debug && (VERBOSE > 2)) fprintf(_debug, "TamTam aclient destroyed\n");
+ if (sys_stuff) delete sys_stuff;
+ delete ll;
}
uintptr_t thread_fn()
{
@@ -588,30 +433,44 @@ struct TamTamSound
if (_debug && (VERBOSE > 2)) fprintf(_debug, "INFO: nsamples = %li nframes = %li\n", csound_nsamples, csound_nframes);
- if (0 > sys_stuff.open(csound_frame_rate, 4, period0, period_per_buffer))
+#if NEWAUDIO
+ sys_stuff = new AlsaStuff( "default", "default", SND_PCM_FORMAT_FLOAT, 2, csound_frame_rate, period0, 4, ll);
+ if (!sys_stuff->good_to_go)
{
- IF_DEBUG(0) fprintf(_debug, "ERROR: failed to open alsa device, thread abort\n");
+ delete sys_stuff;
return 1;
}
- assert(up_ratio = sys_stuff.frame_rate / csound_frame_rate);
-
- float *upbuf = new float[ sys_stuff.period_size * nchannels ]; //2 channels
+ assert(up_ratio = sys_stuff->rate / csound_frame_rate);
+#else
+ if (0 > sys_stuff->open(csound_frame_rate, 4, period0, period_per_buffer))
+ {
+ IF_DEBUG(0) fprintf(_debug, "ERROR: failed to open alsa device, thread abort\n");
+ return 1;
+ }
+
+ assert(up_ratio = sys_stuff->rate / csound_frame_rate);
+#endif
+
+ float *upbuf = new float[ sys_stuff->period_size * nchannels ]; //2 channels
int cbuf_pos = csound_nframes;
float *cbuf = NULL;
- unsigned up_pos = 0;
+ int up_pos = 0;
int ratio_pos = 0;
- sys_stuff.setscheduler(); //it might work...
-
while (PERF_STATUS == CONTINUE)
{
- if (sys_stuff.period_size == (unsigned)csound_nframes )
+ if ((signed)sys_stuff->period_size == csound_nframes )
{
+ //if (0 > sys_stuff->readbuf((char*)csoundGetInputBuffer(csound))) break;
if (csoundPerformBuffer(csound)) break;
- if (0 > sys_stuff.write(sys_stuff.period_size, csoundGetOutputBuffer(csound))) break;
+#if NEWAUDIO
+ if (0 > sys_stuff->writebuf((char*)csoundGetOutputBuffer(csound))) break;
+#else
+ if (0 > sys_stuff->writebuf(csound_nframes,csoundGetOutputBuffer(csound))) break;
+#endif
}
- else
+ else //fill one period of audio buffer data by 0 or more calls to csound
{
up_pos = 0;
int messed = 0;
@@ -620,7 +479,7 @@ struct TamTamSound
if (cbuf_pos == csound_nframes)
{
cbuf_pos = 0;
- if (csoundPerformBuffer(csound)) {messed = 1;break;}
+ if (csoundPerformBuffer(csound)) { messed = 1;break;}
cbuf = csoundGetOutputBuffer(csound);
}
upbuf[2*up_pos+0] = cbuf[cbuf_pos*2+0];
@@ -632,11 +491,15 @@ struct TamTamSound
++cbuf_pos;
}
- if (++up_pos == sys_stuff.period_size) break;
+ if (++up_pos == (signed)sys_stuff->period_size) break;
}
- if (messed || (up_pos != sys_stuff.period_size)) break;
+ if (messed || (up_pos != (signed)sys_stuff->period_size)) break;
- if (0 > sys_stuff.write(sys_stuff.period_size, upbuf)) break;
+#if NEWAUDIO
+ if (0 > sys_stuff->writebuf((char*)upbuf)) break;
+#else
+ if (0 > sys_stuff->writebuf(csound_nframes,csoundGetOutputBuffer(csound))) break;
+#endif
}
if (thread_playloop)
@@ -646,10 +509,17 @@ struct TamTamSound
++nloops;
}
- sys_stuff.close(1);
+#if NEWAUDIO
+ delete sys_stuff;
+ sys_stuff = NULL;
+#else
+ sys_stuff->close(1);
+#endif
+ delete [] upbuf;
if (_debug && (VERBOSE > 2)) fprintf(_debug, "INFO: returning from performance thread\n");
return 0;
}
+ uintptr_t read_thread_fn()
static uintptr_t csThread(void *clientData)
{
return ((TamTamSound*)clientData)->thread_fn();
@@ -664,8 +534,10 @@ struct TamTamSound
{
PERF_STATUS = CONTINUE;
ThreadID = csoundCreateThread(csThread, (void*)this);
+ ll->printf( "INFO(%s:%i) aclient launching performance thread (%p)\n", __FILE__, __LINE__, ThreadID );
return 0;
}
+ ll->printf( "INFO(%s:%i) skipping duplicate request to launch a thread\n", __FILE__, __LINE__ );
return 1;
}
int stop()
@@ -677,10 +549,10 @@ struct TamTamSound
if (ThreadID)
{
PERF_STATUS = STOP;
- if (_debug && (VERBOSE > 2)) fprintf(_debug, "INFO: aclient joining performance thread\n");
+ ll->printf( "INFO(%s:%i) aclient joining performance thread\n", __FILE__, __LINE__ );
uintptr_t rval = csoundJoinThread(ThreadID);
- if (rval)
- if (_debug && (VERBOSE > 0)) fprintf(_debug, "WARNING: thread returned %zu\n", rval);
+ ll->printf( "INFO(%s:%i) ... joined\n", __FILE__, __LINE__ );
+ if (rval) ll->printf( "WARNING: thread returned %zu\n", rval);
ThreadID = NULL;
return 0;
}
@@ -854,9 +726,15 @@ DECL(sc_initialize) //(char * csd)
return NULL;
}
if ( log_file[0] )
+ {
_debug = fopen(log_file,"w");
+ if (_debug==NULL) fprintf(stderr, "Logging disabled due to error in fopen(%s) \n", log_file);
+ }
else
+ {
_debug = NULL;
+ fprintf(stderr, "Logging disabled on purpose\n");
+ }
sc_tt = new TamTamSound(str, period, ppb);
atexit(&cleanup);
if (sc_tt->good())
diff --git a/Util/Clooper/audio.cpp b/Util/Clooper/audio.cpp
new file mode 100644
index 0000000..f757f31
--- /dev/null
+++ b/Util/Clooper/audio.cpp
@@ -0,0 +1,681 @@
+/*
+ * Latency test program
+ *
+ * Author: Jaroslav Kysela <perex@suse.cz>
+ *
+ * This small demo program can be used for measuring latency between
+ * capture and playback. This latency is measured from driver (diff when
+ * playback and capture was started). Scheduler is set to SCHED_RR.
+ *
+ *
+ * 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
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sched.h>
+#include <errno.h>
+#include <getopt.h>
+#include <sys/time.h>
+#include <math.h>
+
+#include <string>
+#include <alsa/asoundlib.h>
+
+#define ERROR_HERE ll->printf("ERROR_HERE: %s %i\n", __FILE__, __LINE__);
+
+struct SystemStuff
+{
+ log_t * ll;
+
+ snd_pcm_t *phandle, *chandle;
+ snd_pcm_uframes_t period_size;
+ unsigned int rate;
+
+ float * bonusbuf;
+ unsigned bonuspos;
+
+ SystemStuff(log_t * ll) : ll(ll), phandle(NULL), chandle(NULL), period_size(0), rate(0), bonusbuf( NULL )
+ {
+ bonusbuf = new float[16000 * 2];
+ bonuspos = 0;
+ }
+ ~SystemStuff()
+ {
+ delete[] bonusbuf;
+ if (phandle) close(0);
+ }
+
+ void setscheduler(void)
+ {
+ struct sched_param sched_param;
+
+ if (sched_getparam(0, &sched_param) < 0) {
+ ll->printf( "Scheduler getparam failed...\n");
+ return;
+ }
+ sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
+ if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
+ ll->printf( "Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority);
+ return;
+ }
+ ll->printf( "!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority);
+ }
+
+ int open(unsigned int rate0, int upsample_max, snd_pcm_uframes_t period0, unsigned int p_per_buff)
+ {
+ snd_pcm_hw_params_t *hw;
+
+ if (phandle)
+ {
+ ll->printf( "ERROR: open called twice! First close the sound device\n");
+ return -1;
+ }
+
+ if ( 0 > snd_pcm_open(&phandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) { ERROR_HERE; return -1; }
+ if ( 0 > snd_pcm_open(&chandle, "default", SND_PCM_STREAM_CAPTURE, 0)) { ERROR_HERE; return -1; }
+ if ( 0 > snd_pcm_hw_params_malloc(&hw)) { ERROR_HERE; snd_pcm_close(phandle); phandle = NULL; return -1; }
+
+ //now we can be a bit flexible with the buffer size and the sample-rate...
+
+ int upsample;
+ for (upsample = 1; upsample < upsample_max; ++upsample)
+ {
+ rate = rate0 * upsample;
+
+ if ( 0 > snd_pcm_hw_params_any(phandle, hw)) { ERROR_HERE; goto open_error;}
+
+ //first do the compulsory steps... interleaved float, 2 channel
+ if ( 0 > snd_pcm_hw_params_set_rate_resample(phandle, hw, 0)) { ERROR_HERE; goto open_error;}
+ if ( 0 > snd_pcm_hw_params_test_access(phandle, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;}
+ if ( 0 > snd_pcm_hw_params_set_access(phandle, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;}
+ if ( 0 > snd_pcm_hw_params_test_format(phandle, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;}
+ if ( 0 > snd_pcm_hw_params_set_format(phandle, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;}
+ if ( 0 > snd_pcm_hw_params_set_channels(phandle, hw, 2)) { ERROR_HERE; goto open_error;}
+
+ if ( snd_pcm_hw_params_test_rate(phandle, hw, rate, 0))
+ {
+ ll->printf("test_rate failed( %i\n", rate);
+ continue;
+ }
+ else
+ {
+ ll->printf(1, "success! setting rate : %i\n", rate);
+ if (0 > snd_pcm_hw_params_set_rate(phandle, hw, rate, 0)) { ERROR_HERE; goto open_error;}
+
+ snd_pcm_uframes_t minb=0, maxb= 0;
+ int mind=0, maxd=0;
+ snd_pcm_hw_params_get_period_size_min(hw, &minb,&mind);
+ snd_pcm_hw_params_get_period_size_max(hw, &maxb,&maxd);
+ ll->printf(2, "FYI: period size range is [%li/%i,%li/%i]\n", minb,mind, maxb, maxd);
+
+ assert(mind == 0); //rate_resample 0 makes this true right?
+ assert(maxd == 0); //rate_resample 0 makes this true right?
+
+ if (period0 < minb)
+ {
+ ll->printf(1, "requested period size (%li) < min (%li), adjusting to min\n", period_size, minb);
+ period_size = minb;
+ }
+ else if (period0 > maxb)
+ {
+ ll->printf(2, "requested period size (%li) < max (%li), adjusting to min\n", period_size, maxb);
+ period_size = maxb;
+ }
+ else
+ {
+ period_size = period0;
+ }
+
+ ll->printf(1, "testing period size : %li\n", period_size);
+ if ( 0 > snd_pcm_hw_params_test_period_size(phandle, hw, period_size, 0)){ ERROR_HERE; goto open_error;}
+
+
+ ll->printf(1, "setting period size : %li\n", period_size);
+ if ( 0 > snd_pcm_hw_params_set_period_size(phandle, hw, period_size, 0)){ ERROR_HERE; goto open_error;}
+
+ ll->printf(1, "setting buffer size : %i * %li = %li\n", p_per_buff, period_size, p_per_buff * period_size);
+ if ( 0 > snd_pcm_hw_params_set_buffer_size(phandle, hw, p_per_buff*period_size)) { ERROR_HERE; goto open_error;}
+
+ break;
+ }
+ }
+
+ if (upsample_max == upsample) { ERROR_HERE; goto open_error; }
+
+ if (0 > snd_pcm_hw_params(phandle, hw)) { ERROR_HERE; goto open_error; }
+ if (0 > snd_pcm_hw_params(chandle, hw)) { ERROR_HERE; goto open_error; }
+
+ snd_pcm_hw_params_free (hw);
+ return 0;
+
+open_error:
+ snd_pcm_hw_params_free (hw);
+ snd_pcm_close(phandle);
+ phandle = NULL;
+ return -1;
+ }
+ void close(int drain = 0)
+ {
+ if (!phandle)
+ {
+ ll->printf(0, "WARNING: attempt to close already-closed pcm\n");
+ return;
+ }
+ ll->printf(1, "INFO: closing phandle device\n");
+ if (drain) snd_pcm_drain(phandle);
+ snd_pcm_close(phandle);
+ snd_pcm_close(chandle);
+ phandle = NULL;
+ chandle = NULL;
+ }
+ void prepare()
+ {
+ if (!phandle)
+ {
+ ll->printf(0, "ERROR: attempt to prepare a closed pcm\n");
+ return;
+ }
+ if (0 > snd_pcm_prepare(phandle)) { ERROR_HERE; }
+ }
+ int writebuf(snd_pcm_uframes_t frame_count, float * frame_data)
+ {
+ if (!phandle)
+ {
+ ll->printf(0, "ERROR: attempt to write a closed phandle\n");
+ return -1;
+ }
+ int err;
+ err = snd_pcm_writei (phandle, frame_data, frame_count );
+ if (err == (signed)frame_count) return 0; //success
+
+ assert(err < 0);
+
+ const char * msg = NULL;
+ snd_pcm_state_t state = snd_pcm_state(phandle);
+ switch (state)
+ {
+ case SND_PCM_STATE_OPEN: msg = "open"; break;
+ case SND_PCM_STATE_SETUP: msg = "setup"; break;
+ case SND_PCM_STATE_PREPARED:msg = "prepared"; break;
+ case SND_PCM_STATE_RUNNING: msg = "running"; break;
+ case SND_PCM_STATE_XRUN: msg = "xrun"; break;
+ case SND_PCM_STATE_DRAINING: msg = "draining"; break;
+ case SND_PCM_STATE_PAUSED: msg = "paused"; break;
+ case SND_PCM_STATE_SUSPENDED: msg = "suspended"; break;
+ case SND_PCM_STATE_DISCONNECTED: msg = "disconnected"; break;
+ }
+ ll->printf(1, "WARNING: write failed (%s)\tstate = %s\ttime=%lf\n", snd_strerror (err), msg, pytime(NULL));
+ if (0 > snd_pcm_recover(phandle, err, 0)) { ERROR_HERE; return err;}
+ if (0 > snd_pcm_prepare(phandle)) { ERROR_HERE; return err;}
+ return 1; //warning
+ }
+ int readbuf(snd_pcm_uframes_t frame_count, float * frame_data)
+ {
+ int tries=0;
+ int err=1;
+ while (err && (tries<2))
+ {
+ ++tries;
+ err = snd_pcm_readi (chandle, frame_data, frame_count );
+ if (err < 0)
+ {
+ const char * msg = NULL;
+ snd_pcm_state_t state = snd_pcm_state(chandle);
+ switch (state)
+ {
+ case SND_PCM_STATE_OPEN: msg = "open"; break;
+ case SND_PCM_STATE_SETUP: msg = "setup"; break;
+ case SND_PCM_STATE_PREPARED:msg = "prepared"; break;
+ case SND_PCM_STATE_RUNNING: msg = "running"; break;
+ case SND_PCM_STATE_XRUN: msg = "xrun"; break;
+ case SND_PCM_STATE_DRAINING: msg = "draining"; break;
+ case SND_PCM_STATE_PAUSED: msg = "paused"; break;
+ case SND_PCM_STATE_SUSPENDED: msg = "suspended"; break;
+ case SND_PCM_STATE_DISCONNECTED: msg = "disconnected"; break;
+ }
+ ll->printf(1, "WARNING: read failed (%s)\tstate = %s\ttime=%lf\n", snd_strerror (err), msg, pytime(NULL));
+ if (0 > snd_pcm_recover(chandle, err, 0)) { ERROR_HERE; return err;}
+ if (0 > snd_pcm_prepare(chandle)) { ERROR_HERE; return err;}
+ }
+ }
+ if (0)
+ {
+ float a = 0.0;
+ for (unsigned i = 0; i < frame_count; ++i)
+ {
+ a = a + frame_data[i] * frame_data[i];
+ }
+ fprintf(stderr, "%lf %i\n", a, err);
+ }
+ return (err == (signed)frame_count) ? 0 : err;
+ }
+};
+#undef ERROR_HERE
+
+struct AlsaStuff
+{
+ bool good_to_go;
+ std::string pdevice, cdevice;
+ snd_pcm_format_t format;
+ int rate;
+ int channels;
+ int buffer_size;
+ int period_size;
+ snd_output_t *output;
+ snd_pcm_t *phandle, *chandle;
+ log_t *ll;
+ int frame_bytes;
+ int allow_resample;
+ int streams_linked;
+
+ snd_pcm_hw_params_t *pt_params, *ct_params; /* templates with rate, format and channels */
+ snd_pcm_hw_params_t *p_params, *c_params;
+ snd_pcm_sw_params_t *p_swparams, *c_swparams;
+
+ AlsaStuff( const char * pdev, const char * cdev, snd_pcm_format_t fmt, int chnl, int r0, int p0, int upsample_max, log_t * ll)
+ : good_to_go(false),
+ pdevice(pdev),
+ cdevice(cdev),
+ format(fmt),
+ rate(0),
+ channels(chnl),
+ buffer_size(0),
+ period_size(0),
+ phandle(NULL), chandle(NULL),
+ ll(ll),
+ frame_bytes((snd_pcm_format_width(format) / 8) * channels),
+ allow_resample(0)
+ {
+ int err;
+ snd_pcm_uframes_t p_size, c_size, p_psize, c_psize;
+ unsigned int p_time, c_time;
+
+ snd_pcm_hw_params_alloca(&p_params);
+ snd_pcm_hw_params_alloca(&c_params);
+ snd_pcm_hw_params_alloca(&pt_params);
+ snd_pcm_hw_params_alloca(&ct_params);
+ snd_pcm_sw_params_alloca(&p_swparams);
+ snd_pcm_sw_params_alloca(&c_swparams);
+
+
+ if ((err = snd_output_stdio_attach(&output, ll->_file, 0)) < 0) {
+ ll->printf("Output failed: %s\n", snd_strerror(err));
+ return;
+ }
+
+ setscheduler();
+
+ if ((err = snd_pcm_open(&phandle, pdevice.c_str(), SND_PCM_STREAM_PLAYBACK, 0 )) < 0) {
+ ll->printf("Playback open error: %s\n", snd_strerror(err));
+ return;
+ }
+ if ((err = snd_pcm_open(&chandle, cdevice.c_str(), SND_PCM_STREAM_CAPTURE, 0 )) < 0) {
+ ll->printf("Record open error: %s\n", snd_strerror(err));
+ return;
+ }
+
+ int upsample=0;
+ while(upsample < upsample_max)
+ {
+ ++upsample;
+
+ rate += r0;
+ period_size += p0;
+
+ // set stream params
+ if ((err = setparams_stream(phandle, pt_params, "playback")) < 0) {
+ ll->printf( "Unable to set parameters for playback stream: %s\n", snd_strerror(err));
+ continue;
+ }
+ if ((err = setparams_stream(chandle, ct_params, "capture")) < 0) {
+ ll->printf("Unable to set parameters for playback stream: %s\n", snd_strerror(err));
+ continue;
+ }
+
+ // set buffer params
+
+ if ((err = setparams_bufsize(phandle, p_params, pt_params, period_size, "playback")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
+ continue;
+ }
+ if ((err = setparams_bufsize(chandle, c_params, ct_params, period_size, "capture")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
+ continue;
+ }
+
+ snd_pcm_hw_params_get_period_size(p_params, &p_psize, NULL);
+ if (p_psize < (unsigned int)period_size) continue;
+
+ snd_pcm_hw_params_get_period_size(c_params, &c_psize, NULL);
+ if (c_psize < (unsigned int)period_size) continue;
+
+ snd_pcm_hw_params_get_period_time(p_params, &p_time, NULL);
+ snd_pcm_hw_params_get_period_time(c_params, &c_time, NULL);
+ if (p_time != c_time) continue;
+
+ snd_pcm_hw_params_get_buffer_size(p_params, &p_size);
+ if (p_psize * 2 < p_size) continue;
+
+ snd_pcm_hw_params_get_buffer_size(c_params, &c_size);
+ if (c_psize * 2 < c_size) continue;
+
+ if ((err = setparams_set(phandle, p_params, p_swparams, "playback")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
+ continue;
+ }
+ if ((err = setparams_set(chandle, c_params, c_swparams, "capture")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
+ continue;
+ }
+ break;
+ }
+
+ if (upsample == upsample_max) return;
+
+ ll->printf("Preparing audio devices\n");
+ if ((err = snd_pcm_prepare(phandle)) < 0) {
+ printf("Prepare playback error: %s\n", snd_strerror(err));
+ return;
+ }
+ if ((err = snd_pcm_prepare(chandle)) < 0) {
+ printf("Prepare capture error: %s\n", snd_strerror(err));
+ return;
+ }
+ good_to_go = true;
+ snd_pcm_dump(phandle, output);
+ snd_pcm_dump(chandle, output);
+ char * silence = (char*)malloc(period_size * frame_bytes);
+ if (snd_pcm_format_set_silence(format, silence, period_size*channels) < 0) {
+ ll->printf( "silence error\n");
+ }
+ if (writebuf(silence) < 0) {
+ ll->printf( "write error\n");
+ good_to_go=false;
+ }
+ if (writebuf(silence) < 0) {
+ ll->printf( "write error\n");
+ good_to_go=false;
+ }
+ free(silence);
+ ll->printf("Starting audio devices\n");
+ if ((err = snd_pcm_start(chandle)) < 0) {
+ ll->printf( "Go capture error: %s\n", snd_strerror(err));
+ good_to_go=false;
+ return;
+ }
+ if ((err = snd_pcm_start(phandle)) < 0) {
+ ll->printf( "Go playback error: %s\n", snd_strerror(err));
+ good_to_go=false;
+ return;
+ }
+ }
+ ~AlsaStuff()
+ {
+ snd_pcm_drop(chandle);
+ snd_pcm_drain(phandle);
+ snd_pcm_hw_free(phandle);
+ snd_pcm_hw_free(chandle);
+ snd_pcm_close(phandle);
+ snd_pcm_close(chandle);
+ }
+
+ void setscheduler(void)
+ {
+ struct sched_param sched_param;
+
+ if (sched_getparam(0, &sched_param) < 0) {
+ ll->printf( "Scheduler getparam failed...\n");
+ return;
+ }
+ sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
+ if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
+ ll->printf( "Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority);
+ return;
+ }
+ ll->printf( "!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority);
+ }
+ long readbuf(char *buf)
+ {
+ return 0;
+ if (!good_to_go) return -1;
+ long frames = period_size;
+ while( frames )
+ {
+ ll->printf( "reading %li\n", frames);
+ long r = snd_pcm_readi(chandle, buf, frames);
+ if (r < 0)
+ {
+ ll->printf( "error in snd_pcm_readi(): %s\n", snd_strerror(r));
+ return r;
+ }
+ buf += r * frame_bytes;
+ frames -= r;
+ }
+ return 0;
+ }
+ long writebuf(const char *buf)
+ {
+ long frames = period_size;
+ if (!good_to_go) return -1;
+ while ( frames ) {
+ ll->printf("snd_pcm_writei ! (%li)\n", frames);
+ long r = snd_pcm_writei(phandle, buf, frames);
+ if (r == frames) break;
+ if (r >= 0)
+ {
+ ll->printf("snd_pcm_writei wrote only some of the frames! (%li)\n", r);
+ break;
+ }
+
+ const char * msg = NULL;
+ snd_pcm_state_t state = snd_pcm_state(phandle);
+ switch (state)
+ {
+ case SND_PCM_STATE_OPEN: msg = "open"; break;
+ case SND_PCM_STATE_SETUP: msg = "setup"; break;
+ case SND_PCM_STATE_PREPARED:msg = "prepared"; break;
+ case SND_PCM_STATE_RUNNING: msg = "running"; break;
+ case SND_PCM_STATE_XRUN: msg = "xrun"; break;
+ case SND_PCM_STATE_DRAINING: msg = "draining"; break;
+ case SND_PCM_STATE_PAUSED: msg = "paused"; break;
+ case SND_PCM_STATE_SUSPENDED: msg = "suspended"; break;
+ case SND_PCM_STATE_DISCONNECTED: msg = "disconnected"; break;
+ }
+ ll->printf( "WARNING: write failed (%s)\tstate = %s\t\n", snd_strerror (r), msg);
+ if (0 > snd_pcm_recover(phandle, r, 0)) { ll->printf( "fuck\n"); return r;}
+ ll->printf( "made it end of recover... looping\n");
+ if (0 > snd_pcm_prepare(phandle)) { ll->printf( "fuck\n"); return r;}
+ ll->printf( "made it end of writebuf... looping\n");
+ }
+ return 0;
+ }
+
+ int setparams_stream(snd_pcm_t *handle, snd_pcm_hw_params_t *params, const char *id)
+ {
+ int err;
+ unsigned int rrate=rate;
+
+ err = snd_pcm_hw_params_any(handle, params);
+ if (err < 0) {
+ printf("Broken configuration for %s PCM: no configurations available: %s\n", snd_strerror(err), id);
+ return err;
+ }
+ err = snd_pcm_hw_params_set_rate_resample(handle, params, allow_resample);
+ if (err < 0) {
+ printf("Resample setup failed for %s (val %i): %s\n", id, allow_resample, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (err < 0) {
+ printf("Access type not available for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_hw_params_set_format(handle, params, format);
+ if (err < 0) {
+ printf("Sample format not available for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_hw_params_set_channels(handle, params, channels);
+ if (err < 0) {
+ printf("Channels count (%i) not available for %s: %s\n", channels, id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
+ if (err < 0) {
+ printf("Rate %iHz not available for %s: %s\n", rate, id, snd_strerror(err));
+ return err;
+ }
+ if ((int)rrate != rate) {
+ printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ int setparams_bufsize(snd_pcm_t *handle,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_params_t *tparams,
+ snd_pcm_uframes_t bufsize,
+ const char *id)
+ {
+ int err;
+ snd_pcm_uframes_t periodsize;
+
+ snd_pcm_hw_params_copy(params, tparams);
+ periodsize = bufsize * 2;
+ err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize);
+ if (err < 0) {
+ printf("Unable to set buffer size %li for %s: %s\n", bufsize * 2, id, snd_strerror(err));
+ return err;
+ }
+ if (period_size > 0)
+ periodsize = period_size;
+ else
+ periodsize /= 2;
+ err = snd_pcm_hw_params_set_period_size_near(handle, params, &periodsize, 0);
+ if (err < 0) {
+ printf("Unable to set period size %li for %s: %s\n", periodsize, id, snd_strerror(err));
+ return err;
+ }
+ return 0;
+ }
+
+ int setparams_set(snd_pcm_t *handle,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_sw_params_t *swparams,
+ const char *id)
+ {
+ int err;
+
+ err = snd_pcm_hw_params(handle, params);
+ if (err < 0) {
+ printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_sw_params_current(handle, swparams);
+ if (err < 0) {
+ printf("Unable to determine current swparams for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff);
+ if (err < 0) {
+ printf("Unable to set start threshold mode for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
+ if (err < 0) {
+ printf("Unable to set transfer align for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_sw_params(handle, swparams);
+ if (err < 0) {
+ printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ return 0;
+ }
+
+ void showstat(snd_pcm_t *handle, size_t frames)
+ {
+ int err;
+ snd_pcm_status_t *status;
+
+ snd_pcm_status_alloca(&status);
+ if ((err = snd_pcm_status(handle, status)) < 0) {
+ printf("Stream status error: %s\n", snd_strerror(err));
+ exit(0);
+ }
+ printf("*** frames = %li ***\n", (long)frames);
+ snd_pcm_status_dump(status, output);
+ snd_pcm_status_free(status);
+ }
+};
+
+typedef char frame_t;
+
+struct Upsampler
+{
+ AlsaStuff * dev;
+ int ratio;
+ int blocklen;
+
+ frame_t * rbuf;
+ frame_t * wbuf;
+ frame_t * rptr;
+ frame_t * wptr;
+
+ Upsampler( AlsaStuff * dev, int ratio, int blocklen )
+ : dev(dev),
+ ratio(ratio),
+ blocklen(blocklen),
+ rbuf( new frame_t[dev->period_size * dev->frame_bytes ]),
+ wbuf( new frame_t[dev->period_size * dev->frame_bytes ]),
+ rptr(rbuf),
+ wptr(wbuf)
+ {
+ }
+ ~Upsampler()
+ {
+ delete[] rbuf;
+ delete[] wbuf;
+ }
+ //store blocklen * dev->frame_bytes in framebuf
+ long readbuf(frame_t * framebuf)
+ {
+ if ((ratio == 1) && (blocklen == dev->period_size))
+ {
+ }
+ else
+ {
+ }
+ return 0;
+ }
+ //write blocklen * dev->frame_bytes in framebuf
+ long writebuf(const frame_t * __restrict__ framebuf)
+ {
+ if ((ratio == 1) && (blocklen == dev->period_size))
+ {
+ }
+ else
+ {
+ }
+ return 0;
+ }
+};
+
+
diff --git a/Util/Clooper/log.cpp b/Util/Clooper/log.cpp
new file mode 100644
index 0000000..1749721
--- /dev/null
+++ b/Util/Clooper/log.cpp
@@ -0,0 +1,47 @@
+
+#include <stdarg.h>
+#include <stdio.h>
+
+struct log_t
+{
+ FILE * _file;
+ int _level;
+ int _close;
+
+ log_t(const char * logpath, int level = 0) : _file(NULL), _level(level), _close(1)
+ {
+ _file = fopen(logpath, "w");
+ if (!_file)
+ {
+ fprintf(stderr, "Failed to open log file for writing: %s\n", logpath);
+ }
+ }
+ log_t(FILE * file, int level = 0): _file(file), _level(level), _close(0)
+ {
+ }
+ ~log_t()
+ {
+ if (_close && _file) fclose(_file);
+ }
+ void printf( const char * fmt, ... ) __attribute__(( format (printf, 2,3)))
+ {
+ if (!_file) return;
+ va_list ap;
+ va_start(ap,fmt);
+ ::vfprintf(_file, fmt, ap);
+ va_end(ap);
+ fflush(_file);
+ }
+ void printf( int level, const char * fmt, ... ) __attribute__(( format (printf, 3,4)))
+ {
+ if (level <= _level)
+ {
+ if (!_file) return;
+ va_list ap;
+ va_start(ap,fmt);
+ ::vfprintf(_file, fmt, ap);
+ va_end(ap);
+ fflush(_file);
+ }
+ }
+};
diff --git a/Util/KeyboardWindow.py b/Util/KeyboardWindow.py
index e9f00ea..4d67375 100644
--- a/Util/KeyboardWindow.py
+++ b/Util/KeyboardWindow.py
@@ -4,25 +4,41 @@ pygtk.require( '2.0' )
import gtk
import random
from ThemeWidgets import keyButton
+import Config
+KEY_MAP_PIANO = Config.KEY_MAP_PIANO
class KeyboardWindow(gtk.Window):
- def __init__(self, size = None):
- gtk.Window.__init__(self , gtk.WINDOW_TOPLEVEL)
- self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
+ def __init__(self, size = None, pos = 0, popup = False):
+ if popup is False:
+ gtk.Window.__init__(self , gtk.WINDOW_TOPLEVEL)
+ else:
+ gtk.Window.__init__(self , gtk.WINDOW_POPUP)
color = gtk.gdk.color_parse("#000000")
self.modify_bg(gtk.STATE_NORMAL, color)
-
- self.connect("destroy",self.hide)
+ self.set_decorated(False)
+
+ self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.ENTER_NOTIFY_MASK | gtk.gdk.KEY_PRESS_MASK)
self.connect("key-press-event",self.handle_keypress)
self.connect("key-release-event",self.handle_keyrelease)
+ self.connect("button-press-event",self.handle_mousePress)
+ self.connect("button-release-event",self.handle_mouseRelease)
+ self.connect("enter-notify-event",self.handle_enter)
- if size == None:
- self.PIXEL_SPACE = 15
- self.HEIGHT = 45
+ self.size = size
+ self.pos = pos
+ self.popup = popup
+ self.set_pos(self.pos)
+
+ if self.size == None:
+ self.pixel_space = 15
+ self.height = 45
else:
- self.PIXEL_SPACE = size
- self.HEIGHT = 3* size
+ self.pixel_space = size
+ self.height = 3 * size
+
+ self.draw()
+ def draw(self):
self.rows = {}
self.rows[1] = [(49,1), (10,3), (11,3), (12,3), (13,3), (14,3), (15,3), (16,3), (17,3), (18,3), (19,3), (20,3), (21,5)]
self.rows[2] = [(23,3), (24,3), (25,3), (26,3), (27,3), (28,3), (29,3), (30,3), (31,3), (32,3), (33,3), (34,3), (35,4)]
@@ -34,58 +50,125 @@ class KeyboardWindow(gtk.Window):
self.btn_dic = {}
+ mainvbox = gtk.VBox()
mainhbox = gtk.HBox()
+ #Main keyboard section
vbox = gtk.VBox()
for row in [1,2,3,4,5]:
hbox = gtk.HBox()
for key in self.rows[row]:
- self.btn_dic[key[0]] = keyButton(self.PIXEL_SPACE * key[1], self.HEIGHT, [0,0,0], [0.5,0.5,0.5])
- self.btn_dic[key[0]].connect("enter",self.handle_mouseEnter)
- self.btn_dic[key[0]].connect("leave",self.handle_mouseLeave)
- hbox.pack_start(self.btn_dic[key[0]], padding = self.PIXEL_SPACE//2)
- vbox.pack_start(hbox, padding = self.PIXEL_SPACE//2)
+ self.btn_dic[key[0]] = keyButton(self.pixel_space * key[1], self.height, [0,0,0], [0.5,0.5,0.5])
+ hbox.pack_start(self.btn_dic[key[0]], padding = self.pixel_space//2)
+ vbox.pack_start(hbox, padding = self.pixel_space//2)
mainhbox.pack_start(vbox)
+ #Right part of the keyboard
right_vbox = gtk.VBox()
right_tophbox = gtk.HBox()
right_lowhbox = gtk.HBox()
- self.btn_dic[self.right_section[0][0]] = keyButton(self.PIXEL_SPACE * self.right_section[0][1], self.HEIGHT, [0,0,0], [0.5,0.5,0.5])
- self.btn_dic[self.right_section[1][0]] = keyButton(self.PIXEL_SPACE * self.right_section[1][1][0], self.PIXEL_SPACE * self.right_section[1][1][1], [0,0,0], [0.5,0.5,0.5])
- self.btn_dic[self.right_section[2][0]] = keyButton(self.PIXEL_SPACE * self.right_section[2][1], self.HEIGHT, [0,0,0], [0.5,0.5,0.5])
- self.btn_dic[self.right_section[3][0]] = keyButton(self.PIXEL_SPACE * self.right_section[3][1], self.HEIGHT, [0,0,0], [0.5,0.5,0.5])
- self.btn_dic[self.right_section[4][0]] = keyButton(self.PIXEL_SPACE * self.right_section[4][1], self.HEIGHT, [0,0,0], [0.5,0.5,0.5])
- self.btn_dic[self.right_section[5][0]] = keyButton(self.PIXEL_SPACE * self.right_section[5][1], self.HEIGHT, [0,0,0], [0.5,0.5,0.5])
-
- for key in self.right_section:
- self.btn_dic[key[0]].connect("enter",self.handle_mouseEnter)
- self.btn_dic[key[0]].connect("leave",self.handle_mouseLeave)
+ self.btn_dic[self.right_section[0][0]] = keyButton(self.pixel_space * self.right_section[0][1], self.height, [0,0,0], [0.5,0.5,0.5])
+ self.btn_dic[self.right_section[1][0]] = keyButton(self.pixel_space * self.right_section[1][1][0], self.pixel_space * self.right_section[1][1][1], [0,0,0], [0.5,0.5,0.5])
+ self.btn_dic[self.right_section[2][0]] = keyButton(self.pixel_space * self.right_section[2][1], self.height, [0,0,0], [0.5,0.5,0.5])
+ self.btn_dic[self.right_section[3][0]] = keyButton(self.pixel_space * self.right_section[3][1], self.height, [0,0,0], [0.5,0.5,0.5])
+ self.btn_dic[self.right_section[4][0]] = keyButton(self.pixel_space * self.right_section[4][1], self.height, [0,0,0], [0.5,0.5,0.5])
+ self.btn_dic[self.right_section[5][0]] = keyButton(self.pixel_space * self.right_section[5][1], self.height, [0,0,0], [0.5,0.5,0.5])
- right_vbox.pack_start(self.btn_dic[self.right_section[0][0]], padding = self.PIXEL_SPACE//2)
- right_vbox.pack_start(self.btn_dic[self.right_section[1][0]], padding = self.PIXEL_SPACE//2)
- right_tophbox.pack_start(self.btn_dic[self.right_section[2][0]], padding = self.PIXEL_SPACE//2)
- right_tophbox.pack_start(self.btn_dic[self.right_section[3][0]], padding = self.PIXEL_SPACE//2)
- right_lowhbox.pack_start(self.btn_dic[self.right_section[4][0]], padding = self.PIXEL_SPACE//2)
- right_lowhbox.pack_start(self.btn_dic[self.right_section[5][0]], padding = self.PIXEL_SPACE//2)
- right_vbox.pack_start(right_tophbox, padding = self.PIXEL_SPACE//2)
- right_vbox.pack_start(right_lowhbox, padding = self.PIXEL_SPACE//2)
+ right_vbox.pack_start(self.btn_dic[self.right_section[0][0]], padding = self.pixel_space//2)
+ right_vbox.pack_start(self.btn_dic[self.right_section[1][0]], padding = self.pixel_space//2)
+ right_tophbox.pack_start(self.btn_dic[self.right_section[2][0]], padding = self.pixel_space//2)
+ right_tophbox.pack_start(self.btn_dic[self.right_section[3][0]], padding = self.pixel_space//2)
+ right_lowhbox.pack_start(self.btn_dic[self.right_section[4][0]], padding = self.pixel_space//2)
+ right_lowhbox.pack_start(self.btn_dic[self.right_section[5][0]], padding = self.pixel_space//2)
+ right_vbox.pack_start(right_tophbox, padding = self.pixel_space//2)
+ right_vbox.pack_start(right_lowhbox, padding = self.pixel_space//2)
+
+ #Mouse buttons
+ mouse_hbox = gtk.HBox()
+ self.btn_dic["left_mouse"] = keyButton(self.pixel_space * 6, self.pixel_space * 2, [0,0,0], [0.5,0.5,0.5])
+ self.btn_dic["right_mouse"] = keyButton(self.pixel_space * 6, self.pixel_space * 2, [0,0,0], [0.5,0.5,0.5])
+ mouse_hbox.pack_start(self.btn_dic["left_mouse"], False, False, padding = self.pixel_space//2)
+ mouse_hbox.pack_start(self.btn_dic["right_mouse"], False, False, padding = self.pixel_space//2)
+
+
+ #Enter and Leave connections
+ for key in self.btn_dic:
+ self.btn_dic[key].connect("enter",self.handle_mouseEnter)
+ self.btn_dic[key].connect("leave",self.handle_mouseLeave)
mainhbox.pack_start(right_vbox)
+ mainvbox.pack_start(mainhbox)
+ mainvbox.pack_start(mouse_hbox, padding = self.pixel_space//2)
+
+ self.add(mainvbox)
+
+ def set_pos(self,_pos = 0):
+ width = self.get_screen().get_width()
+ height = self.get_screen().get_height()
+ win_width = self.get_size()[0]
+ win_height = self.get_size()[1]
- self.add(mainhbox)
+ self.pos = _pos
+
+ pos = [0,0]
+ pos[0] = (0, 0)
+ pos[1] = (width - win_width, height - win_height)
+ self.move(pos[self.pos][0],pos[self.pos][1])
+
+ def color_piano(self):
+ for key in KEY_MAP_PIANO:
+ self.btn_dic[key].set_fillcolor(1,1,1)
+
def handle_keypress(self,widget,event):
- self.btn_dic[event.hardware_keycode].set_fillcolor(random.random(),random.random(),random.random())
+ if event.hardware_keycode == 9: # Hide the keyboard with escape Key
+ self.hide_all()
+ elif event.hardware_keycode == 216: # Send a fake mouse event
+ self.btn_dic["left_mouse"].set_fillcolor(random.random(),random.random(),random.random())
+ elif event.hardware_keycode == 133: # Send a fake mouse event
+ self.btn_dic["right_mouse"].set_fillcolor(random.random(),random.random(),random.random())
+ else:
+ self.btn_dic[event.hardware_keycode].set_fillcolor(random.random(),random.random(),random.random())
def handle_keyrelease(self,widget,event):
- self.btn_dic[event.hardware_keycode].set_fillcolor(0,0,0)
+ if KEY_MAP_PIANO.has_key(event.hardware_keycode):
+ self.btn_dic[event.hardware_keycode].set_fillcolor(1,1,1)
+ else:
+ self.btn_dic[event.hardware_keycode].set_fillcolor(0,0,0)
+ if event.hardware_keycode == 216 or event.hardware_keycode == 133:
+ self.btn_dic["left_mouse"].set_fillcolor(0,0,0)
+ self.btn_dic["right_mouse"].set_fillcolor(0,0,0)
+
+
+ def handle_mousePress(self,widget,event):
+ if event.button == 1:
+ self.btn_dic["left_mouse"].set_fillcolor(random.random(),random.random(),random.random())
+ elif event.button == 3:
+ self.btn_dic["right_mouse"].set_fillcolor(random.random(),random.random(),random.random())
+
+ def handle_mouseRelease(self,widget,event):
+ if event.button == 1:
+ self.btn_dic["left_mouse"].set_fillcolor(0,0,0)
+ elif event.button == 3:
+ self.btn_dic["right_mouse"].set_fillcolor(0,0,0)
def handle_mouseEnter(self,widget,event = None):
widget.set_strokecolor(1,1,1)
def handle_mouseLeave(self,widget,event = None):
widget.set_strokecolor(0.5,0.5,0.5)
+
+ def handle_enter(self,widget,event):
+ if self.popup is False:
+ return
+ if self.pos == 0:
+ self.set_pos(1)
+ else:
+ self.set_pos(0)
+
+ def close(self,widget,event = None):
+ self.hide_all()
diff --git a/Util/Trackpad.py b/Util/Trackpad.py
index ea2990d..f46a62c 100644
--- a/Util/Trackpad.py
+++ b/Util/Trackpad.py
@@ -75,7 +75,7 @@ class Trackpad:
def handle_keyPress(self,widget,event):
if KEY_MAP_PIANO.has_key(event.hardware_keycode) and self.buttonPressed == False:
gtk.gdk.Display.warp_pointer(self.display, self.screen, self.screen.get_width() / 2, self.screen.get_height() / 2)
- gtk.gdk.pointer_grab(self.win.window, event_mask = gtk.gdk.POINTER_MOTION_MASK, cursor = self.invisible_cursor)
+ gtk.gdk.pointer_grab(self.win.window, event_mask = gtk.gdk.POINTER_MOTION_MASK)#, cursor = self.invisible_cursor)
self.buttonPressed = True
self.first_x = self.screen.get_width() / 2
self.first_y = self.screen.get_height() / 2
diff --git a/Welcome.py b/Welcome.py
index c2ebc9e..f4e9fdc 100644
--- a/Welcome.py
+++ b/Welcome.py
@@ -20,6 +20,7 @@ class Welcome(SubActivity):
self.csnd = new_csound_client()
self.noteDB = NoteDB.NoteDB()
first = self.noteDB.addPage( -1, NoteDB.Page(4) )
+ self.tooltips = gtk.Tooltips()
actVBox = RoundVBox(fillcolor = Config.WS_BCK_COLOR, bordercolor = Config.WS_BCK_COLOR, radius = Config.PANEL_RADIUS)
actHBox = gtk.HBox()
@@ -32,6 +33,13 @@ class Welcome(SubActivity):
actBtn.connect('clicked', self.onActivityBtnClicked, activity)
actBtnBox.pack_start(actBtn,True,False,0)
actHBox.pack_start(actBtnBox,True,False,0)
+ if activity == 'mini':
+ self.tooltips.set_tip(actBtn,'TamTamJam')
+ elif activity == 'edit':
+ self.tooltips.set_tip(actBtn,'TamTamEdit')
+ elif activity == 'synth':
+ self.tooltips.set_tip(actBtn,'SynthLab')
+
title = gtk.Image()
title.set_from_file(Config.IMAGE_ROOT + 'TamTam.png')
@@ -41,8 +49,10 @@ class Welcome(SubActivity):
loadButton = ImageButton(Config.IMAGE_ROOT + 'load.png')
loadButton.connect("clicked", self.handleLoad, None)
buttonBox.pack_start(loadButton, False, False, 275)
+ self.tooltips.set_tip(loadButton,'Load TamTamEdit song')
playStopButton = ImageToggleButton(Config.IMAGE_ROOT + 'miniplay.png', Config.IMAGE_ROOT + 'stop.png')
+ self.tooltips.set_tip(playStopButton,"Play loaded song")
playStopButton.connect('button-press-event' , self.handlePlayButton)
buttonBox.pack_start(playStopButton, False, False, 275)