[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Traverso-commit] traverso/src audiofileio/audiofileio.pro comman...
From: |
Remon Sijrier |
Subject: |
[Traverso-commit] traverso/src audiofileio/audiofileio.pro comman... |
Date: |
Sat, 20 Oct 2007 17:38:20 +0000 |
CVSROOT: /sources/traverso
Module name: traverso
Changes by: Remon Sijrier <r_sijrier> 07/10/20 17:38:19
Modified files:
src/audiofileio: audiofileio.pro
src/commands : commands.pro
src/commands/plugins: commandplugin.pri
src/core : Config.cpp Config.h core.pro Information.cpp
Information.h
src/engine : AlsaDriver.cpp AudioDevice.cpp AudioDevice.h
AudioDeviceThread.cpp engine.pro JackDriver.cpp
JackDriver.h
Added files:
src/common : Debugger.cpp Debugger.h Mixer.cpp Mixer.h
RingBuffer.cpp RingBuffer.h RingBufferNPT.h
Tsar.cpp Tsar.h Utils.cpp Utils.h
Removed files:
src/core : Debugger.cpp Debugger.h RingBuffer.cpp
RingBuffer.h RingBufferNPT.h Utils.cpp Utils.h
src/engine : Tsar.cpp Tsar.h
Log message:
* move files that don't belong too any lib but are used by all to a
common dir
* added a message passing function in AudioDevice to not rely on class
Info, and another function to set driver options to not rely on class Config.
These changes make the audiofileio and driver libraries independent of
other traverso libraries
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/traverso/src/audiofileio/audiofileio.pro?cvsroot=traverso&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/traverso/src/commands/commands.pro?cvsroot=traverso&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/traverso/src/commands/plugins/commandplugin.pri?cvsroot=traverso&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Debugger.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Debugger.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Mixer.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Mixer.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/RingBuffer.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/RingBuffer.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/RingBufferNPT.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Tsar.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Tsar.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Utils.cpp?cvsroot=traverso&rev=1.3
http://cvs.savannah.gnu.org/viewcvs/traverso/src/common/Utils.h?cvsroot=traverso&rev=1.3
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Config.cpp?cvsroot=traverso&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Config.h?cvsroot=traverso&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/core.pro?cvsroot=traverso&r1=1.41&r2=1.42
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Information.cpp?cvsroot=traverso&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Information.h?cvsroot=traverso&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Debugger.cpp?cvsroot=traverso&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Debugger.h?cvsroot=traverso&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/RingBuffer.cpp?cvsroot=traverso&r1=1.6&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/RingBuffer.h?cvsroot=traverso&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/RingBufferNPT.h?cvsroot=traverso&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Utils.cpp?cvsroot=traverso&r1=1.23&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/Utils.h?cvsroot=traverso&r1=1.17&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/AlsaDriver.cpp?cvsroot=traverso&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/AudioDevice.cpp?cvsroot=traverso&r1=1.42&r2=1.43
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/AudioDevice.h?cvsroot=traverso&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/AudioDeviceThread.cpp?cvsroot=traverso&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/engine.pro?cvsroot=traverso&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/JackDriver.cpp?cvsroot=traverso&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/JackDriver.h?cvsroot=traverso&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/Tsar.cpp?cvsroot=traverso&r1=1.9&r2=0
http://cvs.savannah.gnu.org/viewcvs/traverso/src/engine/Tsar.h?cvsroot=traverso&r1=1.2&r2=0
Patches:
Index: audiofileio/audiofileio.pro
===================================================================
RCS file: /sources/traverso/traverso/src/audiofileio/audiofileio.pro,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- audiofileio/audiofileio.pro 20 Oct 2007 13:09:26 -0000 1.14
+++ audiofileio/audiofileio.pro 20 Oct 2007 17:38:16 -0000 1.15
@@ -1,7 +1,8 @@
include(../libbase.pri)
-INCLUDEPATH += decode encode \
- ../core \
+INCLUDEPATH += \
+ decode \
+ encode \
../common
QMAKE_LIBDIR = ../../lib
Index: commands/commands.pro
===================================================================
RCS file: /sources/traverso/traverso/src/commands/commands.pro,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- commands/commands.pro 20 Oct 2007 13:09:26 -0000 1.22
+++ commands/commands.pro 20 Oct 2007 17:38:16 -0000 1.23
@@ -47,7 +47,6 @@
INCLUDEPATH += ../core \
../traverso \
../traverso/songcanvas \
-../engine \
../common \
../plugins \
../plugins/native \
Index: commands/plugins/commandplugin.pri
===================================================================
RCS file: /sources/traverso/traverso/src/commands/plugins/commandplugin.pri,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- commands/plugins/commandplugin.pri 20 Oct 2007 13:09:27 -0000 1.5
+++ commands/plugins/commandplugin.pri 20 Oct 2007 17:38:16 -0000 1.6
@@ -10,7 +10,6 @@
../../../common \
../../../traverso/songcanvas \
../../../commands \
- ../../../engine \
../../../plugins \
../../../plugins/native \
Index: core/Config.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/core/Config.cpp,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- core/Config.cpp 14 May 2007 23:43:49 -0000 1.16
+++ core/Config.cpp 20 Oct 2007 17:38:17 -0000 1.17
@@ -22,6 +22,7 @@
#include "Config.h"
#include "../config.h"
#include "InputEngine.h"
+#include "AudioDevice.h"
#include <QSettings>
#include <QString>
@@ -53,6 +54,8 @@
foreach(QString key, keys) {
m_configs.insert(key, settings.value(key));
}
+
+ set_audiodevice_driver_properties();
}
@@ -105,6 +108,9 @@
settings.setValue(i.key(), i.value());
++i;
}
+
+ set_audiodevice_driver_properties();
+
emit configChanged();
}
@@ -127,4 +133,11 @@
}
-//eof
+void Config::set_audiodevice_driver_properties()
+{
+ QHash<QString, QVariant> hardwareconfigs;
+ hardwareconfigs.insert("jackslave", get_property("Hardware",
"jackslave", false));
+ hardwareconfigs.insert("numberofperiods", get_property("Hardware",
"numberofperiods", 2));
+
+ audiodevice().set_driver_properties(hardwareconfigs);
+}
Index: core/Config.h
===================================================================
RCS file: /sources/traverso/traverso/src/core/Config.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- core/Config.h 29 Mar 2007 21:09:42 -0000 1.8
+++ core/Config.h 20 Oct 2007 17:38:17 -0000 1.9
@@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-$Id: Config.h,v 1.8 2007/03/29 21:09:42 benjie Exp $
+$Id: Config.h,v 1.9 2007/10/20 17:38:17 r_sijrier Exp $
*/
#ifndef CONFIG_H
@@ -54,6 +54,7 @@
friend Config& config();
void load_configuration();
+ void set_audiodevice_driver_properties();
QHash<QString, QVariant> m_configs;
Index: core/core.pro
===================================================================
RCS file: /sources/traverso/traverso/src/core/core.pro,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -b -r1.41 -r1.42
--- core/core.pro 20 Oct 2007 13:15:48 -0000 1.41
+++ core/core.pro 20 Oct 2007 17:38:17 -0000 1.42
@@ -19,7 +19,13 @@
TEMPLATE = lib
-SOURCES = AudioClip.cpp \
+SOURCES = \
+ ../common/Utils.cpp \
+ ../common/Tsar.cpp \
+ ../common/Debugger.cpp \
+ ../common/Mixer.cpp \
+ ../common/RingBuffer.cpp \
+ AudioClip.cpp \
AudioClipList.cpp \
AudioClipManager.cpp \
AudioSource.cpp \
@@ -28,20 +34,17 @@
ContextPointer.cpp \
Curve.cpp \
CurveNode.cpp \
- Debugger.cpp \
DiskIO.cpp \
Export.cpp \
FadeCurve.cpp \
FileHelpers.cpp \
Information.cpp \
InputEngine.cpp \
- Mixer.cpp \
Peak.cpp \
Project.cpp \
ProjectManager.cpp \
ReadSource.cpp \
ResourcesManager.cpp \
- RingBuffer.cpp \
Song.cpp \
Track.cpp \
ViewPort.cpp \
@@ -53,9 +56,14 @@
Marker.cpp \
Themer.cpp \
AudioFileMerger.cpp \
- ProjectConverter.cpp \
- Utils.cpp
+ ProjectConverter.cpp
HEADERS = precompile.h \
+ ../common/Utils.h \
+ ../common/Tsar.h \
+ ../common/Debugger.h \
+ ../common/Mixer.h \
+ ../common/RingBuffer.h \
+ ../common/RingBufferNPT.h \
AudioClip.h \
AudioClipList.h \
AudioClipManager.h \
@@ -66,21 +74,17 @@
ContextPointer.h \
CurveNode.h \
Curve.h \
- Debugger.h \
DiskIO.h \
Export.h \
FadeCurve.h \
FileHelpers.h \
Information.h \
InputEngine.h \
- Mixer.h \
Peak.h \
Project.h \
ProjectManager.h \
ReadSource.h \
ResourcesManager.h \
- RingBuffer.h \
- RingBufferNPT.h \
Song.h \
Track.h \
ViewPort.h \
@@ -98,8 +102,7 @@
Marker.h \
Themer.h \
AudioFileMerger.h \
- ProjectConverter.h \
- Utils.h
+ ProjectConverter.h
macx{
QMAKE_LIBDIR += /usr/local/qt/lib
}
Index: core/Information.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/core/Information.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- core/Information.cpp 17 May 2007 23:29:39 -0000 1.4
+++ core/Information.cpp 20 Oct 2007 17:38:18 -0000 1.5
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2005-2006 Remon Sijrier
+ Copyright (C) 2005-2007 Remon Sijrier
This file is part of Traverso
@@ -17,11 +17,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- $Id: Information.cpp,v 1.4 2007/05/17 23:29:39 r_sijrier Exp $
*/
#include "Information.h"
#include "Utils.h"
+#include "AudioDevice.h"
#include "Debugger.h"
@@ -60,4 +60,21 @@
emit message(s);
}
-//eof
+void Information::audiodevice_message(QString message, int severity)
+{
+ switch(severity) {
+ case 0: information(message);
+ break;
+ case 1: warning(message);
+ break;
+ case 2: critical(message);
+ break;
+ default: information(message);
+ }
+}
+
+Information::Information()
+{
+ connect(&audiodevice(), SIGNAL(message(QString, int)),
+ this, SLOT(audiodevice_message(QString, int)));
+}
Index: core/Information.h
===================================================================
RCS file: /sources/traverso/traverso/src/core/Information.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- core/Information.h 20 Apr 2006 14:51:39 -0000 1.1
+++ core/Information.h 20 Oct 2007 17:38:18 -0000 1.2
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2005-2006 Remon Sijrier
+ Copyright (C) 2005-2007 Remon Sijrier
This file is part of Traverso
@@ -17,7 +17,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- $Id: Information.h,v 1.1 2006/04/20 14:51:39 r_sijrier Exp $
*/
#ifndef INFORMATION_H
@@ -46,8 +45,7 @@
void critical(const QString& s);
private:
- Information()
- {}
+ Information();
Information(const Information&) : QObject()
{}
@@ -57,6 +55,9 @@
signals:
void message(InfoStruct );
+
+private slots:
+ void audiodevice_message(QString message, int severity);
};
// use this function to propagate the Information
Index: engine/AlsaDriver.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/engine/AlsaDriver.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- engine/AlsaDriver.cpp 16 Aug 2007 14:26:51 -0000 1.17
+++ engine/AlsaDriver.cpp 20 Oct 2007 17:38:18 -0000 1.18
@@ -20,15 +20,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-$Id: AlsaDriver.cpp,v 1.17 2007/08/16 14:26:51 r_sijrier Exp $
+$Id: AlsaDriver.cpp,v 1.18 2007/10/20 17:38:18 r_sijrier Exp $
*/
#include "AlsaDriver.h"
#include "AudioChannel.h"
#include <Utils.h>
-#include <Config.h>
-#include <Information.h>
#include <math.h>
#include <stdio.h>
@@ -102,7 +100,7 @@
int AlsaDriver::setup(bool capture, bool playback, const QString& pcmName)
{
- unsigned long user_nperiods = config().get_property("Hardware",
"numberofperiods", 2).toInt();
+ unsigned long user_nperiods =
device->get_driver_property("numberofperiods", 2).toInt();
char *playback_pcm_name = pcmName.toAscii().data();
char *capture_pcm_name = pcmName.toAscii().data();
int shorts_first = false;
@@ -169,17 +167,17 @@
if (snd_pcm_open (&playback_handle, alsa_name_playback,
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) {
switch (errno) {
case EBUSY:
- info().information(tr("ALSA Driver: The
playback device %1 is already in use. Please stop the"
- " application using it and run Traverso
again").arg(playback_pcm_name));
+ device->message(tr("ALSA Driver: The playback
device %1 is already in use. Please stop the"
+ " application using it and run Traverso
again").arg(playback_pcm_name), AudioDevice::INFO);
return -1;
break;
case EPERM:
- info().information(tr("ALSA Driver: You do not
have permission to open the audio device %1 for
playback").arg(playback_pcm_name));
+ device->message(tr("ALSA Driver: You do not
have permission to open the audio device %1 for
playback").arg(playback_pcm_name), AudioDevice::INFO);
return -1;
break;
default:
-
info().warning(tr("snd_pcm_open(playback_handle, ..) failed with unknown error
type"));
+
device->message(tr("snd_pcm_open(playback_handle, ..) failed with unknown error
type"), AudioDevice::WARNING);
}
playback_handle = 0;
@@ -194,17 +192,17 @@
if (snd_pcm_open (&capture_handle, alsa_name_capture,
SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) {
switch (errno) {
case EBUSY:
- info().information(tr("ALSA Driver: The capture
device %1 is already in use. Please stop the"
- " application using it and run Traverso
again").arg(capture_pcm_name));
+ device->message(tr("ALSA Driver: The capture
device %1 is already in use. Please stop the"
+ " application using it and run Traverso
again").arg(capture_pcm_name), AudioDevice::INFO);
return -1;
break;
case EPERM:
- info().warning(tr("ALSA Driver: You do not have
permission to open the audio device %1 for capture").arg(capture_pcm_name));
+ device->message(tr("ALSA Driver: You do not
have permission to open the audio device %1 for
capture").arg(capture_pcm_name), AudioDevice::WARNING);
return -1;
break;
default:
- info().warning(tr("ALSA Driver:
snd_pcm_open(capture_handle, ...) failed with unknown error type"));
+ device->message(tr("ALSA Driver:
snd_pcm_open(capture_handle, ...) failed with unknown error type"),
AudioDevice::WARNING);
}
capture_handle = 0;
@@ -220,7 +218,7 @@
/* they asked for playback, but we can't do it */
- info().warning(tr("ALSA Driver: Cannot open PCM device
%1 for playback. Falling back to capture-only mode").arg("alsa_pcm"));
+ device->message(tr("ALSA Driver: Cannot open PCM device
%1 for playback. Falling back to capture-only mode").arg("alsa_pcm"),
AudioDevice::WARNING);
if (capture_handle == 0) {
/* can't do anything */
@@ -235,7 +233,7 @@
/* they asked for capture, but we can't do it */
- info().warning(tr("ALSA: Cannot open PCM device %1 for
capture. Falling back to playback-only mode").arg("alsa_pcm"));
+ device->message(tr("ALSA: Cannot open PCM device %1 for
capture. Falling back to playback-only mode").arg("alsa_pcm"),
AudioDevice::WARNING);
if (playback_handle == 0) {
/* can't do anything */
@@ -553,7 +551,7 @@
if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) {
PERROR ("ALSA: cannot set hardware parameters for %s",
stream_name);
- info().warning(tr("ALSA Driver: Unable to configure hardware,
is it in use by another application?"));
+ device->message(tr("ALSA Driver: Unable to configure hardware,
is it in use by another application?"), AudioDevice::WARNING);
return -1;
}
Index: engine/AudioDevice.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/engine/AudioDevice.cpp,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -b -r1.42 -r1.43
--- engine/AudioDevice.cpp 16 Oct 2007 13:43:00 -0000 1.42
+++ engine/AudioDevice.cpp 20 Oct 2007 17:38:18 -0000 1.43
@@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-$Id: AudioDevice.cpp,v 1.42 2007/10/16 13:43:00 r_sijrier Exp $
+$Id: AudioDevice.cpp,v 1.43 2007/10/20 17:38:18 r_sijrier Exp $
*/
#include "AudioDevice.h"
@@ -41,7 +41,6 @@
#include "AudioChannel.h"
#include "AudioBus.h"
#include "Tsar.h"
-#include "Information.h"
//#include <sys/mman.h>
@@ -403,7 +402,7 @@
if (driverType == "Jack") {
driver = new JackDriver(this, m_rate, m_bufferSize);
if (driver->setup(capture, playback) < 0) {
- info().warning(tr("Audiodevice: Failed to
create the Jack Driver"));
+ message(tr("Audiodevice: Failed to create the
Jack Driver"), WARNING);
delete driver;
driver = 0;
return -1;
@@ -418,7 +417,7 @@
if (driverType == "ALSA") {
driver = new AlsaDriver(this, m_rate, m_bufferSize);
if (driver->setup(capture,playback, cardDevice) < 0) {
- info().warning(tr("Audiodevice: Failed to create the
ALSA Driver"));
+ message(tr("Audiodevice: Failed to create the ALSA
Driver"), WARNING);
delete driver;
driver = 0;
return -1;
@@ -432,7 +431,7 @@
if (driverType == "PortAudio") {
driver = new PADriver(this, m_rate, m_bufferSize);
if (driver->setup(capture, playback, cardDevice) < 0) {
- info().warning(tr("Audiodevice: Failed to create the
PortAudio Driver"));
+ message(tr("Audiodevice: Failed to create the PortAudio
Driver"), WARNING);
delete driver;
driver = 0;
return -1;
@@ -742,7 +741,7 @@
if ( ! jackdriver->is_jack_running()) {
jackShutDownChecker.stop();
printf("jack shutdown detected\n");
- info().critical(tr("The Jack server has been
shutdown!"));
+ message(tr("The Jack server has been
shutdown!"), CRITICAL);
delete driver;
driver = 0;
set_parameters(44100, m_bufferSize, "Null
Driver");
@@ -755,8 +754,8 @@
void AudioDevice::switch_to_null_driver()
{
- info().critical(tr("AudioDevice:: Buffer underrun 'Storm' detected,
switching to Null Driver"));
- info().information(tr("AudioDevice:: For trouble shooting this problem,
please see Chapter 11 from the user manual!"));
+ message(tr("AudioDevice:: Buffer underrun 'Storm' detected, switching
to Null Driver"), CRITICAL);
+ message(tr("AudioDevice:: For trouble shooting this problem, please see
Chapter 11 from the user manual!"), INFO);
set_parameters(44100, m_bufferSize, "Null Driver");
}
@@ -857,3 +856,24 @@
return TimeRef(m_bufferSize, m_rate);
}
+void AudioDevice::emit_message(const QString & string, int severity)
+{
+ emit message(string, severity);
+}
+
+void AudioDevice::set_driver_properties(QHash< QString, QVariant > &
properties)
+{
+ m_driverProperties = properties;
+ if (libjack_is_present) {
+ JackDriver* jackdriver = qobject_cast<JackDriver*>(driver);
+ if (jackdriver) {
+ jackdriver->update_config();
+ }
+ }
+}
+
+QVariant AudioDevice::get_driver_property(const QString& property, QVariant
defaultValue)
+{
+ return m_driverProperties.value(property, defaultValue);
+}
+
Index: engine/AudioDevice.h
===================================================================
RCS file: /sources/traverso/traverso/src/engine/AudioDevice.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- engine/AudioDevice.h 16 Oct 2007 13:43:00 -0000 1.23
+++ engine/AudioDevice.h 20 Oct 2007 17:38:19 -0000 1.24
@@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-$Id: AudioDevice.h,v 1.23 2007/10/16 13:43:00 r_sijrier Exp $
+$Id: AudioDevice.h,v 1.24 2007/10/20 17:38:19 r_sijrier Exp $
*/
#ifndef AUDIODEVICE_H
@@ -29,6 +29,8 @@
#include <QStringList>
#include <QByteArray>
#include <QTimer>
+#include <QVariant>
+
#include "RingBufferNPT.h"
#include "defines.h"
@@ -115,21 +117,20 @@
void show_descriptors();
+ void set_driver_properties(QHash<QString, QVariant>& properties);
int shutdown();
uint capture_buses_count() const;
uint playback_buses_count() const;
-
trav_time_t get_cpu_time();
private:
AudioDevice();
~AudioDevice();
- AudioDevice(const AudioDevice&) : QObject()
- {}
+ AudioDevice(const AudioDevice&) : QObject() {}
// allow this function to create one instance
friend AudioDevice& audiodevice();
@@ -164,6 +165,7 @@
uint m_bitdepth;
uint m_xrunCount;
QString m_driverType;
+ QHash<QString, QVariant> m_driverProperties;
int run_one_cycle(nframes_t nframes, float delayed_usecs);
int create_driver(QString driverType, bool capture, bool playback,
const QString& cardDevice);
@@ -195,16 +197,22 @@
m_cpuTime->write(&runcycleTime, 1);
}
- Driver* get_driver() const
- {
- return driver;
- }
+ Driver* get_driver() const {return driver;}
void mili_sleep(int msec);
void xrun();
size_t run_audio_thread() const;
+ enum {
+ INFO = 0,
+ WARNING = 1,
+ CRITICAL = 2
+ };
+
+ void emit_message(const QString& string, int severity);
+ QVariant get_driver_property(const QString& property, QVariant
defaultValue);
+
signals:
/**
* The stopped() signal is emited just before the
AudioDeviceThread will be stopped.
@@ -240,6 +248,8 @@
void xrunStormDetected();
+ void message(QString, int);
+
private slots:
void private_add_client(Client* client);
void private_remove_client(Client* client);
Index: engine/AudioDeviceThread.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/engine/AudioDeviceThread.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- engine/AudioDeviceThread.cpp 12 Oct 2007 08:52:13 -0000 1.20
+++ engine/AudioDeviceThread.cpp 20 Oct 2007 17:38:19 -0000 1.21
@@ -1,5 +1,5 @@
/*
-Copyright (C) 2005-2006 Remon Sijrier
+Copyright (C) 2005-2007 Remon Sijrier
This file is part of Traverso
@@ -17,14 +17,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-$Id: AudioDeviceThread.cpp,v 1.20 2007/10/12 08:52:13 r_sijrier Exp $
+$Id: AudioDeviceThread.cpp,v 1.21 2007/10/20 17:38:19 r_sijrier Exp $
*/
#include "AudioDeviceThread.h"
#include "AudioDevice.h"
#include "Driver.h"
-#include <Information.h>
#if defined (Q_WS_X11)
#include <dlfcn.h>
@@ -130,11 +129,11 @@
struct sched_param param;
param.sched_priority = 70;
if (pthread_setschedparam (pthread_self(), SCHED_FIFO, ¶m)
!= 0) {
- info().critical(tr("Unable to set Audiodevice Thread to
realtime priority!!!"
+ m_device->message(tr("Unable to set Audiodevice Thread
to realtime priority!!!"
"This most likely results in unreliable
playback/capture and "
"lots of buffer underruns (== sound drops)."
"In the worst case the program can even
malfunction!"
- "Please make sure you run this program with
realtime privileges!!!"));
+ "Please make sure you run this program with
realtime privileges!!!"), AudioDevice::CRITICAL);
return -1;
} else {
printf("AudioThread: Running with realtime priority\n");
@@ -176,4 +175,3 @@
#endif
}
-//eof
Index: engine/engine.pro
===================================================================
RCS file: /sources/traverso/traverso/src/engine/engine.pro,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- engine/engine.pro 20 Oct 2007 13:09:28 -0000 1.19
+++ engine/engine.pro 20 Oct 2007 17:38:19 -0000 1.20
@@ -1,7 +1,6 @@
include(../libbase.pri)
-INCLUDEPATH += ../core \
- ../common \
+INCLUDEPATH += ../common
TARGET = traversoaudiobackend
DESTDIR = ../../lib
@@ -18,7 +17,6 @@
Driver.cpp \
JackDriver.cpp \
memops.cpp \
-Tsar.cpp \
PADriver.cpp
HEADERS += AlsaDriver.h \
AudioBus.h \
@@ -33,7 +31,6 @@
libtraverso.h \
memops.h \
precompile.h \
-Tsar.h \
PADriver.h
release{
PRECOMPILED_HEADER -= precompile.h
Index: engine/JackDriver.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/engine/JackDriver.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- engine/JackDriver.cpp 16 Aug 2007 14:26:51 -0000 1.20
+++ engine/JackDriver.cpp 20 Oct 2007 17:38:19 -0000 1.21
@@ -17,14 +17,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- $Id: JackDriver.cpp,v 1.20 2007/08/16 14:26:51 r_sijrier Exp $
+ $Id: JackDriver.cpp,v 1.21 2007/10/20 17:38:19 r_sijrier Exp $
*/
#include "JackDriver.h"
-#include <Information.h>
-#include "Config.h"
-
#include <jack/jack.h>
#if defined (ALSA_SUPPORT)
@@ -45,8 +42,6 @@
write = MakeDelegate(this, &JackDriver::_write);
run_cycle = RunCycleCallback(this, &JackDriver::_run_cycle);
m_running = false;
-
- connect(&config(), SIGNAL(configChanged()), this,
SLOT(update_config()));
}
JackDriver::~JackDriver( )
@@ -108,7 +103,7 @@
printf("Connecting to the Jack server...\n");
if ( (client = jack_client_new (client_name)) == NULL) {
- info().warning(tr("Jack Driver: Couldn't connect to the jack
server, is jack running?"));
+// info().warning(tr("Jack Driver: Couldn't connect to the jack
server, is jack running?"));
return -1;
}
@@ -205,7 +200,7 @@
update_config();
- info().information(tr("Jack Driver: Connected successfully to the jack
server!"));
+// info().information(tr("Jack Driver: Connected successfully to the jack
server!"));
return 1;
}
@@ -327,7 +322,8 @@
void JackDriver::update_config()
{
- m_isSlave = config().get_property("Hardware", "jackslave",
false).toBool();
+ m_isSlave = device->get_driver_property("jackslave", false).toBool();
+ printf("m_isSlave %d\n", m_isSlave);
if (m_isSlave) {
jack_set_sync_callback (client, _jack_sync_callback, this);
Index: engine/JackDriver.h
===================================================================
RCS file: /sources/traverso/traverso/src/engine/JackDriver.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- engine/JackDriver.h 22 Jun 2007 12:29:28 -0000 1.8
+++ engine/JackDriver.h 20 Oct 2007 17:38:19 -0000 1.9
@@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- $Id: JackDriver.h,v 1.8 2007/06/22 12:29:28 r_sijrier Exp $
+ $Id: JackDriver.h,v 1.9 2007/10/20 17:38:19 r_sijrier Exp $
*/
#ifndef JACKDRIVER_H
@@ -52,6 +52,7 @@
size_t is_jack_running() const {return m_running == 1;}
jack_client_t* get_client() const {return client;}
bool is_slave() const {return m_isSlave;}
+ void update_config();
private:
volatile size_t m_running;
@@ -70,9 +71,6 @@
signals:
void jackShutDown();
-private slots:
- void update_config();
-
};
Index: common/Debugger.cpp
===================================================================
RCS file: common/Debugger.cpp
diff -N common/Debugger.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Debugger.cpp 20 Oct 2007 17:38:16 -0000 1.1
@@ -0,0 +1,395 @@
+/*
+ Copyright (C) 2005-2006 Remon Sijrier
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ $Id: Debugger.cpp,v 1.1 2007/10/20 17:38:16 r_sijrier Exp $
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "Debugger.h"
+
+namespace Debugger
+{
+int ntabs = 0;
+int debugLevel = OFF;
+FILE* logFile = (FILE*) 0;
+QString logFileName = 0;
+bool logging = false;
+}
+
+void Debugger::fill_tabs()
+{
+ for (int i=0; i < ntabs; i++)
+ printf("| ");
+}
+
+QString Debugger::get_tabs()
+{
+ QString t="";
+ for (int i=0; i < ntabs; i++)
+ t=t.append(" ");
+ return t;
+}
+
+
+void Debugger::more_tabs()
+{
+ ntabs++;
+}
+
+
+void Debugger::less_tabs()
+{
+ ntabs--;
+}
+
+
+void Debugger::set_debug_level(int l)
+{
+ debugLevel = l;
+}
+
+
+int Debugger::get_debug_level()
+{
+ return debugLevel;
+}
+
+
+void Debugger::create_log(QString fn)
+{
+ logFileName = QString(getenv("HOME")) + "/" + fn;
+ logFile = fopen(logFileName.toAscii(),"a+");
+ if (!logFile) {
+ PERROR("Cannot create Debugger Log file
(%s)",fn.toAscii().data());
+ logging=false;
+ } else {
+ fclose(logFile);
+ logging=true;
+ }
+}
+
+
+
+void Debugger::close_log()
+{
+ logging=false;
+}
+
+
+
+void Debugger::log(QString s)
+{
+ const char* sc = s.toAscii();
+ int len = s.length();
+ logFile = fopen(logFileName.toAscii(),"a+");
+ fwrite(sc,len,1,logFile);
+ fclose(logFile);
+}
+
+bool Debugger::is_logging()
+{
+ return logging;
+}
+
+
+#ifdef USE_DEBUGGER
+
+static void print_enter(int lvl, const char* file, const char* function)
+{
+ using namespace Debugger;
+
+ if (get_debug_level()>=lvl) {
+ if (is_logging()) {
+ QString output = get_tabs() + "ENTERING " +
QString(file) + "::" + QString(function) + "\n";
+ log(output);
+ more_tabs();
+ } else {
+ fill_tabs();
+ CHANGE_COLOR_GREEN;
+ printf("ENTERING ");
+ CHANGE_COLOR_WHITE;
+ printf("%s::%s\n", file, function);
+ more_tabs();
+ }
+ }
+}
+
+static void print_exit(int lvl, const char* file, const char* function)
+{
+ using namespace Debugger;
+
+ if (get_debug_level()>=lvl) {
+ if (is_logging()) {
+ less_tabs();
+ QString output = get_tabs() + "LEAVING " +
QString(file) + "::" + QString(function) + "\n";
+ log(output);
+ } else {
+ less_tabs();
+ fill_tabs();
+ CHANGE_COLOR_BLUE;
+ printf("LEAVING ");
+ CHANGE_COLOR_WHITE;
+ printf("%s::%s\n", file, function);
+ }
+ }
+}
+
+FunctionEnter::FunctionEnter(int level, const char* file, const char* function)
+ : m_file(file), m_function(function), lvl(level)
+{
+ print_enter(lvl, m_file, m_function);
+}
+
+FunctionEnter::~ FunctionEnter( )
+{
+ print_exit(lvl, m_file, m_function);
+}
+
+ConstructorEnter::ConstructorEnter(int level, const char* file, const char*
function)
+ : m_file(file), m_function(function), lvl(level)
+{
+ using namespace Debugger;
+ if (get_debug_level()>=lvl) {
+ if (is_logging()) {
+ QString output = get_tabs() + "ENTERING " +
QString(m_function) + " (CONSTRUCTOR)\n";
+ log(output);
+ more_tabs();
+ } else {
+ fill_tabs();
+ CHANGE_COLOR_GREEN;
+ printf("ENTERING ");
+ CHANGE_COLOR_WHITE;
+ printf("%s",m_function);
+ CHANGE_COLOR_CYAN;
+ printf(" (CONSTRUCTOR)");
+ CHANGE_COLOR_WHITE;
+ printf("\n");
+ more_tabs();
+ }
+ }
+}
+
+ConstructorEnter::~ ConstructorEnter( )
+{
+ using namespace Debugger;
+ if (get_debug_level()>=lvl) {
+ if (is_logging()) {
+ less_tabs();
+ QString output = get_tabs() + "LEAVING " +
QString(m_function) + " (CONSTRUCTOR)\n";
+ log(output);
+ } else {
+ less_tabs();
+ fill_tabs();
+ CHANGE_COLOR_BLUE;
+ printf("LEAVING ");
+ CHANGE_COLOR_WHITE;
+ printf("%s", m_function);
+ CHANGE_COLOR_CYAN;
+ printf(" (CONSTRUCTOR)");
+ CHANGE_COLOR_WHITE;
+ printf("\n");
+ }
+ }
+}
+
+DestructorEnter::DestructorEnter(int level, const char* file, const char*
function)
+ : m_file(file), m_function(function), lvl(level)
+{
+ using namespace Debugger;
+ if (get_debug_level()>=lvl) {
+ if (is_logging()) {
+ QString output = get_tabs() + "ENTERING " +
QString(m_function) + " (DESTRUCTOR)\n";
+ log(output);
+ more_tabs();
+ } else {
+ fill_tabs();
+ CHANGE_COLOR_GREEN;
+ printf("ENTERING ");
+ CHANGE_COLOR_WHITE;
+ printf("%s", m_function);
+ CHANGE_COLOR_CYAN;
+ printf(" (DESTRUCTOR)");
+ CHANGE_COLOR_WHITE;
+ printf("\n");
+ more_tabs();
+ }
+ }
+}
+
+DestructorEnter::~ DestructorEnter( )
+{
+ using namespace Debugger;
+ if (get_debug_level()>=lvl) {
+ if (is_logging()) {
+ less_tabs();
+ QString output = get_tabs() + "LEAVING " +
QString(m_function) + " (DESTRUCTOR)\n";
+ log(output);
+ } else {
+ less_tabs();
+ fill_tabs();
+ CHANGE_COLOR_BLUE;
+ printf("LEAVING ");
+ CHANGE_COLOR_WHITE;
+ printf("%s", m_function);
+ CHANGE_COLOR_CYAN;
+ printf(" (DESTRUCTOR)");
+ CHANGE_COLOR_WHITE;
+ printf("\n");
+ }
+ }
+}
+#endif
+
+
+#if defined (USE_MEM_CHECKER)
+
+//: C02:MemCheck.cpp {O}
+// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
+// (c) 1995-2004 MindView, Inc. All Rights Reserved.
+// See source code use permissions stated in the file 'License.txt',
+// distributed with the code package available at www.MindView.net.
+#include <cstdio>
+ #include <cstdlib>
+ #include <cassert>
+ #include <cstddef>
+using namespace std;
+#undef new
+
+// Global flags set by macros in MemCheck.h
+bool traceFlag = true;
+bool activeFlag = false;
+
+namespace
+{
+
+// Memory map entry type
+struct Info
+{
+ void* ptr;
+ const char* file;
+ long line;
+ size_t size;
+};
+
+// Memory map data
+const size_t MAXPTRS = 10000u;
+Info memMap[MAXPTRS];
+size_t nptrs = 0;
+
+// Searches the map for an address
+int findPointer(void* p)
+{
+ for(size_t i = 0; i < nptrs; ++i)
+ if(memMap[i].ptr == p)
+ return i;
+ return -1;
+}
+
+void delPointer(void* p)
+{
+ long pos = findPointer(p);
+ assert(pos >= 0);
+ // Remove pointer from map
+ for(size_t i = pos; i < nptrs-1; ++i)
+ memMap[i] = memMap[i+1];
+ --nptrs;
+}
+
+// Dummy type for static destructor
+struct Sentinel
+{
+ ~Sentinel()
+ {
+ if(nptrs > 0) {
+ printf("Leaked memory at:\n");
+ for(size_t i = 0; i < nptrs; ++i)
+ printf("\t%p (file: %s, line %ld)\n",
+ memMap[i].ptr, memMap[i].file,
memMap[i].line);
+ } else
+ printf("No memory leaks found in Traverso!\n");
+ }
+};
+
+// Static dummy object
+Sentinel s;
+
+} // End anonymous namespace
+
+// Overload scalar new
+void*
+operator new(size_t siz, const char* file, long line)
+{
+ void* p = malloc(siz);
+ if(activeFlag) {
+ if(nptrs == MAXPTRS) {
+ printf("memory map too small (increase MAXPTRS)\n");
+ exit(1);
+ }
+ memMap[nptrs].ptr = p;
+ memMap[nptrs].file = file;
+ memMap[nptrs].line = line;
+ memMap[nptrs].size = siz;
+
+ ++nptrs;
+ }
+ if(traceFlag) {
+ printf("Allocated %.2f KBytes at address %p (file: %s, line:
%ld)\n", (float)siz/1024, p, file, line);
+ }
+ fflush(NULL);
+ return p;
+}
+
+// Overload array new
+void*
+operator new[](size_t siz, const char* file, long line)
+{
+ return operator new(siz, file, line);
+}
+
+// Override scalar delete
+void operator delete(void* p)
+{
+ int i;
+ if( (i = findPointer(p)) >= 0) {
+ free(p);
+ assert(nptrs > 0);
+ delPointer(p);
+ if(traceFlag) {
+ if (memMap[i].size > 1024)
+ printf("Deleted %u bytes at address %p, file:
%s, line: %ld\n", memMap[i].size, p, memMap[i].file, memMap[i].line);
+ }
+ } else if(!p && activeFlag)
+ printf("Attempt to delete unknown pointer: %p\n", p);
+ fflush(NULL);
+}
+
+// Override array delete
+void operator delete[](void* p)
+{
+ operator delete(p);
+} ///:~
+
+
+#endif //USE_MEM_CHECKER ///:~
+
+
+//eof
+
Index: common/Debugger.h
===================================================================
RCS file: common/Debugger.h
diff -N common/Debugger.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Debugger.h 20 Oct 2007 17:38:16 -0000 1.1
@@ -0,0 +1,234 @@
+/*
+ Copyright (C) 2005-2006 Remon Sijrier
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ $Id: Debugger.h,v 1.1 2007/10/20 17:38:16 r_sijrier Exp $
+*/
+
+#ifndef DEBUGGER_H
+#define DEBUGGER_H
+
+#include <QString>
+
+
+//Debugging Macros
+#define CHANGE_COLOR_BLACK printf("%c[0;31m",27)
+#define CHANGE_COLOR_RED printf("%c[0;31m",27)
+#define CHANGE_COLOR_GREEN printf("%c[0;32m",27)
+#define CHANGE_COLOR_ORANGE printf("%c[0;33m",27)
+#define CHANGE_COLOR_BLUE printf("%c[0;34m",27)
+#define CHANGE_COLOR_MAGENTA printf("%c[0;35m",27)
+#define CHANGE_COLOR_CYAN printf("%c[0;36m",27)
+#define CHANGE_COLOR_WHITE printf("%c[0;37m",27)
+#define CHANGE_COLOR_YELLOW printf("%c[0;33m",27)
+
+#ifdef USE_DEBUGGER
+
+class FunctionEnter
+{
+ const char* m_file;
+ const char* m_function;
+ int lvl;
+public:
+ FunctionEnter(int level, const char* file, const char* function);
+ ~FunctionEnter();
+};
+
+class ConstructorEnter
+{
+ const char* m_file;
+ const char* m_function;
+ int lvl;
+public:
+ ConstructorEnter(int level, const char* file, const char* function);
+ ~ConstructorEnter();
+};
+
+class DestructorEnter
+{
+ const char* m_file;
+ const char* m_function;
+ int lvl;
+public:
+ DestructorEnter(int level, const char* file, const char* function);
+ ~DestructorEnter();
+};
+
+#define PMESG(args...) { using namespace Debugger; if
(get_debug_level()>=BASIC) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
+#define PMESG2(args...) { using namespace Debugger; if
(get_debug_level()>=FLOOD) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
+#define PMESG3(args...) { using namespace Debugger; if
(get_debug_level()>=SUPER_FLOOD) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
+#define PMESG4(args...) { using namespace Debugger; if
(get_debug_level()>=ALL) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
+
+#define PDEBUG(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "DEBUG : " + QString(__FILE__) +
"::" + QString(__FUNCTION__) + ":" + x + "\n"; log(output); } else {
CHANGE_COLOR_GREEN; printf("DEBUG : ");printf("%s",__FILE__); printf("::");
printf("%s",__FUNCTION__); printf(":"); printf(args); CHANGE_COLOR_WHITE;
printf("\n"); } }
+#define PERROR(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "\n *** Error in " +
QString(__PRETTY_FUNCTION__) + "\n" + x + "\n\n"; } else { printf("\n");
CHANGE_COLOR_RED; printf("*** Error in "); printf("%s",__PRETTY_FUNCTION__);
printf("\n"); printf(args); CHANGE_COLOR_WHITE; printf("\n\n"); } }
+#define PERROR2(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "\n *** Error in " +
QString(__PRETTY_FUNCTION__) + "\n" + x + "\n\n"; } else if
(get_debug_level()>=FLOOD) { printf("\n"); CHANGE_COLOR_RED; printf("*** Error
in "); printf("%s",__PRETTY_FUNCTION__); printf("\n"); printf(args);
CHANGE_COLOR_WHITE; printf("\n\n"); } }
+#define PWARN(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "WARNING: " + x + "\n";
log(output); } else { CHANGE_COLOR_YELLOW; printf("WARNING: "); printf(args);
CHANGE_COLOR_WHITE; printf("\n"); } }
+#define PWARN2(args...) { using namespace Debugger; if
(get_debug_level()>=FLOOD) { if (is_logging()) { QString x; x.sprintf(args);
QString output = "WARNING: " + x + "\n"; log(output); } else {
CHANGE_COLOR_YELLOW; printf("WARNING: "); printf(args); CHANGE_COLOR_WHITE;
printf("\n"); } } }
+
+
+#define PENTER FunctionEnter enter(Debugger::BASIC, __FILE__,
__FUNCTION__)
+#define PENTER2 FunctionEnter enter(Debugger::FLOOD,
__FILE__, __FUNCTION__)
+#define PENTER3 FunctionEnter
enter(Debugger::SUPER_FLOOD, __FILE__, __FUNCTION__)
+#define PENTER4 FunctionEnter enter(Debugger::ALL,
__FILE__, __FUNCTION__)
+
+#define PENTERCONS ConstructorEnter enter(Debugger::BASIC,
__FILE__, __FUNCTION__)
+#define PENTERDES DestructorEnter enter(Debugger::BASIC,
__FILE__, __FUNCTION__)
+#define PENTERCONS2 ConstructorEnter enter(Debugger::FLOOD,
__FILE__, __FUNCTION__)
+#define PENTERDES2 DestructorEnter enter(Debugger::FLOOD,
__FILE__, __FUNCTION__)
+#define PENTERCONS3 ConstructorEnter enter(Debugger::SUPER_FLOOD,
__FILE__, __FUNCTION__)
+#define PENTERDES3 DestructorEnter enter(Debugger::SUPER_FLOOD,
__FILE__, __FUNCTION__)
+#define PENTERCONS4 ConstructorEnter enter(Debugger::ALL, __FILE__,
__FUNCTION__)
+#define PENTERDES4 DestructorEnter enter(Debugger::ALL,
__FILE__, __FUNCTION__)
+
+#else
+
+#define PMESG(args...)
+#define PMESG2(args...)
+#define PMESG3(args...)
+#define PMESG4(args...)
+
+#define PMESG_START(args...)
+#define PMESG_END(args...)
+#define PMESG2_START(args...)
+#define PMESG2_END(args...)
+
+#define PDEBUG(args...)
+#define PERROR(args...)
+#define PERROR2(args...)
+#define PWARN(args...)
+#define PWARN2(args...)
+#define PMARK(args...)
+
+#define PENTER
+#define PENTER2
+#define PENTER3
+#define PENTER4
+#define PENTERCONS
+#define PENTERDES
+#define PENTERCONS2
+#define PENTERDES2
+#define PENTERCONS3
+#define PENTERDES3
+#define PENTERCONS4
+#define PENTERDES4
+
+#endif
+/*!
+ Debugger is a collection of macros that makes easier the job of debugging a
Application.
+
+ PENTER - Outputs a message when entering a method in level 1. Used in the
FIRST line of a method;
+ PEXIT - Outputs a message when leaving a method in level 1. Used in the LAST
line of a method,
+ except if the last line is a return statement (in this case is put
immediately before
+ the return statement
+ PENTER2 - Same as PENTER for levels 1 and 2
+ PEXIT2 - Same as PEXIT for levels 1 and 2
+ PENTER3 - Same as PENTER for levels 1 2 and 3
+ PEXIT3 - Same as PEXIT for levels 1 2 and 3
+ PENTER4 - Same as PENTER for levels 1 2 3 and 4
+ PEXIT4 - Same as PEXIT for levels 1 2 3 and 4
+ PMESG(message) - Outputs a message in level 1
+ PMESG2(message) - Outputs a message in level 1 and 2
+ PENTERCONS - Outputs a message when entering a constructor in levels 2, 3,
and 4. Similar to PENTER
+ PEXITCONS - Outputs a message when leaving a constructor in levels 2, 3, and
4. Similar to PEXIT
+ PENTERDES - Outputs a message when entering a destructor in levels 2, 3, and
4. Similar to PENTER
+ PEXITDES - Outputs a message when leaving a destructor in levels 2, 3, and
4. Similar to PEXIT
+ Same can be done for PENTERCONS2, PEXITCONS2, PENTERCONS3... and so on...
+ */
+
+namespace Debugger
+ {
+ static const int OFF = 0; //< no debug output at all
+ static const int BASIC = 1; //< only level 1 calls
+ static const int FLOOD = 2; //< level 1 , level 2 and
constructors/destructor calls
+ static const int SUPER_FLOOD = 3; //< all previous plus low level JMB
messages
+ static const int ALL = 4; //< all messages (including in timer
loops)
+
+ //! Used internally by Debugger. Align the output with the level of
execution in a given moment
+ void fill_tabs();
+
+ //! Used internally by Debugger. Get a " " (space) sequence whch
aligns the output with the level of execution in a given moment,
+ QString get_tabs();
+
+
+ //! Used internally by Debugger. Increase one level of execution in
output messages
+ void more_tabs();
+
+ //! Used internally by Debugger. Decrease one level of execution in
output messages
+ void less_tabs();
+
+ //! Set the debug level
+ void set_debug_level(int l);
+
+ //! Used internally by Debugger. Returns true if debugOn flag is true.
+ int get_debug_level();
+
+ //! create a log file "fn" under home dir and enable copy of all
debugging messagem to this file.
+ void create_log(QString fn);
+
+ //! close the log file
+ void close_log();
+
+ //! Used internally by Debugger. Feed the log file.
+ void log(QString msg);
+
+ //! Used internally to check if output is stdout or a log file
+ bool is_logging();
+ }
+
+
+#endif // DEBUGGER_H ///:~
+
+
+
+
+//: C02:MemCheck.h
+// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
+// (c) 1995-2004 MindView, Inc. All Rights Reserved.
+// See source code use permissions stated in the file 'License.txt',
+// distributed with the code package available at www.MindView.net.
+#ifndef MEMCHECK_H
+#define MEMCHECK_H
+#include <cstddef> // For size_t
+
+#if defined (USE_MEM_CHECKER)
+
+// Usurp the new operator (both scalar and array versions)
+void* operator new(std::size_t, const char*, long);
+void* operator new[](std::size_t, const char*, long);
+#define new new (__FILE__, __LINE__)
+
+extern bool traceFlag;
+#define TRACE_ON() traceFlag = true
+#define TRACE_OFF() traceFlag = false
+
+extern bool activeFlag;
+#define MEM_ON() activeFlag = true
+#define MEM_OFF() activeFlag = false
+
+
+#else
+
+#define TRACE_OFF()
+#define TRACE_ON()
+#define MEM_OFF()
+#define MEM_ON()
+
+#endif // MEMCHECK_H ///:~
+
+
+#endif //USE_MEM_CHECKER ///:~
Index: common/Mixer.cpp
===================================================================
RCS file: common/Mixer.cpp
diff -N common/Mixer.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Mixer.cpp 20 Oct 2007 17:38:16 -0000 1.1
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 2005-2006 Remon Sijrier
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ $Id: Mixer.cpp,v 1.1 2007/10/20 17:38:16 r_sijrier Exp $
+*/
+
+#include "Mixer.h"
+#include "defines.h"
+#include <cmath>
+
+Mixer::compute_peak_t Mixer::compute_peak = 0;
+Mixer::apply_gain_to_buffer_t Mixer::apply_gain_to_buffer = 0;
+Mixer::mix_buffers_with_gain_t Mixer::mix_buffers_with_gain = 0;
+Mixer::mix_buffers_no_gain_t Mixer::mix_buffers_no_gain = 0;
+
+
+
+float default_compute_peak (audio_sample_t* buf, nframes_t nsamples, float
current)
+{
+ for (nframes_t i = 0; i < nsamples; ++i) {
+ current = f_max (current, fabsf (buf[i]));
+ }
+
+ return current;
+}
+
+void default_apply_gain_to_buffer (audio_sample_t* buf, nframes_t nframes,
float gain)
+{
+ for (nframes_t i=0; i<nframes; i++)
+ buf[i] *= gain;
+}
+
+void default_mix_buffers_with_gain (audio_sample_t* dst, audio_sample_t* src,
nframes_t nframes, float gain)
+{
+ for (nframes_t i = 0; i < nframes; i++) {
+ dst[i] += src[i] * gain;
+ }
+}
+
+void default_mix_buffers_no_gain (audio_sample_t* dst, audio_sample_t* src,
nframes_t nframes)
+{
+ for (nframes_t i=0; i < nframes; i++) {
+ dst[i] += src[i];
+ }
+}
Index: common/Mixer.h
===================================================================
RCS file: common/Mixer.h
diff -N common/Mixer.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Mixer.h 20 Oct 2007 17:38:17 -0000 1.1
@@ -0,0 +1,99 @@
+/*
+ Copyright (C) 2005-2006 Remon Sijrier
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ $Id: Mixer.h,v 1.1 2007/10/20 17:38:17 r_sijrier Exp $
+*/
+
+#ifndef MIXER_H
+#define MIXER_H
+
+#include "defines.h"
+#include <cmath>
+
+
+static inline float f_max(float x, float a)
+{
+ x -= a;
+ x += fabsf (x);
+ x *= 0.5f;
+ x += a;
+
+ return (x);
+}
+
+// This is for VU : db = 20 * log ( sample / MaxSample )
+static inline float dB_to_scale_factor (float dB)
+{
+ // examples :
+ // dB = 0 will return 1.0
+ // db = -6.0 will return 0.5
+ // db = -inf will return 0.0
+ return dB > -120.0f ? ::pow(10.0f, dB * 0.05f) : 0.0f;
+}
+
+
+static inline float coefficient_to_dB (float coeff)
+{
+ // examples :
+ // coeff = 1.0 will return 0 dB
+ // coeff = 0.5 will return -6 dB
+ // coeff = 0.0 will return -infinite dB
+ if (coeff < 0.000001f) //Should be (coeff == 0), but this will
do...
+ return (-120.0f); //Should be minus infinity, but it will
do for busMonitor purposes
+ return 20.0f * log10 (coeff);
+}
+
+
+float default_compute_peak (audio_sample_t* buf,
nframes_t nsamples, float current);
+void default_apply_gain_to_buffer (audio_sample_t* buf,
nframes_t nframes, float gain);
+void default_mix_buffers_with_gain (audio_sample_t* dst,
audio_sample_t* src, nframes_t nframes, float gain);
+void default_mix_buffers_no_gain (audio_sample_t* dst,
audio_sample_t* src, nframes_t nframes);
+
+#if defined (SSE_OPTIMIZATIONS)
+
+extern "C"
+{
+ /* SSE functions */
+ float x86_sse_compute_peak (audio_sample_t* buf,
nframes_t nsamples, float current);
+ void x86_sse_apply_gain_to_buffer (audio_sample_t* buf,
nframes_t nframes, float gain);
+ void x86_sse_mix_buffers_with_gain (audio_sample_t* dst,
audio_sample_t* src, nframes_t nframes, float gain);
+ void x86_sse_mix_buffers_no_gain (audio_sample_t* dst,
audio_sample_t* src, nframes_t nframes);
+}
+#endif
+
+
+
+class Mixer
+{
+public:
+ typedef float (*compute_peak_t)
(audio_sample_t* , nframes_t, float);
+ typedef void (*apply_gain_to_buffer_t)
(audio_sample_t* , nframes_t, float);
+ typedef void (*mix_buffers_with_gain_t) (audio_sample_t* ,
audio_sample_t* , nframes_t, float);
+ typedef void (*mix_buffers_no_gain_t) (audio_sample_t* ,
audio_sample_t* , nframes_t);
+
+ static compute_peak_t compute_peak;
+ static apply_gain_to_buffer_t apply_gain_to_buffer;
+ static mix_buffers_with_gain_t mix_buffers_with_gain;
+ static mix_buffers_no_gain_t mix_buffers_no_gain;
+};
+
+#endif
+
+
+//eof
Index: common/RingBuffer.cpp
===================================================================
RCS file: common/RingBuffer.cpp
diff -N common/RingBuffer.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/RingBuffer.cpp 20 Oct 2007 17:38:17 -0000 1.1
@@ -0,0 +1,359 @@
+/*
+ Copyright (C) 2006 Remon Sijrier
+ Ported to C++ for use in Traverso
+
+ Copyright (C) 2000 Paul Davis
+ Copyright (C) 2003 Rohan Drape
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code.
+ This is safe for the case of one read thread and one write thread.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef USE_MLOCK
+
+#ifdef Q_WS_MAC
+#include <sys/types.h>
+#endif /* Q_WS_MAC */
+
+#include <sys/mman.h>
+#endif /* USE_MLOCK */
+
+#include "RingBuffer.h"
+
+// Always put me below _all_ includes, this is needed
+// in case we run with memory leak detection enabled!
+#include "Debugger.h"
+
+
+/* Create a new ringbuffer to hold at least `sz' bytes of data. The
+ actual buffer size is rounded up to the next power of two. */
+
+RingBuffer::RingBuffer(size_t sz)
+{
+ int power_of_two;
+
+ for (power_of_two = 1; 1 << power_of_two < (int)sz; power_of_two++)
+ ;
+
+ size = 1 << power_of_two;
+ size_mask = size;
+ size_mask -= 1;
+ write_ptr = 0;
+ read_ptr = 0;
+ buf = new char[size];
+
+ mlocked = 0;
+ if (mlock_buffer() < 0) {
+ PERROR("Failed to memory lock buffer!");
+ }
+}
+
+
+RingBuffer::~RingBuffer()
+{
+#ifdef USE_MLOCK
+ if (mlocked) {
+ munlock (buf, size);
+ }
+#endif /* USE_MLOCK */
+ delete [] buf;
+}
+
+/* Lock the data block using the system call 'mlock'. */
+
+int RingBuffer::mlock_buffer()
+{
+#if defined (USE_MLOCK)
+ if (mlock (buf, size)) {
+ printf("Unable to lock memory\n");
+ return -1;
+ }
+ mlocked = 1;
+#endif /* USE_MLOCK */
+
+ return 0;
+}
+
+/* Reset the read and write pointers to zero. This is not thread
+ safe. */
+
+void RingBuffer::reset ()
+{
+ read_ptr = 0;
+ write_ptr = 0;
+}
+
+/* Return the number of bytes available for reading. This is the
+ number of bytes in front of the read pointer and behind the write
+ pointer. */
+
+size_t RingBuffer::read_space ()
+{
+ size_t w, r;
+
+ w = write_ptr;
+ r = read_ptr;
+
+ if (w > r) {
+ return w - r;
+ } else {
+ return (w - r + size) & size_mask;
+ }
+}
+
+/* Return the number of bytes available for writing. This is the
+ number of bytes in front of the write pointer and behind the read
+ pointer. */
+
+size_t RingBuffer::write_space ()
+{
+ size_t w, r;
+
+ w = write_ptr;
+ r = read_ptr;
+
+ if (w > r) {
+ return ((r - w + size) & size_mask) - 1;
+ } else if (w < r) {
+ return (r - w) - 1;
+ } else {
+ return size - 1;
+ }
+}
+
+/* The copying data reader. Copy at most `cnt' bytes to
+ `dest'. Returns the actual number of bytes copied. */
+
+size_t RingBuffer::read (char *dest, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_read;
+ size_t n1, n2;
+
+ if ( ( free_cnt = read_space () ) == 0) {
+ return 0;
+ }
+
+ to_read = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = read_ptr + to_read;
+
+ if (cnt2 > size) {
+ n1 = size - read_ptr;
+ n2 = cnt2 & size_mask;
+ } else {
+ n1 = to_read;
+ n2 = 0;
+ }
+
+ memcpy (dest, &(buf[read_ptr]), n1 * sizeof(char));
+ read_ptr += n1;
+ read_ptr &= size_mask;
+
+ if (n2) {
+ memcpy (dest + n1, &(buf[read_ptr]), n2 * sizeof(char));
+ read_ptr += n2;
+ read_ptr &= size_mask;
+ }
+
+ return to_read;
+}
+
+/* The copying data reader w/o read pointer advance. Copy at most
+ `cnt' bytes from `dest'. Returns the actual number of bytes copied. */
+
+size_t RingBuffer::peek (char *dest, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_read;
+ size_t n1, n2;
+ size_t tmp_read_ptr;
+
+ tmp_read_ptr = read_ptr;
+
+ if ((free_cnt = read_space ()) == 0) {
+ return 0;
+ }
+
+ to_read = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = tmp_read_ptr + to_read;
+
+ if (cnt2 > size) {
+ n1 = size - tmp_read_ptr;
+ n2 = cnt2 & size_mask;
+ } else {
+ n1 = to_read;
+ n2 = 0;
+ }
+
+ memcpy (dest, &(buf[tmp_read_ptr]), n1);
+ tmp_read_ptr += n1;
+ tmp_read_ptr &= size_mask;
+
+ if (n2) {
+ memcpy (dest + n1, &(buf[tmp_read_ptr]), n2);
+ tmp_read_ptr += n2;
+ tmp_read_ptr &= size_mask;
+ }
+
+ return to_read;
+}
+
+
+/* The copying data writer. Copy at most `cnt' bytes to `rb' from
+ `src'. Returns the actual number of bytes copied. */
+
+size_t RingBuffer::write (const char *src, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_write;
+ size_t n1, n2;
+
+ if ((free_cnt = write_space ()) == 0) {
+ return 0;
+ }
+
+ to_write = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = write_ptr + to_write;
+
+ if (cnt2 > size) {
+ n1 = size - write_ptr;
+ n2 = cnt2 & size_mask;
+ } else {
+ n1 = to_write;
+ n2 = 0;
+ }
+
+ memcpy (&(buf[write_ptr]), src, n1 * sizeof(char));
+ write_ptr += n1;
+ write_ptr &= size_mask;
+
+ if (n2) {
+ memcpy (&(buf[write_ptr]), src + n1, n2 * sizeof(char));
+ write_ptr += n2;
+ write_ptr &= size_mask;
+ }
+
+ return to_write;
+}
+
+/* Advance the read pointer `cnt' places. */
+
+void RingBuffer::read_advance (size_t cnt)
+{
+ read_ptr += cnt;
+ read_ptr &= size_mask;
+}
+
+/* Advance the write pointer `cnt' places. */
+
+void RingBuffer::write_advance (size_t cnt)
+{
+ write_ptr += cnt;
+ write_ptr &= size_mask;
+}
+
+/* The non-copying data reader. `vec' is an array of two places. Set
+ the values at `vec' to hold the current readable data'. If the readable
+ data is in one segment the second segment has zero length. */
+
+void RingBuffer::get_read_vector (ringbuffer_data_t * vec)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = write_ptr;
+ r = read_ptr;
+
+ if (w > r) {
+ free_cnt = w - r;
+ } else {
+ free_cnt = (w - r + size) & size_mask;
+ }
+
+ cnt2 = r + free_cnt;
+
+ if (cnt2 > size) {
+
+ /* Two part vector: the rest of the buffer after the current
write
+ ptr, plus some from the start of the buffer. */
+
+ vec[0].buf = &(buf[r]);
+ vec[0].len = size - r;
+ vec[1].buf = buf;
+ vec[1].len = cnt2 & size_mask;
+
+ } else {
+
+ /* Single part vector: just the rest of the buffer */
+
+ vec[0].buf = &(buf[r]);
+ vec[0].len = free_cnt;
+ vec[1].len = 0;
+ }
+}
+
+/* The non-copying data writer. `vec' is an array of two places. Set
+ the values at `vec' to hold the current writeable data. If the writeable
+ data is in one segment the second segment has zero length. */
+
+void RingBuffer::get_write_vector (ringbuffer_data_t * vec)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = write_ptr;
+ r = read_ptr;
+
+ if (w > r) {
+ free_cnt = ((r - w + size) & size_mask) - 1;
+ } else if (w < r) {
+ free_cnt = (r - w) - 1;
+ } else {
+ free_cnt = size - 1;
+ }
+
+ cnt2 = w + free_cnt;
+
+ if (cnt2 > size) {
+
+ /* Two part vector: the rest of the buffer after the current
write
+ ptr, plus some from the start of the buffer. */
+
+ vec[0].buf = &(buf[w]);
+ vec[0].len = size - w;
+ vec[1].buf = buf;
+ vec[1].len = cnt2 & size_mask;
+ } else {
+ vec[0].buf = &(buf[w]);
+ vec[0].len = free_cnt;
+ vec[1].len = 0;
+ }
+}
+
+//eof
Index: common/RingBuffer.h
===================================================================
RCS file: common/RingBuffer.h
diff -N common/RingBuffer.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/RingBuffer.h 20 Oct 2007 17:38:17 -0000 1.1
@@ -0,0 +1,198 @@
+/*
+ Copyright (C) 2006 Remon Sijrier
+ Ported to C++ for use in Traverso
+
+ Copyright (C) 2000 Paul Davis
+ Copyright (C) 2003 Rohan Drape
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ $Id: RingBuffer.h,v 1.1 2007/10/20 17:38:17 r_sijrier Exp $
+*/
+
+#ifndef _RINGBUFFER_H
+#define _RINGBUFFER_H
+
+
+#include <sys/types.h>
+#include "defines.h"
+
+
+typedef struct
+{
+ char *buf;
+ size_t len;
+}
+ringbuffer_data_t ;
+
+
+/**
+* The key attribute of a ringbuffer is that it can be safely accessed
+* by two threads simultaneously -- one reading from the buffer and
+* the other writing to it -- without using any synchronization or
+* mutual exclusion primitives. For this to work correctly, there can
+* only be a single reader and a single writer thread. Their
+* identities cannot be interchanged.
+*/
+class RingBuffer
+{
+
+public:
+ RingBuffer(size_t size);
+ ~RingBuffer();
+
+ /**
+ * Fill a data structure with a description of the current readable
+ * data held in the ringbuffer. This description is returned in a two
+ * element array of ringbuffer_data_t. Two elements are needed
+ * because the data to be read may be split across the end of the
+ * ringbuffer.
+ *
+ * The first element will always contain a valid @a len field, which
+ * may be zero or greater. If the @a len field is non-zero, then data
+ * can be read in a contiguous fashion using the address given in the
+ * corresponding @a buf field.
+ *
+ * If the second element has a non-zero @a len field, then a second
+ * contiguous stretch of data can be read from the address given in
+ * its corresponding @a buf field.
+ *
+ * @param vec a pointer to a 2 element array of ringbuffer_data_t.
+ *
+ */
+ void get_read_vector(ringbuffer_data_t *vec);
+
+ /**
+ * Fill a data structure with a description of the current writable
+ * space in the ringbuffer. The description is returned in a two
+ * element array of ringbuffer_data_t. Two elements are needed
+ * because the space available for writing may be split across the end
+ * of the ringbuffer.
+ *
+ * The first element will always contain a valid @a len field, which
+ * may be zero or greater. If the @a len field is non-zero, then data
+ * can be written in a contiguous fashion using the address given in
+ * the corresponding @a buf field.
+ *
+ * If the second element has a non-zero @a len field, then a second
+ * contiguous stretch of data can be written to the address given in
+ * the corresponding @a buf field.
+ *
+ * @param vec a pointer to a 2 element array of ringbuffer_data_t.
+ */
+ void get_write_vector(ringbuffer_data_t *vec);
+
+ /**
+ * Read data from the ringbuffer.
+ *
+ * @param dest a pointer to a buffer where data read from the
+ * ringbuffer will go.
+ * @param cnt the number of bytes to read.
+ *
+ * @return the number of bytes read, which may range from 0 to cnt.
+ */
+ size_t read(char *dest, size_t cnt);
+
+ /**
+ * Read data from the ringbuffer. Opposed to read()
+ * this function does not move the read pointer. Thus it's
+ * a convenient way to inspect data in the ringbuffer in a
+ * continous fashion. The price is that the data is copied
+ * into a user provided buffer. For "raw" non-copy inspection
+ * of the data in the ringbuffer use get_read_vector().
+ *
+ * @param dest a pointer to a buffer where data read from the
+ * ringbuffer will go.
+ * @param cnt the number of bytes to read.
+ *
+ * @return the number of bytes read, which may range from 0 to cnt.
+ */
+ size_t peek(char *dest, size_t cnt);
+
+ /**
+ * Advance the read pointer.
+ *
+ * After data have been read from the ringbuffer using the pointers
+ * returned by get_read_vector(), use this function to
+ * advance the buffer pointers, making that space available for future
+ * write operations.
+ *
+ * @param cnt the number of bytes read.
+ */
+ void read_advance(size_t cnt);
+
+ /**
+ * Return the number of bytes available for reading.
+ *
+ * @return the number of bytes available to read.
+ */
+ size_t read_space();
+
+ /**
+ * Lock a ringbuffer data block into memory.
+ *
+ * Uses the mlock() system call. This is not a realtime operation.
+ */
+ int mlock_buffer();
+
+ /**
+ * Reset the read and write pointers, making an empty buffer.
+ *
+ * This is not thread safe.
+ */
+ void reset();
+
+ /**
+ * Write data into the ringbuffer.
+ *
+ * @param src a pointer to the data to be written to the ringbuffer.
+ * @param cnt the number of bytes to write.
+ *
+ * @return the number of bytes write, which may range from 0 to cnt
+ */
+ size_t write(const char *src, size_t cnt);
+
+ /**
+ * Advance the write pointer.
+ *
+ * After data have been written the ringbuffer using the pointers
+ * returned by get_write_vector(), use this function
+ * to advance the buffer pointer, making the data available for future
+ * read operations.
+ *
+ * @param cnt the number of bytes written.
+ */
+ void write_advance(size_t cnt);
+
+ /**
+ * Return the number of bytes available for writing.
+ *
+ * @return the amount of free space (in bytes) available for writing.
+ */
+ size_t write_space();
+
+private:
+ char *buf;
+ volatile size_t write_ptr;
+ volatile size_t read_ptr;
+ size_t size;
+ size_t size_mask;
+ int mlocked;
+
+};
+
+#endif
Index: common/RingBufferNPT.h
===================================================================
RCS file: common/RingBufferNPT.h
diff -N common/RingBufferNPT.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/RingBufferNPT.h 20 Oct 2007 17:38:17 -0000 1.1
@@ -0,0 +1,287 @@
+/*
+ Copyright (C) 2000 Paul Davis & Benno Senoner
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id: RingBufferNPT.h,v 1.1 2007/10/20 17:38:17 r_sijrier Exp $
+*/
+
+#ifndef ringbuffer_npt_h
+#define ringbuffer_npt_h
+
+#include <stdio.h>
+
+#if ! defined (Q_WS_WIN)
+#include <sys/mman.h>
+#endif
+
+#include "defines.h"
+
+/* ringbuffer class where the element size is not required to be a power of
two */
+
+template<class T>
+class RingBufferNPT
+{
+ public:
+ RingBufferNPT (size_t sz) {
+ size = sz;
+ buf = new T[size];
+#ifdef USE_MLOCK
+ if (mlock (buf, size)) {
+ printf("Unable to lock memory\n");
+ }
+#endif /* USE_MLOCK */
+ reset ();
+
+ };
+
+ virtual ~RingBufferNPT() {
+#ifdef USE_MLOCK
+ munlock (buf, size);
+#endif /* USE_MLOCK */
+ delete [] buf;
+ }
+
+ void reset () {
+ /* !!! NOT THREAD SAFE !!! */
+ t_atomic_int_set (&write_ptr, 0);
+ t_atomic_int_set (&read_ptr, 0);
+ }
+
+ void set (size_t r, size_t w) {
+ /* !!! NOT THREAD SAFE !!! */
+ t_atomic_int_set (&write_ptr, w);
+ t_atomic_int_set (&read_ptr, r);
+ }
+
+ size_t read (T *dest, size_t cnt);
+ size_t write (T *src, size_t cnt);
+
+ struct rw_vector {
+ T *buf[2];
+ size_t len[2];
+ };
+
+ void get_read_vector (rw_vector *);
+ void get_write_vector (rw_vector *);
+
+ void decrement_read_ptr (size_t cnt) {
+ t_atomic_int_set (&read_ptr, (t_atomic_int_get(&read_ptr) -
cnt) % size);
+ }
+
+ void increment_read_ptr (size_t cnt) {
+ t_atomic_int_set (&read_ptr, (t_atomic_int_get(&read_ptr) +
cnt) % size);
+ }
+
+ void increment_write_ptr (size_t cnt) {
+ t_atomic_int_set (&write_ptr, (t_atomic_int_get(&write_ptr) +
cnt) % size);
+ }
+
+ size_t write_space () {
+ size_t w, r;
+
+ w = t_atomic_int_get (&write_ptr);
+ r = t_atomic_int_get (&read_ptr);
+
+ if (w > r) {
+ return ((r - w + size) % size) - 1;
+ } else if (w < r) {
+ return (r - w) - 1;
+ } else {
+ return size - 1;
+ }
+ }
+
+ size_t read_space () {
+ size_t w, r;
+
+ w = t_atomic_int_get (&write_ptr);
+ r = t_atomic_int_get (&read_ptr);
+
+ if (w > r) {
+ return w - r;
+ } else {
+ return (w - r + size) % size;
+ }
+ }
+
+ T *buffer () { return buf; }
+ size_t get_write_ptr () const { return t_atomic_int_get (&write_ptr); }
+ size_t get_read_ptr () const { return t_atomic_int_get (&read_ptr); }
+ size_t bufsize () const { return size; }
+
+ protected:
+ T *buf;
+ size_t size;
+ mutable volatile int write_ptr;
+ mutable volatile int read_ptr;
+};
+
+template<class T> size_t
+RingBufferNPT<T>::read (T *dest, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_read;
+ size_t n1, n2;
+ size_t priv_read_ptr;
+
+ priv_read_ptr=t_atomic_int_get(&read_ptr);
+
+ if ((free_cnt = read_space ()) == 0) {
+ return 0;
+ }
+
+ to_read = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = priv_read_ptr + to_read;
+
+ if (cnt2 > size) {
+ n1 = size - priv_read_ptr;
+ n2 = cnt2 % size;
+ } else {
+ n1 = to_read;
+ n2 = 0;
+ }
+
+ memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
+ priv_read_ptr = (priv_read_ptr + n1) % size;
+
+ if (n2) {
+ memcpy (dest+n1, buf, n2 * sizeof (T));
+ priv_read_ptr = n2;
+ }
+
+ t_atomic_int_set(&read_ptr, priv_read_ptr);
+ return to_read;
+}
+
+template<class T> size_t
+RingBufferNPT<T>::write (T *src, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_write;
+ size_t n1, n2;
+ size_t priv_write_ptr;
+
+ priv_write_ptr=t_atomic_int_get(&write_ptr);
+
+ if ((free_cnt = write_space ()) == 0) {
+ return 0;
+ }
+
+ to_write = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = priv_write_ptr + to_write;
+
+ if (cnt2 > size) {
+ n1 = size - priv_write_ptr;
+ n2 = cnt2 % size;
+ } else {
+ n1 = to_write;
+ n2 = 0;
+ }
+
+ memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
+ priv_write_ptr = (priv_write_ptr + n1) % size;
+
+ if (n2) {
+ memcpy (buf, src+n1, n2 * sizeof (T));
+ priv_write_ptr = n2;
+ }
+
+ t_atomic_int_set(&write_ptr, priv_write_ptr);
+ return to_write;
+}
+
+template<class T> void
+RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = t_atomic_int_get (&write_ptr);
+ r = t_atomic_int_get (&read_ptr);
+
+ if (w > r) {
+ free_cnt = w - r;
+ } else {
+ free_cnt = (w - r + size) % size;
+ }
+
+ cnt2 = r + free_cnt;
+
+ if (cnt2 > size) {
+ /* Two part vector: the rest of the buffer after the
+ current write ptr, plus some from the start of
+ the buffer.
+ */
+
+ vec->buf[0] = &buf[r];
+ vec->len[0] = size - r;
+ vec->buf[1] = buf;
+ vec->len[1] = cnt2 % size;
+
+ } else {
+
+ /* Single part vector: just the rest of the buffer */
+
+ vec->buf[0] = &buf[r];
+ vec->len[0] = free_cnt;
+ vec->len[1] = 0;
+ }
+}
+
+template<class T> void
+RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = t_atomic_int_get (&write_ptr);
+ r = t_atomic_int_get (&read_ptr);
+
+ if (w > r) {
+ free_cnt = ((r - w + size) % size) - 1;
+ } else if (w < r) {
+ free_cnt = (r - w) - 1;
+ } else {
+ free_cnt = size - 1;
+ }
+
+ cnt2 = w + free_cnt;
+
+ if (cnt2 > size) {
+
+ /* Two part vector: the rest of the buffer after the
+ current write ptr, plus some from the start of
+ the buffer.
+ */
+
+ vec->buf[0] = &buf[w];
+ vec->len[0] = size - w;
+ vec->buf[1] = buf;
+ vec->len[1] = cnt2 % size;
+ } else {
+ vec->buf[0] = &buf[w];
+ vec->len[0] = free_cnt;
+ vec->len[1] = 0;
+ }
+}
+
+#endif /* __ringbuffer_npt_h__ */
Index: common/Tsar.cpp
===================================================================
RCS file: common/Tsar.cpp
diff -N common/Tsar.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Tsar.cpp 20 Oct 2007 17:38:17 -0000 1.1
@@ -0,0 +1,319 @@
+/*
+Copyright (C) 2006 Remon Sijrier
+
+This file is part of Traverso
+
+Traverso is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$Id: Tsar.cpp,v 1.1 2007/10/20 17:38:17 r_sijrier Exp $
+*/
+
+#include "Tsar.h"
+
+#include "AudioDevice.h"
+#include <QMetaMethod>
+#include <QMessageBox>
+#include <QCoreApplication>
+#include <QThread>
+
+
+// Always put me below _all_ includes, this is needed
+// in case we run with memory leak detection enabled!
+#include "Debugger.h"
+
+/**
+ * \class Tsar
+ * \brief Tsar (Thread Save Add and Remove) is a singleton class to call
+ * functions (both signals and slots) in a thread save way without
+ * using any mutual exclusion primitives (mutex)
+ *
+ */
+
+
+/**
+ *
+ * @return The Tsar instance.
+ */
+Tsar& tsar()
+{
+ static Tsar ThreadSaveAddRemove;
+ return ThreadSaveAddRemove;
+}
+
+Tsar::Tsar()
+{
+ m_eventCounter = 0;
+
+ m_events.append(new RingBufferNPT<TsarEvent>(1000));
+ m_events.append(new RingBufferNPT<TsarEvent>(100));
+ oldEvents = new RingBufferNPT<TsarEvent>(1000);
+
+#if defined (THREAD_CHECK)
+ m_threadId = QThread::currentThreadId ();
+#endif
+
+ connect(&finishOldEventsTimer, SIGNAL(timeout()), this,
SLOT(finish_processed_events()));
+
+ finishOldEventsTimer.start( 20 );
+}
+
+Tsar::~ Tsar( )
+{
+ foreach(RingBufferNPT<TsarEvent>* eventBuffer, m_events) {
+ delete eventBuffer;
+ }
+ delete oldEvents;
+}
+
+/**
+ * Use this function to add events to the event queue when
+ * called from the GUI thread.
+ *
+ * Note: This function should be called ONLY from the GUI thread!
+ * @param event The event to add to the event queue
+ */
+void Tsar::add_event(TsarEvent& event )
+{
+#if defined (THREAD_CHECK)
+ Q_ASSERT_X(m_threadId == QThread::currentThreadId (),
"Tsar::add_event", "Adding event from other then GUI thread!!");
+#endif
+ m_events.at(0)->write(&event, 1);
+ m_eventCounter++;
+}
+
+/**
+ * Use this function to add events to the event queue when
+ * called from the audio processing (real time) thread
+ *
+ * Note: This function should be called ONLY from the realtime audio
thread and has a
+ * non blocking behaviour! (That is, it's a real time save function)
+ *
+ * @param event The event to add to the event queue
+ */
+void Tsar::add_rt_event( TsarEvent& event )
+{
+#if defined (THREAD_CHECK)
+ Q_ASSERT_X(m_threadId != QThread::currentThreadId (),
"Tsar::add_rt_event", "Adding event from NON-RT Thread!!");
+#endif
+ m_events.at(1)->write(&event, 1);
+}
+
+//
+// Function called in RealTime AudioThread processing path
+//
+void Tsar::process_events( )
+{
+// #define profile
+
+ for (int i=0; i<m_events.size(); ++i) {
+ RingBufferNPT<TsarEvent>* newEvents = m_events.at(i);
+
+ int processedCount = 0;
+ int newEventCount = newEvents->read_space();
+
+ while((newEventCount > 0) && (processedCount < 10)) {
+#if defined (profile)
+ trav_time_t starttime = get_microseconds();
+#endif
+ TsarEvent event;
+
+ newEvents->read(&event, 1);
+
+ process_event_slot(event);
+
+ oldEvents->write(&event, 1);
+
+ --newEventCount;
+ ++processedCount;
+
+#if defined (profile)
+ int processtime = (int) (get_microseconds() -
starttime);
+ printf("called %s::%s, (signal: %s) \n",
event.caller->metaObject()->className(),
+ (event.slotindex >= 0) ?
event.caller->metaObject()->method(event.slotindex).signature() : "",
+ (event.signalindex >= 0) ?
event.caller->metaObject()->method(event.signalindex + 4).signature() : "");
+ printf("Process time: %d useconds\n\n", processtime);
+#endif
+ }
+ }
+}
+
+void Tsar::finish_processed_events( )
+{
+
+ while(oldEvents->read_space() >= 1 ) {
+ TsarEvent event;
+ // Read one TsarEvent from the processed events ringbuffer
'queue'
+ oldEvents->read(&event, 1);
+
+ process_event_signal(event);
+
+ --m_eventCounter;
+// printf("finish_processed_objects:: Count is %d\n",
m_eventCounter);
+ }
+
+ static int retryCount;
+
+ retryCount++;
+
+ if (retryCount > 100) {
+ if (audiodevice().get_driver_type() != "Null Driver") {
+ QMessageBox::critical( 0,
+ tr("Traverso - Malfunction!"),
+ tr("The Audiodriver Thread seems to be
stalled/stopped, but Traverso didn't ask for it!\n"
+ "This effectively makes Traverso unusable,
since it relies heavily on the AudioDriver Thread\n"
+ "To ensure proper operation, Traverso will
fallback to the 'Null Driver'.\n"
+ "Potential issues why this can show up are:
\n\n"
+ "* You're not running with real time
privileges! Please make sure this is setup properly.\n\n"
+ "* The audio chipset isn't supported
(completely), you probably have to turn off some of it's features.\n"
+ "\nFor more information, see the Help file,
section: \n\n AudioDriver: 'Thread stalled error'\n\n"),
+ "OK",
+ 0 );
+ audiodevice().set_parameters(44100, 1024, "Null
Driver", true, true);
+ retryCount = 0;
+ } else {
+ QMessageBox::critical( 0,
+ tr("Traverso - Fatal!"),
+ tr("The Null AudioDriver stalled too, exiting
application!"),
+ "OK",
+ 0 );
+ QCoreApplication::exit(-1);
+ }
+ }
+
+ if (m_eventCounter <= 0) {
+ retryCount = 0;
+ }
+}
+
+/**
+ * Creates a Tsar event. Add the tsar event to the event queue by calling
add_event()
+ * If you need to add an event from the real time audio processing thread,
use
+ * add_rt_event() instead!
+ *
+ * Note: This function can be called both from the GUI and realtime audio
thread and has a
+ * non blocking behaviour! (That is, it's a real time save function)
+ *
+ * @param caller The calling object, needs to be derived from a QObject
+ * @param argument The slot and/or signal argument which can be of any
type.
+ * @param slotSignature The 'signature' of the calling objects slot (equals
the name of the slot function)
+ * @param signalSignature The 'signature' of the calling objects signal
(equals the name of the signal function)
+ * @return The newly created event.
+ */
+TsarEvent Tsar::create_event( QObject* caller, void* argument, char*
slotSignature, char* signalSignature )
+{
+ PENTER3;
+ TsarEvent event;
+ event.caller = caller;
+ event.argument = argument;
+ int index;
+
+ if (qstrlen(slotSignature) > 0) {
+ index = caller->metaObject()->indexOfMethod(slotSignature);
+ if (index < 0) {
+ PWARN("Slot signature contains whitespaces, please
remove to avoid unneeded processing (%s::%s)",
caller->metaObject()->className(), slotSignature);
+ QByteArray norm =
QMetaObject::normalizedSignature(slotSignature);
+ index =
caller->metaObject()->indexOfMethod(norm.constData());
+ if (index < 0) {
+ PERROR("Couldn't find a valid index for %s",
slotSignature);
+ }
+ }
+ event.slotindex = index;
+ } else {
+ event.slotindex = -1;
+ }
+
+ if (qstrlen(signalSignature) > 0) {
+ /* the signal index seems to have an offset of 4, so we have to
substract 4 from */
+ /* the value returned by caller->metaObject()->indexOfMethod*/
+ index = caller->metaObject()->indexOfMethod(signalSignature) -
4;
+ if (index < 0) {
+ PWARN("Signal signature contains whitespaces, please
remove to avoid unneeded processing (%s::%s)",
caller->metaObject()->className(), signalSignature);
+ QByteArray norm =
QMetaObject::normalizedSignature(signalSignature);
+ index =
caller->metaObject()->indexOfMethod(norm.constData()) - 4;
+ }
+ event.signalindex = index;
+ } else {
+ event.signalindex = -1;
+ }
+
+ event.valid = true;
+
+ return event;
+}
+
+/**
+* This function can be used to process the events 'slot' part.
+* Usefull when you have a Tsar event, but don't want/need to use tsar
+* to call the events slot in a thread save way
+*
+* Note: This function doesn't provide the thread savetiness you get with
+* the add_event() function!
+*
+* @param event The TsarEvent to be processed
+*/
+void Tsar::process_event_slot(const TsarEvent& event )
+{
+ // If there is an object to be added, do the magic to call the slot :-)
+ if (event.slotindex > -1) {
+
+ void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const
void*>(&event.argument)) };
+
+ // This equals QMetaObject::invokeMethod(), without type
checking. But we know that the types
+ // are the correct ones, and will be casted just fine!
+ if ( !
(event.caller->qt_metacall(QMetaObject::InvokeMetaMethod, event.slotindex, _a)
< 0) ) {
+ qDebug("Tsar::process_event_slot failed (%s::%s)",
event.caller->metaObject()->className(),
event.caller->metaObject()->method(event.slotindex).signature());
+ }
+ }
+}
+
+/**
+* This function can be used to process the events 'signal' part.
+* Usefull when you have a Tsar event, but don't want/need to use tsar
+* to call the events signal in a thread save way
+*
+* Note: This function doesn't provide the thread savetiness you get with
+* the add_event() function!
+*
+* @param event The TsarEvent to be processed
+*/
+void Tsar::process_event_signal(const TsarEvent & event )
+{
+ // In case the signalindex > -1, emit the signal!
+ if (event.signalindex > -1) {
+ // This equals emit someSignal() :-)
+ void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const
void*>(&event.argument)) };
+ QMetaObject::activate(event.caller, event.caller->metaObject(),
event.signalindex, _a);
+ }
+}
+
+/**
+* Convenience function. Calls both process_event_slot() and
process_event_signal()
+*
+* \sa process_event_slot() \sa process_event_signal()
+*
+* Note: This function doesn't provide the thread savetiness you get with
+* the add_event() function!
+*
+* @param event The TsarEvent to be processed
+*/
+void Tsar::process_event_slot_signal(const TsarEvent & event )
+{
+ process_event_slot(event);
+ process_event_signal(event);
+}
+
+
+//eof
+
Index: common/Tsar.h
===================================================================
RCS file: common/Tsar.h
diff -N common/Tsar.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Tsar.h 20 Oct 2007 17:38:17 -0000 1.1
@@ -0,0 +1,121 @@
+/*
+Copyright (C) 2006 Remon Sijrier
+
+This file is part of Traverso
+
+Traverso is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$Id: Tsar.h,v 1.1 2007/10/20 17:38:17 r_sijrier Exp $
+*/
+
+#ifndef TSAR_H
+#define TSAR_H
+
+#include <QObject>
+#include <QTimer>
+#include <QByteArray>
+#include "RingBufferNPT.h"
+
+#define THREAD_SAVE_INVOKE(caller, argument, slotSignature) { \
+ TsarEvent event = tsar().create_event(caller, argument,
#slotSignature, ""); \
+ tsar().add_event(event);\
+ }
+
+#define RT_THREAD_EMIT(cal, arg, signalSignature) {\
+ TsarEvent event; \
+ event.caller = cal; \
+ event.argument = arg; \
+ event.slotindex = -1; \
+ static int retrievedsignalindex; \
+ \
+ if ( ! retrievedsignalindex ) { \
+ /* the signal index seems to have an offset of 4, so we have to
substract 4 from */ \
+ /* the value returned by caller->metaObject()->indexOfMethod*/
\
+ retrievedsignalindex =
cal->metaObject()->indexOfMethod(#signalSignature) - 4; \
+ Q_ASSERT(retrievedsignalindex >= 0); \
+ } \
+ event.signalindex = retrievedsignalindex; \
+ event.valid = true; \
+ tsar().add_rt_event(event); \
+}\
+
+
+#define THREAD_SAVE_INVOKE_AND_EMIT_SIGNAL(caller, argument, slotSignature,
signalSignature) { \
+ TsarEvent event = tsar().create_event(caller, argument, #slotSignature,
#signalSignature); \
+ tsar().add_event(event);\
+ }\
+
+
+struct TsarEvent {
+// used for slot invokation stuff
+ QObject* caller;
+ void* argument;
+ int slotindex;
+ void* _a[];
+
+// Used for the signal emiting stuff
+ int signalindex;
+
+ bool valid;
+};
+
+class Tsar : public QObject
+{
+ Q_OBJECT
+
+public:
+ TsarEvent create_event(QObject* caller, void* argument, char*
slotSignature, char* signalSignature);
+
+ void add_event(TsarEvent& event);
+ void add_rt_event(TsarEvent& event);
+ void process_event_slot(const TsarEvent& event);
+ void process_event_signal(const TsarEvent& event);
+ void process_event_slot_signal(const TsarEvent& event);
+
+private:
+ Tsar();
+ ~Tsar();
+ Tsar(const Tsar&);
+
+ // allow this function to create one instance
+ friend Tsar& tsar();
+ // The AudioDevice instance is the _only_ one who
+ // is allowed to call process_events() !!
+ friend class AudioDevice;
+
+ QList<RingBufferNPT<TsarEvent>*> m_events;
+ RingBufferNPT<TsarEvent>* oldEvents;
+ QTimer finishOldEventsTimer;
+ int m_eventCounter;
+#if defined (THREAD_CHECK)
+ unsigned long m_threadId;
+#endif
+
+ void process_events();
+
+private slots:
+ void finish_processed_events();
+
+};
+
+#endif
+
+// use this function to access the context pointer
+Tsar& tsar();
+
+//eof
+
+
+
Index: common/Utils.cpp
===================================================================
RCS file: common/Utils.cpp
diff -N common/Utils.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Utils.cpp 20 Oct 2007 17:38:17 -0000 1.3
@@ -0,0 +1,198 @@
+/*
+ Copyright (C) 2005-2007 Remon Sijrier
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include "Utils.h"
+#include "Mixer.h"
+
+#include <QString>
+#include <QStringList>
+#include <QDateTime>
+#include <QPixmapCache>
+#include <QRegExp>
+#include <QLocale>
+#include <QChar>
+
+
+TimeRef msms_to_timeref(QString str)
+{
+ TimeRef out;
+ QStringList lst = str.simplified().split(QRegExp("[;,.:]"),
QString::SkipEmptyParts);
+
+ if (lst.size() >= 1) out += TimeRef(lst.at(0).toInt() *
ONE_MINUTE_UNIVERSAL_SAMPLE_RATE);
+ if (lst.size() >= 2) out += TimeRef(lst.at(1).toInt() *
UNIVERSAL_SAMPLE_RATE);
+ if (lst.size() >= 3) out += TimeRef(lst.at(2).toInt() *
UNIVERSAL_SAMPLE_RATE / 1000);
+
+ return out;
+}
+
+TimeRef cd_to_timeref(QString str)
+{
+ TimeRef out;
+ QStringList lst = str.simplified().split(QRegExp("[;,.:]"),
QString::SkipEmptyParts);
+
+ if (lst.size() >= 1) out += TimeRef(lst.at(0).toInt() *
ONE_MINUTE_UNIVERSAL_SAMPLE_RATE);
+ if (lst.size() >= 2) out += TimeRef(lst.at(1).toInt() *
UNIVERSAL_SAMPLE_RATE);
+ if (lst.size() >= 3) out += TimeRef(lst.at(2).toInt() *
UNIVERSAL_SAMPLE_RATE / 75);
+
+ return out;
+}
+
+QString coefficient_to_dbstring ( float coeff )
+{
+ float db = coefficient_to_dB ( coeff );
+
+ QString gainIndB;
+
+ if ( db < -99 )
+ gainIndB = "- INF";
+ else if ( db < 0 )
+ gainIndB = "- " + QByteArray::number ( ( -1 * db ), 'f', 1 ) +
" dB";
+ else
+ gainIndB = "+ " + QByteArray::number ( db, 'f', 1 ) + " dB";
+
+ return gainIndB;
+}
+
+qint64 create_id( )
+{
+ int r = rand();
+ QDateTime time = QDateTime::currentDateTime();
+ uint timeValue = time.toTime_t();
+ qint64 id = timeValue;
+ id *= 1000000000;
+ id += r;
+
+ return id;
+}
+
+QDateTime extract_date_time(qint64 id)
+{
+ QDateTime time;
+ time.setTime_t(id / 1000000000);
+ return time;
+}
+
+QPixmap find_pixmap ( const QString & pixname )
+{
+ QPixmap pixmap;
+
+ if ( ! QPixmapCache::find ( pixname, pixmap ) )
+ {
+ pixmap = QPixmap ( pixname );
+ QPixmapCache::insert ( pixname, pixmap );
+ }
+
+ return pixmap;
+}
+
+QString timeref_to_hms(const TimeRef& ref)
+{
+ qint64 remainder;
+ int hours, mins, secs;
+
+ qint64 universalframe = ref.universal_frame();
+
+ hours = (int) (universalframe / ONE_HOUR_UNIVERSAL_SAMPLE_RATE);
+ remainder = (long unsigned int) (universalframe - (hours *
ONE_HOUR_UNIVERSAL_SAMPLE_RATE));
+ mins = (int) (remainder / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE ));
+ remainder -= mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE;
+ secs = (int) (remainder / UNIVERSAL_SAMPLE_RATE);
+ return QString().sprintf("%02d:%02d:%02d", hours, mins, secs);
+}
+
+QString timeref_to_ms(const TimeRef& ref)
+{
+ long unsigned int remainder;
+ int mins, secs;
+
+ qint64 universalframe = ref.universal_frame();
+
+ mins = (int) (universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE ));
+ remainder = (long unsigned int) (universalframe - (mins *
ONE_MINUTE_UNIVERSAL_SAMPLE_RATE));
+ secs = (int) (remainder / UNIVERSAL_SAMPLE_RATE);
+ return QString().sprintf("%02d:%02d", mins, secs);
+}
+
+// TimeRef to MM:SS.99 (hundredths)
+QString timeref_to_ms_2 (const TimeRef& ref)
+{
+ QString spos;
+ long unsigned int remainder;
+ int mins, secs, frames;
+
+ qint64 universalframe = ref.universal_frame();
+
+ mins = universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE );
+ remainder = universalframe - ( mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE
);
+ secs = remainder / UNIVERSAL_SAMPLE_RATE;
+ remainder -= secs * UNIVERSAL_SAMPLE_RATE;
+ frames = remainder * 100 / UNIVERSAL_SAMPLE_RATE;
+ spos.sprintf ( " %02d:%02d%c%02d", mins, secs,
QLocale::system().decimalPoint().toAscii(), frames );
+
+ return spos;
+}
+
+// TimeRef to MM:SS.999 (ms)
+QString timeref_to_ms_3(const TimeRef& ref)
+{
+ QString spos;
+ long unsigned int remainder;
+ int mins, secs, frames;
+
+ qint64 universalframe = ref.universal_frame();
+
+ mins = universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE );
+ remainder = universalframe - ( mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE
);
+ secs = remainder / UNIVERSAL_SAMPLE_RATE;
+ remainder -= secs * UNIVERSAL_SAMPLE_RATE;
+ frames = remainder * 1000 / UNIVERSAL_SAMPLE_RATE;
+ spos.sprintf ( " %02d:%02d%c%03d", mins, secs,
QLocale::system().decimalPoint().toAscii(), frames );
+
+ return spos;
+}
+
+// Frame to MM:SS:75 (75ths of a second, for CD burning)
+QString timeref_to_cd (const TimeRef& ref)
+{
+ QString spos;
+ long unsigned int remainder;
+ int mins, secs, frames;
+
+ qint64 universalframe = ref.universal_frame();
+
+ mins = universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE );
+ remainder = universalframe - ( mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE
);
+ secs = remainder / UNIVERSAL_SAMPLE_RATE;
+ remainder -= secs * UNIVERSAL_SAMPLE_RATE;
+ frames = remainder * 75 / UNIVERSAL_SAMPLE_RATE;
+ spos.sprintf ( " %02d:%02d:%02d", mins, secs, frames );
+
+ return spos;
+}
+
+QString timeref_to_text(const TimeRef & ref, int scalefactor)
+{
+ if (scalefactor >= 512*640) {
+ return timeref_to_ms_2(ref);
+ } else {
+ return timeref_to_ms_3(ref);
+ }
+}
Index: common/Utils.h
===================================================================
RCS file: common/Utils.h
diff -N common/Utils.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ common/Utils.h 20 Oct 2007 17:38:17 -0000 1.3
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2005-2007 Remon Sijrier
+
+ This file is part of Traverso
+
+ Traverso is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "defines.h"
+#include <QPixmap>
+#include <QDateTime>
+
+#define QS_C(x) x.toAscii().data()
+
+class QString;
+
+QString timeref_to_hms(const TimeRef& ref);
+QString timeref_to_ms(const TimeRef& ref);
+QString timeref_to_ms_2 (const TimeRef& ref);
+QString timeref_to_ms_3 (const TimeRef& ref);
+QString timeref_to_text(const TimeRef& ref, int scalefactor);
+QString timeref_to_cd(const TimeRef& ref);
+
+TimeRef msms_to_timeref(QString str);
+TimeRef cd_to_timeref(QString str);
+QString coefficient_to_dbstring(float coeff);
+QDateTime extract_date_time(qint64 id);
+
+qint64 create_id();
+
+static inline unsigned int is_power_of_two (unsigned int n)
+{
+ return !(n & (n - 1));
+}
+
+QPixmap find_pixmap(const QString& pixname);
+
+#endif
Index: core/Debugger.cpp
===================================================================
RCS file: core/Debugger.cpp
diff -N core/Debugger.cpp
--- core/Debugger.cpp 17 Aug 2007 00:18:30 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,395 +0,0 @@
-/*
- Copyright (C) 2005-2006 Remon Sijrier
-
- This file is part of Traverso
-
- Traverso is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- $Id: Debugger.cpp,v 1.2 2007/08/17 00:18:30 r_sijrier Exp $
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "Debugger.h"
-
-namespace Debugger
-{
-int ntabs = 0;
-int debugLevel = OFF;
-FILE* logFile = (FILE*) 0;
-QString logFileName = 0;
-bool logging = false;
-}
-
-void Debugger::fill_tabs()
-{
- for (int i=0; i < ntabs; i++)
- printf("| ");
-}
-
-QString Debugger::get_tabs()
-{
- QString t="";
- for (int i=0; i < ntabs; i++)
- t=t.append(" ");
- return t;
-}
-
-
-void Debugger::more_tabs()
-{
- ntabs++;
-}
-
-
-void Debugger::less_tabs()
-{
- ntabs--;
-}
-
-
-void Debugger::set_debug_level(int l)
-{
- debugLevel = l;
-}
-
-
-int Debugger::get_debug_level()
-{
- return debugLevel;
-}
-
-
-void Debugger::create_log(QString fn)
-{
- logFileName = QString(getenv("HOME")) + "/" + fn;
- logFile = fopen(logFileName.toAscii(),"a+");
- if (!logFile) {
- PERROR("Cannot create Debugger Log file
(%s)",fn.toAscii().data());
- logging=false;
- } else {
- fclose(logFile);
- logging=true;
- }
-}
-
-
-
-void Debugger::close_log()
-{
- logging=false;
-}
-
-
-
-void Debugger::log(QString s)
-{
- const char* sc = s.toAscii();
- int len = s.length();
- logFile = fopen(logFileName.toAscii(),"a+");
- fwrite(sc,len,1,logFile);
- fclose(logFile);
-}
-
-bool Debugger::is_logging()
-{
- return logging;
-}
-
-
-#ifdef USE_DEBUGGER
-
-static void print_enter(int lvl, const char* file, const char* function)
-{
- using namespace Debugger;
-
- if (get_debug_level()>=lvl) {
- if (is_logging()) {
- QString output = get_tabs() + "ENTERING " +
QString(file) + "::" + QString(function) + "\n";
- log(output);
- more_tabs();
- } else {
- fill_tabs();
- CHANGE_COLOR_GREEN;
- printf("ENTERING ");
- CHANGE_COLOR_WHITE;
- printf("%s::%s\n", file, function);
- more_tabs();
- }
- }
-}
-
-static void print_exit(int lvl, const char* file, const char* function)
-{
- using namespace Debugger;
-
- if (get_debug_level()>=lvl) {
- if (is_logging()) {
- less_tabs();
- QString output = get_tabs() + "LEAVING " +
QString(file) + "::" + QString(function) + "\n";
- log(output);
- } else {
- less_tabs();
- fill_tabs();
- CHANGE_COLOR_BLUE;
- printf("LEAVING ");
- CHANGE_COLOR_WHITE;
- printf("%s::%s\n", file, function);
- }
- }
-}
-
-FunctionEnter::FunctionEnter(int level, const char* file, const char* function)
- : m_file(file), m_function(function), lvl(level)
-{
- print_enter(lvl, m_file, m_function);
-}
-
-FunctionEnter::~ FunctionEnter( )
-{
- print_exit(lvl, m_file, m_function);
-}
-
-ConstructorEnter::ConstructorEnter(int level, const char* file, const char*
function)
- : m_file(file), m_function(function), lvl(level)
-{
- using namespace Debugger;
- if (get_debug_level()>=lvl) {
- if (is_logging()) {
- QString output = get_tabs() + "ENTERING " +
QString(m_function) + " (CONSTRUCTOR)\n";
- log(output);
- more_tabs();
- } else {
- fill_tabs();
- CHANGE_COLOR_GREEN;
- printf("ENTERING ");
- CHANGE_COLOR_WHITE;
- printf("%s",m_function);
- CHANGE_COLOR_CYAN;
- printf(" (CONSTRUCTOR)");
- CHANGE_COLOR_WHITE;
- printf("\n");
- more_tabs();
- }
- }
-}
-
-ConstructorEnter::~ ConstructorEnter( )
-{
- using namespace Debugger;
- if (get_debug_level()>=lvl) {
- if (is_logging()) {
- less_tabs();
- QString output = get_tabs() + "LEAVING " +
QString(m_function) + " (CONSTRUCTOR)\n";
- log(output);
- } else {
- less_tabs();
- fill_tabs();
- CHANGE_COLOR_BLUE;
- printf("LEAVING ");
- CHANGE_COLOR_WHITE;
- printf("%s", m_function);
- CHANGE_COLOR_CYAN;
- printf(" (CONSTRUCTOR)");
- CHANGE_COLOR_WHITE;
- printf("\n");
- }
- }
-}
-
-DestructorEnter::DestructorEnter(int level, const char* file, const char*
function)
- : m_file(file), m_function(function), lvl(level)
-{
- using namespace Debugger;
- if (get_debug_level()>=lvl) {
- if (is_logging()) {
- QString output = get_tabs() + "ENTERING " +
QString(m_function) + " (DESTRUCTOR)\n";
- log(output);
- more_tabs();
- } else {
- fill_tabs();
- CHANGE_COLOR_GREEN;
- printf("ENTERING ");
- CHANGE_COLOR_WHITE;
- printf("%s", m_function);
- CHANGE_COLOR_CYAN;
- printf(" (DESTRUCTOR)");
- CHANGE_COLOR_WHITE;
- printf("\n");
- more_tabs();
- }
- }
-}
-
-DestructorEnter::~ DestructorEnter( )
-{
- using namespace Debugger;
- if (get_debug_level()>=lvl) {
- if (is_logging()) {
- less_tabs();
- QString output = get_tabs() + "LEAVING " +
QString(m_function) + " (DESTRUCTOR)\n";
- log(output);
- } else {
- less_tabs();
- fill_tabs();
- CHANGE_COLOR_BLUE;
- printf("LEAVING ");
- CHANGE_COLOR_WHITE;
- printf("%s", m_function);
- CHANGE_COLOR_CYAN;
- printf(" (DESTRUCTOR)");
- CHANGE_COLOR_WHITE;
- printf("\n");
- }
- }
-}
-#endif
-
-
-#if defined (USE_MEM_CHECKER)
-
-//: C02:MemCheck.cpp {O}
-// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
-// (c) 1995-2004 MindView, Inc. All Rights Reserved.
-// See source code use permissions stated in the file 'License.txt',
-// distributed with the code package available at www.MindView.net.
-#include <cstdio>
- #include <cstdlib>
- #include <cassert>
- #include <cstddef>
-using namespace std;
-#undef new
-
-// Global flags set by macros in MemCheck.h
-bool traceFlag = true;
-bool activeFlag = false;
-
-namespace
-{
-
-// Memory map entry type
-struct Info
-{
- void* ptr;
- const char* file;
- long line;
- size_t size;
-};
-
-// Memory map data
-const size_t MAXPTRS = 10000u;
-Info memMap[MAXPTRS];
-size_t nptrs = 0;
-
-// Searches the map for an address
-int findPointer(void* p)
-{
- for(size_t i = 0; i < nptrs; ++i)
- if(memMap[i].ptr == p)
- return i;
- return -1;
-}
-
-void delPointer(void* p)
-{
- long pos = findPointer(p);
- assert(pos >= 0);
- // Remove pointer from map
- for(size_t i = pos; i < nptrs-1; ++i)
- memMap[i] = memMap[i+1];
- --nptrs;
-}
-
-// Dummy type for static destructor
-struct Sentinel
-{
- ~Sentinel()
- {
- if(nptrs > 0) {
- printf("Leaked memory at:\n");
- for(size_t i = 0; i < nptrs; ++i)
- printf("\t%p (file: %s, line %ld)\n",
- memMap[i].ptr, memMap[i].file,
memMap[i].line);
- } else
- printf("No memory leaks found in Traverso!\n");
- }
-};
-
-// Static dummy object
-Sentinel s;
-
-} // End anonymous namespace
-
-// Overload scalar new
-void*
-operator new(size_t siz, const char* file, long line)
-{
- void* p = malloc(siz);
- if(activeFlag) {
- if(nptrs == MAXPTRS) {
- printf("memory map too small (increase MAXPTRS)\n");
- exit(1);
- }
- memMap[nptrs].ptr = p;
- memMap[nptrs].file = file;
- memMap[nptrs].line = line;
- memMap[nptrs].size = siz;
-
- ++nptrs;
- }
- if(traceFlag) {
- printf("Allocated %.2f KBytes at address %p (file: %s, line:
%ld)\n", (float)siz/1024, p, file, line);
- }
- fflush(NULL);
- return p;
-}
-
-// Overload array new
-void*
-operator new[](size_t siz, const char* file, long line)
-{
- return operator new(siz, file, line);
-}
-
-// Override scalar delete
-void operator delete(void* p)
-{
- int i;
- if( (i = findPointer(p)) >= 0) {
- free(p);
- assert(nptrs > 0);
- delPointer(p);
- if(traceFlag) {
- if (memMap[i].size > 1024)
- printf("Deleted %u bytes at address %p, file:
%s, line: %ld\n", memMap[i].size, p, memMap[i].file, memMap[i].line);
- }
- } else if(!p && activeFlag)
- printf("Attempt to delete unknown pointer: %p\n", p);
- fflush(NULL);
-}
-
-// Override array delete
-void operator delete[](void* p)
-{
- operator delete(p);
-} ///:~
-
-
-#endif //USE_MEM_CHECKER ///:~
-
-
-//eof
-
Index: core/Debugger.h
===================================================================
RCS file: core/Debugger.h
diff -N core/Debugger.h
--- core/Debugger.h 20 Apr 2006 14:51:39 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,234 +0,0 @@
-/*
- Copyright (C) 2005-2006 Remon Sijrier
-
- This file is part of Traverso
-
- Traverso is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- $Id: Debugger.h,v 1.1 2006/04/20 14:51:39 r_sijrier Exp $
-*/
-
-#ifndef DEBUGGER_H
-#define DEBUGGER_H
-
-#include <QString>
-
-
-//Debugging Macros
-#define CHANGE_COLOR_BLACK printf("%c[0;31m",27)
-#define CHANGE_COLOR_RED printf("%c[0;31m",27)
-#define CHANGE_COLOR_GREEN printf("%c[0;32m",27)
-#define CHANGE_COLOR_ORANGE printf("%c[0;33m",27)
-#define CHANGE_COLOR_BLUE printf("%c[0;34m",27)
-#define CHANGE_COLOR_MAGENTA printf("%c[0;35m",27)
-#define CHANGE_COLOR_CYAN printf("%c[0;36m",27)
-#define CHANGE_COLOR_WHITE printf("%c[0;37m",27)
-#define CHANGE_COLOR_YELLOW printf("%c[0;33m",27)
-
-#ifdef USE_DEBUGGER
-
-class FunctionEnter
-{
- const char* m_file;
- const char* m_function;
- int lvl;
-public:
- FunctionEnter(int level, const char* file, const char* function);
- ~FunctionEnter();
-};
-
-class ConstructorEnter
-{
- const char* m_file;
- const char* m_function;
- int lvl;
-public:
- ConstructorEnter(int level, const char* file, const char* function);
- ~ConstructorEnter();
-};
-
-class DestructorEnter
-{
- const char* m_file;
- const char* m_function;
- int lvl;
-public:
- DestructorEnter(int level, const char* file, const char* function);
- ~DestructorEnter();
-};
-
-#define PMESG(args...) { using namespace Debugger; if
(get_debug_level()>=BASIC) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
-#define PMESG2(args...) { using namespace Debugger; if
(get_debug_level()>=FLOOD) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
-#define PMESG3(args...) { using namespace Debugger; if
(get_debug_level()>=SUPER_FLOOD) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
-#define PMESG4(args...) { using namespace Debugger; if
(get_debug_level()>=ALL) { if (is_logging()) { QString x;
x.sprintf(args); QString output = get_tabs() + "[ " + x + " ]\n"; log(output);
} else { fill_tabs(); CHANGE_COLOR_MAGENTA; printf("[ "); printf(args);
printf(" ]"); CHANGE_COLOR_WHITE; printf("\n"); } } }
-
-#define PDEBUG(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "DEBUG : " + QString(__FILE__) +
"::" + QString(__FUNCTION__) + ":" + x + "\n"; log(output); } else {
CHANGE_COLOR_GREEN; printf("DEBUG : ");printf("%s",__FILE__); printf("::");
printf("%s",__FUNCTION__); printf(":"); printf(args); CHANGE_COLOR_WHITE;
printf("\n"); } }
-#define PERROR(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "\n *** Error in " +
QString(__PRETTY_FUNCTION__) + "\n" + x + "\n\n"; } else { printf("\n");
CHANGE_COLOR_RED; printf("*** Error in "); printf("%s",__PRETTY_FUNCTION__);
printf("\n"); printf(args); CHANGE_COLOR_WHITE; printf("\n\n"); } }
-#define PERROR2(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "\n *** Error in " +
QString(__PRETTY_FUNCTION__) + "\n" + x + "\n\n"; } else if
(get_debug_level()>=FLOOD) { printf("\n"); CHANGE_COLOR_RED; printf("*** Error
in "); printf("%s",__PRETTY_FUNCTION__); printf("\n"); printf(args);
CHANGE_COLOR_WHITE; printf("\n\n"); } }
-#define PWARN(args...) { using namespace Debugger; if (is_logging())
{ QString x; x.sprintf(args); QString output = "WARNING: " + x + "\n";
log(output); } else { CHANGE_COLOR_YELLOW; printf("WARNING: "); printf(args);
CHANGE_COLOR_WHITE; printf("\n"); } }
-#define PWARN2(args...) { using namespace Debugger; if
(get_debug_level()>=FLOOD) { if (is_logging()) { QString x; x.sprintf(args);
QString output = "WARNING: " + x + "\n"; log(output); } else {
CHANGE_COLOR_YELLOW; printf("WARNING: "); printf(args); CHANGE_COLOR_WHITE;
printf("\n"); } } }
-
-
-#define PENTER FunctionEnter enter(Debugger::BASIC, __FILE__,
__FUNCTION__)
-#define PENTER2 FunctionEnter enter(Debugger::FLOOD,
__FILE__, __FUNCTION__)
-#define PENTER3 FunctionEnter
enter(Debugger::SUPER_FLOOD, __FILE__, __FUNCTION__)
-#define PENTER4 FunctionEnter enter(Debugger::ALL,
__FILE__, __FUNCTION__)
-
-#define PENTERCONS ConstructorEnter enter(Debugger::BASIC,
__FILE__, __FUNCTION__)
-#define PENTERDES DestructorEnter enter(Debugger::BASIC,
__FILE__, __FUNCTION__)
-#define PENTERCONS2 ConstructorEnter enter(Debugger::FLOOD,
__FILE__, __FUNCTION__)
-#define PENTERDES2 DestructorEnter enter(Debugger::FLOOD,
__FILE__, __FUNCTION__)
-#define PENTERCONS3 ConstructorEnter enter(Debugger::SUPER_FLOOD,
__FILE__, __FUNCTION__)
-#define PENTERDES3 DestructorEnter enter(Debugger::SUPER_FLOOD,
__FILE__, __FUNCTION__)
-#define PENTERCONS4 ConstructorEnter enter(Debugger::ALL, __FILE__,
__FUNCTION__)
-#define PENTERDES4 DestructorEnter enter(Debugger::ALL,
__FILE__, __FUNCTION__)
-
-#else
-
-#define PMESG(args...)
-#define PMESG2(args...)
-#define PMESG3(args...)
-#define PMESG4(args...)
-
-#define PMESG_START(args...)
-#define PMESG_END(args...)
-#define PMESG2_START(args...)
-#define PMESG2_END(args...)
-
-#define PDEBUG(args...)
-#define PERROR(args...)
-#define PERROR2(args...)
-#define PWARN(args...)
-#define PWARN2(args...)
-#define PMARK(args...)
-
-#define PENTER
-#define PENTER2
-#define PENTER3
-#define PENTER4
-#define PENTERCONS
-#define PENTERDES
-#define PENTERCONS2
-#define PENTERDES2
-#define PENTERCONS3
-#define PENTERDES3
-#define PENTERCONS4
-#define PENTERDES4
-
-#endif
-/*!
- Debugger is a collection of macros that makes easier the job of debugging a
Application.
-
- PENTER - Outputs a message when entering a method in level 1. Used in the
FIRST line of a method;
- PEXIT - Outputs a message when leaving a method in level 1. Used in the LAST
line of a method,
- except if the last line is a return statement (in this case is put
immediately before
- the return statement
- PENTER2 - Same as PENTER for levels 1 and 2
- PEXIT2 - Same as PEXIT for levels 1 and 2
- PENTER3 - Same as PENTER for levels 1 2 and 3
- PEXIT3 - Same as PEXIT for levels 1 2 and 3
- PENTER4 - Same as PENTER for levels 1 2 3 and 4
- PEXIT4 - Same as PEXIT for levels 1 2 3 and 4
- PMESG(message) - Outputs a message in level 1
- PMESG2(message) - Outputs a message in level 1 and 2
- PENTERCONS - Outputs a message when entering a constructor in levels 2, 3,
and 4. Similar to PENTER
- PEXITCONS - Outputs a message when leaving a constructor in levels 2, 3, and
4. Similar to PEXIT
- PENTERDES - Outputs a message when entering a destructor in levels 2, 3, and
4. Similar to PENTER
- PEXITDES - Outputs a message when leaving a destructor in levels 2, 3, and
4. Similar to PEXIT
- Same can be done for PENTERCONS2, PEXITCONS2, PENTERCONS3... and so on...
- */
-
-namespace Debugger
- {
- static const int OFF = 0; //< no debug output at all
- static const int BASIC = 1; //< only level 1 calls
- static const int FLOOD = 2; //< level 1 , level 2 and
constructors/destructor calls
- static const int SUPER_FLOOD = 3; //< all previous plus low level JMB
messages
- static const int ALL = 4; //< all messages (including in timer
loops)
-
- //! Used internally by Debugger. Align the output with the level of
execution in a given moment
- void fill_tabs();
-
- //! Used internally by Debugger. Get a " " (space) sequence whch
aligns the output with the level of execution in a given moment,
- QString get_tabs();
-
-
- //! Used internally by Debugger. Increase one level of execution in
output messages
- void more_tabs();
-
- //! Used internally by Debugger. Decrease one level of execution in
output messages
- void less_tabs();
-
- //! Set the debug level
- void set_debug_level(int l);
-
- //! Used internally by Debugger. Returns true if debugOn flag is true.
- int get_debug_level();
-
- //! create a log file "fn" under home dir and enable copy of all
debugging messagem to this file.
- void create_log(QString fn);
-
- //! close the log file
- void close_log();
-
- //! Used internally by Debugger. Feed the log file.
- void log(QString msg);
-
- //! Used internally to check if output is stdout or a log file
- bool is_logging();
- }
-
-
-#endif // DEBUGGER_H ///:~
-
-
-
-
-//: C02:MemCheck.h
-// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
-// (c) 1995-2004 MindView, Inc. All Rights Reserved.
-// See source code use permissions stated in the file 'License.txt',
-// distributed with the code package available at www.MindView.net.
-#ifndef MEMCHECK_H
-#define MEMCHECK_H
-#include <cstddef> // For size_t
-
-#if defined (USE_MEM_CHECKER)
-
-// Usurp the new operator (both scalar and array versions)
-void* operator new(std::size_t, const char*, long);
-void* operator new[](std::size_t, const char*, long);
-#define new new (__FILE__, __LINE__)
-
-extern bool traceFlag;
-#define TRACE_ON() traceFlag = true
-#define TRACE_OFF() traceFlag = false
-
-extern bool activeFlag;
-#define MEM_ON() activeFlag = true
-#define MEM_OFF() activeFlag = false
-
-
-#else
-
-#define TRACE_OFF()
-#define TRACE_ON()
-#define MEM_OFF()
-#define MEM_ON()
-
-#endif // MEMCHECK_H ///:~
-
-
-#endif //USE_MEM_CHECKER ///:~
Index: core/RingBuffer.cpp
===================================================================
RCS file: core/RingBuffer.cpp
diff -N core/RingBuffer.cpp
--- core/RingBuffer.cpp 17 Apr 2007 19:56:46 -0000 1.6
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,359 +0,0 @@
-/*
- Copyright (C) 2006 Remon Sijrier
- Ported to C++ for use in Traverso
-
- Copyright (C) 2000 Paul Davis
- Copyright (C) 2003 Rohan Drape
-
- This file is part of Traverso
-
- Traverso is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code.
- This is safe for the case of one read thread and one write thread.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#ifdef USE_MLOCK
-
-#ifdef Q_WS_MAC
-#include <sys/types.h>
-#endif /* Q_WS_MAC */
-
-#include <sys/mman.h>
-#endif /* USE_MLOCK */
-
-#include "RingBuffer.h"
-
-// Always put me below _all_ includes, this is needed
-// in case we run with memory leak detection enabled!
-#include "Debugger.h"
-
-
-/* Create a new ringbuffer to hold at least `sz' bytes of data. The
- actual buffer size is rounded up to the next power of two. */
-
-RingBuffer::RingBuffer(size_t sz)
-{
- int power_of_two;
-
- for (power_of_two = 1; 1 << power_of_two < (int)sz; power_of_two++)
- ;
-
- size = 1 << power_of_two;
- size_mask = size;
- size_mask -= 1;
- write_ptr = 0;
- read_ptr = 0;
- buf = new char[size];
-
- mlocked = 0;
- if (mlock_buffer() < 0) {
- PERROR("Failed to memory lock buffer!");
- }
-}
-
-
-RingBuffer::~RingBuffer()
-{
-#ifdef USE_MLOCK
- if (mlocked) {
- munlock (buf, size);
- }
-#endif /* USE_MLOCK */
- delete [] buf;
-}
-
-/* Lock the data block using the system call 'mlock'. */
-
-int RingBuffer::mlock_buffer()
-{
-#if defined (USE_MLOCK)
- if (mlock (buf, size)) {
- printf("Unable to lock memory\n");
- return -1;
- }
- mlocked = 1;
-#endif /* USE_MLOCK */
-
- return 0;
-}
-
-/* Reset the read and write pointers to zero. This is not thread
- safe. */
-
-void RingBuffer::reset ()
-{
- read_ptr = 0;
- write_ptr = 0;
-}
-
-/* Return the number of bytes available for reading. This is the
- number of bytes in front of the read pointer and behind the write
- pointer. */
-
-size_t RingBuffer::read_space ()
-{
- size_t w, r;
-
- w = write_ptr;
- r = read_ptr;
-
- if (w > r) {
- return w - r;
- } else {
- return (w - r + size) & size_mask;
- }
-}
-
-/* Return the number of bytes available for writing. This is the
- number of bytes in front of the write pointer and behind the read
- pointer. */
-
-size_t RingBuffer::write_space ()
-{
- size_t w, r;
-
- w = write_ptr;
- r = read_ptr;
-
- if (w > r) {
- return ((r - w + size) & size_mask) - 1;
- } else if (w < r) {
- return (r - w) - 1;
- } else {
- return size - 1;
- }
-}
-
-/* The copying data reader. Copy at most `cnt' bytes to
- `dest'. Returns the actual number of bytes copied. */
-
-size_t RingBuffer::read (char *dest, size_t cnt)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t to_read;
- size_t n1, n2;
-
- if ( ( free_cnt = read_space () ) == 0) {
- return 0;
- }
-
- to_read = cnt > free_cnt ? free_cnt : cnt;
-
- cnt2 = read_ptr + to_read;
-
- if (cnt2 > size) {
- n1 = size - read_ptr;
- n2 = cnt2 & size_mask;
- } else {
- n1 = to_read;
- n2 = 0;
- }
-
- memcpy (dest, &(buf[read_ptr]), n1 * sizeof(char));
- read_ptr += n1;
- read_ptr &= size_mask;
-
- if (n2) {
- memcpy (dest + n1, &(buf[read_ptr]), n2 * sizeof(char));
- read_ptr += n2;
- read_ptr &= size_mask;
- }
-
- return to_read;
-}
-
-/* The copying data reader w/o read pointer advance. Copy at most
- `cnt' bytes from `dest'. Returns the actual number of bytes copied. */
-
-size_t RingBuffer::peek (char *dest, size_t cnt)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t to_read;
- size_t n1, n2;
- size_t tmp_read_ptr;
-
- tmp_read_ptr = read_ptr;
-
- if ((free_cnt = read_space ()) == 0) {
- return 0;
- }
-
- to_read = cnt > free_cnt ? free_cnt : cnt;
-
- cnt2 = tmp_read_ptr + to_read;
-
- if (cnt2 > size) {
- n1 = size - tmp_read_ptr;
- n2 = cnt2 & size_mask;
- } else {
- n1 = to_read;
- n2 = 0;
- }
-
- memcpy (dest, &(buf[tmp_read_ptr]), n1);
- tmp_read_ptr += n1;
- tmp_read_ptr &= size_mask;
-
- if (n2) {
- memcpy (dest + n1, &(buf[tmp_read_ptr]), n2);
- tmp_read_ptr += n2;
- tmp_read_ptr &= size_mask;
- }
-
- return to_read;
-}
-
-
-/* The copying data writer. Copy at most `cnt' bytes to `rb' from
- `src'. Returns the actual number of bytes copied. */
-
-size_t RingBuffer::write (const char *src, size_t cnt)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t to_write;
- size_t n1, n2;
-
- if ((free_cnt = write_space ()) == 0) {
- return 0;
- }
-
- to_write = cnt > free_cnt ? free_cnt : cnt;
-
- cnt2 = write_ptr + to_write;
-
- if (cnt2 > size) {
- n1 = size - write_ptr;
- n2 = cnt2 & size_mask;
- } else {
- n1 = to_write;
- n2 = 0;
- }
-
- memcpy (&(buf[write_ptr]), src, n1 * sizeof(char));
- write_ptr += n1;
- write_ptr &= size_mask;
-
- if (n2) {
- memcpy (&(buf[write_ptr]), src + n1, n2 * sizeof(char));
- write_ptr += n2;
- write_ptr &= size_mask;
- }
-
- return to_write;
-}
-
-/* Advance the read pointer `cnt' places. */
-
-void RingBuffer::read_advance (size_t cnt)
-{
- read_ptr += cnt;
- read_ptr &= size_mask;
-}
-
-/* Advance the write pointer `cnt' places. */
-
-void RingBuffer::write_advance (size_t cnt)
-{
- write_ptr += cnt;
- write_ptr &= size_mask;
-}
-
-/* The non-copying data reader. `vec' is an array of two places. Set
- the values at `vec' to hold the current readable data'. If the readable
- data is in one segment the second segment has zero length. */
-
-void RingBuffer::get_read_vector (ringbuffer_data_t * vec)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t w, r;
-
- w = write_ptr;
- r = read_ptr;
-
- if (w > r) {
- free_cnt = w - r;
- } else {
- free_cnt = (w - r + size) & size_mask;
- }
-
- cnt2 = r + free_cnt;
-
- if (cnt2 > size) {
-
- /* Two part vector: the rest of the buffer after the current
write
- ptr, plus some from the start of the buffer. */
-
- vec[0].buf = &(buf[r]);
- vec[0].len = size - r;
- vec[1].buf = buf;
- vec[1].len = cnt2 & size_mask;
-
- } else {
-
- /* Single part vector: just the rest of the buffer */
-
- vec[0].buf = &(buf[r]);
- vec[0].len = free_cnt;
- vec[1].len = 0;
- }
-}
-
-/* The non-copying data writer. `vec' is an array of two places. Set
- the values at `vec' to hold the current writeable data. If the writeable
- data is in one segment the second segment has zero length. */
-
-void RingBuffer::get_write_vector (ringbuffer_data_t * vec)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t w, r;
-
- w = write_ptr;
- r = read_ptr;
-
- if (w > r) {
- free_cnt = ((r - w + size) & size_mask) - 1;
- } else if (w < r) {
- free_cnt = (r - w) - 1;
- } else {
- free_cnt = size - 1;
- }
-
- cnt2 = w + free_cnt;
-
- if (cnt2 > size) {
-
- /* Two part vector: the rest of the buffer after the current
write
- ptr, plus some from the start of the buffer. */
-
- vec[0].buf = &(buf[w]);
- vec[0].len = size - w;
- vec[1].buf = buf;
- vec[1].len = cnt2 & size_mask;
- } else {
- vec[0].buf = &(buf[w]);
- vec[0].len = free_cnt;
- vec[1].len = 0;
- }
-}
-
-//eof
Index: core/RingBuffer.h
===================================================================
RCS file: core/RingBuffer.h
diff -N core/RingBuffer.h
--- core/RingBuffer.h 31 Aug 2006 12:38:35 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,198 +0,0 @@
-/*
- Copyright (C) 2006 Remon Sijrier
- Ported to C++ for use in Traverso
-
- Copyright (C) 2000 Paul Davis
- Copyright (C) 2003 Rohan Drape
-
- This file is part of Traverso
-
- Traverso is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- $Id: RingBuffer.h,v 1.3 2006/08/31 12:38:35 r_sijrier Exp $
-*/
-
-#ifndef _RINGBUFFER_H
-#define _RINGBUFFER_H
-
-
-#include <sys/types.h>
-#include "defines.h"
-
-
-typedef struct
-{
- char *buf;
- size_t len;
-}
-ringbuffer_data_t ;
-
-
-/**
-* The key attribute of a ringbuffer is that it can be safely accessed
-* by two threads simultaneously -- one reading from the buffer and
-* the other writing to it -- without using any synchronization or
-* mutual exclusion primitives. For this to work correctly, there can
-* only be a single reader and a single writer thread. Their
-* identities cannot be interchanged.
-*/
-class RingBuffer
-{
-
-public:
- RingBuffer(size_t size);
- ~RingBuffer();
-
- /**
- * Fill a data structure with a description of the current readable
- * data held in the ringbuffer. This description is returned in a two
- * element array of ringbuffer_data_t. Two elements are needed
- * because the data to be read may be split across the end of the
- * ringbuffer.
- *
- * The first element will always contain a valid @a len field, which
- * may be zero or greater. If the @a len field is non-zero, then data
- * can be read in a contiguous fashion using the address given in the
- * corresponding @a buf field.
- *
- * If the second element has a non-zero @a len field, then a second
- * contiguous stretch of data can be read from the address given in
- * its corresponding @a buf field.
- *
- * @param vec a pointer to a 2 element array of ringbuffer_data_t.
- *
- */
- void get_read_vector(ringbuffer_data_t *vec);
-
- /**
- * Fill a data structure with a description of the current writable
- * space in the ringbuffer. The description is returned in a two
- * element array of ringbuffer_data_t. Two elements are needed
- * because the space available for writing may be split across the end
- * of the ringbuffer.
- *
- * The first element will always contain a valid @a len field, which
- * may be zero or greater. If the @a len field is non-zero, then data
- * can be written in a contiguous fashion using the address given in
- * the corresponding @a buf field.
- *
- * If the second element has a non-zero @a len field, then a second
- * contiguous stretch of data can be written to the address given in
- * the corresponding @a buf field.
- *
- * @param vec a pointer to a 2 element array of ringbuffer_data_t.
- */
- void get_write_vector(ringbuffer_data_t *vec);
-
- /**
- * Read data from the ringbuffer.
- *
- * @param dest a pointer to a buffer where data read from the
- * ringbuffer will go.
- * @param cnt the number of bytes to read.
- *
- * @return the number of bytes read, which may range from 0 to cnt.
- */
- size_t read(char *dest, size_t cnt);
-
- /**
- * Read data from the ringbuffer. Opposed to read()
- * this function does not move the read pointer. Thus it's
- * a convenient way to inspect data in the ringbuffer in a
- * continous fashion. The price is that the data is copied
- * into a user provided buffer. For "raw" non-copy inspection
- * of the data in the ringbuffer use get_read_vector().
- *
- * @param dest a pointer to a buffer where data read from the
- * ringbuffer will go.
- * @param cnt the number of bytes to read.
- *
- * @return the number of bytes read, which may range from 0 to cnt.
- */
- size_t peek(char *dest, size_t cnt);
-
- /**
- * Advance the read pointer.
- *
- * After data have been read from the ringbuffer using the pointers
- * returned by get_read_vector(), use this function to
- * advance the buffer pointers, making that space available for future
- * write operations.
- *
- * @param cnt the number of bytes read.
- */
- void read_advance(size_t cnt);
-
- /**
- * Return the number of bytes available for reading.
- *
- * @return the number of bytes available to read.
- */
- size_t read_space();
-
- /**
- * Lock a ringbuffer data block into memory.
- *
- * Uses the mlock() system call. This is not a realtime operation.
- */
- int mlock_buffer();
-
- /**
- * Reset the read and write pointers, making an empty buffer.
- *
- * This is not thread safe.
- */
- void reset();
-
- /**
- * Write data into the ringbuffer.
- *
- * @param src a pointer to the data to be written to the ringbuffer.
- * @param cnt the number of bytes to write.
- *
- * @return the number of bytes write, which may range from 0 to cnt
- */
- size_t write(const char *src, size_t cnt);
-
- /**
- * Advance the write pointer.
- *
- * After data have been written the ringbuffer using the pointers
- * returned by get_write_vector(), use this function
- * to advance the buffer pointer, making the data available for future
- * read operations.
- *
- * @param cnt the number of bytes written.
- */
- void write_advance(size_t cnt);
-
- /**
- * Return the number of bytes available for writing.
- *
- * @return the amount of free space (in bytes) available for writing.
- */
- size_t write_space();
-
-private:
- char *buf;
- volatile size_t write_ptr;
- volatile size_t read_ptr;
- size_t size;
- size_t size_mask;
- int mlocked;
-
-};
-
-#endif
Index: core/RingBufferNPT.h
===================================================================
RCS file: core/RingBufferNPT.h
diff -N core/RingBufferNPT.h
--- core/RingBufferNPT.h 22 Jun 2007 12:29:28 -0000 1.5
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,287 +0,0 @@
-/*
- Copyright (C) 2000 Paul Davis & Benno Senoner
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id: RingBufferNPT.h,v 1.5 2007/06/22 12:29:28 r_sijrier Exp $
-*/
-
-#ifndef ringbuffer_npt_h
-#define ringbuffer_npt_h
-
-#include <stdio.h>
-
-#if ! defined (Q_WS_WIN)
-#include <sys/mman.h>
-#endif
-
-#include "defines.h"
-
-/* ringbuffer class where the element size is not required to be a power of
two */
-
-template<class T>
-class RingBufferNPT
-{
- public:
- RingBufferNPT (size_t sz) {
- size = sz;
- buf = new T[size];
-#ifdef USE_MLOCK
- if (mlock (buf, size)) {
- printf("Unable to lock memory\n");
- }
-#endif /* USE_MLOCK */
- reset ();
-
- };
-
- virtual ~RingBufferNPT() {
-#ifdef USE_MLOCK
- munlock (buf, size);
-#endif /* USE_MLOCK */
- delete [] buf;
- }
-
- void reset () {
- /* !!! NOT THREAD SAFE !!! */
- t_atomic_int_set (&write_ptr, 0);
- t_atomic_int_set (&read_ptr, 0);
- }
-
- void set (size_t r, size_t w) {
- /* !!! NOT THREAD SAFE !!! */
- t_atomic_int_set (&write_ptr, w);
- t_atomic_int_set (&read_ptr, r);
- }
-
- size_t read (T *dest, size_t cnt);
- size_t write (T *src, size_t cnt);
-
- struct rw_vector {
- T *buf[2];
- size_t len[2];
- };
-
- void get_read_vector (rw_vector *);
- void get_write_vector (rw_vector *);
-
- void decrement_read_ptr (size_t cnt) {
- t_atomic_int_set (&read_ptr, (t_atomic_int_get(&read_ptr) -
cnt) % size);
- }
-
- void increment_read_ptr (size_t cnt) {
- t_atomic_int_set (&read_ptr, (t_atomic_int_get(&read_ptr) +
cnt) % size);
- }
-
- void increment_write_ptr (size_t cnt) {
- t_atomic_int_set (&write_ptr, (t_atomic_int_get(&write_ptr) +
cnt) % size);
- }
-
- size_t write_space () {
- size_t w, r;
-
- w = t_atomic_int_get (&write_ptr);
- r = t_atomic_int_get (&read_ptr);
-
- if (w > r) {
- return ((r - w + size) % size) - 1;
- } else if (w < r) {
- return (r - w) - 1;
- } else {
- return size - 1;
- }
- }
-
- size_t read_space () {
- size_t w, r;
-
- w = t_atomic_int_get (&write_ptr);
- r = t_atomic_int_get (&read_ptr);
-
- if (w > r) {
- return w - r;
- } else {
- return (w - r + size) % size;
- }
- }
-
- T *buffer () { return buf; }
- size_t get_write_ptr () const { return t_atomic_int_get (&write_ptr); }
- size_t get_read_ptr () const { return t_atomic_int_get (&read_ptr); }
- size_t bufsize () const { return size; }
-
- protected:
- T *buf;
- size_t size;
- mutable volatile int write_ptr;
- mutable volatile int read_ptr;
-};
-
-template<class T> size_t
-RingBufferNPT<T>::read (T *dest, size_t cnt)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t to_read;
- size_t n1, n2;
- size_t priv_read_ptr;
-
- priv_read_ptr=t_atomic_int_get(&read_ptr);
-
- if ((free_cnt = read_space ()) == 0) {
- return 0;
- }
-
- to_read = cnt > free_cnt ? free_cnt : cnt;
-
- cnt2 = priv_read_ptr + to_read;
-
- if (cnt2 > size) {
- n1 = size - priv_read_ptr;
- n2 = cnt2 % size;
- } else {
- n1 = to_read;
- n2 = 0;
- }
-
- memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
- priv_read_ptr = (priv_read_ptr + n1) % size;
-
- if (n2) {
- memcpy (dest+n1, buf, n2 * sizeof (T));
- priv_read_ptr = n2;
- }
-
- t_atomic_int_set(&read_ptr, priv_read_ptr);
- return to_read;
-}
-
-template<class T> size_t
-RingBufferNPT<T>::write (T *src, size_t cnt)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t to_write;
- size_t n1, n2;
- size_t priv_write_ptr;
-
- priv_write_ptr=t_atomic_int_get(&write_ptr);
-
- if ((free_cnt = write_space ()) == 0) {
- return 0;
- }
-
- to_write = cnt > free_cnt ? free_cnt : cnt;
-
- cnt2 = priv_write_ptr + to_write;
-
- if (cnt2 > size) {
- n1 = size - priv_write_ptr;
- n2 = cnt2 % size;
- } else {
- n1 = to_write;
- n2 = 0;
- }
-
- memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
- priv_write_ptr = (priv_write_ptr + n1) % size;
-
- if (n2) {
- memcpy (buf, src+n1, n2 * sizeof (T));
- priv_write_ptr = n2;
- }
-
- t_atomic_int_set(&write_ptr, priv_write_ptr);
- return to_write;
-}
-
-template<class T> void
-RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t w, r;
-
- w = t_atomic_int_get (&write_ptr);
- r = t_atomic_int_get (&read_ptr);
-
- if (w > r) {
- free_cnt = w - r;
- } else {
- free_cnt = (w - r + size) % size;
- }
-
- cnt2 = r + free_cnt;
-
- if (cnt2 > size) {
- /* Two part vector: the rest of the buffer after the
- current write ptr, plus some from the start of
- the buffer.
- */
-
- vec->buf[0] = &buf[r];
- vec->len[0] = size - r;
- vec->buf[1] = buf;
- vec->len[1] = cnt2 % size;
-
- } else {
-
- /* Single part vector: just the rest of the buffer */
-
- vec->buf[0] = &buf[r];
- vec->len[0] = free_cnt;
- vec->len[1] = 0;
- }
-}
-
-template<class T> void
-RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec)
-{
- size_t free_cnt;
- size_t cnt2;
- size_t w, r;
-
- w = t_atomic_int_get (&write_ptr);
- r = t_atomic_int_get (&read_ptr);
-
- if (w > r) {
- free_cnt = ((r - w + size) % size) - 1;
- } else if (w < r) {
- free_cnt = (r - w) - 1;
- } else {
- free_cnt = size - 1;
- }
-
- cnt2 = w + free_cnt;
-
- if (cnt2 > size) {
-
- /* Two part vector: the rest of the buffer after the
- current write ptr, plus some from the start of
- the buffer.
- */
-
- vec->buf[0] = &buf[w];
- vec->len[0] = size - w;
- vec->buf[1] = buf;
- vec->len[1] = cnt2 % size;
- } else {
- vec->buf[0] = &buf[w];
- vec->len[0] = free_cnt;
- vec->len[1] = 0;
- }
-}
-
-#endif /* __ringbuffer_npt_h__ */
Index: core/Utils.cpp
===================================================================
RCS file: core/Utils.cpp
diff -N core/Utils.cpp
--- core/Utils.cpp 20 Oct 2007 13:09:27 -0000 1.23
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,198 +0,0 @@
-/*
- Copyright (C) 2005-2007 Remon Sijrier
-
- This file is part of Traverso
-
- Traverso is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-*/
-
-#include "Utils.h"
-#include "Mixer.h"
-
-#include <QString>
-#include <QStringList>
-#include <QDateTime>
-#include <QPixmapCache>
-#include <QRegExp>
-#include <QLocale>
-#include <QChar>
-
-
-TimeRef msms_to_timeref(QString str)
-{
- TimeRef out;
- QStringList lst = str.simplified().split(QRegExp("[;,.:]"),
QString::SkipEmptyParts);
-
- if (lst.size() >= 1) out += TimeRef(lst.at(0).toInt() *
ONE_MINUTE_UNIVERSAL_SAMPLE_RATE);
- if (lst.size() >= 2) out += TimeRef(lst.at(1).toInt() *
UNIVERSAL_SAMPLE_RATE);
- if (lst.size() >= 3) out += TimeRef(lst.at(2).toInt() *
UNIVERSAL_SAMPLE_RATE / 1000);
-
- return out;
-}
-
-TimeRef cd_to_timeref(QString str)
-{
- TimeRef out;
- QStringList lst = str.simplified().split(QRegExp("[;,.:]"),
QString::SkipEmptyParts);
-
- if (lst.size() >= 1) out += TimeRef(lst.at(0).toInt() *
ONE_MINUTE_UNIVERSAL_SAMPLE_RATE);
- if (lst.size() >= 2) out += TimeRef(lst.at(1).toInt() *
UNIVERSAL_SAMPLE_RATE);
- if (lst.size() >= 3) out += TimeRef(lst.at(2).toInt() *
UNIVERSAL_SAMPLE_RATE / 75);
-
- return out;
-}
-
-QString coefficient_to_dbstring ( float coeff )
-{
- float db = coefficient_to_dB ( coeff );
-
- QString gainIndB;
-
- if ( db < -99 )
- gainIndB = "- INF";
- else if ( db < 0 )
- gainIndB = "- " + QByteArray::number ( ( -1 * db ), 'f', 1 ) +
" dB";
- else
- gainIndB = "+ " + QByteArray::number ( db, 'f', 1 ) + " dB";
-
- return gainIndB;
-}
-
-qint64 create_id( )
-{
- int r = rand();
- QDateTime time = QDateTime::currentDateTime();
- uint timeValue = time.toTime_t();
- qint64 id = timeValue;
- id *= 1000000000;
- id += r;
-
- return id;
-}
-
-QDateTime extract_date_time(qint64 id)
-{
- QDateTime time;
- time.setTime_t(id / 1000000000);
- return time;
-}
-
-QPixmap find_pixmap ( const QString & pixname )
-{
- QPixmap pixmap;
-
- if ( ! QPixmapCache::find ( pixname, pixmap ) )
- {
- pixmap = QPixmap ( pixname );
- QPixmapCache::insert ( pixname, pixmap );
- }
-
- return pixmap;
-}
-
-QString timeref_to_hms(const TimeRef& ref)
-{
- qint64 remainder;
- int hours, mins, secs;
-
- qint64 universalframe = ref.universal_frame();
-
- hours = (int) (universalframe / ONE_HOUR_UNIVERSAL_SAMPLE_RATE);
- remainder = (long unsigned int) (universalframe - (hours *
ONE_HOUR_UNIVERSAL_SAMPLE_RATE));
- mins = (int) (remainder / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE ));
- remainder -= mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE;
- secs = (int) (remainder / UNIVERSAL_SAMPLE_RATE);
- return QString().sprintf("%02d:%02d:%02d", hours, mins, secs);
-}
-
-QString timeref_to_ms(const TimeRef& ref)
-{
- long unsigned int remainder;
- int mins, secs;
-
- qint64 universalframe = ref.universal_frame();
-
- mins = (int) (universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE ));
- remainder = (long unsigned int) (universalframe - (mins *
ONE_MINUTE_UNIVERSAL_SAMPLE_RATE));
- secs = (int) (remainder / UNIVERSAL_SAMPLE_RATE);
- return QString().sprintf("%02d:%02d", mins, secs);
-}
-
-// TimeRef to MM:SS.99 (hundredths)
-QString timeref_to_ms_2 (const TimeRef& ref)
-{
- QString spos;
- long unsigned int remainder;
- int mins, secs, frames;
-
- qint64 universalframe = ref.universal_frame();
-
- mins = universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE );
- remainder = universalframe - ( mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE
);
- secs = remainder / UNIVERSAL_SAMPLE_RATE;
- remainder -= secs * UNIVERSAL_SAMPLE_RATE;
- frames = remainder * 100 / UNIVERSAL_SAMPLE_RATE;
- spos.sprintf ( " %02d:%02d%c%02d", mins, secs,
QLocale::system().decimalPoint().toAscii(), frames );
-
- return spos;
-}
-
-// TimeRef to MM:SS.999 (ms)
-QString timeref_to_ms_3(const TimeRef& ref)
-{
- QString spos;
- long unsigned int remainder;
- int mins, secs, frames;
-
- qint64 universalframe = ref.universal_frame();
-
- mins = universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE );
- remainder = universalframe - ( mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE
);
- secs = remainder / UNIVERSAL_SAMPLE_RATE;
- remainder -= secs * UNIVERSAL_SAMPLE_RATE;
- frames = remainder * 1000 / UNIVERSAL_SAMPLE_RATE;
- spos.sprintf ( " %02d:%02d%c%03d", mins, secs,
QLocale::system().decimalPoint().toAscii(), frames );
-
- return spos;
-}
-
-// Frame to MM:SS:75 (75ths of a second, for CD burning)
-QString timeref_to_cd (const TimeRef& ref)
-{
- QString spos;
- long unsigned int remainder;
- int mins, secs, frames;
-
- qint64 universalframe = ref.universal_frame();
-
- mins = universalframe / ( ONE_MINUTE_UNIVERSAL_SAMPLE_RATE );
- remainder = universalframe - ( mins * ONE_MINUTE_UNIVERSAL_SAMPLE_RATE
);
- secs = remainder / UNIVERSAL_SAMPLE_RATE;
- remainder -= secs * UNIVERSAL_SAMPLE_RATE;
- frames = remainder * 75 / UNIVERSAL_SAMPLE_RATE;
- spos.sprintf ( " %02d:%02d:%02d", mins, secs, frames );
-
- return spos;
-}
-
-QString timeref_to_text(const TimeRef & ref, int scalefactor)
-{
- if (scalefactor >= 512*640) {
- return timeref_to_ms_2(ref);
- } else {
- return timeref_to_ms_3(ref);
- }
-}
Index: core/Utils.h
===================================================================
RCS file: core/Utils.h
diff -N core/Utils.h
--- core/Utils.h 20 Oct 2007 13:09:27 -0000 1.17
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,54 +0,0 @@
-/*
- Copyright (C) 2005-2007 Remon Sijrier
-
- This file is part of Traverso
-
- Traverso is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-*/
-
-#ifndef UTILS_H
-#define UTILS_H
-
-#include "defines.h"
-#include <QPixmap>
-#include <QDateTime>
-
-#define QS_C(x) x.toAscii().data()
-
-class QString;
-
-QString timeref_to_hms(const TimeRef& ref);
-QString timeref_to_ms(const TimeRef& ref);
-QString timeref_to_ms_2 (const TimeRef& ref);
-QString timeref_to_ms_3 (const TimeRef& ref);
-QString timeref_to_text(const TimeRef& ref, int scalefactor);
-QString timeref_to_cd(const TimeRef& ref);
-
-TimeRef msms_to_timeref(QString str);
-TimeRef cd_to_timeref(QString str);
-QString coefficient_to_dbstring(float coeff);
-QDateTime extract_date_time(qint64 id);
-
-qint64 create_id();
-
-static inline unsigned int is_power_of_two (unsigned int n)
-{
- return !(n & (n - 1));
-}
-
-QPixmap find_pixmap(const QString& pixname);
-
-#endif
Index: engine/Tsar.cpp
===================================================================
RCS file: engine/Tsar.cpp
diff -N engine/Tsar.cpp
--- engine/Tsar.cpp 25 Jun 2007 13:32:28 -0000 1.9
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,319 +0,0 @@
-/*
-Copyright (C) 2006 Remon Sijrier
-
-This file is part of Traverso
-
-Traverso is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-$Id: Tsar.cpp,v 1.9 2007/06/25 13:32:28 r_sijrier Exp $
-*/
-
-#include "Tsar.h"
-
-#include "AudioDevice.h"
-#include <QMetaMethod>
-#include <QMessageBox>
-#include <QCoreApplication>
-#include <QThread>
-
-
-// Always put me below _all_ includes, this is needed
-// in case we run with memory leak detection enabled!
-#include "Debugger.h"
-
-/**
- * \class Tsar
- * \brief Tsar (Thread Save Add and Remove) is a singleton class to call
- * functions (both signals and slots) in a thread save way without
- * using any mutual exclusion primitives (mutex)
- *
- */
-
-
-/**
- *
- * @return The Tsar instance.
- */
-Tsar& tsar()
-{
- static Tsar ThreadSaveAddRemove;
- return ThreadSaveAddRemove;
-}
-
-Tsar::Tsar()
-{
- m_eventCounter = 0;
-
- m_events.append(new RingBufferNPT<TsarEvent>(1000));
- m_events.append(new RingBufferNPT<TsarEvent>(100));
- oldEvents = new RingBufferNPT<TsarEvent>(1000);
-
-#if defined (THREAD_CHECK)
- m_threadId = QThread::currentThreadId ();
-#endif
-
- connect(&finishOldEventsTimer, SIGNAL(timeout()), this,
SLOT(finish_processed_events()));
-
- finishOldEventsTimer.start( 20 );
-}
-
-Tsar::~ Tsar( )
-{
- foreach(RingBufferNPT<TsarEvent>* eventBuffer, m_events) {
- delete eventBuffer;
- }
- delete oldEvents;
-}
-
-/**
- * Use this function to add events to the event queue when
- * called from the GUI thread.
- *
- * Note: This function should be called ONLY from the GUI thread!
- * @param event The event to add to the event queue
- */
-void Tsar::add_event(TsarEvent& event )
-{
-#if defined (THREAD_CHECK)
- Q_ASSERT_X(m_threadId == QThread::currentThreadId (),
"Tsar::add_event", "Adding event from other then GUI thread!!");
-#endif
- m_events.at(0)->write(&event, 1);
- m_eventCounter++;
-}
-
-/**
- * Use this function to add events to the event queue when
- * called from the audio processing (real time) thread
- *
- * Note: This function should be called ONLY from the realtime audio
thread and has a
- * non blocking behaviour! (That is, it's a real time save function)
- *
- * @param event The event to add to the event queue
- */
-void Tsar::add_rt_event( TsarEvent& event )
-{
-#if defined (THREAD_CHECK)
- Q_ASSERT_X(m_threadId != QThread::currentThreadId (),
"Tsar::add_rt_event", "Adding event from NON-RT Thread!!");
-#endif
- m_events.at(1)->write(&event, 1);
-}
-
-//
-// Function called in RealTime AudioThread processing path
-//
-void Tsar::process_events( )
-{
-// #define profile
-
- for (int i=0; i<m_events.size(); ++i) {
- RingBufferNPT<TsarEvent>* newEvents = m_events.at(i);
-
- int processedCount = 0;
- int newEventCount = newEvents->read_space();
-
- while((newEventCount > 0) && (processedCount < 10)) {
-#if defined (profile)
- trav_time_t starttime = get_microseconds();
-#endif
- TsarEvent event;
-
- newEvents->read(&event, 1);
-
- process_event_slot(event);
-
- oldEvents->write(&event, 1);
-
- --newEventCount;
- ++processedCount;
-
-#if defined (profile)
- int processtime = (int) (get_microseconds() -
starttime);
- printf("called %s::%s, (signal: %s) \n",
event.caller->metaObject()->className(),
- (event.slotindex >= 0) ?
event.caller->metaObject()->method(event.slotindex).signature() : "",
- (event.signalindex >= 0) ?
event.caller->metaObject()->method(event.signalindex + 4).signature() : "");
- printf("Process time: %d useconds\n\n", processtime);
-#endif
- }
- }
-}
-
-void Tsar::finish_processed_events( )
-{
-
- while(oldEvents->read_space() >= 1 ) {
- TsarEvent event;
- // Read one TsarEvent from the processed events ringbuffer
'queue'
- oldEvents->read(&event, 1);
-
- process_event_signal(event);
-
- --m_eventCounter;
-// printf("finish_processed_objects:: Count is %d\n",
m_eventCounter);
- }
-
- static int retryCount;
-
- retryCount++;
-
- if (retryCount > 100) {
- if (audiodevice().get_driver_type() != "Null Driver") {
- QMessageBox::critical( 0,
- tr("Traverso - Malfunction!"),
- tr("The Audiodriver Thread seems to be
stalled/stopped, but Traverso didn't ask for it!\n"
- "This effectively makes Traverso unusable,
since it relies heavily on the AudioDriver Thread\n"
- "To ensure proper operation, Traverso will
fallback to the 'Null Driver'.\n"
- "Potential issues why this can show up are:
\n\n"
- "* You're not running with real time
privileges! Please make sure this is setup properly.\n\n"
- "* The audio chipset isn't supported
(completely), you probably have to turn off some of it's features.\n"
- "\nFor more information, see the Help file,
section: \n\n AudioDriver: 'Thread stalled error'\n\n"),
- "OK",
- 0 );
- audiodevice().set_parameters(44100, 1024, "Null
Driver", true, true);
- retryCount = 0;
- } else {
- QMessageBox::critical( 0,
- tr("Traverso - Fatal!"),
- tr("The Null AudioDriver stalled too, exiting
application!"),
- "OK",
- 0 );
- QCoreApplication::exit(-1);
- }
- }
-
- if (m_eventCounter <= 0) {
- retryCount = 0;
- }
-}
-
-/**
- * Creates a Tsar event. Add the tsar event to the event queue by calling
add_event()
- * If you need to add an event from the real time audio processing thread,
use
- * add_rt_event() instead!
- *
- * Note: This function can be called both from the GUI and realtime audio
thread and has a
- * non blocking behaviour! (That is, it's a real time save function)
- *
- * @param caller The calling object, needs to be derived from a QObject
- * @param argument The slot and/or signal argument which can be of any
type.
- * @param slotSignature The 'signature' of the calling objects slot (equals
the name of the slot function)
- * @param signalSignature The 'signature' of the calling objects signal
(equals the name of the signal function)
- * @return The newly created event.
- */
-TsarEvent Tsar::create_event( QObject* caller, void* argument, char*
slotSignature, char* signalSignature )
-{
- PENTER3;
- TsarEvent event;
- event.caller = caller;
- event.argument = argument;
- int index;
-
- if (qstrlen(slotSignature) > 0) {
- index = caller->metaObject()->indexOfMethod(slotSignature);
- if (index < 0) {
- PWARN("Slot signature contains whitespaces, please
remove to avoid unneeded processing (%s::%s)",
caller->metaObject()->className(), slotSignature);
- QByteArray norm =
QMetaObject::normalizedSignature(slotSignature);
- index =
caller->metaObject()->indexOfMethod(norm.constData());
- if (index < 0) {
- PERROR("Couldn't find a valid index for %s",
slotSignature);
- }
- }
- event.slotindex = index;
- } else {
- event.slotindex = -1;
- }
-
- if (qstrlen(signalSignature) > 0) {
- /* the signal index seems to have an offset of 4, so we have to
substract 4 from */
- /* the value returned by caller->metaObject()->indexOfMethod*/
- index = caller->metaObject()->indexOfMethod(signalSignature) -
4;
- if (index < 0) {
- PWARN("Signal signature contains whitespaces, please
remove to avoid unneeded processing (%s::%s)",
caller->metaObject()->className(), signalSignature);
- QByteArray norm =
QMetaObject::normalizedSignature(signalSignature);
- index =
caller->metaObject()->indexOfMethod(norm.constData()) - 4;
- }
- event.signalindex = index;
- } else {
- event.signalindex = -1;
- }
-
- event.valid = true;
-
- return event;
-}
-
-/**
-* This function can be used to process the events 'slot' part.
-* Usefull when you have a Tsar event, but don't want/need to use tsar
-* to call the events slot in a thread save way
-*
-* Note: This function doesn't provide the thread savetiness you get with
-* the add_event() function!
-*
-* @param event The TsarEvent to be processed
-*/
-void Tsar::process_event_slot(const TsarEvent& event )
-{
- // If there is an object to be added, do the magic to call the slot :-)
- if (event.slotindex > -1) {
-
- void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const
void*>(&event.argument)) };
-
- // This equals QMetaObject::invokeMethod(), without type
checking. But we know that the types
- // are the correct ones, and will be casted just fine!
- if ( !
(event.caller->qt_metacall(QMetaObject::InvokeMetaMethod, event.slotindex, _a)
< 0) ) {
- qDebug("Tsar::process_event_slot failed (%s::%s)",
event.caller->metaObject()->className(),
event.caller->metaObject()->method(event.slotindex).signature());
- }
- }
-}
-
-/**
-* This function can be used to process the events 'signal' part.
-* Usefull when you have a Tsar event, but don't want/need to use tsar
-* to call the events signal in a thread save way
-*
-* Note: This function doesn't provide the thread savetiness you get with
-* the add_event() function!
-*
-* @param event The TsarEvent to be processed
-*/
-void Tsar::process_event_signal(const TsarEvent & event )
-{
- // In case the signalindex > -1, emit the signal!
- if (event.signalindex > -1) {
- // This equals emit someSignal() :-)
- void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const
void*>(&event.argument)) };
- QMetaObject::activate(event.caller, event.caller->metaObject(),
event.signalindex, _a);
- }
-}
-
-/**
-* Convenience function. Calls both process_event_slot() and
process_event_signal()
-*
-* \sa process_event_slot() \sa process_event_signal()
-*
-* Note: This function doesn't provide the thread savetiness you get with
-* the add_event() function!
-*
-* @param event The TsarEvent to be processed
-*/
-void Tsar::process_event_slot_signal(const TsarEvent & event )
-{
- process_event_slot(event);
- process_event_signal(event);
-}
-
-
-//eof
-
Index: engine/Tsar.h
===================================================================
RCS file: engine/Tsar.h
diff -N engine/Tsar.h
--- engine/Tsar.h 25 Jun 2007 13:32:29 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,121 +0,0 @@
-/*
-Copyright (C) 2006 Remon Sijrier
-
-This file is part of Traverso
-
-Traverso is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-$Id: Tsar.h,v 1.2 2007/06/25 13:32:29 r_sijrier Exp $
-*/
-
-#ifndef TSAR_H
-#define TSAR_H
-
-#include <QObject>
-#include <QTimer>
-#include <QByteArray>
-#include "RingBufferNPT.h"
-
-#define THREAD_SAVE_INVOKE(caller, argument, slotSignature) { \
- TsarEvent event = tsar().create_event(caller, argument,
#slotSignature, ""); \
- tsar().add_event(event);\
- }
-
-#define RT_THREAD_EMIT(cal, arg, signalSignature) {\
- TsarEvent event; \
- event.caller = cal; \
- event.argument = arg; \
- event.slotindex = -1; \
- static int retrievedsignalindex; \
- \
- if ( ! retrievedsignalindex ) { \
- /* the signal index seems to have an offset of 4, so we have to
substract 4 from */ \
- /* the value returned by caller->metaObject()->indexOfMethod*/
\
- retrievedsignalindex =
cal->metaObject()->indexOfMethod(#signalSignature) - 4; \
- Q_ASSERT(retrievedsignalindex >= 0); \
- } \
- event.signalindex = retrievedsignalindex; \
- event.valid = true; \
- tsar().add_rt_event(event); \
-}\
-
-
-#define THREAD_SAVE_INVOKE_AND_EMIT_SIGNAL(caller, argument, slotSignature,
signalSignature) { \
- TsarEvent event = tsar().create_event(caller, argument, #slotSignature,
#signalSignature); \
- tsar().add_event(event);\
- }\
-
-
-struct TsarEvent {
-// used for slot invokation stuff
- QObject* caller;
- void* argument;
- int slotindex;
- void* _a[];
-
-// Used for the signal emiting stuff
- int signalindex;
-
- bool valid;
-};
-
-class Tsar : public QObject
-{
- Q_OBJECT
-
-public:
- TsarEvent create_event(QObject* caller, void* argument, char*
slotSignature, char* signalSignature);
-
- void add_event(TsarEvent& event);
- void add_rt_event(TsarEvent& event);
- void process_event_slot(const TsarEvent& event);
- void process_event_signal(const TsarEvent& event);
- void process_event_slot_signal(const TsarEvent& event);
-
-private:
- Tsar();
- ~Tsar();
- Tsar(const Tsar&);
-
- // allow this function to create one instance
- friend Tsar& tsar();
- // The AudioDevice instance is the _only_ one who
- // is allowed to call process_events() !!
- friend class AudioDevice;
-
- QList<RingBufferNPT<TsarEvent>*> m_events;
- RingBufferNPT<TsarEvent>* oldEvents;
- QTimer finishOldEventsTimer;
- int m_eventCounter;
-#if defined (THREAD_CHECK)
- unsigned long m_threadId;
-#endif
-
- void process_events();
-
-private slots:
- void finish_processed_events();
-
-};
-
-#endif
-
-// use this function to access the context pointer
-Tsar& tsar();
-
-//eof
-
-
-