summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/al
diff options
context:
space:
mode:
authorRobert Jonsson <spamatica@gmail.com>2009-12-27 11:30:35 +0000
committerRobert Jonsson <spamatica@gmail.com>2009-12-27 11:30:35 +0000
commitb703eab295330e6f81564fbb39a10a1a2fdd2f54 (patch)
treee46b5c9a6bc22fd661c15d1d2123f5bf631cef80 /muse_qt4_evolution/al
parent5d5fa0fdf913907edbc3d2d29a7548f0cb658c94 (diff)
moved old qt4 branch
Diffstat (limited to 'muse_qt4_evolution/al')
-rw-r--r--muse_qt4_evolution/al/CMakeLists.txt32
-rw-r--r--muse_qt4_evolution/al/al.cpp29
-rw-r--r--muse_qt4_evolution/al/al.h34
-rw-r--r--muse_qt4_evolution/al/dsp.cpp120
-rw-r--r--muse_qt4_evolution/al/dsp.h83
-rw-r--r--muse_qt4_evolution/al/dspSSE.cpp531
-rw-r--r--muse_qt4_evolution/al/dspXMM.cpp115
-rw-r--r--muse_qt4_evolution/al/marker.cpp86
-rw-r--r--muse_qt4_evolution/al/marker.h67
-rw-r--r--muse_qt4_evolution/al/pos.cpp616
-rw-r--r--muse_qt4_evolution/al/pos.h129
-rw-r--r--muse_qt4_evolution/al/sig.cpp407
-rw-r--r--muse_qt4_evolution/al/sig.h103
-rw-r--r--muse_qt4_evolution/al/tempo.cpp393
-rw-r--r--muse_qt4_evolution/al/tempo.h101
-rw-r--r--muse_qt4_evolution/al/xml.cpp362
-rw-r--r--muse_qt4_evolution/al/xml.h69
17 files changed, 3277 insertions, 0 deletions
diff --git a/muse_qt4_evolution/al/CMakeLists.txt b/muse_qt4_evolution/al/CMakeLists.txt
new file mode 100644
index 00000000..ef819f5c
--- /dev/null
+++ b/muse_qt4_evolution/al/CMakeLists.txt
@@ -0,0 +1,32 @@
+#
+#
+#
+#
+
+include(${PROJECT_SOURCE_DIR}/pch.txt)
+
+set (al_src
+ al.cpp marker.cpp pos.cpp sig.cpp tempo.cpp xml.cpp
+ dsp.cpp
+ )
+
+if (USE_SSE)
+ set(al_src ${al_src} dspSSE.cpp dspXMM.cpp)
+endif (USE_SSE)
+
+add_library(al STATIC
+ ${al_src}
+ ${PROJECT_BINARY_DIR}/all.h.pch
+ )
+
+set_source_files_properties(
+ al.cpp marker.cpp pos.cpp sig.cpp tempo.cpp xml.cpp
+ dsp.cpp
+ dspXMM.cpp
+ PROPERTIES COMPILE_FLAGS "-fPIC -include ${PROJECT_BINARY_DIR}/all.h"
+ )
+
+set_source_files_properties( dspSSE.cpp
+ PROPERTIES COMPILE_FLAGS "-x assembler"
+ )
+
diff --git a/muse_qt4_evolution/al/al.cpp b/muse_qt4_evolution/al/al.cpp
new file mode 100644
index 00000000..50a2299d
--- /dev/null
+++ b/muse_qt4_evolution/al/al.cpp
@@ -0,0 +1,29 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#include "al.h"
+
+namespace AL {
+ int sampleRate = 44100;
+ int mtcType = 0;
+ int division = 384;
+ bool debugMsg = false;
+ };
+
diff --git a/muse_qt4_evolution/al/al.h b/muse_qt4_evolution/al/al.h
new file mode 100644
index 00000000..d88d7c0d
--- /dev/null
+++ b/muse_qt4_evolution/al/al.h
@@ -0,0 +1,34 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#ifndef __AL_H__
+#define __AL_H__
+
+namespace AL {
+
+ extern bool debugMsg;
+ extern int sampleRate;
+ extern int mtcType;
+ extern int division;
+
+ }
+
+#endif
+
diff --git a/muse_qt4_evolution/al/dsp.cpp b/muse_qt4_evolution/al/dsp.cpp
new file mode 100644
index 00000000..7fb41fe7
--- /dev/null
+++ b/muse_qt4_evolution/al/dsp.cpp
@@ -0,0 +1,120 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#include "dsp.h"
+#include "config.h"
+
+namespace AL {
+
+Dsp* dsp;
+
+#ifdef __i386__
+
+//---------------------------------------------------------
+// DspSSE86
+//---------------------------------------------------------
+
+extern "C" {
+extern float x86_sse_compute_peak(float*, unsigned, float);
+extern void x86_sse_apply_gain_to_buffer(float*, unsigned, float);
+extern void x86_sse_mix_buffers_with_gain(float*, float*, unsigned, float);
+extern void x86_sse_mix_buffers_no_gain(float*, float*, unsigned);
+ };
+
+class DspSSE86 : public Dsp {
+ public:
+ DspSSE86() {}
+ virtual ~DspSSE86() {}
+
+ virtual float peak(float* buf, unsigned n, float current) {
+ if ( ((intptr_t)buf % 16) != 0) {
+ fprintf(stderr, "peak(): buffer unaligned! (%p)\n", buf);
+ return Dsp::peak(buf, n, current);
+ }
+ return x86_sse_compute_peak(buf, n, current);
+ }
+
+ virtual void applyGainToBuffer(float* buf, unsigned n, float gain) {
+ if ( ((intptr_t)buf % 16) != 0) {
+ fprintf(stderr, "applyGainToBuffer(): buffer unaligned! (%p)\n", buf);
+ Dsp::applyGainToBuffer(buf, n, gain);
+ }
+ else
+ x86_sse_apply_gain_to_buffer(buf, n, gain);
+ }
+
+ virtual void mixWithGain(float* dst, float* src, unsigned n, float gain) {
+ if ( ((intptr_t)dst & 15) != 0)
+ fprintf(stderr, "mixWithGainain(): dst unaligned! (%p)\n", dst);
+ if (((intptr_t)dst & 15) != ((intptr_t)src & 15) ) {
+ fprintf(stderr, "mixWithGain(): dst & src don't have the same alignment!\n");
+ Dsp::mixWithGain(dst, src,n, gain);
+ }
+ else
+ x86_sse_mix_buffers_with_gain(dst, src, n, gain);
+ }
+ virtual void mix(float* dst, float* src, unsigned n) {
+ if ( ((intptr_t)dst & 15) != 0)
+ fprintf(stderr, "mix_buffers_no_gain(): dst unaligned! %p\n", dst);
+ if ( ((intptr_t)dst & 15) != ((intptr_t)src & 15) ) {
+ fprintf(stderr, "mix_buffers_no_gain(): dst & src don't have the same alignment!\n");
+ Dsp::mix(dst, src, n);
+ }
+ else
+ x86_sse_mix_buffers_no_gain(dst, src, n);
+ }
+ };
+#endif
+
+//---------------------------------------------------------
+// initDsp
+//---------------------------------------------------------
+
+void initDsp()
+ {
+#if defined(__i386__) && defined(USE_SSE)
+ unsigned long useSSE = 0;
+
+#ifdef __x86_64__
+ useSSE = 1 << 25; // we know the platform has SSE
+#else
+ asm (
+ "mov $1, %%eax\n"
+ "pushl %%ebx\n"
+ "cpuid\n"
+ "movl %%edx, %0\n"
+ "popl %%ebx\n"
+ : "=r" (useSSE)
+ :
+ : "%eax", "%ecx", "%edx", "memory");
+#endif
+ useSSE &= (1 << 25); // bit 25 = SSE support
+ if (useSSE) {
+ printf("Using SSE optimized routines\n");
+ dsp = new DspSSE86();
+ return;
+ }
+ // fall through to not hardware optimized routines
+#endif
+ dsp = new Dsp();
+ }
+
+}
+
diff --git a/muse_qt4_evolution/al/dsp.h b/muse_qt4_evolution/al/dsp.h
new file mode 100644
index 00000000..6c7123ac
--- /dev/null
+++ b/muse_qt4_evolution/al/dsp.h
@@ -0,0 +1,83 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#ifndef __DSP_H__
+#define __DSP_H__
+
+namespace AL {
+
+//---------------------------------------------------------
+// f_max
+//---------------------------------------------------------
+
+static inline float f_max(float x, float a)
+ {
+ x -= a;
+ x += fabsf(x);
+ x *= 0.5f;
+ x += a;
+ return x;
+ }
+
+//---------------------------------------------------------
+// Dsp
+// standard version of all dsp routines without any
+// hw acceleration
+//---------------------------------------------------------
+
+class Dsp {
+ public:
+ Dsp() {}
+ virtual ~Dsp() {}
+
+ virtual float peak(float* buf, unsigned n, float current) {
+ for (unsigned i = 0; i < n; ++i)
+ current = f_max(current, fabsf(buf[i]));
+ return current;
+ }
+ virtual void applyGainToBuffer(float* buf, unsigned n, float gain) {
+ for (unsigned i = 0; i < n; ++i)
+ buf[i] *= gain;
+ }
+ virtual void mixWithGain(float* dst, float* src, unsigned n, float gain) {
+ for (unsigned i = 0; i < n; ++i)
+ dst[i] += src[i] * gain;
+ }
+ virtual void mix(float* dst, float* src, unsigned n) {
+ for (unsigned i = 0; i < n; ++i)
+ dst[i] += src[i];
+ }
+ virtual void cpy(float* dst, float* src, unsigned n) {
+#if defined(ARCH_X86) || defined(ARCH_X86_64)
+ register unsinged long int dummy;
+ __asm__ __volatile__ "rep; movsl" :"=&D"(dst), "=&S"(src), "=&c"(dummy) :"0" (to), "1" (from),"2" (n) : "memory");
+#else
+ memcpy(dst, src, sizeof(float) * n);
+#endif
+ }
+ };
+
+extern void initDsp();
+extern Dsp* dsp;
+
+}
+
+#endif
+
diff --git a/muse_qt4_evolution/al/dspSSE.cpp b/muse_qt4_evolution/al/dspSSE.cpp
new file mode 100644
index 00000000..0f3d84b9
--- /dev/null
+++ b/muse_qt4_evolution/al/dspSSE.cpp
@@ -0,0 +1,531 @@
+/*
+ Copyright (C) 2005 Paul Davis
+
+ 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.
+
+ Author: Sampo Savolainen
+
+ $Id: sse_functions.s 988 2006-10-17 20:40:39Z paul $
+*/
+
+
+#; void x86_sse_mix_buffers_with_gain (float *dst, float *src, long nframes, float gain);
+
+.globl x86_sse_mix_buffers_with_gain
+ .type x86_sse_mix_buffers_with_gain,@function
+
+x86_sse_mix_buffers_with_gain:
+#; 8(%ebp) = float *dst = %edi
+#; 12(%ebp) = float *src = %esi
+#; 16(%ebp) = long nframes = %ecx
+#; 20(%ebp) = float gain = st(0)
+
+ pushl %ebp
+ movl %esp, %ebp
+
+ #; save the registers
+#; pushl %eax
+ pushl %ebx
+#; pushl %ecx
+ pushl %edi
+ pushl %esi
+
+ #; if nframes == 0, go to end
+ movl 16(%ebp), %ecx #; nframes
+ cmp $0, %ecx
+ je .MBWG_END
+
+ #; Check for alignment
+
+ movl 8(%ebp), %edi #; dst
+ movl 12(%ebp), %esi #; src
+
+ movl %edi, %eax
+ andl $12, %eax #; mask alignemnt offset
+
+ movl %esi, %ebx
+ andl $12, %ebx #; mask alignment offset
+
+ cmp %eax, %ebx
+ jne .MBWG_NONALIGN #; if not aligned, calculate manually
+
+ #; if we are aligned
+ cmp $0, %ebx
+ jz .MBWG_SSE
+
+ #; Pre-loop, we need to run 1-3 frames "manually" without
+ #; SSE instructions
+
+ movss 20(%ebp), %xmm1 #; xmm1
+
+.MBWG_PRELOOP:
+
+ movss (%esi), %xmm0
+ mulss %xmm1, %xmm0
+ addss (%edi), %xmm0
+ movss %xmm0, (%edi)
+
+ addl $4, %edi #; dst++
+ addl $4, %esi #; src++
+ decl %ecx #; nframes--
+ jz .MBWG_END
+
+#; cmp $0, %ecx
+#; je .MBWG_END #; if we run out of frames, go to end
+
+ addl $4, %ebx
+
+ cmp $16, %ebx #; test if we've reached 16 byte alignment
+ jne .MBWG_PRELOOP
+
+
+.MBWG_SSE:
+
+ cmp $4, %ecx #; we know it's not zero, but if it's not >=4, then
+ jnge .MBWG_NONALIGN #; we jump straight to the "normal" code
+
+ #; copy gain to fill %xmm1
+ movss 20(%ebp), %xmm1
+ shufps $0x00, %xmm1, %xmm1
+
+
+.MBWG_SSELOOP:
+
+ movaps (%esi), %xmm0 #; source => xmm0
+ mulps %xmm1, %xmm0 #; apply gain to source
+ addps (%edi), %xmm0 #; mix with destination
+ movaps %xmm0, (%edi) #; copy result to destination
+
+ addl $16, %edi #; dst+=4
+ addl $16, %esi #; src+=4
+
+ subl $4, %ecx #; nframes-=4
+ cmp $4, %ecx
+ jge .MBWG_SSELOOP
+
+ cmp $0, %ecx
+ je .MBWG_END
+
+ #; if there are remaining frames, the nonalign code will do nicely
+ #; for the rest 1-3 frames.
+
+.MBWG_NONALIGN:
+ #; not aligned!
+
+ movss 20(%ebp), %xmm1 #; gain => xmm1
+
+.MBWG_NONALIGNLOOP:
+
+ movss (%esi), %xmm0
+ mulss %xmm1, %xmm0
+ addss (%edi), %xmm0
+ movss %xmm0, (%edi)
+
+ addl $4, %edi
+ addl $4, %esi
+
+ decl %ecx
+ jnz .MBWG_NONALIGNLOOP
+
+.MBWG_END:
+
+ popl %esi
+ popl %edi
+#; popl %ecx
+ popl %ebx
+#; popl %eax
+
+ #; return
+ leave
+ ret
+
+.size x86_sse_mix_buffers_with_gain, .-x86_sse_mix_buffers_with_gain
+
+
+
+
+#; void x86_sse_mix_buffers_no_gain (float *dst, float *src, long nframes);
+
+.globl x86_sse_mix_buffers_no_gain
+ .type x86_sse_mix_buffers_no_gain,@function
+
+x86_sse_mix_buffers_no_gain:
+#; 8(%ebp) = float *dst = %edi
+#; 12(%ebp) = float *src = %esi
+#; 16(%ebp) = long nframes = %ecx
+
+ pushl %ebp
+ movl %esp, %ebp
+
+ #; save the registers
+#; pushl %eax
+ pushl %ebx
+#; pushl %ecx
+ pushl %edi
+ pushl %esi
+
+ #; the real function
+
+ #; if nframes == 0, go to end
+ movl 16(%ebp), %ecx #; nframes
+ cmp $0, %ecx
+ je .MBNG_END
+
+ #; Check for alignment
+
+ movl 8(%ebp), %edi #; dst
+ movl 12(%ebp), %esi #; src
+
+ movl %edi, %eax
+ andl $12, %eax #; mask alignemnt offset
+
+ movl %esi, %ebx
+ andl $12, %ebx #; mask alignment offset
+
+ cmp %eax, %ebx
+ jne .MBNG_NONALIGN #; if not aligned, calculate manually
+
+ cmp $0, %ebx
+ je .MBNG_SSE
+
+ #; Pre-loop, we need to run 1-3 frames "manually" without
+ #; SSE instructions
+
+.MBNG_PRELOOP:
+
+ movss (%esi), %xmm0
+ addss (%edi), %xmm0
+ movss %xmm0, (%edi)
+
+ addl $4, %edi #; dst++
+ addl $4, %esi #; src++
+ decl %ecx #; nframes--
+ jz .MBNG_END
+ addl $4, %ebx
+
+ cmp $16, %ebx #; test if we've reached 16 byte alignment
+ jne .MBNG_PRELOOP
+
+.MBNG_SSE:
+
+ cmp $4, %ecx #; if there are frames left, but less than 4
+ jnge .MBNG_NONALIGN #; we can't run SSE
+
+.MBNG_SSELOOP:
+
+ movaps (%esi), %xmm0 #; source => xmm0
+ addps (%edi), %xmm0 #; mix with destination
+ movaps %xmm0, (%edi) #; copy result to destination
+
+ addl $16, %edi #; dst+=4
+ addl $16, %esi #; src+=4
+
+ subl $4, %ecx #; nframes-=4
+ cmp $4, %ecx
+ jge .MBNG_SSELOOP
+
+ cmp $0, %ecx
+ je .MBNG_END
+
+ #; if there are remaining frames, the nonalign code will do nicely
+ #; for the rest 1-3 frames.
+
+.MBNG_NONALIGN:
+ #; not aligned!
+
+ movss (%esi), %xmm0 #; src => xmm0
+ addss (%edi), %xmm0 #; xmm0 += dst
+ movss %xmm0, (%edi) #; xmm0 => dst
+
+ addl $4, %edi
+ addl $4, %esi
+
+ decl %ecx
+ jnz .MBNG_NONALIGN
+
+.MBNG_END:
+
+ popl %esi
+ popl %edi
+#; popl %ecx
+ popl %ebx
+#; popl %eax
+
+ #; return
+ leave
+ ret
+
+.size x86_sse_mix_buffers_no_gain, .-x86_sse_mix_buffers_no_gain
+
+
+
+
+#; void x86_sse_apply_gain_to_buffer (float *buf, long nframes, float gain);
+
+.globl x86_sse_apply_gain_to_buffer
+ .type x86_sse_apply_gain_to_buffer,@function
+
+x86_sse_apply_gain_to_buffer:
+#; 8(%ebp) = float *buf = %edi
+#; 12(%ebp) = long nframes = %ecx
+#; 16(%ebp) = float gain = st(0)
+
+ pushl %ebp
+ movl %esp, %ebp
+
+ #; save %edi
+ pushl %edi
+
+ #; the real function
+
+ #; if nframes == 0, go to end
+ movl 12(%ebp), %ecx #; nframes
+ cmp $0, %ecx
+ je .AG_END
+
+ #; create the gain buffer in %xmm1
+ movss 16(%ebp), %xmm1
+ shufps $0x00, %xmm1, %xmm1
+
+ #; Check for alignment
+
+ movl 8(%ebp), %edi #; buf
+ movl %edi, %edx #; buf => %edx
+ andl $12, %edx #; mask bits 1 & 2, result = 0, 4, 8 or 12
+ jz .AG_SSE #; if buffer IS aligned
+
+ #; PRE-LOOP
+ #; we iterate 1-3 times, doing normal x87 float comparison
+ #; so we reach a 16 byte aligned "buf" (=%edi) value
+
+.AGLP_START:
+
+ #; Load next value from the buffer
+ movss (%edi), %xmm0
+ mulss %xmm1, %xmm0
+ movss %xmm0, (%edi)
+
+ #; increment buffer, decrement counter
+ addl $4, %edi #; buf++;
+
+ decl %ecx #; nframes--
+ jz .AG_END #; if we run out of frames, we go to the end
+
+ addl $4, %edx #; one non-aligned byte less
+ cmp $16, %edx
+ jne .AGLP_START #; if more non-aligned frames exist, we do a do-over
+
+.AG_SSE:
+
+ #; We have reached the 16 byte aligned "buf" ("edi") value
+
+ #; Figure out how many loops we should do
+ movl %ecx, %eax #; copy remaining nframes to %eax for division
+ movl $0, %edx #; 0 the edx register
+
+
+ pushl %edi
+ movl $4, %edi
+ divl %edi #; %edx = remainder == 0
+ popl %edi
+
+ #; %eax = SSE iterations
+ cmp $0, %eax
+ je .AGPOST_START
+
+
+.AGLP_SSE:
+
+ movaps (%edi), %xmm0
+ mulps %xmm1, %xmm0
+ movaps %xmm0, (%edi)
+
+ addl $16, %edi
+#; subl $4, %ecx #; nframes-=4
+
+ decl %eax
+ jnz .AGLP_SSE
+
+ #; Next we need to post-process all remaining frames
+ #; the remaining frame count is in %ecx
+
+ #; if no remaining frames, jump to the end
+#; cmp $0, %ecx
+ andl $3, %ecx #; nframes % 4
+ je .AG_END
+
+.AGPOST_START:
+
+ movss (%edi), %xmm0
+ mulss %xmm1, %xmm0
+ movss %xmm0, (%edi)
+
+ #; increment buffer, decrement counter
+ addl $4, %edi #; buf++;
+
+ decl %ecx #; nframes--
+ jnz .AGPOST_START #; if we run out of frames, we go to the end
+
+.AG_END:
+
+
+ popl %edi
+
+ #; return
+ leave
+ ret
+
+.size x86_sse_apply_gain_to_buffer, .-x86_sse_apply_gain_to_buffer
+#; end proc
+
+
+
+#; float x86_sse_compute_peak(float *buf, long nframes, float current);
+
+.globl x86_sse_compute_peak
+ .type x86_sse_compute_peak,@function
+
+x86_sse_compute_peak:
+#; 8(%ebp) = float *buf = %edi
+#; 12(%ebp) = long nframes = %ecx
+#; 16(%ebp) = float current = st(0)
+
+ pushl %ebp
+ movl %esp, %ebp
+
+ #; save %edi
+ pushl %edi
+
+ #; the real function
+
+ #; Load "current" in xmm0
+ movss 16(%ebp), %xmm0
+
+ #; if nframes == 0, go to end
+ movl 12(%ebp), %ecx #; nframes
+ cmp $0, %ecx
+ je .CP_END
+
+ #; create the "abs" mask in %xmm2
+ pushl $2147483647
+ movss (%esp), %xmm2
+ addl $4, %esp
+ shufps $0x00, %xmm2, %xmm2
+
+ #; Check for alignment
+
+ movl 8(%ebp), %edi #; buf
+ movl %edi, %edx #; buf => %edx
+ andl $12, %edx #; mask bits 1 & 2, result = 0, 4, 8 or 12
+ jz .CP_SSE #; if buffer IS aligned
+
+ #; PRE-LOOP
+ #; we iterate 1-3 times, doing normal x87 float comparison
+ #; so we reach a 16 byte aligned "buf" (=%edi) value
+
+.LP_START:
+
+ #; Load next value from the buffer
+ movss (%edi), %xmm1
+ andps %xmm2, %xmm1
+ maxss %xmm1, %xmm0
+
+ #; increment buffer, decrement counter
+ addl $4, %edi #; buf++;
+
+ decl %ecx #; nframes--
+ jz .CP_END #; if we run out of frames, we go to the end
+
+ addl $4, %edx #; one non-aligned byte less
+ cmp $16, %edx
+ jne .LP_START #; if more non-aligned frames exist, we do a do-over
+
+.CP_SSE:
+
+ #; We have reached the 16 byte aligned "buf" ("edi") value
+
+ #; Figure out how many loops we should do
+ movl %ecx, %eax #; copy remaining nframes to %eax for division
+
+ shr $2,%eax #; unsigned divide by 4
+ jz .POST_START
+
+ #; %eax = SSE iterations
+
+ #; current maximum is at %xmm0, but we need to ..
+ shufps $0x00, %xmm0, %xmm0 #; shuffle "current" to all 4 FP's
+
+ #;prefetcht0 16(%edi)
+
+.LP_SSE:
+
+ movaps (%edi), %xmm1
+ andps %xmm2, %xmm1
+ maxps %xmm1, %xmm0
+
+ addl $16, %edi
+
+ decl %eax
+ jnz .LP_SSE
+
+ #; Calculate the maximum value contained in the 4 FP's in %xmm0
+ movaps %xmm0, %xmm1
+ shufps $0x4e, %xmm1, %xmm1 #; shuffle left & right pairs (1234 => 3412)
+ maxps %xmm1, %xmm0 #; maximums of the two pairs
+ movaps %xmm0, %xmm1
+ shufps $0xb1, %xmm1, %xmm1 #; shuffle the floats inside the two pairs (1234 => 2143)
+ maxps %xmm1, %xmm0
+
+ #; now every float in %xmm0 is the same value, current maximum value
+
+ #; Next we need to post-process all remaining frames
+ #; the remaining frame count is in %ecx
+
+ #; if no remaining frames, jump to the end
+
+ andl $3, %ecx #; nframes % 4
+ jz .CP_END
+
+.POST_START:
+
+ movss (%edi), %xmm1
+ andps %xmm2, %xmm1
+ maxss %xmm1, %xmm0
+
+ addl $4, %edi #; buf++;
+
+ decl %ecx #; nframes--;
+ jnz .POST_START
+
+.CP_END:
+
+ #; Load the value from xmm0 to the float stack for returning
+ movss %xmm0, 16(%ebp)
+ flds 16(%ebp)
+
+ popl %edi
+
+ #; return
+ leave
+ ret
+
+.size x86_sse_compute_peak, .-x86_sse_compute_peak
+#; end proc
+
+#ifdef __ELF__
+.section .note.GNU-stack,"",%progbits
+#endif
+
+
diff --git a/muse_qt4_evolution/al/dspXMM.cpp b/muse_qt4_evolution/al/dspXMM.cpp
new file mode 100644
index 00000000..1943fa7d
--- /dev/null
+++ b/muse_qt4_evolution/al/dspXMM.cpp
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 2007 Paul sDavis
+ Written by Sampo Savolainen
+
+ 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.
+
+*/
+
+#include <xmmintrin.h>
+
+void
+x86_sse_find_peaks(float *buf, unsigned nframes, float *min, float *max)
+{
+ __m128 current_max, current_min, work;
+
+ // Load max and min values into all four slots of the XMM registers
+ current_min = _mm_set1_ps(*min);
+ current_max = _mm_set1_ps(*max);
+
+ // Work input until "buf" reaches 16 byte alignment
+ while ( ((unsigned long)buf) % 16 != 0 && nframes > 0) {
+
+ // Load the next float into the work buffer
+ work = _mm_set1_ps(*buf);
+
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+
+ buf++;
+ nframes--;
+ }
+
+ // use 64 byte prefetch for quadruple quads
+ while (nframes >= 16) {
+ __builtin_prefetch(buf+64,0,0);
+
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ nframes-=16;
+ }
+
+ // work through aligned buffers
+ while (nframes >= 4) {
+
+ work = _mm_load_ps(buf);
+
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+
+ buf+=4;
+ nframes-=4;
+ }
+
+ // work through the rest < 4 samples
+ while ( nframes > 0) {
+
+ // Load the next float into the work buffer
+ work = _mm_set1_ps(*buf);
+
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+
+ buf++;
+ nframes--;
+ }
+
+ // Find min & max value in current_max through shuffle tricks
+
+ work = current_min;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(2, 3, 0, 1));
+ work = _mm_min_ps (work, current_min);
+ current_min = work;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(1, 0, 3, 2));
+ work = _mm_min_ps (work, current_min);
+
+ _mm_store_ss(min, work);
+
+ work = current_max;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(2, 3, 0, 1));
+ work = _mm_max_ps (work, current_max);
+ current_max = work;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(1, 0, 3, 2));
+ work = _mm_max_ps (work, current_max);
+
+ _mm_store_ss(max, work);
+}
+
+
+
diff --git a/muse_qt4_evolution/al/marker.cpp b/muse_qt4_evolution/al/marker.cpp
new file mode 100644
index 00000000..5b4ef87c
--- /dev/null
+++ b/muse_qt4_evolution/al/marker.cpp
@@ -0,0 +1,86 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#include "marker.h"
+#include "xml.h"
+
+namespace AL {
+
+//---------------------------------------------------------
+// add
+//---------------------------------------------------------
+
+Marker* MarkerList::add(const Marker& marker)
+ {
+ iMarker i = insert(std::pair<const int, Marker> (marker.tick(), Marker(marker)));
+ return &i->second;
+ }
+
+Marker* MarkerList::add(const QString& s, const Pos& pos)
+ {
+ Marker marker(pos);
+ marker.setName(s);
+ iMarker i = insert(std::pair<const int, Marker> (pos.tick(), marker));
+ return &i->second;
+ }
+
+//---------------------------------------------------------
+// read
+//---------------------------------------------------------
+
+void Marker::read(QDomNode node)
+ {
+ Pos::read(node);
+ QDomElement e = node.toElement();
+ _name = e.attribute("name");
+ }
+
+//---------------------------------------------------------
+// write
+//---------------------------------------------------------
+
+void MarkerList::write(Xml& xml) const
+ {
+ for (ciMarker i = begin(); i != end(); ++i) {
+ const Marker& m = i->second;
+ if (m.type() == TICKS)
+ xml.tagE(QString("marker tick=\"%1\" name=\"%2\"").arg(m.tick()).arg(m.name()));
+ else
+ xml.tagE(QString("marker sample=\"%1\" name=\"%2\"").arg(m.frame()).arg(m.name()));
+ }
+ }
+
+//---------------------------------------------------------
+// remove
+//---------------------------------------------------------
+
+void MarkerList::remove(Marker* m)
+ {
+ for (iMarker i = begin(); i != end(); ++i) {
+ Marker* mm = &i->second;
+ if (mm == m) {
+ erase(i);
+ return;
+ }
+ }
+ printf("MarkerList::remove(): marker not found\n");
+ }
+}
+
diff --git a/muse_qt4_evolution/al/marker.h b/muse_qt4_evolution/al/marker.h
new file mode 100644
index 00000000..7c77f72e
--- /dev/null
+++ b/muse_qt4_evolution/al/marker.h
@@ -0,0 +1,67 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#ifndef __MARKER_H__
+#define __MARKER_H__
+
+#include "pos.h"
+
+namespace AL {
+ class Xml;
+
+//---------------------------------------------------------
+// Marker
+//---------------------------------------------------------
+
+class Marker : public Pos {
+ QString _name;
+ bool _current;
+
+ public:
+ Marker() : _current(false) {}
+ Marker(const Pos& m) : Pos(m), _current(false) {}
+ Marker(const QString& s, bool cur = false)
+ : _name(s), _current(cur) {}
+ void read(QDomNode);
+ const QString name() const { return _name; }
+ void setName(const QString& s) { _name = s; }
+ bool current() const { return _current; }
+ void setCurrent(bool f) { _current = f; }
+ };
+
+//---------------------------------------------------------
+// MarkerList
+//---------------------------------------------------------
+
+class MarkerList : public std::multimap<unsigned, Marker, std::less<unsigned> > {
+ public:
+ Marker* add(const Marker& m);
+ Marker* add(const QString& s, const Pos&);
+ void write(Xml&) const;
+ void remove(Marker*);
+ };
+
+typedef std::multimap<unsigned, Marker, std::less<unsigned> >::iterator iMarker;
+typedef std::multimap<unsigned, Marker, std::less<unsigned> >::const_iterator ciMarker;
+
+} // end namespace AL
+
+#endif
+
diff --git a/muse_qt4_evolution/al/pos.cpp b/muse_qt4_evolution/al/pos.cpp
new file mode 100644
index 00000000..f8418a00
--- /dev/null
+++ b/muse_qt4_evolution/al/pos.cpp
@@ -0,0 +1,616 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#include "al.h"
+#include "pos.h"
+#include "xml.h"
+#include "tempo.h"
+#include "sig.h"
+
+namespace AL {
+
+//---------------------------------------------------------
+// Pos
+//---------------------------------------------------------
+
+Pos::Pos()
+ {
+ _type = TICKS;
+ _tick = 0;
+ _frame = 0;
+ sn = -1;
+ }
+
+Pos::Pos(unsigned t, TType timeType)
+ {
+ _type = timeType;
+ if (_type == TICKS)
+ _tick = t;
+ else
+ _frame = t;
+ sn = -1;
+ }
+
+Pos::Pos(const QString& s)
+ {
+ int m, b, t;
+ sscanf(s.toLatin1().data(), "%04d.%02d.%03d", &m, &b, &t);
+ _tick = sigmap.bar2tick(m, b, t);
+ _type = TICKS;
+ sn = -1;
+ }
+
+Pos::Pos(int measure, int beat, int tick)
+ {
+ _tick = sigmap.bar2tick(measure, beat, tick);
+ _type = TICKS;
+ sn = -1;
+ }
+
+Pos::Pos(int min, int sec, int frame, int subframe)
+ {
+ double time = min * 60.0 + sec;
+
+ double f = frame + subframe/100.0;
+ switch (AL::mtcType) {
+ case 0: // 24 frames sec
+ time += f * 1.0/24.0;
+ break;
+ case 1: // 25
+ time += f * 1.0/25.0;
+ break;
+ case 2: // 30 drop frame
+ time += f * 1.0/30.0;
+ break;
+ case 3: // 30 non drop frame
+ time += f * 1.0/30.0;
+ break;
+ }
+ _type = FRAMES;
+ _frame = lrint(time * AL::sampleRate);
+ sn = -1;
+ }
+
+//---------------------------------------------------------
+// setType
+//---------------------------------------------------------
+
+void Pos::setType(TType t)
+ {
+ if (t == _type)
+ return;
+
+ if (_type == TICKS) {
+ // convert from ticks to frames
+ _frame = tempomap.tick2frame(_tick, _frame, &sn);
+ }
+ else {
+ // convert from frames to ticks
+ _tick = tempomap.frame2tick(_frame, _tick, &sn);
+ }
+ _type = t;
+ }
+
+//---------------------------------------------------------
+// operator+=
+//---------------------------------------------------------
+
+Pos& Pos::operator+=(const Pos& a)
+ {
+ if (_type == FRAMES)
+ _frame += a.frame();
+ else
+ _tick += a.tick();
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+//---------------------------------------------------------
+// operator-=
+//---------------------------------------------------------
+
+Pos& Pos::operator-=(const Pos& a)
+ {
+ if (_type == FRAMES)
+ _frame -= a.frame();
+ else
+ _tick -= a.tick();
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+//---------------------------------------------------------
+// operator+=
+//---------------------------------------------------------
+
+Pos& Pos::operator+=(int a)
+ {
+ if (_type == FRAMES)
+ _frame += a;
+ else
+ _tick += a;
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+//---------------------------------------------------------
+// operator-=
+//---------------------------------------------------------
+
+Pos& Pos::operator-=(int a)
+ {
+ if (_type == FRAMES)
+ _frame -= a;
+ else
+ _tick -= a;
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+Pos operator+(const Pos& a, int b)
+ {
+ Pos c(a);
+ return c += b;
+ }
+
+Pos operator-(const Pos& a, int b)
+ {
+ Pos c(a);
+ return c -= b;
+ }
+
+Pos operator+(const Pos& a, const Pos& b)
+ {
+ Pos c(a);
+ return c += b;
+ }
+
+Pos operator-(const Pos& a, const Pos& b)
+ {
+ Pos c(a);
+ return c -= b;
+ }
+
+bool Pos::operator>=(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame >= s.frame();
+ else
+ return _tick >= s.tick();
+ }
+
+bool Pos::operator>(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame > s.frame();
+ else
+ return _tick > s.tick();
+ }
+
+bool Pos::operator<(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame < s.frame();
+ else
+ return _tick < s.tick();
+ }
+
+bool Pos::operator<=(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame <= s.frame();
+ else
+ return _tick <= s.tick();
+ }
+
+bool Pos::operator==(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame == s.frame();
+ else
+ return _tick == s.tick();
+ }
+
+bool Pos::operator!=(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame != s.frame();
+ else
+ return _tick != s.tick();
+ }
+
+//---------------------------------------------------------
+// tick
+//---------------------------------------------------------
+
+unsigned Pos::tick() const
+ {
+ if (_type == FRAMES)
+ _tick = tempomap.frame2tick(_frame, _tick, &sn);
+ return _tick;
+ }
+
+//---------------------------------------------------------
+// frame
+//---------------------------------------------------------
+
+unsigned Pos::frame() const
+ {
+ if (_type == TICKS)
+ _frame = tempomap.tick2frame(_tick, _frame, &sn);
+ return _frame;
+ }
+
+//---------------------------------------------------------
+// setTick
+//---------------------------------------------------------
+
+void Pos::setTick(unsigned pos)
+ {
+ _tick = pos;
+ sn = -1;
+ if (_type == FRAMES)
+ _frame = tempomap.tick2frame(pos, &sn);
+ }
+
+//---------------------------------------------------------
+// setFrame
+//---------------------------------------------------------
+
+void Pos::setFrame(unsigned pos)
+ {
+ _frame = pos;
+ sn = -1;
+ if (_type == TICKS)
+ _tick = tempomap.frame2tick(pos, &sn);
+ }
+
+//---------------------------------------------------------
+// write
+//---------------------------------------------------------
+
+void Pos::write(Xml& xml, const char* name) const
+ {
+ if (_type == TICKS)
+ xml.tagE(QString("%1 tick=\"%2\"").arg(name).arg(_tick));
+ else
+ xml.tagE(QString("%1 frame=\"%2\"").arg(name).arg(_frame));
+ }
+
+//---------------------------------------------------------
+// read
+//---------------------------------------------------------
+
+void Pos::read(QDomNode node)
+ {
+ sn = -1;
+
+ QDomElement e = node.toElement();
+ QString s;
+ s = e.attribute("tick");
+ if (!s.isEmpty()) {
+ _tick = s.toInt();
+ _type = TICKS;
+ }
+ s = e.attribute("frame");
+ if (!s.isEmpty()) {
+ _frame = s.toInt();
+ _type = FRAMES;
+ }
+ }
+
+//---------------------------------------------------------
+// PosLen
+//---------------------------------------------------------
+
+PosLen::PosLen()
+ {
+ _lenTick = 0;
+ _lenFrame = 0;
+ sn = -1;
+ }
+
+PosLen::PosLen(const PosLen& p)
+ : Pos(p)
+ {
+ _lenTick = p._lenTick;
+ _lenFrame = p._lenFrame;
+ sn = -1;
+ }
+
+//---------------------------------------------------------
+// dump
+//---------------------------------------------------------
+
+void PosLen::dump(int n) const
+ {
+ Pos::dump(n);
+ printf(" Len(");
+ switch(type()) {
+ case FRAMES:
+ printf("samples=%d)\n", _lenFrame);
+ break;
+ case TICKS:
+ printf("ticks=%d)\n", _lenTick);
+ break;
+ }
+ }
+
+void Pos::dump(int /*n*/) const
+ {
+ printf("Pos(%s, sn=%d, ", type() == FRAMES ? "Frames" : "Ticks", sn);
+ switch(type()) {
+ case FRAMES:
+ printf("samples=%d)", _frame);
+ break;
+ case TICKS:
+ printf("ticks=%d)", _tick);
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// write
+//---------------------------------------------------------
+
+void PosLen::write(Xml& xml, const char* name) const
+ {
+ if (type() == TICKS)
+ xml.tagE(QString("%1 tick=\"%2\" len=\"%3\"").arg(name).arg(tick()).arg(_lenTick));
+ else
+ xml.tagE(QString("%1 sample=\"%2\" len=\"%3\"").arg(name).arg(frame()).arg(_lenFrame));
+ }
+
+//---------------------------------------------------------
+// read
+//---------------------------------------------------------
+
+void PosLen::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ QString s;
+ s = e.attribute("tick");
+ if (!s.isEmpty()) {
+ setType(TICKS);
+ setTick(s.toInt());
+ }
+ s = e.attribute("sample");
+ if (!s.isEmpty()) {
+ setType(FRAMES);
+ setFrame(s.toInt());
+ }
+ s = e.attribute("len");
+ if (!s.isEmpty()) {
+ int n = s.toInt();
+ if (type() == TICKS)
+ setLenTick(n);
+ else
+ setLenFrame(n);
+ }
+ }
+
+//---------------------------------------------------------
+// setLenTick
+//---------------------------------------------------------
+
+void PosLen::setLenTick(unsigned len)
+ {
+ _lenTick = len;
+ sn = -1;
+ if (type() == FRAMES)
+ _lenFrame = tempomap.tick2frame(len, &sn);
+ else
+ _lenTick = len;
+ }
+
+//---------------------------------------------------------
+// setLenFrame
+//---------------------------------------------------------
+
+void PosLen::setLenFrame(unsigned len)
+ {
+ sn = -1;
+ if (type() == TICKS)
+ _lenTick = tempomap.frame2tick(len, &sn);
+ else
+ _lenFrame = len;
+ }
+
+//---------------------------------------------------------
+// lenTick
+//---------------------------------------------------------
+
+unsigned PosLen::lenTick() const
+ {
+ if (type() == FRAMES)
+ _lenTick = tempomap.frame2tick(_lenFrame, _lenTick, &sn);
+ return _lenTick;
+ }
+
+//---------------------------------------------------------
+// lenFrame
+//---------------------------------------------------------
+
+unsigned PosLen::lenFrame() const
+ {
+ if (type() == TICKS)
+ _lenFrame = tempomap.tick2frame(_lenTick, _lenFrame, &sn);
+ return _lenFrame;
+ }
+
+//---------------------------------------------------------
+// end
+//---------------------------------------------------------
+
+Pos PosLen::end() const
+ {
+ Pos pos(*this);
+ pos.invalidSn();
+ switch(type()) {
+ case FRAMES:
+ pos.setFrame(pos.frame() + _lenFrame);
+ break;
+ case TICKS:
+ pos.setTick(pos.tick() + _lenTick);
+ break;
+ }
+ return pos;
+ }
+
+//---------------------------------------------------------
+// setPos
+//---------------------------------------------------------
+
+void PosLen::setPos(const Pos& pos)
+ {
+ switch(pos.type()) {
+ case FRAMES:
+ setFrame(pos.frame());
+ break;
+ case TICKS:
+ setTick(pos.tick());
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// operator==
+//---------------------------------------------------------
+
+bool PosLen::operator==(const PosLen& pl) const {
+ if(type()==TICKS)
+ return (_lenTick==pl._lenTick && Pos::operator==((const Pos&)pl));
+ else
+ return (_lenFrame==pl._lenFrame && Pos::operator==((const Pos&)pl));
+}
+
+//---------------------------------------------------------
+// mbt
+//---------------------------------------------------------
+
+void Pos::mbt(int* bar, int* beat, int* tk) const
+ {
+ sigmap.tickValues(tick(), bar, beat, (unsigned*)tk);
+ }
+
+//---------------------------------------------------------
+// msf
+//---------------------------------------------------------
+
+void Pos::msf(int* min, int* sec, int* fr, int* subFrame) const
+ {
+#if 0
+ //double has been replaced by float because it prevents (mysteriously)
+ //from a segfault that occurs at the launching of muse
+ /*double*/ float time = double(frame()) / double(AL::sampleRate);
+ *min = int(time) / 60;
+ *sec = int(time) % 60;
+ //double has been replaced by float because it prevents (mysteriously)
+ //from a segfault that occurs at the launching of muse
+ /*double*/ float rest = time - (*min * 60 + *sec);
+ switch(AL::mtcType) {
+ case 0: // 24 frames sec
+ rest *= 24;
+ break;
+ case 1: // 25
+ rest *= 25;
+ break;
+ case 2: // 30 drop frame
+ rest *= 30;
+ break;
+ case 3: // 30 non drop frame
+ rest *= 30;
+ break;
+ }
+ *fr = int(rest);
+ *subFrame = int((rest- *fr)*100);
+#else
+ // for further testing:
+
+ double time = double(frame()) / double(AL::sampleRate);
+ *min = int(time) / 60;
+ *sec = int(time) % 60;
+ double rest = time - ((*min) * 60 + (*sec));
+ switch(AL::mtcType) {
+ case 0: // 24 frames sec
+ rest *= 24;
+ break;
+ case 1: // 25
+ rest *= 25;
+ break;
+ case 2: // 30 drop frame
+ rest *= 30;
+ break;
+ case 3: // 30 non drop frame
+ rest *= 30;
+ break;
+ }
+ *fr = lrint(rest);
+ *subFrame = lrint((rest - (*fr)) * 100.0);
+#endif
+ }
+
+//---------------------------------------------------------
+// timesig
+//---------------------------------------------------------
+
+TimeSignature Pos::timesig() const
+ {
+ return sigmap.timesig(tick());
+ }
+
+//---------------------------------------------------------
+// snap
+// raster = 1 no snap
+// raster = 0 snap to measure
+// all other raster values snap to raster tick
+//---------------------------------------------------------
+
+void Pos::snap(int raster)
+ {
+ setTick(sigmap.raster(tick(), raster));
+ }
+
+void Pos::upSnap(int raster)
+ {
+ setTick(sigmap.raster2(tick(), raster));
+ }
+
+void Pos::downSnap(int raster)
+ {
+ setTick(sigmap.raster1(tick(), raster));
+ }
+
+Pos Pos::snaped(int raster) const
+ {
+ return Pos(sigmap.raster(tick(), raster));
+ }
+
+Pos Pos::upSnaped(int raster) const
+ {
+ return Pos(sigmap.raster2(tick(), raster));
+ }
+
+Pos Pos::downSnaped(int raster) const
+ {
+ return Pos(sigmap.raster1(tick(), raster));
+ }
+}
+
diff --git a/muse_qt4_evolution/al/pos.h b/muse_qt4_evolution/al/pos.h
new file mode 100644
index 00000000..6226cfef
--- /dev/null
+++ b/muse_qt4_evolution/al/pos.h
@@ -0,0 +1,129 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#ifndef __POS_H__
+#define __POS_H__
+
+#include "sig.h"
+
+namespace AL {
+
+class Xml;
+
+enum TType { TICKS, FRAMES };
+
+//---------------------------------------------------------
+// Pos
+// depending on type _tick or _frame is a cached
+// value. When the tempomap changes, all cached values
+// are invalid. Sn is used to check for tempomap
+// changes.
+//---------------------------------------------------------
+
+class Pos {
+ public:
+
+ private:
+ TType _type;
+ mutable int sn;
+ mutable unsigned _tick;
+ mutable unsigned _frame;
+
+ public:
+ Pos();
+ Pos(int measure, int beat, int tick);
+ Pos(int minute, int sec, int frame, int subframe);
+ Pos(unsigned, TType type = TICKS);
+ Pos(const QString&);
+ void dump(int n = 0) const;
+
+ unsigned time(TType t) const { return t == TICKS ? tick() : frame(); }
+ void mbt(int* measure, int* beat, int* tick) const;
+ void msf(int* minute, int* sec, int* frame, int* subframe) const;
+ TimeSignature timesig() const;
+ void snap(int);
+ void upSnap(int);
+ void downSnap(int);
+ Pos snaped(int) const;
+ Pos upSnaped(int) const;
+ Pos downSnaped(int) const;
+
+ void invalidSn() { sn = -1; }
+
+ TType type() const { return _type; }
+ void setType(TType t);
+
+ Pos& operator+=(const Pos& a);
+ Pos& operator+=(int a);
+ Pos& operator-=(const Pos& a);
+ Pos& operator-=(int a);
+
+ bool operator>=(const Pos& s) const;
+ bool operator>(const Pos& s) const;
+ bool operator<(const Pos& s) const;
+ bool operator<=(const Pos& s) const;
+ bool operator==(const Pos& s) const;
+ bool operator!=(const Pos& s) const;
+
+ friend Pos operator+(const Pos& a, const Pos& b);
+ friend Pos operator-(const Pos& a, const Pos& b);
+ friend Pos operator+(const Pos& a, int b);
+ friend Pos operator-(const Pos& a, int b);
+
+ unsigned tick() const;
+ unsigned frame() const;
+ void setTick(unsigned);
+ void setFrame(unsigned);
+
+ void write(Xml&, const char*) const;
+ void read(QDomNode);
+ bool isValid() const { return true; }
+ };
+
+//---------------------------------------------------------
+// PosLen
+//---------------------------------------------------------
+
+class PosLen : public Pos {
+ mutable unsigned _lenTick;
+ mutable unsigned _lenFrame;
+ mutable int sn;
+
+ public:
+ PosLen();
+ PosLen(const PosLen&);
+ void dump(int n = 0) const;
+
+ void write(Xml&, const char*) const;
+ void read(QDomNode);
+ void setLenTick(unsigned);
+ void setLenFrame(unsigned);
+ unsigned lenTick() const;
+ unsigned lenFrame() const;
+ Pos end() const;
+ unsigned endTick() const { return end().tick(); }
+ unsigned endFrame() const { return end().frame(); }
+ void setPos(const Pos&);
+
+ bool operator==(const PosLen& s) const;
+ };
+}
+
+#endif
diff --git a/muse_qt4_evolution/al/sig.cpp b/muse_qt4_evolution/al/sig.cpp
new file mode 100644
index 00000000..d8672200
--- /dev/null
+++ b/muse_qt4_evolution/al/sig.cpp
@@ -0,0 +1,407 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#include "al.h"
+#include "sig.h"
+#include "xml.h"
+
+namespace AL {
+
+SigList sigmap;
+
+//---------------------------------------------------------
+// SigList
+//---------------------------------------------------------
+
+SigList::SigList()
+ {
+ insert(std::pair<const unsigned, SigEvent*> (MAX_TICK, new SigEvent(TimeSignature(4, 4), 0)));
+ }
+
+//---------------------------------------------------------
+// add
+// signatures are only allowed at the beginning of
+// a bar
+//---------------------------------------------------------
+
+void SigList::add(unsigned tick, const TimeSignature& s)
+ {
+ if (s.z == 0 || s.n == 0) {
+ printf("illegal signature %d/%d\n", s.z, s.n);
+ }
+ tick = raster1(tick, 0);
+ iSigEvent e = upper_bound(tick);
+
+ if (tick == e->second->tick) {
+ e->second->sig = s;
+ }
+ else {
+ SigEvent* ne = e->second;
+ SigEvent* ev = new SigEvent(ne->sig, ne->tick);
+ ne->sig = s;
+ ne->tick = tick;
+ insert(std::pair<const unsigned, SigEvent*> (tick, ev));
+ }
+ normalize();
+ }
+
+//---------------------------------------------------------
+// del
+//---------------------------------------------------------
+
+void SigList::del(unsigned tick)
+ {
+// printf("SigList::del(%d)\n", tick);
+ iSigEvent e = find(tick);
+ if (e == end()) {
+ printf("SigList::del(%d): not found\n", tick);
+ return;
+ }
+ iSigEvent ne = e;
+ ++ne;
+ if (ne == end()) {
+ printf("SigList::del() HALLO\n");
+ return;
+ }
+ ne->second->sig = e->second->sig;
+ ne->second->tick = e->second->tick;
+ erase(e);
+ normalize();
+ }
+
+//---------------------------------------------------------
+// SigList::normalize
+//---------------------------------------------------------
+
+void SigList::normalize()
+ {
+ TimeSignature sig(0, 0);
+ unsigned tick = 0;
+ iSigEvent ee;
+
+ for (iSigEvent e = begin(); e != end();) {
+ if (sig.z == e->second->sig.z && sig.n == e->second->sig.n) {
+ e->second->tick = tick;
+ erase(ee);
+ }
+ sig = e->second->sig;
+ ee = e;
+ tick = e->second->tick;
+ ++e;
+ }
+
+ int bar = 0;
+ for (iSigEvent e = begin(); e != end();) {
+ e->second->bar = bar;
+ int delta = e->first - e->second->tick;
+ int ticksB = ticks_beat(e->second->sig.n);
+ int ticksM = ticksB * e->second->sig.z;
+ bar += delta / ticksM;
+ if (delta % ticksM) // Teil eines Taktes
+ ++bar;
+ ++e;
+ }
+ }
+
+//---------------------------------------------------------
+// SigList::dump
+//---------------------------------------------------------
+
+void SigList::dump() const
+ {
+ printf("\nSigList:\n");
+ for (ciSigEvent i = begin(); i != end(); ++i) {
+ printf("%6d %06d Bar %3d %02d/%d\n",
+ i->first, i->second->tick,
+ i->second->bar, i->second->sig.z, i->second->sig.n);
+ }
+ }
+
+void SigList::clear()
+ {
+ for (iSigEvent i = begin(); i != end(); ++i)
+ delete i->second;
+ SIGLIST::clear();
+ insert(std::pair<const unsigned, SigEvent*> (MAX_TICK, new SigEvent(TimeSignature(4, 4), 0)));
+ }
+
+//---------------------------------------------------------
+// ticksMeasure
+//---------------------------------------------------------
+
+int SigList::ticksMeasure(const TimeSignature& sig) const
+ {
+ return ticks_beat(sig.n) * sig.z;
+ }
+
+int SigList::ticksMeasure(unsigned tick) const
+ {
+ ciSigEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("ticksMeasure: not found %d\n", tick);
+ // abort();
+ return 0;
+ }
+ return ticksMeasure(i->second->sig);
+ }
+
+//---------------------------------------------------------
+// ticksBeat
+//---------------------------------------------------------
+
+int SigList::ticksBeat(unsigned tick) const
+ {
+ ciSigEvent i = upper_bound(tick);
+ return ticks_beat(i->second->sig.n);
+ }
+
+int SigList::ticks_beat(int n) const
+ {
+ int m = AL::division;
+ switch (n) {
+ case 1: m <<= 2; break; // 1536
+ case 2: m <<= 1; break; // 768
+ case 3: m += m >> 1; break; // 384+192
+ case 4: break; // 384
+ case 8: m >>= 1; break; // 192
+ case 16: m >>= 2; break; // 96
+ case 32: m >>= 3; break; // 48
+ case 64: m >>= 4; break; // 24
+ case 128: m >>= 5; break; // 12
+ default: break;
+ }
+ return m;
+ }
+
+//---------------------------------------------------------
+// timesig
+//---------------------------------------------------------
+
+TimeSignature SigList::timesig(unsigned tick) const
+ {
+ ciSigEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("timesig(%d): not found\n", tick);
+ // abort();
+ return TimeSignature(4,4);
+ }
+ return i->second->sig;
+ }
+
+//---------------------------------------------------------
+// tickValues
+//---------------------------------------------------------
+
+void SigList::tickValues(unsigned t, int* bar, int* beat, unsigned* tick) const
+ {
+ ciSigEvent e = upper_bound(t);
+ if (e == end()) {
+ fprintf(stderr, "tickValues(0x%x) not found(%zd)\n", t, size());
+//DEBUG
+// abort();
+ *bar = 0;
+ *beat = 0;
+ *tick = 0;
+ return;
+ }
+
+ int delta = t - e->second->tick;
+ int ticksB = ticks_beat(e->second->sig.n);
+ int ticksM = ticksB * e->second->sig.z;
+ *bar = e->second->bar + delta / ticksM;
+ int rest = delta % ticksM;
+ *beat = rest / ticksB;
+ *tick = rest % ticksB;
+ }
+
+//---------------------------------------------------------
+// bar2tick
+//---------------------------------------------------------
+
+unsigned SigList::bar2tick(int bar, int beat, unsigned tick) const
+ {
+ ciSigEvent e;
+
+ if (bar < 0)
+ bar = 0;
+ for (e = begin(); e != end();) {
+ ciSigEvent ee = e;
+ ++ee;
+ if (ee == end())
+ break;
+ if (bar < ee->second->bar)
+ break;
+ e = ee;
+ }
+ int ticksB = ticks_beat(e->second->sig.n);
+ int ticksM = ticksB * e->second->sig.z;
+ return e->second->tick + (bar-e->second->bar)*ticksM + ticksB*beat + tick;
+ }
+
+//---------------------------------------------------------
+// raster
+//---------------------------------------------------------
+
+unsigned SigList::raster(unsigned t, int raster) const
+ {
+ if (raster == 1)
+ return t;
+ ciSigEvent e = upper_bound(t);
+ if (e == end()) {
+ printf("SigList::raster(%x,)\n", t);
+ // abort();
+ return t;
+ }
+ int delta = t - e->second->tick;
+ int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
+ if (raster == 0)
+ raster = ticksM;
+ int rest = delta % ticksM;
+ int bb = (delta/ticksM)*ticksM;
+ return e->second->tick + bb + ((rest + raster/2)/raster)*raster;
+ }
+
+//---------------------------------------------------------
+// raster1
+// round down
+//---------------------------------------------------------
+
+unsigned SigList::raster1(unsigned t, int raster) const
+ {
+ if (raster == 1)
+ return t;
+ ciSigEvent e = upper_bound(t);
+
+ int delta = t - e->second->tick;
+ int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
+ if (raster == 0)
+ raster = ticksM;
+ int rest = delta % ticksM;
+ int bb = (delta/ticksM)*ticksM;
+ return e->second->tick + bb + (rest/raster)*raster;
+ }
+
+//---------------------------------------------------------
+// raster2
+// round up
+//---------------------------------------------------------
+
+unsigned SigList::raster2(unsigned t, int raster) const
+ {
+ if (raster == 1)
+ return t;
+ ciSigEvent e = upper_bound(t);
+
+ int delta = t - e->second->tick;
+ int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
+ if (raster == 0)
+ raster = ticksM;
+ int rest = delta % ticksM;
+ int bb = (delta/ticksM)*ticksM;
+ return e->second->tick + bb + ((rest+raster-1)/raster)*raster;
+ }
+
+//---------------------------------------------------------
+// rasterStep
+//---------------------------------------------------------
+
+int SigList::rasterStep(unsigned t, int raster) const
+ {
+ if (raster == 0) {
+ ciSigEvent e = upper_bound(t);
+ return ticks_beat(e->second->sig.n) * e->second->sig.z;
+ }
+ return raster;
+ }
+
+//---------------------------------------------------------
+// SigList::write
+//---------------------------------------------------------
+
+void SigList::write(Xml& xml) const
+ {
+ xml.stag("siglist");
+ for (ciSigEvent i = begin(); i != end(); ++i)
+ i->second->write(xml, i->first);
+ xml.etag("siglist");
+ }
+
+//---------------------------------------------------------
+// SigList::read
+//---------------------------------------------------------
+
+void SigList::read(QDomNode node)
+ {
+ while (!node.isNull()) {
+ QDomElement e = node.toElement();
+ if (e.tagName() == "sig") {
+ SigEvent* t = new SigEvent();
+ unsigned tick = t->read(node);
+ iSigEvent pos = find(tick);
+ if (pos != end())
+ erase(pos);
+ insert(std::pair<const unsigned, SigEvent*> (tick, t));
+ }
+ else
+ printf("MusE:SigList: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ normalize();
+ }
+
+//---------------------------------------------------------
+// SigEvent::write
+//---------------------------------------------------------
+
+void SigEvent::write(Xml& xml, int at) const
+ {
+ xml.stag(QString("sig at=\"%1\"").arg(at));
+ xml.tag("tick", tick);
+ xml.tag("nom", sig.z);
+ xml.tag("denom", sig.n);
+ xml.etag("sig");
+ }
+
+//---------------------------------------------------------
+// SigEvent::read
+//---------------------------------------------------------
+
+int SigEvent::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ int at = e.attribute("at", "0").toInt();
+ node = node.firstChild();
+
+ while (!node.isNull()) {
+ QDomElement e = node.toElement();
+ if (e.tagName() == "tick")
+ tick = e.text().toInt();
+ else if (e.tagName() == "nom")
+ sig.z = e.text().toInt();
+ else if (e.tagName() == "denom")
+ sig.n = e.text().toInt();
+ else
+ printf("MusE:SigEvent: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ return at;
+ }
+
+}
diff --git a/muse_qt4_evolution/al/sig.h b/muse_qt4_evolution/al/sig.h
new file mode 100644
index 00000000..d0c70410
--- /dev/null
+++ b/muse_qt4_evolution/al/sig.h
@@ -0,0 +1,103 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#ifndef __SIG_H__
+#define __SIG_H__
+
+namespace AL {
+
+#ifndef MAX_TICK
+#define MAX_TICK (0x7fffffff/100)
+#endif
+
+class Xml;
+
+//---------------------------------------------------------
+// TimeSignature
+//---------------------------------------------------------
+
+struct TimeSignature {
+ int z, n;
+ TimeSignature() { z = 4; n = 4; }
+ TimeSignature(int a, int b) { z = a; n = b; }
+ };
+
+//---------------------------------------------------------
+// Signature Event
+//---------------------------------------------------------
+
+struct SigEvent {
+ TimeSignature sig;
+ unsigned tick; // signature valid from this position
+ int bar; // precomputed
+
+ int read(QDomNode);
+ void write(Xml&, int) const;
+
+ SigEvent() { }
+ SigEvent(const TimeSignature& s, unsigned tk) {
+ sig = s;
+ tick = tk;
+ bar = 0;
+ }
+ };
+
+//---------------------------------------------------------
+// SigList
+//---------------------------------------------------------
+
+typedef std::map<unsigned, SigEvent*, std::less<unsigned> > SIGLIST;
+typedef SIGLIST::iterator iSigEvent;
+typedef SIGLIST::const_iterator ciSigEvent;
+typedef SIGLIST::reverse_iterator riSigEvent;
+typedef SIGLIST::const_reverse_iterator criSigEvent;
+
+class SigList : public SIGLIST {
+ int ticks_beat(int N) const;
+ void normalize();
+ int ticksMeasure(const TimeSignature&) const;
+
+ public:
+ SigList();
+ void clear();
+ void add(unsigned tick, const TimeSignature& s);
+ void del(unsigned tick);
+
+ void read(QDomNode);
+ void write(Xml&) const;
+ void dump() const;
+
+ TimeSignature timesig(unsigned tick) const;
+ void tickValues(unsigned t, int* bar, int* beat, unsigned* tick) const;
+ unsigned bar2tick(int bar, int beat, unsigned tick) const;
+
+ int ticksMeasure(unsigned tick) const;
+ int ticksBeat(unsigned tick) const;
+ unsigned raster(unsigned tick, int raster) const;
+ unsigned raster1(unsigned tick, int raster) const; // round down
+ unsigned raster2(unsigned tick, int raster) const; // round up
+ int rasterStep(unsigned tick, int raster) const;
+ };
+
+extern SigList sigmap;
+
+}
+
+#endif
diff --git a/muse_qt4_evolution/al/tempo.cpp b/muse_qt4_evolution/al/tempo.cpp
new file mode 100644
index 00000000..7d65c732
--- /dev/null
+++ b/muse_qt4_evolution/al/tempo.cpp
@@ -0,0 +1,393 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#include "al.h"
+#include "tempo.h"
+#include "xml.h"
+
+namespace AL {
+
+TempoList tempomap;
+
+//---------------------------------------------------------
+// TempoList
+//---------------------------------------------------------
+
+TempoList::TempoList()
+ {
+ _tempo = 500000;
+ insert(std::pair<const unsigned, TEvent*> (MAX_TICK+1, new TEvent(_tempo, 0)));
+ _tempoSN = 1;
+ _globalTempo = 100;
+ useList = true;
+ }
+
+//---------------------------------------------------------
+// add
+//---------------------------------------------------------
+
+void TempoList::add(unsigned tick, int tempo)
+ {
+ if (tick > MAX_TICK)
+ tick = MAX_TICK;
+
+ iTEvent e = upper_bound(tick);
+
+ if (tick == e->second->tick)
+ e->second->tempo = tempo;
+ else {
+ TEvent* ne = e->second;
+ TEvent* ev = new TEvent(ne->tempo, ne->tick);
+ ne->tempo = tempo;
+ ne->tick = tick;
+ insert(std::pair<const unsigned, TEvent*> (tick, ev));
+ }
+ normalize();
+ }
+
+//---------------------------------------------------------
+// TempoList::normalize
+//---------------------------------------------------------
+
+void TempoList::normalize()
+ {
+ int frame = 0;
+ for (iTEvent e = begin(); e != end(); ++e) {
+ e->second->frame = frame;
+ unsigned dtick = e->first - e->second->tick;
+ double dtime = double(dtick) / (division * _globalTempo * 10000.0/e->second->tempo);
+ frame += lrint(dtime * sampleRate);
+ }
+ }
+
+//---------------------------------------------------------
+// TempoList::dump
+//---------------------------------------------------------
+
+void TempoList::dump() const
+ {
+ printf("\nTempoList:\n");
+ for (ciTEvent i = begin(); i != end(); ++i) {
+ printf("%6d %06d Tempo %6d Frame %d\n",
+ i->first, i->second->tick, i->second->tempo,
+ i->second->frame);
+ }
+ }
+
+//---------------------------------------------------------
+// clear
+//---------------------------------------------------------
+
+void TempoList::clear()
+ {
+ for (iTEvent i = begin(); i != end(); ++i)
+ delete i->second;
+ TEMPOLIST::clear();
+ insert(std::pair<const unsigned, TEvent*> (MAX_TICK+1, new TEvent(500000, 0)));
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// tempo
+//---------------------------------------------------------
+
+int TempoList::tempo(unsigned tick) const
+ {
+ if (useList) {
+ ciTEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("no TEMPO at tick %d,0x%x\n", tick, tick);
+ return 1000;
+ }
+ return i->second->tempo;
+ }
+ else
+ return _tempo;
+ }
+
+//---------------------------------------------------------
+// del
+//---------------------------------------------------------
+
+void TempoList::del(unsigned tick)
+ {
+// printf("TempoList::del(%d)\n", tick);
+ iTEvent e = find(tick);
+ if (e == end()) {
+ printf("TempoList::del(%d): not found\n", tick);
+ return;
+ }
+ del(e);
+ ++_tempoSN;
+ }
+
+void TempoList::del(iTEvent e)
+ {
+ iTEvent ne = e;
+ ++ne;
+ if (ne == end()) {
+ printf("TempoList::del(): not found\n");
+ return;
+ }
+ ne->second->tempo = e->second->tempo;
+ ne->second->tick = e->second->tick;
+ erase(e);
+ normalize();
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// change
+//---------------------------------------------------------
+
+void TempoList::change(unsigned tick, int newTempo)
+ {
+ iTEvent e = find(tick);
+ e->second->tempo = newTempo;
+ normalize();
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// setTempo
+// called from transport window
+// & slave mode tempo changes
+//---------------------------------------------------------
+
+void TempoList::setTempo(unsigned tick, int newTempo)
+ {
+ if (useList)
+ add(tick, newTempo);
+ else
+ _tempo = newTempo;
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// setGlobalTempo
+//---------------------------------------------------------
+
+void TempoList::setGlobalTempo(int val)
+ {
+ _globalTempo = val;
+ ++_tempoSN;
+ normalize();
+ }
+
+//---------------------------------------------------------
+// addTempo
+//---------------------------------------------------------
+
+void TempoList::addTempo(unsigned t, int tempo)
+ {
+ add(t, tempo);
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// delTempo
+//---------------------------------------------------------
+
+void TempoList::delTempo(unsigned tick)
+ {
+ del(tick);
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// changeTempo
+//---------------------------------------------------------
+
+void TempoList::changeTempo(unsigned tick, int newTempo)
+ {
+ change(tick, newTempo);
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// setMasterFlag
+//---------------------------------------------------------
+
+bool TempoList::setMasterFlag(unsigned /*tick*/, bool val)
+ {
+ if (useList != val) {
+ useList = val;
+ ++_tempoSN;
+ return true;
+ }
+ return false;
+ }
+
+//---------------------------------------------------------
+// tick2frame
+//---------------------------------------------------------
+
+unsigned TempoList::tick2frame(unsigned tick, unsigned frame, int* sn) const
+ {
+ return (*sn == _tempoSN) ? frame : tick2frame(tick, sn);
+ }
+
+//---------------------------------------------------------
+// tick2frame
+//---------------------------------------------------------
+
+unsigned TempoList::tick2frame(unsigned tick, int* sn) const
+ {
+ int f;
+ if (useList) {
+ ciTEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("tick2frame(%d,0x%x): not found\n", tick, tick);
+ abort(); // debug
+ return 0;
+ }
+ unsigned dtick = tick - i->second->tick;
+ double dtime = double(dtick) / (division * _globalTempo * 10000.0/ i->second->tempo);
+ unsigned dframe = lrint(dtime * sampleRate);
+ f = i->second->frame + dframe;
+ }
+ else {
+ double t = (double(tick) * double(_tempo)) / (double(division) * _globalTempo * 10000.0);
+ f = lrint(t * sampleRate);
+ }
+ if (sn)
+ *sn = _tempoSN;
+ return f;
+ }
+
+//---------------------------------------------------------
+// frame2tick
+// return cached value t if list did not change
+//---------------------------------------------------------
+
+unsigned TempoList::frame2tick(unsigned frame, unsigned t, int* sn) const
+ {
+ return (*sn == _tempoSN) ? t : frame2tick(frame, sn);
+ }
+
+//---------------------------------------------------------
+// frame2tick
+//---------------------------------------------------------
+
+unsigned TempoList::frame2tick(unsigned frame, int* sn) const
+ {
+ unsigned tick;
+ if (useList) {
+ ciTEvent e;
+ for (e = begin(); e != end();) {
+ ciTEvent ee = e;
+ ++ee;
+ if (ee == end())
+ break;
+ if (frame < ee->second->frame)
+ break;
+ e = ee;
+ }
+ unsigned te = e->second->tempo;
+ int dframe = frame - e->second->frame;
+ double dtime = double(dframe) / double(sampleRate);
+ tick = e->second->tick + lrint(dtime * _globalTempo * division * 10000.0 / te);
+ }
+ else
+ tick = lrint((double(frame)/double(sampleRate)) * _globalTempo * division * 10000.0 / double(_tempo));
+ if (sn)
+ *sn = _tempoSN;
+ return tick;
+ }
+
+//---------------------------------------------------------
+// TempoList::write
+//---------------------------------------------------------
+
+void TempoList::write(Xml& xml) const
+ {
+ xml.stag(QString("tempolist fix=\"%1\"").arg(_tempo));
+ if (_globalTempo != 100)
+ xml.tag("globalTempo", _globalTempo);
+ for (ciTEvent i = begin(); i != end(); ++i)
+ i->second->write(xml, i->first);
+ xml.etag("tempolist");
+ }
+
+//---------------------------------------------------------
+// TempoList::read
+//---------------------------------------------------------
+
+void TempoList::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ _tempo = e.attribute("fix","500000").toInt();
+
+ node = node.firstChild();
+ while (!node.isNull()) {
+ e = node.toElement();
+ if (e.tagName() == "tempo") {
+ TEvent* t = new TEvent();
+ unsigned tick = t->read(node);
+ iTEvent pos = find(tick);
+ if (pos != end())
+ erase(pos);
+ insert(std::pair<const int, TEvent*> (tick, t));
+ }
+ else if (e.tagName() == "globalTempo")
+ _globalTempo = e.text().toInt();
+ else
+ printf("MusE:Tempolist: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ normalize();
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// TEvent::write
+//---------------------------------------------------------
+
+void TEvent::write(Xml& xml, int at) const
+ {
+ xml.stag(QString("tempo at=\"%1\"").arg(at));
+ xml.tag("tick", tick);
+ xml.tag("val", tempo);
+ xml.etag("tempo");
+ }
+
+//---------------------------------------------------------
+// TEvent::read
+//---------------------------------------------------------
+
+int TEvent::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ int at = e.attribute("at","0").toInt();
+
+ node = node.firstChild();
+ while (!node.isNull()) {
+ e = node.toElement();
+ if (e.tagName() == "tick")
+ tick = e.text().toInt();
+ else if (e.tagName() == "val")
+ tempo = e.text().toInt();
+ else
+ printf("MusE:TEvent: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ return at;
+ }
+}
diff --git a/muse_qt4_evolution/al/tempo.h b/muse_qt4_evolution/al/tempo.h
new file mode 100644
index 00000000..e2342003
--- /dev/null
+++ b/muse_qt4_evolution/al/tempo.h
@@ -0,0 +1,101 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#ifndef __TEMPO_H__
+#define __TEMPO_H__
+
+namespace AL {
+
+#ifndef MAX_TICK
+#define MAX_TICK (0x7fffffff/100)
+#endif
+
+class Xml;
+
+//---------------------------------------------------------
+// Tempo Event
+//---------------------------------------------------------
+
+struct TEvent {
+ int tempo;
+ unsigned tick; // new tempo at tick
+ unsigned frame; // precomputed time for tick in sec
+
+ int read(QDomNode);
+ void write(Xml&, int) const;
+
+ TEvent() { }
+ TEvent(unsigned t, unsigned tk) {
+ tempo = t;
+ tick = tk;
+ frame = 0;
+ }
+ };
+
+//---------------------------------------------------------
+// TempoList
+//---------------------------------------------------------
+
+typedef std::map<unsigned, TEvent*, std::less<unsigned> > TEMPOLIST;
+typedef TEMPOLIST::iterator iTEvent;
+typedef TEMPOLIST::const_iterator ciTEvent;
+typedef TEMPOLIST::reverse_iterator riTEvent;
+typedef TEMPOLIST::const_reverse_iterator criTEvent;
+
+class TempoList : public TEMPOLIST {
+ int _tempoSN; // serial no to track tempo changes
+ bool useList;
+ int _tempo; // tempo if not using tempo list
+ int _globalTempo; // %percent 50-200%
+
+ void normalize();
+ void add(unsigned tick, int tempo);
+ void change(unsigned tick, int newTempo);
+ void del(iTEvent);
+ void del(unsigned tick);
+
+ public:
+ TempoList();
+ void clear();
+
+ void read(QDomNode);
+ void write(Xml&) const;
+ void dump() const;
+
+ int tempo(unsigned tick) const;
+ unsigned tick2frame(unsigned tick, unsigned frame, int* sn) const;
+ unsigned tick2frame(unsigned tick, int* sn = 0) const;
+ unsigned frame2tick(unsigned frame, int* sn = 0) const;
+ unsigned frame2tick(unsigned frame, unsigned tick, int* sn) const;
+ int tempoSN() const { return _tempoSN; }
+ void setTempo(unsigned tick, int newTempo);
+ void addTempo(unsigned t, int tempo);
+ void delTempo(unsigned tick);
+ void changeTempo(unsigned tick, int newTempo);
+ bool setMasterFlag(unsigned tick, bool val);
+ int globalTempo() const { return _globalTempo; }
+ void setGlobalTempo(int val);
+ };
+
+extern TempoList tempomap;
+}
+
+#endif
+
diff --git a/muse_qt4_evolution/al/xml.cpp b/muse_qt4_evolution/al/xml.cpp
new file mode 100644
index 00000000..7ae40b3e
--- /dev/null
+++ b/muse_qt4_evolution/al/xml.cpp
@@ -0,0 +1,362 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#include "xml.h"
+#include "al.h"
+
+namespace AL {
+
+//---------------------------------------------------------
+// Xml
+//---------------------------------------------------------
+
+Xml::Xml()
+ {
+ level = 0;
+ }
+
+Xml::Xml(QIODevice* device)
+ : QTextStream(device)
+ {
+ setCodec("utf8");
+ level = 0;
+ }
+
+//---------------------------------------------------------
+// putLevel
+//---------------------------------------------------------
+
+void Xml::putLevel()
+ {
+ for (int i = 0; i < level*2; ++i)
+ *this << ' ';
+ }
+
+//---------------------------------------------------------
+// header
+//---------------------------------------------------------
+
+void Xml::header()
+ {
+ *this << "<?xml version=\"1.0\" encoding=\"utf8\"?>" << endl;
+ }
+
+//---------------------------------------------------------
+// put
+//---------------------------------------------------------
+
+void Xml::put(const QString& s)
+ {
+ putLevel();
+ *this << xmlString(s) << endl;
+ }
+
+//---------------------------------------------------------
+// stag
+// <mops attribute="value">
+//---------------------------------------------------------
+
+void Xml::stag(const QString& s)
+ {
+ putLevel();
+ *this << '<' << s << '>' << endl;
+ ++level;
+ }
+
+//---------------------------------------------------------
+// etag
+//---------------------------------------------------------
+
+void Xml::etag(const char* s)
+ {
+ putLevel();
+ *this << "</" << s << '>' << endl;
+ --level;
+ }
+
+//---------------------------------------------------------
+// tagE
+// <mops attribute="value"/>
+//---------------------------------------------------------
+
+void Xml::tagE(const QString& s)
+ {
+ putLevel();
+ *this << '<' << s << "/>" << endl;
+ }
+
+void Xml::tag(const char* name, int val)
+ {
+ putLevel();
+ *this << '<' << name << '>' << val << "</" << name << '>' << endl;
+ }
+
+void Xml::tag(const char* name, unsigned val)
+ {
+ putLevel();
+ *this << '<' << name << '>' << val << "</" << name << '>' << endl;
+ }
+
+void Xml::tag(const char* name, float val)
+ {
+ putLevel();
+ *this << '<' << name << '>' << val << "</" << name << '>' << endl;
+ }
+
+void Xml::tag(const char* name, const double& val)
+ {
+ putLevel();
+ *this << '<' << name << '>' << val << "</" << name << '>' << endl;
+ }
+
+void Xml::tag(const char* name, const QString& val)
+ {
+ putLevel();
+ *this << "<" << name << ">" << xmlString(val) << "</" << name << '>' << endl;
+ }
+
+void Xml::tag(const char* name, const QColor& color)
+ {
+ putLevel();
+ *this << QString("<%1 r=\"%2\" g=\"%3\" b=\"%4\"/>")
+ .arg(name).arg(color.red()).arg(color.green()).arg(color.blue()) << endl;
+ }
+
+void Xml::tag(const char* name, const QWidget* g)
+ {
+ tag(name, QRect(g->pos(), g->size()));
+ }
+
+void Xml::tag(const char* name, const QRect& r)
+ {
+ putLevel();
+ *this << "<" << name;
+ *this << QString(" x=\"%1\" y=\"%2\" w=\"%3\" h=\"%4\"/>")
+ .arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height()) << endl;
+ }
+
+//---------------------------------------------------------
+// xmlString
+//---------------------------------------------------------
+
+QString Xml::xmlString(const QString& ss)
+ {
+ QString s(ss);
+ s.replace('&', "&amp;");
+ s.replace('<', "&lt;");
+ s.replace('>', "&gt;");
+ s.replace('\'', "&apos;");
+ s.replace('"', "&quot;");
+ return s;
+ }
+
+//---------------------------------------------------------
+// readGeometry
+//---------------------------------------------------------
+
+QRect readGeometry(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ int x = e.attribute("x","0").toInt();
+ int y = e.attribute("y","0").toInt();
+ int w = e.attribute("w","50").toInt();
+ int h = e.attribute("h","50").toInt();
+ return QRect(x, y, w, h);
+ }
+
+//---------------------------------------------------------
+// writeProperties
+//---------------------------------------------------------
+
+void Xml::writeProperties(const QObject* o)
+ {
+ const QMetaObject* meta = o->metaObject();
+
+ //
+ // start from dummy "muse" property, assuming this is the
+ // first muse propertie in widget hierarchy
+ //
+ int from = meta->indexOfProperty("muse") + 1;
+ int n = meta->propertyCount();
+ for (int i = from; i < n; ++i) {
+ QMetaProperty p = meta->property(i);
+ if (!p.isScriptable())
+ continue;
+ const char* name = p.name();
+ QVariant v = p.read(o);
+ switch(v.type()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ tag(name, v.toInt());
+ break;
+ case QVariant::Double:
+ tag(name, v.toDouble());
+ break;
+ case QVariant::String:
+ tag(name, v.toString());
+ break;
+ case QVariant::Rect:
+ tag(name, v.toRect());
+ break;
+ case QVariant::Point:
+ {
+ QPoint p = v.toPoint();
+ putLevel();
+ *this << "<" << name << QString(" x=\"%1\" y=\"%2\" />")
+ .arg(p.x()).arg(p.y()) << endl;
+ }
+ break;
+
+ default:
+ printf("MusE:%s type %d not implemented\n",
+ meta->className(), v.type());
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// readProperties
+//---------------------------------------------------------
+
+void readProperties(QObject* o, QDomNode node)
+ {
+ const QMetaObject* meta = o->metaObject();
+
+ QDomElement e = node.toElement();
+ QString tag(e.tagName());
+ int idx = meta->indexOfProperty(tag.toLatin1().data());
+ if (idx == -1) {
+ printf("MusE:%s: unknown tag %s\n",
+ meta->className(), tag.toLatin1().data());
+ return;
+ }
+ QMetaProperty p = meta->property(idx);
+ QVariant v;
+ switch(p.type()) {
+ case QVariant::Int:
+ case QVariant::Bool:
+ v.setValue(e.text().toInt());
+ break;
+ case QVariant::Double:
+ v.setValue(e.text().toDouble());
+ break;
+ case QVariant::String:
+ v.setValue(e.text());
+ break;
+ case QVariant::Rect:
+ v.setValue(AL::readGeometry(node));
+ break;
+ case QVariant::Point:
+ {
+ int x = e.attribute("x","0").toInt();
+ int y = e.attribute("y","0").toInt();
+ v.setValue(QPoint(x, y));
+ }
+ break;
+ default:
+ printf("MusE:%s type %d not implemented\n",
+ meta->className(), p.type());
+ return;
+ }
+ if (p.isWritable())
+ p.write(o, v);
+ }
+
+//---------------------------------------------------------
+// dump
+//---------------------------------------------------------
+
+void Xml::dump(int len, const unsigned char* p)
+ {
+ putLevel();
+ int col = 0;
+ setFieldWidth(5);
+ setNumberFlags(numberFlags() | QTextStream::ShowBase);
+ setIntegerBase(16);
+ for (int i = 0; i < len; ++i, ++col) {
+ if (col >= 16) {
+ setFieldWidth(0);
+ *this << endl;
+ col = 0;
+ putLevel();
+ setFieldWidth(5);
+ }
+ *this << (p[i] & 0xff);
+ }
+ if (col)
+ *this << endl << dec;
+ setFieldWidth(0);
+ setIntegerBase(10);
+ }
+
+//---------------------------------------------------------
+// domError
+//---------------------------------------------------------
+
+void domError(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ QString tag(e.tagName());
+ QString s;
+ QDomNode dn(node);
+ while (!dn.parentNode().isNull()) {
+ dn = dn.parentNode();
+ const QDomElement e = dn.toElement();
+ const QString k(e.tagName());
+ if (!s.isEmpty())
+ s += ":";
+ s += k;
+ }
+ fprintf(stderr, "%s: Unknown Node <%s>, type %d\n",
+ s.toLatin1().data(), tag.toLatin1().data(), node.nodeType());
+ if (node.isText()) {
+ fprintf(stderr, " text node <%s>\n", node.toText().data().toLatin1().data());
+ }
+ }
+
+//---------------------------------------------------------
+// domNotImplemented
+//---------------------------------------------------------
+
+void domNotImplemented(QDomNode node)
+ {
+ if (!AL::debugMsg)
+ return;
+ QDomElement e = node.toElement();
+ QString tag(e.tagName());
+ QString s;
+ QDomNode dn(node);
+ while (!dn.parentNode().isNull()) {
+ dn = dn.parentNode();
+ const QDomElement e = dn.toElement();
+ const QString k(e.tagName());
+ if (!s.isEmpty())
+ s += ":";
+ s += k;
+ }
+ fprintf(stderr, "%s: Node not implemented: <%s>, type %d\n",
+ s.toLatin1().data(), tag.toLatin1().data(), node.nodeType());
+ if (node.isText()) {
+ fprintf(stderr, " text node <%s>\n", node.toText().data().toLatin1().data());
+ }
+ }
+}
+
diff --git a/muse_qt4_evolution/al/xml.h b/muse_qt4_evolution/al/xml.h
new file mode 100644
index 00000000..340d8190
--- /dev/null
+++ b/muse_qt4_evolution/al/xml.h
@@ -0,0 +1,69 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// 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.
+//=============================================================================
+
+#ifndef __XML_H__
+#define __XML_H__
+
+namespace AL {
+
+//---------------------------------------------------------
+// Xml
+//---------------------------------------------------------
+
+class Xml : public QTextStream {
+ int level;
+
+ public:
+ Xml();
+ Xml(QIODevice*);
+
+ void header();
+ void putLevel();
+
+ void put(const QString&);
+
+ void stag(const QString&);
+ void etag(const char*);
+
+ void tagE(const QString&);
+
+ void tag(const char* name, int);
+ void tag(const char* name, unsigned);
+ void tag(const char* name, const double& val);
+ void tag(const char* name, float val);
+ void tag(const char* name, const QString& s);
+ void tag(const char* name, const QColor& color);
+ void tag(const char* name, const QWidget* g);
+ void tag(const char* name, const QRect& r);
+
+ void dump(int n, const unsigned char*);
+ void writeProperties(const QObject*);
+
+ static QString xmlString(const QString&);
+ };
+
+extern QRect readGeometry(QDomNode);
+extern void readProperties(QObject* o, QDomNode node);
+extern void domError(QDomNode node);
+extern void domNotImplemented(QDomNode node);
+}
+
+#endif
+