]> git.saurik.com Git - wxWidgets.git/commitdiff
* Added wxMMedia in the repository so people interrested in it can work on it
authorGuilhem Lavaux <lavaux@easynet.fr>
Mon, 9 Nov 1998 18:37:38 +0000 (18:37 +0000)
committerGuilhem Lavaux <lavaux@easynet.fr>
Mon, 9 Nov 1998 18:37:38 +0000 (18:37 +0000)
* WARNING! It is quite unstable on Windows and it doesn't work on Linux for
  the moment because I didn't finish fixing the CODEC stream.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@975 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

54 files changed:
utils/wxMMedia/Makefile [new file with mode: 0644]
utils/wxMMedia/Makefile.in [new file with mode: 0644]
utils/wxMMedia/adpcm/g711.cpp [new file with mode: 0644]
utils/wxMMedia/adpcm/g721.cpp [new file with mode: 0644]
utils/wxMMedia/adpcm/g723_24.cpp [new file with mode: 0644]
utils/wxMMedia/adpcm/g723_40.cpp [new file with mode: 0644]
utils/wxMMedia/adpcm/g72x.cpp [new file with mode: 0644]
utils/wxMMedia/adpcm/g72x.h [new file with mode: 0644]
utils/wxMMedia/cdbase.cpp [new file with mode: 0644]
utils/wxMMedia/cdbase.h [new file with mode: 0644]
utils/wxMMedia/cdunix.cpp [new file with mode: 0644]
utils/wxMMedia/cdunix.h [new file with mode: 0644]
utils/wxMMedia/cdwin.cpp [new file with mode: 0644]
utils/wxMMedia/cdwin.h [new file with mode: 0644]
utils/wxMMedia/mmdata.cpp [new file with mode: 0644]
utils/wxMMedia/mmedia.h [new file with mode: 0644]
utils/wxMMedia/mmfile.cpp [new file with mode: 0644]
utils/wxMMedia/mmfile.h [new file with mode: 0644]
utils/wxMMedia/mmriff.cpp [new file with mode: 0644]
utils/wxMMedia/mmriff.h [new file with mode: 0644]
utils/wxMMedia/mmsolve.cpp [new file with mode: 0644]
utils/wxMMedia/mmsolve.h [new file with mode: 0644]
utils/wxMMedia/mmtype.h [new file with mode: 0644]
utils/wxMMedia/sndaiff.cpp [new file with mode: 0644]
utils/wxMMedia/sndaiff.h [new file with mode: 0644]
utils/wxMMedia/sndau.cpp [new file with mode: 0644]
utils/wxMMedia/sndau.h [new file with mode: 0644]
utils/wxMMedia/sndfile.cpp [new file with mode: 0644]
utils/wxMMedia/sndfile.h [new file with mode: 0644]
utils/wxMMedia/sndfrag.cpp [new file with mode: 0644]
utils/wxMMedia/sndfrag.h [new file with mode: 0644]
utils/wxMMedia/sndfrmt.cpp [new file with mode: 0644]
utils/wxMMedia/sndfrmt.h [new file with mode: 0644]
utils/wxMMedia/sndmulaw.cpp [new file with mode: 0644]
utils/wxMMedia/sndmulaw.h [new file with mode: 0644]
utils/wxMMedia/sndpcm.cpp [new file with mode: 0644]
utils/wxMMedia/sndpcm.h [new file with mode: 0644]
utils/wxMMedia/sndsnd.cpp [new file with mode: 0644]
utils/wxMMedia/sndsnd.h [new file with mode: 0644]
utils/wxMMedia/snduss.cpp [new file with mode: 0644]
utils/wxMMedia/snduss.h [new file with mode: 0644]
utils/wxMMedia/sndwav.cpp [new file with mode: 0644]
utils/wxMMedia/sndwav.h [new file with mode: 0644]
utils/wxMMedia/sndwin.cpp [new file with mode: 0644]
utils/wxMMedia/sndwin.h [new file with mode: 0644]
utils/wxMMedia/ulaw.h [new file with mode: 0644]
utils/wxMMedia/vidbase.cpp [new file with mode: 0644]
utils/wxMMedia/vidbase.h [new file with mode: 0644]
utils/wxMMedia/vidwin.cpp [new file with mode: 0644]
utils/wxMMedia/vidwin.h [new file with mode: 0644]
utils/wxMMedia/vidxanm.cpp [new file with mode: 0644]
utils/wxMMedia/vidxanm.h [new file with mode: 0644]
utils/wxMMedia/wave.cpp [new file with mode: 0644]
utils/wxMMedia/wave.h [new file with mode: 0644]

diff --git a/utils/wxMMedia/Makefile b/utils/wxMMedia/Makefile
new file mode 100644 (file)
index 0000000..bccce53
--- /dev/null
@@ -0,0 +1 @@
+include ../../setup/general/makeapp
diff --git a/utils/wxMMedia/Makefile.in b/utils/wxMMedia/Makefile.in
new file mode 100644 (file)
index 0000000..e4effa2
--- /dev/null
@@ -0,0 +1,38 @@
+# WXXT base directory
+WXBASEDIR=@WXBASEDIR@
+
+# set the OS type for compilation
+OS=@OS@
+# compile a library only
+RULE=gslib
+
+# define common stuff
+
+# define library name
+LIB_TARGET=wxmmedia
+LIB_MAJOR=2
+LIB_MINOR=0
+# define library sources
+ADPCM_SRC=\
+g711.cpp g721.cpp g723_24.cpp g723_40.cpp g72x.cpp
+
+MMEDIA_SRC=\
+mmdata.cpp mmfile.cpp mmsolve.cpp sndsnd.cpp sndfrmt.cpp sndpcm.o \
+snduss.cpp sndfile.cpp sndwav.cpp mmriff.cpp vidbase.cpp vidxanm.cpp \
+cdbase.cpp cdunix.cpp
+
+LIB_SRC= $(ADPCM_SRC:%.cpp=adpcm/%.cpp) $(MMEDIA_SRC)
+
+#define library objects
+LIB_OBJ=\
+$(LIB_SRC:%.cpp=%.o)
+
+#additional things needed for compile
+ADD_COMPILE= -I$(UTILS)/wxthread
+
+all::
+       -mkdir -p adpcm
+
+# include the definitions now
+include ../../../template.mak
+
diff --git a/utils/wxMMedia/adpcm/g711.cpp b/utils/wxMMedia/adpcm/g711.cpp
new file mode 100644 (file)
index 0000000..d4d60a5
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use.  Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * g711.c
+ *
+ * u-law, A-law and linear PCM conversions.
+ */
+#define        SIGN_BIT        (0x80)          /* Sign bit for a A-law byte. */
+#define        QUANT_MASK      (0xf)           /* Quantization field mask. */
+#define        NSEGS           (8)             /* Number of A-law segments. */
+#define        SEG_SHIFT       (4)             /* Left shift for segment number. */
+#define        SEG_MASK        (0x70)          /* Segment field mask. */
+
+static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
+                           0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
+
+/* copy from CCITT G.711 specifications */
+unsigned char _u2a[128] = {                    /* u- to A-law conversions */
+       1,      1,      2,      2,      3,      3,      4,      4,
+       5,      5,      6,      6,      7,      7,      8,      8,
+       9,      10,     11,     12,     13,     14,     15,     16,
+       17,     18,     19,     20,     21,     22,     23,     24,
+       25,     27,     29,     31,     33,     34,     35,     36,
+       37,     38,     39,     40,     41,     42,     43,     44,
+       46,     48,     49,     50,     51,     52,     53,     54,
+       55,     56,     57,     58,     59,     60,     61,     62,
+       64,     65,     66,     67,     68,     69,     70,     71,
+       72,     73,     74,     75,     76,     77,     78,     79,
+       81,     82,     83,     84,     85,     86,     87,     88,
+       89,     90,     91,     92,     93,     94,     95,     96,
+       97,     98,     99,     100,    101,    102,    103,    104,
+       105,    106,    107,    108,    109,    110,    111,    112,
+       113,    114,    115,    116,    117,    118,    119,    120,
+       121,    122,    123,    124,    125,    126,    127,    128};
+
+unsigned char _a2u[128] = {                    /* A- to u-law conversions */
+       1,      3,      5,      7,      9,      11,     13,     15,
+       16,     17,     18,     19,     20,     21,     22,     23,
+       24,     25,     26,     27,     28,     29,     30,     31,
+       32,     32,     33,     33,     34,     34,     35,     35,
+       36,     37,     38,     39,     40,     41,     42,     43,
+       44,     45,     46,     47,     48,     48,     49,     49,
+       50,     51,     52,     53,     54,     55,     56,     57,
+       58,     59,     60,     61,     62,     63,     64,     64,
+       65,     66,     67,     68,     69,     70,     71,     72,
+       73,     74,     75,     76,     77,     78,     79,     79,
+       80,     81,     82,     83,     84,     85,     86,     87,
+       88,     89,     90,     91,     92,     93,     94,     95,
+       96,     97,     98,     99,     100,    101,    102,    103,
+       104,    105,    106,    107,    108,    109,    110,    111,
+       112,    113,    114,    115,    116,    117,    118,    119,
+       120,    121,    122,    123,    124,    125,    126,    127};
+
+static int
+search(
+       int             val,
+       short           *table,
+       int             size)
+{
+       int             i;
+
+       for (i = 0; i < size; i++) {
+               if (val <= *table++)
+                       return (i);
+       }
+       return (size);
+}
+
+/*
+ * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
+ *
+ * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
+ *
+ *             Linear Input Code       Compressed Code
+ *     ------------------------        ---------------
+ *     0000000wxyza                    000wxyz
+ *     0000001wxyza                    001wxyz
+ *     000001wxyzab                    010wxyz
+ *     00001wxyzabc                    011wxyz
+ *     0001wxyzabcd                    100wxyz
+ *     001wxyzabcde                    101wxyz
+ *     01wxyzabcdef                    110wxyz
+ *     1wxyzabcdefg                    111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char
+linear2alaw(
+       int             pcm_val)        /* 2's complement (16-bit range) */
+{
+       int             mask;
+       int             seg;
+       unsigned char   aval;
+
+       if (pcm_val >= 0) {
+               mask = 0xD5;            /* sign (7th) bit = 1 */
+       } else {
+               mask = 0x55;            /* sign bit = 0 */
+               pcm_val = -pcm_val - 8;
+       }
+
+       /* Convert the scaled magnitude to segment number. */
+       seg = search(pcm_val, seg_end, 8);
+
+       /* Combine the sign, segment, and quantization bits. */
+
+       if (seg >= 8)           /* out of range, return maximum value. */
+               return (0x7F ^ mask);
+       else {
+               aval = seg << SEG_SHIFT;
+               if (seg < 2)
+                       aval |= (pcm_val >> 4) & QUANT_MASK;
+               else
+                       aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
+               return (aval ^ mask);
+       }
+}
+
+/*
+ * alaw2linear() - Convert an A-law value to 16-bit linear PCM
+ *
+ */
+int
+alaw2linear(
+       unsigned char   a_val)
+{
+       int             t;
+       int             seg;
+
+       a_val ^= 0x55;
+
+       t = (a_val & QUANT_MASK) << 4;
+       seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
+       switch (seg) {
+       case 0:
+               t += 8;
+               break;
+       case 1:
+               t += 0x108;
+               break;
+       default:
+               t += 0x108;
+               t <<= seg - 1;
+       }
+       return ((a_val & SIGN_BIT) ? t : -t);
+}
+
+#define        BIAS            (0x84)          /* Bias for linear code. */
+
+/*
+ * linear2ulaw() - Convert a linear PCM value to u-law
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ *     Biased Linear Input Code        Compressed Code
+ *     ------------------------        ---------------
+ *     00000001wxyza                   000wxyz
+ *     0000001wxyzab                   001wxyz
+ *     000001wxyzabc                   010wxyz
+ *     00001wxyzabcd                   011wxyz
+ *     0001wxyzabcde                   100wxyz
+ *     001wxyzabcdef                   101wxyz
+ *     01wxyzabcdefg                   110wxyz
+ *     1wxyzabcdefgh                   111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz.  * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char
+linear2ulaw(
+       int             pcm_val)        /* 2's complement (16-bit range) */
+{
+       int             mask;
+       int             seg;
+       unsigned char   uval;
+
+       /* Get the sign and the magnitude of the value. */
+       if (pcm_val < 0) {
+               pcm_val = BIAS - pcm_val;
+               mask = 0x7F;
+       } else {
+               pcm_val += BIAS;
+               mask = 0xFF;
+       }
+
+       /* Convert the scaled magnitude to segment number. */
+       seg = search(pcm_val, seg_end, 8);
+
+       /*
+        * Combine the sign, segment, quantization bits;
+        * and complement the code word.
+        */
+       if (seg >= 8)           /* out of range, return maximum value. */
+               return (0x7F ^ mask);
+       else {
+               uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
+               return (uval ^ mask);
+       }
+
+}
+
+/*
+ * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
+ *
+ * First, a biased linear code is derived from the code word. An unbiased
+ * output can then be obtained by subtracting 33 from the biased code.
+ *
+ * Note that this function expects to be passed the complement of the
+ * original code word. This is in keeping with ISDN conventions.
+ */
+int
+ulaw2linear(
+       unsigned char   u_val)
+{
+       int             t;
+
+       /* Complement to obtain normal u-law value. */
+       u_val = ~u_val;
+
+       /*
+        * Extract and bias the quantization bits. Then
+        * shift up by the segment number and subtract out the bias.
+        */
+       t = ((u_val & QUANT_MASK) << 3) + BIAS;
+       t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
+
+       return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
+}
+
+/* A-law to u-law conversion */
+unsigned char
+alaw2ulaw(
+       unsigned char   aval)
+{
+       aval &= 0xff;
+       return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
+           (0x7F ^ _a2u[aval ^ 0x55]));
+}
+
+/* u-law to A-law conversion */
+unsigned char
+ulaw2alaw(
+       unsigned char   uval)
+{
+       uval &= 0xff;
+       return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
+           (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
+}
diff --git a/utils/wxMMedia/adpcm/g721.cpp b/utils/wxMMedia/adpcm/g721.cpp
new file mode 100644 (file)
index 0000000..3411d1a
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use.  Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * g721.c
+ *
+ * Description:
+ *
+ * g721_encoder(), g721_decoder()
+ *
+ * These routines comprise an implementation of the CCITT G.721 ADPCM
+ * coding algorithm.  Essentially, this implementation is identical to
+ * the bit level description except for a few deviations which
+ * take advantage of work station attributes, such as hardware 2's
+ * complement arithmetic and large memory.  Specifically, certain time
+ * consuming operations such as multiplications are replaced
+ * with lookup tables and software 2's complement operations are
+ * replaced with hardware 2's complement.
+ *
+ * The deviation from the bit level specification (lookup tables)
+ * preserves the bit level performance specifications.
+ *
+ * As outlined in the G.721 Recommendation, the algorithm is broken
+ * down into modules.  Each section of code below is preceded by
+ * the name of the module which it is implementing.
+ *
+ */
+#include "g72x.h"
+
+static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400};
+/*
+ * Maps G.721 code word to reconstructed scale factor normalized log
+ * magnitude values.
+ */
+static short   _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
+                               425, 373, 323, 273, 213, 135, 4, -2048};
+
+/* Maps G.721 code word to log of scale factor multiplier. */
+static short   _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
+                               1122, 355, 198, 112, 64, 41, 18, -12};
+/*
+ * Maps G.721 code words to a set of values whose long and short
+ * term averages are computed and then compared to give an indication
+ * how stationary (steady state) the signal is.
+ */
+static short   _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
+                               0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
+
+/*
+ * g721_encoder()
+ *
+ * Encodes the input vale of linear PCM, A-law or u-law data sl and returns
+ * the resulting code. -1 is returned for unknown input coding value.
+ */
+int
+g721_encoder(
+       int             sl,
+       int             in_coding,
+       struct g72x_state *state_ptr)
+{
+       short           sezi, se, sez;          /* ACCUM */
+       short           d;                      /* SUBTA */
+       short           sr;                     /* ADDB */
+       short           y;                      /* MIX */
+       short           dqsez;                  /* ADDC */
+       short           dq, i;
+
+       switch (in_coding) {    /* linearize input sample to 14-bit PCM */
+       case AUDIO_ENCODING_ALAW:
+               sl = alaw2linear(sl) >> 2;
+               break;
+       case AUDIO_ENCODING_ULAW:
+               sl = ulaw2linear(sl) >> 2;
+               break;
+       case AUDIO_ENCODING_LINEAR:
+               sl = ((short)sl) >> 2;          /* 14-bit dynamic range */
+               break;
+       default:
+               return (-1);
+       }
+
+       sezi = predictor_zero(state_ptr);
+       sez = sezi >> 1;
+       se = (sezi + predictor_pole(state_ptr)) >> 1;   /* estimated signal */
+
+       d = sl - se;                            /* estimation difference */
+
+       /* quantize the prediction difference */
+       y = step_size(state_ptr);               /* quantizer step size */
+       i = quantize(d, y, qtab_721, 7);        /* i = ADPCM code */
+
+       dq = reconstruct(i & 8, _dqlntab[i], y);        /* quantized est diff */
+
+       sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq;   /* reconst. signal */
+
+       dqsez = sr + sez - se;                  /* pole prediction diff. */
+
+       update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
+
+       return (i);
+}
+
+/*
+ * g721_decoder()
+ *
+ * Description:
+ *
+ * Decodes a 4-bit code of G.721 encoded data of i and
+ * returns the resulting linear PCM, A-law or u-law value.
+ * return -1 for unknown out_coding value.
+ */
+int
+g721_decoder(
+       int             i,
+       int             out_coding,
+       struct g72x_state *state_ptr)
+{
+       short           sezi, sei, sez, se;     /* ACCUM */
+       short           y;                      /* MIX */
+       short           sr;                     /* ADDB */
+       short           dq;
+       short           dqsez;
+
+       i &= 0x0f;                      /* mask to get proper bits */
+       sezi = predictor_zero(state_ptr);
+       sez = sezi >> 1;
+       sei = sezi + predictor_pole(state_ptr);
+       se = sei >> 1;                  /* se = estimated signal */
+
+       y = step_size(state_ptr);       /* dynamic quantizer step size */
+
+       dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */
+
+       sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */
+
+       dqsez = sr - se + sez;                  /* pole prediction diff. */
+
+       update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
+
+       switch (out_coding) {
+       case AUDIO_ENCODING_ALAW:
+               return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721));
+       case AUDIO_ENCODING_ULAW:
+               return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721));
+       case AUDIO_ENCODING_LINEAR:
+               return (sr << 2);       /* sr was 14-bit dynamic range */
+       default:
+               return (-1);
+       }
+}
diff --git a/utils/wxMMedia/adpcm/g723_24.cpp b/utils/wxMMedia/adpcm/g723_24.cpp
new file mode 100644 (file)
index 0000000..ba122ea
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use.  Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * g723_24.c
+ *
+ * Description:
+ *
+ * g723_24_encoder(), g723_24_decoder()
+ *
+ * These routines comprise an implementation of the CCITT G.723 24 Kbps
+ * ADPCM coding algorithm.  Essentially, this implementation is identical to
+ * the bit level description except for a few deviations which take advantage
+ * of workstation attributes, such as hardware 2's complement arithmetic.
+ *
+ */
+#include "g72x.h"
+
+/*
+ * Maps G.723_24 code word to reconstructed scale factor normalized log
+ * magnitude values.
+ */
+static short   _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048};
+
+/* Maps G.723_24 code word to log of scale factor multiplier. */
+static short   _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128};
+
+/*
+ * Maps G.723_24 code words to a set of values whose long and short
+ * term averages are computed and then compared to give an indication
+ * how stationary (steady state) the signal is.
+ */
+static short   _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0};
+
+static short qtab_723_24[3] = {8, 218, 331};
+
+/*
+ * g723_24_encoder()
+ *
+ * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.
+ * Returns -1 if invalid input coding value.
+ */
+int
+g723_24_encoder(
+       int             sl,
+       int             in_coding,
+       struct g72x_state *state_ptr)
+{
+       short           sei, sezi, se, sez;     /* ACCUM */
+       short           d;                      /* SUBTA */
+       short           y;                      /* MIX */
+       short           sr;                     /* ADDB */
+       short           dqsez;                  /* ADDC */
+       short           dq, i;
+
+       switch (in_coding) {    /* linearize input sample to 14-bit PCM */
+       case AUDIO_ENCODING_ALAW:
+               sl = alaw2linear(sl) >> 2;
+               break;
+       case AUDIO_ENCODING_ULAW:
+               sl = ulaw2linear(sl) >> 2;
+               break;
+       case AUDIO_ENCODING_LINEAR:
+               sl = ((short)sl) >> 2;          /* sl of 14-bit dynamic range */
+               break;
+       default:
+               return (-1);
+       }
+
+       sezi = predictor_zero(state_ptr);
+       sez = sezi >> 1;
+       sei = sezi + predictor_pole(state_ptr);
+       se = sei >> 1;                  /* se = estimated signal */
+
+       d = sl - se;                    /* d = estimation diff. */
+
+       /* quantize prediction difference d */
+       y = step_size(state_ptr);       /* quantizer step size */
+       i = quantize(d, y, qtab_723_24, 3);     /* i = ADPCM code */
+       dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */
+
+       sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
+
+       dqsez = sr + sez - se;          /* pole prediction diff. */
+
+       update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+       return (i);
+}
+
+/*
+ * g723_24_decoder()
+ *
+ * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns
+ * the resulting 16-bit linear PCM, A-law or u-law sample value.
+ * -1 is returned if the output coding is unknown.
+ */
+int
+g723_24_decoder(
+       int             i,
+       int             out_coding,
+       struct g72x_state *state_ptr)
+{
+       short           sezi, sei, sez, se;     /* ACCUM */
+       short           y;                      /* MIX */
+       short           sr;                     /* ADDB */
+       short           dq;
+       short           dqsez;
+
+       i &= 0x07;                      /* mask to get proper bits */
+       sezi = predictor_zero(state_ptr);
+       sez = sezi >> 1;
+       sei = sezi + predictor_pole(state_ptr);
+       se = sei >> 1;                  /* se = estimated signal */
+
+       y = step_size(state_ptr);       /* adaptive quantizer step size */
+       dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */
+
+       sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
+
+       dqsez = sr - se + sez;                  /* pole prediction diff. */
+
+       update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+       switch (out_coding) {
+       case AUDIO_ENCODING_ALAW:
+               return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24));
+       case AUDIO_ENCODING_ULAW:
+               return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24));
+       case AUDIO_ENCODING_LINEAR:
+               return (sr << 2);       /* sr was of 14-bit dynamic range */
+       default:
+               return (-1);
+       }
+}
diff --git a/utils/wxMMedia/adpcm/g723_40.cpp b/utils/wxMMedia/adpcm/g723_40.cpp
new file mode 100644 (file)
index 0000000..b8ec06a
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use.  Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * g723_40.c
+ *
+ * Description:
+ *
+ * g723_40_encoder(), g723_40_decoder()
+ *
+ * These routines comprise an implementation of the CCITT G.723 40Kbps
+ * ADPCM coding algorithm.  Essentially, this implementation is identical to
+ * the bit level description except for a few deviations which
+ * take advantage of workstation attributes, such as hardware 2's
+ * complement arithmetic.
+ *
+ * The deviation from the bit level specification (lookup tables),
+ * preserves the bit level performance specifications.
+ *
+ * As outlined in the G.723 Recommendation, the algorithm is broken
+ * down into modules.  Each section of code below is preceded by
+ * the name of the module which it is implementing.
+ *
+ */
+#include "g72x.h"
+
+/*
+ * Maps G.723_40 code word to ructeconstructed scale factor normalized log
+ * magnitude values.
+ */
+static short   _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318,
+                               358, 395, 429, 459, 488, 514, 539, 566,
+                               566, 539, 514, 488, 459, 429, 395, 358,
+                               318, 274, 224, 169, 104, 28, -66, -2048};
+
+/* Maps G.723_40 code word to log of scale factor multiplier. */
+static short   _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200,
+                       4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272,
+                       22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512,
+                       3200, 1856, 1312, 1280, 1248, 768, 448, 448};
+
+/*
+ * Maps G.723_40 code words to a set of values whose long and short
+ * term averages are computed and then compared to give an indication
+ * how stationary (steady state) the signal is.
+ */
+static short   _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200,
+                       0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00,
+                       0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200,
+                       0x200, 0x200, 0x200, 0, 0, 0, 0, 0};
+
+static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339,
+                               378, 413, 445, 475, 502, 528, 553};
+
+/*
+ * g723_40_encoder()
+ *
+ * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens
+ * the resulting 5-bit CCITT G.723 40Kbps code.
+ * Returns -1 if the input coding value is invalid.
+ */
+int
+g723_40_encoder(
+       int             sl,
+       int             in_coding,
+       struct g72x_state *state_ptr)
+{
+       short           sei, sezi, se, sez;     /* ACCUM */
+       short           d;                      /* SUBTA */
+       short           y;                      /* MIX */
+       short           sr;                     /* ADDB */
+       short           dqsez;                  /* ADDC */
+       short           dq, i;
+
+       switch (in_coding) {    /* linearize input sample to 14-bit PCM */
+       case AUDIO_ENCODING_ALAW:
+               sl = alaw2linear(sl) >> 2;
+               break;
+       case AUDIO_ENCODING_ULAW:
+               sl = ulaw2linear(sl) >> 2;
+               break;
+       case AUDIO_ENCODING_LINEAR:
+               sl = ((short) sl) >> 2;         /* sl of 14-bit dynamic range */
+               break;
+       default:
+               return (-1);
+       }
+
+       sezi = predictor_zero(state_ptr);
+       sez = sezi >> 1;
+       sei = sezi + predictor_pole(state_ptr);
+       se = sei >> 1;                  /* se = estimated signal */
+
+       d = sl - se;                    /* d = estimation difference */
+
+       /* quantize prediction difference */
+       y = step_size(state_ptr);       /* adaptive quantizer step size */
+       i = quantize(d, y, qtab_723_40, 15);    /* i = ADPCM code */
+
+       dq = reconstruct(i & 0x10, _dqlntab[i], y);     /* quantized diff */
+
+       sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */
+
+       dqsez = sr + sez - se;          /* dqsez = pole prediction diff. */
+
+       update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+       return (i);
+}
+
+/*
+ * g723_40_decoder()
+ *
+ * Decodes a 5-bit CCITT G.723 40Kbps code and returns
+ * the resulting 16-bit linear PCM, A-law or u-law sample value.
+ * -1 is returned if the output coding is unknown.
+ */
+int
+g723_40_decoder(
+       int             i,
+       int             out_coding,
+       struct g72x_state *state_ptr)
+{
+       short           sezi, sei, sez, se;     /* ACCUM */
+       short           y;                      /* MIX */
+       short           sr;                     /* ADDB */
+       short           dq;
+       short           dqsez;
+
+       i &= 0x1f;                      /* mask to get proper bits */
+       sezi = predictor_zero(state_ptr);
+       sez = sezi >> 1;
+       sei = sezi + predictor_pole(state_ptr);
+       se = sei >> 1;                  /* se = estimated signal */
+
+       y = step_size(state_ptr);       /* adaptive quantizer step size */
+       dq = reconstruct(i & 0x10, _dqlntab[i], y);     /* estimation diff. */
+
+       sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */
+
+       dqsez = sr - se + sez;          /* pole prediction diff. */
+
+       update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+       switch (out_coding) {
+       case AUDIO_ENCODING_ALAW:
+               return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40));
+       case AUDIO_ENCODING_ULAW:
+               return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40));
+       case AUDIO_ENCODING_LINEAR:
+               return (sr << 2);       /* sr was of 14-bit dynamic range */
+       default:
+               return (-1);
+       }
+}
diff --git a/utils/wxMMedia/adpcm/g72x.cpp b/utils/wxMMedia/adpcm/g72x.cpp
new file mode 100644 (file)
index 0000000..ff571bd
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use.  Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * g72x.c
+ *
+ * Common routines for G.721 and G.723 conversions.
+ */
+
+#include <stdlib.h>
+#include "g72x.h"
+
+static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
+                       0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000};
+
+/*
+ * quan()
+ *
+ * quantizes the input val against the table of size short integers.
+ * It returns i if table[i - 1] <= val < table[i].
+ *
+ * Using linear search for simple coding.
+ */
+static int
+quan(
+       int             val,
+       short           *table,
+       int             size)
+{
+       int             i;
+
+       for (i = 0; i < size; i++)
+               if (val < *table++)
+                       break;
+       return (i);
+}
+
+static char quan2_tab[65536];
+static short base2_tab[65536];
+static int init_tabs_done = 0;
+
+inline char quan2 (unsigned short val)
+{
+       return quan2_tab[val];
+}
+
+inline short base2 (unsigned short val)
+{
+       return base2_tab[val];
+}
+
+static void init_quan2_tab (void)
+{
+       long i;
+
+       for (i = 0; i < 65536; i++) {
+               quan2_tab[i] = quan (i, power2, 15);
+       };
+}
+
+static void init_base2_tab (void)
+{
+       long i;
+       short exp;
+
+       for (i = 0; i < 65536; i++) {
+               exp = quan2 (short (i));
+               base2_tab[i] = short ((exp << 6) + ((i << 6) >> exp));
+       };
+}
+
+static void init_tabs (void)
+{
+       if (init_tabs_done) return;
+
+       init_quan2_tab();
+       init_base2_tab();
+
+       init_tabs_done = 1;
+}
+
+/*
+ * fmult()
+ *
+ * returns the integer product of the 14-bit integer "an" and
+ * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
+ */
+static int
+fmult(
+       int             an,
+       int             srn)
+{
+       short           anmag, anexp, anmant;
+       short           wanexp, wanmant;
+       short           retval;
+
+       anmag = (an > 0) ? an : ((-an) & 0x1FFF);
+       anexp = quan2(anmag) - 6;
+       anmant = (anmag == 0) ? 32 :
+           (anexp >= 0) ? anmag >> anexp : anmag << -anexp;
+       wanexp = anexp + ((srn >> 6) & 0xF) - 13;
+
+       wanmant = (anmant * (srn & 077) + 0x30) >> 4;
+       retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
+           (wanmant >> -wanexp);
+
+       return (((an ^ srn) < 0) ? -retval : retval);
+}
+
+/*
+ * g72x_init_state()
+ *
+ * This routine initializes and/or resets the g72x_state structure
+ * pointed to by 'state_ptr'.
+ * All the initial state values are specified in the CCITT G.721 document.
+ */
+void
+g72x_init_state(
+       struct g72x_state *state_ptr)
+{
+       int             cnta;
+
+       init_tabs ();
+
+       state_ptr->yl = 34816;
+       state_ptr->yu = 544;
+       state_ptr->dms = 0;
+       state_ptr->dml = 0;
+       state_ptr->ap = 0;
+       for (cnta = 0; cnta < 2; cnta++) {
+               state_ptr->a[cnta] = 0;
+               state_ptr->pk[cnta] = 0;
+               state_ptr->sr[cnta] = 32;
+       }
+       for (cnta = 0; cnta < 6; cnta++) {
+               state_ptr->b[cnta] = 0;
+               state_ptr->dq[cnta] = 32;
+       }
+       state_ptr->td = 0;
+}
+
+/*
+ * predictor_zero()
+ *
+ * computes the estimated signal from 6-zero predictor.
+ *
+ */
+int
+predictor_zero(
+       struct g72x_state *state_ptr)
+{
+       int             i;
+       int             sezi;
+
+       sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
+       for (i = 1; i < 6; i++)                 /* ACCUM */
+               sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
+       return (sezi);
+}
+/*
+ * predictor_pole()
+ *
+ * computes the estimated signal from 2-pole predictor.
+ *
+ */
+int
+predictor_pole(
+       struct g72x_state *state_ptr)
+{
+       return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
+           fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
+}
+/*
+ * step_size()
+ *
+ * computes the quantization step size of the adaptive quantizer.
+ *
+ */
+int
+step_size(
+       struct g72x_state *state_ptr)
+{
+       int             y;
+       int             dif;
+       int             al;
+
+       if (state_ptr->ap >= 256)
+               return (state_ptr->yu);
+       else {
+               y = state_ptr->yl >> 6;
+               dif = state_ptr->yu - y;
+               al = state_ptr->ap >> 2;
+               if (dif > 0)
+                       y += (dif * al) >> 6;
+               else if (dif < 0)
+                       y += (dif * al + 0x3F) >> 6;
+               return (y);
+       }
+}
+
+/*
+ * quantize()
+ *
+ * Given a raw sample, 'd', of the difference signal and a
+ * quantization step size scale factor, 'y', this routine returns the
+ * ADPCM codeword to which that sample gets quantized.  The step
+ * size scale factor division operation is done in the log base 2 domain
+ * as a subtraction.
+ */
+int
+quantize(
+       int             d,      /* Raw difference signal sample */
+       int             y,      /* Step size multiplier */
+       short           *table, /* quantization table */
+       int             size)   /* table size of short integers */
+{
+       short           dqm;    /* Magnitude of 'd' */
+       short           exp;    /* Integer part of base 2 log of 'd' */
+       short           mant;   /* Fractional part of base 2 log */
+       short           dl;     /* Log of magnitude of 'd' */
+       short           dln;    /* Step size scale factor normalized log */
+       int             i;
+
+       /*
+        * LOG
+        *
+        * Compute base 2 log of 'd', and store in 'dl'.
+        */
+       dqm = abs(d);
+       exp = quan2(dqm >> 1);
+       mant = ((dqm << 7) >> exp) & 0x7F;      /* Fractional portion. */
+       dl = (exp << 7) + mant;
+
+       /*
+        * SUBTB
+        *
+        * "Divide" by step size multiplier.
+        */
+       dln = dl - (y >> 2);
+
+       /*
+        * QUAN
+        *
+        * Obtain codword i for 'd'.
+        */
+       i = quan(dln, table, size);
+       if (d < 0)                      /* take 1's complement of i */
+               return ((size << 1) + 1 - i);
+       else if (i == 0)                /* take 1's complement of 0 */
+               return ((size << 1) + 1); /* new in 1988 */
+       else
+               return (i);
+}
+/*
+ * reconstruct()
+ *
+ * Returns reconstructed difference signal 'dq' obtained from
+ * codeword 'i' and quantization step size scale factor 'y'.
+ * Multiplication is performed in log base 2 domain as addition.
+ */
+int
+reconstruct(
+       int             sign,   /* 0 for non-negative value */
+       int             dqln,   /* G.72x codeword */
+       int             y)      /* Step size multiplier */
+{
+       short           dql;    /* Log of 'dq' magnitude */
+       short           dex;    /* Integer part of log */
+       short           dqt;
+       short           dq;     /* Reconstructed difference signal sample */
+
+       dql = dqln + (y >> 2);  /* ADDA */
+
+       if (dql < 0) {
+               return ((sign) ? -0x8000 : 0);
+       } else {                /* ANTILOG */
+               dex = (dql >> 7) & 15;
+               dqt = 128 + (dql & 127);
+               dq = (dqt << 7) >> (14 - dex);
+               return ((sign) ? (dq - 0x8000) : dq);
+       }
+}
+
+
+/*
+ * update()
+ *
+ * updates the state variables for each output code
+ */
+void
+update(
+       int             code_size,      /* distinguish 723_40 with others */
+       int             y,              /* quantizer step size */
+       int             wi,             /* scale factor multiplier */
+       int             fi,             /* for long/short term energies */
+       int             dq,             /* quantized prediction difference */
+       int             sr,             /* reconstructed signal */
+       int             dqsez,          /* difference from 2-pole predictor */
+       struct g72x_state *state_ptr)   /* coder state pointer */
+{
+       int             cnt;
+       short           mag;    /* Adaptive predictor, FLOAT A */
+       short           a2p;            /* LIMC */
+       short           a1ul;           /* UPA1 */
+       short           pks1;   /* UPA2 */
+       short           fa1;
+       char            tr;             /* tone/transition detector */
+       short           ylint, thr2, dqthr;
+       short           ylfrac, thr1;
+       short           pk0;
+
+       pk0 = (dqsez < 0) ? 1 : 0;      /* needed in updating predictor poles */
+
+       mag = dq & 0x7FFF;              /* prediction difference magnitude */
+       /* TRANS */
+       ylint = short (state_ptr->yl >> 15);    /* exponent part of yl */
+       ylfrac = (state_ptr->yl >> 10) & 0x1F;  /* fractional part of yl */
+       thr1 = (32 + ylfrac) << ylint;          /* threshold */
+       thr2 = (ylint > 9) ? 31 << 10 : thr1;   /* limit thr2 to 31 << 10 */
+       dqthr = (thr2 + (thr2 >> 1)) >> 1;      /* dqthr = 0.75 * thr2 */
+       if (state_ptr->td == 0)         /* signal supposed voice */
+               tr = 0;
+       else if (mag <= dqthr)          /* supposed data, but small mag */
+               tr = 0;                 /* treated as voice */
+       else                            /* signal is data (modem) */
+               tr = 1;
+
+       /*
+        * Quantizer scale factor adaptation.
+        */
+
+       /* FUNCTW & FILTD & DELAY */
+       /* update non-steady state step size multiplier */
+       state_ptr->yu = y + ((wi - y) >> 5);
+
+       /* LIMB */
+       if (state_ptr->yu < 544)        /* 544 <= yu <= 5120 */
+               state_ptr->yu = 544;
+       else if (state_ptr->yu > 5120)
+               state_ptr->yu = 5120;
+
+       /* FILTE & DELAY */
+       /* update steady state step size multiplier */
+       state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
+
+       /*
+        * Adaptive predictor coefficients.
+        */
+       if (tr == 1) {                  /* reset a's and b's for modem signal */
+               state_ptr->a[0] = 0;
+               state_ptr->a[1] = 0;
+               state_ptr->b[0] = 0;
+               state_ptr->b[1] = 0;
+               state_ptr->b[2] = 0;
+               state_ptr->b[3] = 0;
+               state_ptr->b[4] = 0;
+               state_ptr->b[5] = 0;
+
+               a2p = 0;                /* eliminate Compiler Warnings */
+       } else {                        /* update a's and b's */
+               pks1 = pk0 ^ state_ptr->pk[0];          /* UPA2 */
+
+               /* update predictor pole a[1] */
+               a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
+               if (dqsez != 0) {
+                       fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
+                       if (fa1 < -8191)        /* a2p = function of fa1 */
+                               a2p -= 0x100;
+                       else if (fa1 > 8191)
+                               a2p += 0xFF;
+                       else
+                               a2p += fa1 >> 5;
+
+                       if (pk0 ^ state_ptr->pk[1])
+                               /* LIMC */
+                               if (a2p <= -12160)
+                                       a2p = -12288;
+                               else if (a2p >= 12416)
+                                       a2p = 12288;
+                               else
+                                       a2p -= 0x80;
+                       else if (a2p <= -12416)
+                               a2p = -12288;
+                       else if (a2p >= 12160)
+                               a2p = 12288;
+                       else
+                               a2p += 0x80;
+               }
+
+               /* TRIGB & DELAY */
+               state_ptr->a[1] = a2p;
+
+               /* UPA1 */
+               /* update predictor pole a[0] */
+               state_ptr->a[0] -= state_ptr->a[0] >> 8;
+               if (dqsez != 0)
+                       if (pks1 == 0)
+                               state_ptr->a[0] += 192;
+                       else
+                               state_ptr->a[0] -= 192;
+
+               /* LIMD */
+               a1ul = 15360 - a2p;
+               if (state_ptr->a[0] < -a1ul)
+                       state_ptr->a[0] = -a1ul;
+               else if (state_ptr->a[0] > a1ul)
+                       state_ptr->a[0] = a1ul;
+
+               /* UPB : update predictor zeros b[6] */
+               for (cnt = 0; cnt < 6; cnt++) {
+                       if (code_size == 5)             /* for 40Kbps G.723 */
+                               state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
+                       else                    /* for G.721 and 24Kbps G.723 */
+                               state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
+                       if (dq & 0x7FFF) {                      /* XOR */
+                               if ((dq ^ state_ptr->dq[cnt]) >= 0)
+                                       state_ptr->b[cnt] += 128;
+                               else
+                                       state_ptr->b[cnt] -= 128;
+                       }
+               }
+       }
+
+       for (cnt = 5; cnt > 0; cnt--)
+               state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
+       /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
+       if (mag == 0) {
+               state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20;
+       } else {
+               state_ptr->dq[0] = (dq >= 0) ?
+                    base2 (mag) : base2 (mag) - 0x400;
+       }
+
+       state_ptr->sr[1] = state_ptr->sr[0];
+       /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
+       if (sr == 0) {
+               state_ptr->sr[0] = 0x20;
+       } else if (sr > 0) {
+               state_ptr->sr[0] = base2(sr);
+       } else if (sr > -32768) {
+               mag = -sr;
+               state_ptr->sr[0] = base2(mag) - 0x400;
+       } else
+               state_ptr->sr[0] = short (0xFC20);
+
+       /* DELAY A */
+       state_ptr->pk[1] = state_ptr->pk[0];
+       state_ptr->pk[0] = pk0;
+
+       /* TONE */
+       if (tr == 1)            /* this sample has been treated as data */
+               state_ptr->td = 0;      /* next one will be treated as voice */
+       else if (a2p < -11776)  /* small sample-to-sample correlation */
+               state_ptr->td = 1;      /* signal may be data */
+       else                            /* signal is voice */
+               state_ptr->td = 0;
+
+       /*
+        * Adaptation speed control.
+        */
+       state_ptr->dms += (fi - state_ptr->dms) >> 5;           /* FILTA */
+       state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7);  /* FILTB */
+
+       if (tr == 1)
+               state_ptr->ap = 256;
+       else if (y < 1536)                                      /* SUBTC */
+               state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
+       else if (state_ptr->td == 1)
+               state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
+       else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
+           (state_ptr->dml >> 3))
+               state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
+       else
+               state_ptr->ap += (-state_ptr->ap) >> 4;
+}
+
+/*
+ * tandem_adjust(sr, se, y, i, sign)
+ *
+ * At the end of ADPCM decoding, it simulates an encoder which may be receiving
+ * the output of this decoder as a tandem process. If the output of the
+ * simulated encoder differs from the input to this decoder, the decoder output
+ * is adjusted by one level of A-law or u-law codes.
+ *
+ * Input:
+ *     sr      decoder output linear PCM sample,
+ *     se      predictor estimate sample,
+ *     y       quantizer step size,
+ *     i       decoder input code,
+ *     sign    sign bit of code i
+ *
+ * Return:
+ *     adjusted A-law or u-law compressed sample.
+ */
+int
+tandem_adjust_alaw(
+       int             sr,     /* decoder output linear PCM sample */
+       int             se,     /* predictor estimate sample */
+       int             y,      /* quantizer step size */
+       int             i,      /* decoder input code */
+       int             sign,
+       short           *qtab)
+{
+       unsigned char   sp;     /* A-law compressed 8-bit code */
+       short           dx;     /* prediction error */
+       char            id;     /* quantized prediction error */
+       int             sd;     /* adjusted A-law decoded sample value */
+       int             im;     /* biased magnitude of i */
+       int             imx;    /* biased magnitude of id */
+
+       if (sr <= -32768)
+               sr = -1;
+       sp = linear2alaw((sr >> 1) << 3);       /* short to A-law compression */
+       dx = (alaw2linear(sp) >> 2) - se;       /* 16-bit prediction error */
+       id = quantize(dx, y, qtab, sign - 1);
+
+       if (id == i) {                  /* no adjustment on sp */
+               return (sp);
+       } else {                        /* sp adjustment needed */
+               /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
+               im = i ^ sign;          /* 2's complement to biased unsigned */
+               imx = id ^ sign;
+
+               if (imx > im) {         /* sp adjusted to next lower value */
+                       if (sp & 0x80) {
+                               sd = (sp == 0xD5) ? 0x55 :
+                                   ((sp ^ 0x55) - 1) ^ 0x55;
+                       } else {
+                               sd = (sp == 0x2A) ? 0x2A :
+                                   ((sp ^ 0x55) + 1) ^ 0x55;
+                       }
+               } else {                /* sp adjusted to next higher value */
+                       if (sp & 0x80)
+                               sd = (sp == 0xAA) ? 0xAA :
+                                   ((sp ^ 0x55) + 1) ^ 0x55;
+                       else
+                               sd = (sp == 0x55) ? 0xD5 :
+                                   ((sp ^ 0x55) - 1) ^ 0x55;
+               }
+               return (sd);
+       }
+}
+
+int
+tandem_adjust_ulaw(
+       int             sr,     /* decoder output linear PCM sample */
+       int             se,     /* predictor estimate sample */
+       int             y,      /* quantizer step size */
+       int             i,      /* decoder input code */
+       int             sign,
+       short           *qtab)
+{
+       unsigned char   sp;     /* u-law compressed 8-bit code */
+       short           dx;     /* prediction error */
+       char            id;     /* quantized prediction error */
+       int             sd;     /* adjusted u-law decoded sample value */
+       int             im;     /* biased magnitude of i */
+       int             imx;    /* biased magnitude of id */
+
+       if (sr <= -32768)
+               sr = 0;
+       sp = linear2ulaw(sr << 2);      /* short to u-law compression */
+       dx = (ulaw2linear(sp) >> 2) - se;       /* 16-bit prediction error */
+       id = quantize(dx, y, qtab, sign - 1);
+       if (id == i) {
+               return (sp);
+       } else {
+               /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
+               im = i ^ sign;          /* 2's complement to biased unsigned */
+               imx = id ^ sign;
+               if (imx > im) {         /* sp adjusted to next lower value */
+                       if (sp & 0x80)
+                               sd = (sp == 0xFF) ? 0x7E : sp + 1;
+                       else
+                               sd = (sp == 0) ? 0 : sp - 1;
+
+               } else {                /* sp adjusted to next higher value */
+                       if (sp & 0x80)
+                               sd = (sp == 0x80) ? 0x80 : sp - 1;
+                       else
+                               sd = (sp == 0x7F) ? 0xFE : sp + 1;
+               }
+               return (sd);
+       }
+}
diff --git a/utils/wxMMedia/adpcm/g72x.h b/utils/wxMMedia/adpcm/g72x.h
new file mode 100644 (file)
index 0000000..dbfd64f
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use.  Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * g72x.h
+ *
+ * Header file for CCITT conversion routines.
+ *
+ */
+#ifndef _G72X_H
+#define        _G72X_H
+
+#define        AUDIO_ENCODING_ULAW     (1)     /* ISDN u-law */
+#define        AUDIO_ENCODING_ALAW     (2)     /* ISDN A-law */
+#define        AUDIO_ENCODING_LINEAR   (3)     /* PCM 2's-complement (0-center) */
+
+/*
+ * The following is the definition of the state structure
+ * used by the G.721/G.723 encoder and decoder to preserve their internal
+ * state between successive calls.  The meanings of the majority
+ * of the state structure fields are explained in detail in the
+ * CCITT Recommendation G.721.  The field names are essentially indentical
+ * to variable names in the bit level description of the coding algorithm
+ * included in this Recommendation.
+ */
+struct g72x_state {
+       long yl;        /* Locked or steady state step size multiplier. */
+       short yu;       /* Unlocked or non-steady state step size multiplier. */
+       short dms;      /* Short term energy estimate. */
+       short dml;      /* Long term energy estimate. */
+       short ap;       /* Linear weighting coefficient of 'yl' and 'yu'. */
+
+       short a[2];     /* Coefficients of pole portion of prediction filter. */
+       short b[6];     /* Coefficients of zero portion of prediction filter. */
+       short pk[2];    /*
+                        * Signs of previous two samples of a partially
+                        * reconstructed signal.
+                        */
+       short dq[6];    /*
+                        * Previous 6 samples of the quantized difference
+                        * signal represented in an internal floating point
+                        * format.
+                        */
+       short sr[2];    /*
+                        * Previous 2 samples of the quantized difference
+                        * signal represented in an internal floating point
+                        * format.
+                        */
+       char td;        /* delayed tone detect, new in 1988 version */
+};
+
+/* External function definitions. */
+
+extern unsigned char linear2alaw (int pcm_val);        /* 2's complement (16-bit range) */
+extern int alaw2linear (unsigned char a_val);
+extern unsigned char linear2ulaw (int pcm_val);        /* 2's complement (16-bit range) */
+extern int ulaw2linear (unsigned char u_val);
+extern int predictor_zero (struct g72x_state *state_ptr);
+extern int predictor_pole (struct g72x_state *state_ptr);
+extern int step_size (struct g72x_state *state_ptr);
+extern int quantize (int d, int y, short *table, int size);
+extern int reconstruct (int sign, int dqln, int y);
+
+extern void update
+    ( int code_size, int y, int wi, int fi, int dq
+       , int sr, int dqsez, struct g72x_state *state_ptr);
+
+int tandem_adjust_alaw
+    (int sr, int se, int y, int i, int sign, short *qtab);
+
+int tandem_adjust_ulaw
+    (int sr, int se, int y, int i, int sign, short *qtab);
+
+extern void g72x_init_state (struct g72x_state *);
+extern int g721_encoder(
+               int sample,
+               int in_coding,
+               struct g72x_state *state_ptr);
+extern int g721_decoder(
+               int code,
+               int out_coding,
+               struct g72x_state *state_ptr);
+extern int g723_24_encoder(
+               int sample,
+               int in_coding,
+               struct g72x_state *state_ptr);
+extern int g723_24_decoder(
+               int code,
+               int out_coding,
+               struct g72x_state *state_ptr);
+extern int g723_40_encoder(
+               int sample,
+               int in_coding,
+               struct g72x_state *state_ptr);
+extern int g723_40_decoder(
+               int code,
+               int out_coding,
+               struct g72x_state *state_ptr);
+
+#endif /* !_G72X_H */
diff --git a/utils/wxMMedia/cdbase.cpp b/utils/wxMMedia/cdbase.cpp
new file mode 100644 (file)
index 0000000..ea98837
--- /dev/null
@@ -0,0 +1,52 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       sndsnd.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "cdbase.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxCDtime wxCDAudio::CDtoc::GetTrackTime(wxUint8 track) const
+{
+  if (track > total_time.track) {
+    wxCDtime dummy_time = {0, 0, 0, 0};
+    return dummy_time;
+  }
+  return tracks_time[track];
+}
+
+wxCDtime wxCDAudio::CDtoc::GetTrackPos(wxUint8 track) const
+{
+  if (track > total_time.track) {
+    wxCDtime dummy_time = {0, 0, 0, 0};
+    return dummy_time;
+  }
+  return tracks_pos[track];
+}
+
+bool wxCDAudio::Play(const wxCDtime& beg_play)
+{
+  return Play(beg_play, GetToc().GetTotalTime());
+}
+
+bool wxCDAudio::Play(wxUint8 beg_track, wxUint8 end_track)
+{
+  wxCDtime beg_play = GetToc().GetTrackPos(beg_track);
+  wxCDtime end_play;
+
+  if (end_track)
+    end_play = GetToc().GetTrackPos(end_track);
+  else
+    end_play = GetToc().GetTotalTime();
+  return Play(beg_play, end_play);
+}
diff --git a/utils/wxMMedia/cdbase.h b/utils/wxMMedia/cdbase.h
new file mode 100644 (file)
index 0000000..1c254b0
--- /dev/null
@@ -0,0 +1,88 @@
+// -*- c++ -*-
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       cdbase.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __CDA_base_H__
+#define __CDA_base_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+
+typedef struct wxCDtime {
+  wxUint8 track;
+  wxUint8 hour, min, sec;
+} wxCDtime;
+
+///
+class WXDLLEXPORT wxCDAudio : public wxObject {
+  DECLARE_ABSTRACT_CLASS(wxCDAudio)
+public:
+  ///
+  typedef enum { PLAYING, PAUSED, STOPPED } CDstatus;
+  /// Table of contents manager
+  class CDtoc {
+  protected:
+    wxCDtime *tracks_time, *tracks_pos;
+    wxCDtime total_time;
+  public:
+    ///
+    CDtoc(wxCDtime& tot_tm, wxCDtime *trks_tm, wxCDtime *trks_pos)
+      { tracks_time = trks_tm; total_time = tot_tm; tracks_pos = trks_pos; }
+
+    /// Returns the length of the specified track
+    /** @param track track to get length */
+    wxCDtime GetTrackTime(wxUint8 track) const;
+    /** Returns the position of the specified
+        @param track track to get position */
+    wxCDtime GetTrackPos(wxUint8 track) const;
+    /// Returns the total time
+    inline wxCDtime GetTotalTime() const { return total_time; }
+  };
+public:
+  ///
+  wxCDAudio() : wxObject() {}
+  ///
+  virtual ~wxCDAudio() {}
+
+  /// Play audio at the specified position
+  /**
+   * @param beg_play start position
+   * @param end_play end position
+   */
+  virtual bool Play(const wxCDtime& beg_play, const wxCDtime& end_play) = 0;
+  /// Play audio from the specified to the end of the CD audio
+  /**
+   * @param beg_play start position
+   */
+  bool Play(const wxCDtime& beg_play);
+  ///
+  bool Play(wxUint8 beg_track, wxUint8 end_track = 0);
+  /// Pause the audio playing
+  virtual bool Pause() = 0;
+  /// Resume a paused audio playing
+  virtual bool Resume() = 0;
+  /// Get the current CD status
+  virtual CDstatus GetStatus() = 0;
+  /// Get the current playing time
+  virtual wxCDtime GetTime() = 0;
+  /// Returns the table of contents
+  virtual const CDtoc& GetToc() = 0;
+  /// CD ok
+  virtual bool Ok() const = 0;
+};
+
+#endif
diff --git a/utils/wxMMedia/cdunix.cpp b/utils/wxMMedia/cdunix.cpp
new file mode 100644 (file)
index 0000000..07f5ea0
--- /dev/null
@@ -0,0 +1,198 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       cdlinux.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "cdunix.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef __linux__
+#include <linux/cdrom.h>
+#else
+// For Solaris
+#include <sys/cdio.h>
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+#include "cdunix.h"
+
+wxCDAudioLinux::wxCDAudioLinux()
+  : wxCDAudio(), m_fd(-1)
+{
+  OpenDevice("/dev/cdrom");
+}
+
+wxCDAudioLinux::wxCDAudioLinux(const char *dev_name)
+  : wxCDAudio(), m_fd(-1)
+{
+  OpenDevice(dev_name);
+}
+
+wxCDAudioLinux::~wxCDAudioLinux()
+{
+  if (m_fd != -1) {
+    close(m_fd);
+    wxDELETE(m_trksize);
+    wxDELETE(m_trkpos);
+  }
+}
+
+void wxCDAudioLinux::OpenDevice(const char *dev_name)
+{
+  struct cdrom_tocentry entry, old_entry;
+  struct cdrom_tochdr diskinf;
+  struct cdrom_msf0 *msf = &entry.cdte_addr.msf,
+                   *old_msf = &old_entry.cdte_addr.msf;
+  wxCDtime *the_track;
+  wxCDtime tot_tm;
+  wxUint8 nb_tracks, i;
+  int hour, minute, second;
+
+  if (m_fd != -1)
+    return;
+
+  m_fd = open(dev_name, O_RDONLY);
+  if (m_fd == -1) {
+    m_toc = NULL;
+    return;
+  }
+  m_status = STOPPED;  
+
+  ioctl(m_fd, CDROMREADTOCHDR, &diskinf);
+
+  nb_tracks = diskinf.cdth_trk1-diskinf.cdth_trk0+1;
+  m_trksize = new wxCDtime[nb_tracks+1];
+  m_trkpos  = new wxCDtime[nb_tracks+1];
+
+  old_msf->minute = 0;
+  old_msf->second = 0;
+  for (i=diskinf.cdth_trk0;i<=diskinf.cdth_trk1;i++) {
+    entry.cdte_track = i;
+    entry.cdte_format = CDROM_MSF;
+    ioctl(m_fd, CDROMREADTOCENTRY, &entry);
+
+    minute = msf->minute - old_msf->minute;
+    second = msf->second - old_msf->second;
+    if (second < 0) {
+      minute--;
+      second += 60;
+    }
+
+    hour = minute / 60;
+    minute %= 60;
+
+    the_track = &m_trksize[i-diskinf.cdth_trk0];
+    the_track->track = i-diskinf.cdth_trk0;
+    the_track->hour = hour;
+    the_track->min = minute;
+    the_track->sec = second;
+    
+    the_track = &m_trkpos[i-diskinf.cdth_trk0];
+    the_track->track = i-diskinf.cdth_trk0;
+    the_track->hour = old_msf->minute / 60;
+    the_track->min = old_msf->minute % 60;
+    the_track->sec = old_msf->second;
+    old_entry = entry;
+  }
+
+  entry.cdte_track = CDROM_LEADOUT;
+  entry.cdte_format = CDROM_MSF;
+  ioctl(m_fd, CDROMREADTOCENTRY, &entry);
+
+  tot_tm.track = nb_tracks;
+  tot_tm.hour = msf->minute / 60;
+  tot_tm.min = msf->minute % 60;
+  tot_tm.sec = msf->second % 60;
+
+  m_trksize[nb_tracks].track = nb_tracks;
+  minute = msf->minute - old_msf->minute;
+  second = msf->second - old_msf->second;
+  if (second < 0) {
+    minute--;
+    second += 60;
+  }
+  hour = minute / 60;
+  minute %= 60;
+
+  m_trksize[nb_tracks].hour = hour;
+  m_trksize[nb_tracks].min  = minute;
+  m_trksize[nb_tracks].sec  = second;
+  m_trkpos[nb_tracks].track = nb_tracks;
+  m_trkpos[nb_tracks].hour  = old_msf->minute / 60;
+  m_trkpos[nb_tracks].min   = old_msf->minute % 60;
+  m_trkpos[nb_tracks].sec   = old_msf->second;
+
+  m_toc = new CDtoc(tot_tm, m_trksize, m_trkpos);
+}
+
+bool wxCDAudioLinux::Play(const wxCDtime& beg_time, const wxCDtime& end_time)
+{
+  struct cdrom_msf track_msf;
+
+  track_msf.cdmsf_min0 = beg_time.hour * 60 + beg_time.min;
+  track_msf.cdmsf_sec0 = beg_time.sec;
+  track_msf.cdmsf_frame0 = 0;
+  track_msf.cdmsf_min1 = end_time.hour * 60 + end_time.min;
+  track_msf.cdmsf_sec1 = end_time.sec;
+  track_msf.cdmsf_frame1 = 0;
+  return (ioctl(m_fd, CDROMPLAYMSF, &track_msf) != -1);
+}
+
+bool wxCDAudioLinux::Pause()
+{
+  return (ioctl(m_fd, CDROMPAUSE, 0) != -1);
+}
+
+bool wxCDAudioLinux::Resume()
+{
+  return (ioctl(m_fd, CDROMRESUME, 0) != -1);
+}
+
+wxCDAudio::CDstatus wxCDAudioLinux::GetStatus()
+{
+  struct cdrom_subchnl subchnl;
+  ioctl(m_fd, CDROMSUBCHNL, &subchnl);
+  switch (subchnl.cdsc_audiostatus) {
+  case CDROM_AUDIO_PLAY: return PLAYING;
+  case CDROM_AUDIO_PAUSED: return PAUSED;
+  case CDROM_AUDIO_COMPLETED: return STOPPED;
+  }
+
+  return STOPPED;
+}
+
+wxCDtime wxCDAudioLinux::GetTime()
+{
+  wxCDtime cdtime;
+  struct cdrom_subchnl subchnl;
+
+  ioctl(m_fd, CDROMSUBCHNL, &subchnl);
+  cdtime.track = subchnl.cdsc_trk;
+  cdtime.min = subchnl.cdsc_reladdr.msf.minute;
+  cdtime.hour = cdtime.min / 60;
+  cdtime.min %= 60;
+  cdtime.sec = subchnl.cdsc_reladdr.msf.second;
+
+  return cdtime;
+}
+
+wxCDAudio::CDtoc& wxCDAudioLinux::GetToc()
+{
+  return *m_toc;
+}
diff --git a/utils/wxMMedia/cdunix.h b/utils/wxMMedia/cdunix.h
new file mode 100644 (file)
index 0000000..0f8d73b
--- /dev/null
@@ -0,0 +1,61 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       cdunix.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __CDUNIXH__
+#define __CDUNIXH__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+#include "cdbase.h"
+
+///
+class WXDLLEXPORT wxCDAudioLinux : public wxCDAudio {
+  DECLARE_DYNAMIC_CLASS(wxCDAudioLinux)
+protected:
+  wxCDtime m_time;
+  CDstatus m_status;
+  CDtoc *m_toc;
+  int m_fd;
+  wxCDtime *m_trksize, *m_trkpos;
+public:
+  ///
+  wxCDAudioLinux();
+  ///
+  wxCDAudioLinux(const char *dev_name);
+  ///
+  virtual ~wxCDAudioLinux();
+
+  ///
+  virtual bool Play(const wxCDtime& beg_time, const wxCDtime& end_time);
+  ///
+  virtual bool Pause();
+  ///
+  virtual bool Resume();
+  ///
+  virtual CDstatus GetStatus();
+  ///
+  virtual wxCDtime GetTime();
+  ///
+  virtual CDtoc& GetToc();
+  ///
+  virtual inline bool Ok() const { return (m_fd != -1); }
+protected:
+  ///
+  void OpenDevice(const char *dev_name);
+};
+
+#endif
diff --git a/utils/wxMMedia/cdwin.cpp b/utils/wxMMedia/cdwin.cpp
new file mode 100644 (file)
index 0000000..abe8469
--- /dev/null
@@ -0,0 +1,208 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       cdwin.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "cdwin.h"
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <mmsystem.h>
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#define WXMMEDIA_INTERNAL
+#include "mmtype.h"
+#include "cdbase.h"
+#include "cdwin.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxCDAudioWin::wxCDAudioWin(void)
+  : wxCDAudio(), m_trksize(NULL), m_trkpos(NULL), m_ok(TRUE), m_toc(NULL)
+{
+  MCI_OPEN_PARMS open_struct;
+  MCI_SET_PARMS set_struct;
+  DWORD ret;
+
+  m_internal = new CDAW_Internal;
+  open_struct.lpstrDeviceType = "cdaudio";
+  ret = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE,
+                       (DWORD)&open_struct);
+  if (ret) {
+    m_ok = FALSE;
+    return;
+  }
+  m_internal->dev_id = open_struct.wDeviceID;
+
+  set_struct.dwTimeFormat = MCI_FORMAT_MSF;
+  ret = mciSendCommand(m_internal->dev_id, MCI_SET, MCI_SET_TIME_FORMAT,
+                       (DWORD)(LPVOID)&set_struct);
+
+  PrepareToc();
+
+  set_struct.dwTimeFormat = MCI_FORMAT_TMSF;
+  ret = mciSendCommand(m_internal->dev_id, MCI_SET, MCI_SET_TIME_FORMAT,
+                       (DWORD)(LPVOID)&set_struct);
+}
+
+wxCDAudioWin::~wxCDAudioWin(void)
+{
+  if (m_ok) {
+    mciSendCommand(m_internal->dev_id, MCI_CLOSE, 0, NULL);
+    delete m_toc;
+    delete[] m_trksize;
+    delete[] m_trkpos;
+  }
+  delete m_internal;
+}
+
+void wxCDAudioWin::PrepareToc(void)
+{
+  MCI_STATUS_PARMS status_struct;
+  MCI_SET_PARMS set_struct;
+  wxUint16 i, nb_m_trksize;
+  wxCDtime total_time, *trk;
+  DWORD ret, tmem;
+
+  if (!m_ok)
+    return;
+
+  status_struct.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
+  ret = mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+                 (DWORD)&status_struct);
+  nb_m_trksize = status_struct.dwReturn;
+
+  m_trksize = new wxCDtime[nb_m_trksize+1];
+  m_trkpos = new wxCDtime[nb_m_trksize+1];
+
+  status_struct.dwItem = MCI_STATUS_LENGTH;
+  ret = mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+                 (DWORD)&status_struct);
+  total_time.track = nb_m_trksize;
+  tmem = status_struct.dwReturn;
+  total_time.min = MCI_MSF_MINUTE(tmem);
+  total_time.sec = MCI_MSF_SECOND(tmem);
+  total_time.hour = total_time.min / 60;
+  total_time.min %= 60;
+
+  for (i=1;i<=nb_m_trksize;i++) {
+    status_struct.dwItem = MCI_STATUS_POSITION;
+    status_struct.dwTrack = i;
+    ret  = mciSendCommand(m_internal->dev_id, MCI_STATUS,
+                   MCI_STATUS_ITEM | MCI_TRACK,
+                   (DWORD)(LPVOID)&status_struct);
+    tmem = status_struct.dwReturn;
+
+    trk        = &m_trkpos[i];
+    trk->track = i;
+    trk->min   = MCI_MSF_MINUTE(tmem);
+    trk->sec   = MCI_MSF_SECOND(tmem);
+    trk->hour  = trk->min / 60;
+    trk->min  %= 60;
+
+    status_struct.dwItem = MCI_STATUS_LENGTH;
+    status_struct.dwTrack = i;
+    ret  = mciSendCommand(m_internal->dev_id, MCI_STATUS,
+                   MCI_STATUS_ITEM | MCI_TRACK,
+                   (DWORD)(LPVOID)&status_struct);
+    tmem = status_struct.dwReturn;
+
+    trk        = &m_trksize[i];
+    trk->track = i;
+    trk->min   = MCI_MSF_MINUTE(tmem);
+    trk->sec   = MCI_MSF_SECOND(tmem);
+    trk->hour  = trk->min / 60;
+    trk->min  %= 60;
+  }
+
+  m_toc = new CDtoc(total_time, m_trksize, m_trkpos);
+}
+
+bool wxCDAudioWin::Play(const wxCDtime& beg_time, const wxCDtime& end_time)
+{
+  DWORD tmsf;
+  MCI_PLAY_PARMS play_struct;
+
+  if (!m_ok)
+    return FALSE;
+
+  tmsf = MCI_MAKE_TMSF(beg_time.track, beg_time.min,
+                       beg_time.sec, 0);
+  play_struct.dwFrom = tmsf;
+  tmsf = MCI_MAKE_TMSF(end_time.track, end_time.min,
+                       end_time.sec, 0);
+  play_struct.dwTo = tmsf;
+
+  mciSendCommand(m_internal->dev_id, MCI_PLAY, 0, (DWORD)&play_struct);
+  return TRUE;
+}
+
+bool wxCDAudioWin::Pause(void)
+{
+  if (!m_ok)
+    return FALSE;
+
+  return (mciSendCommand(m_internal->dev_id, MCI_PAUSE, 0, 0) == 0);
+}
+
+bool wxCDAudioWin::Resume(void)
+{
+  if (!m_ok)
+    return FALSE;
+
+  return (mciSendCommand(m_internal->dev_id, MCI_RESUME, 0, 0) == 0);
+}
+
+wxCDAudio::CDstatus wxCDAudioWin::GetStatus(void)
+{
+  MCI_STATUS_PARMS status_struct;
+
+  if (!m_ok)
+    return STOPPED;
+
+  status_struct.dwItem = MCI_STATUS_MODE;
+  mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+                 (DWORD)&status_struct);
+  switch (status_struct.dwReturn) {
+  case MCI_MODE_PAUSE:
+    return PAUSED;
+  case MCI_MODE_PLAY:
+    return PLAYING;
+  }
+  return STOPPED;
+}
+
+wxCDtime wxCDAudioWin::GetTime(void)
+{
+  MCI_STATUS_PARMS status_struct;
+  wxCDtime cd_time = {-1, -1, -1, -1};
+
+  if (!m_ok)
+    return cd_time;
+
+  status_struct.dwItem = MCI_STATUS_TIME_FORMAT;
+  mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+                 (DWORD)&status_struct);
+  cd_time.track = MCI_TMSF_TRACK(status_struct.dwReturn);
+  cd_time.min = MCI_TMSF_MINUTE(status_struct.dwReturn);
+  cd_time.sec = MCI_TMSF_SECOND(status_struct.dwReturn);
+  cd_time.hour = cd_time.min / 60;
+  cd_time.min %= 60;
+  return cd_time;
+}
+
+wxCDAudio::CDtoc& wxCDAudioWin::GetToc(void)
+{
+  return *m_toc;
+}
diff --git a/utils/wxMMedia/cdwin.h b/utils/wxMMedia/cdwin.h
new file mode 100644 (file)
index 0000000..21db70e
--- /dev/null
@@ -0,0 +1,67 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       cdwin.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __CDA_win_H__
+#define __CDA_win_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+#include "cdbase.h"
+
+#ifdef WXMMEDIA_INTERNAL
+#include <windows.h>
+#include <mmsystem.h>
+typedef struct CDAW_Internal {
+  MCIDEVICEID dev_id;
+} CDAW_Internal;
+#endif
+
+///
+class WXDLLEXPORT wxCDAudioWin : public wxCDAudio {
+  DECLARE_DYNAMIC_CLASS(wxCDAudioWin)
+protected:
+  struct CDAW_Internal *m_internal;
+  wxCDtime *m_trksize, *m_trkpos;
+  CDtoc *m_toc;
+  bool m_ok;
+public:
+  ///
+  wxCDAudioWin(void);
+  ///
+  wxCDAudioWin(const char *dev_name);
+  ///
+  virtual ~wxCDAudioWin(void);
+
+  ///
+  virtual bool Play(const wxCDtime& beg_time, const wxCDtime& end_time);
+  ///
+  virtual bool Pause(void);
+  ///
+  virtual bool Resume(void);
+  ///
+  virtual CDstatus GetStatus(void);
+  ///
+  virtual wxCDtime GetTime(void);
+  ///
+  virtual CDtoc& GetToc(void);
+  ///
+  virtual inline bool Ok(void) const { return m_ok; }
+protected:
+  void PrepareToc();
+};
+
+#endif
diff --git a/utils/wxMMedia/mmdata.cpp b/utils/wxMMedia/mmdata.cpp
new file mode 100644 (file)
index 0000000..11b0922
--- /dev/null
@@ -0,0 +1,92 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       mmdata.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#include "mmfile.h"
+
+#include "sndsnd.h"
+#include "sndfrmt.h"
+#if defined(__UNIX__)
+#include "snduss.h"
+#endif
+#include "sndfrag.h"
+#include "sndfile.h"
+#include "sndwav.h"
+#include "sndaiff.h"
+#include "sndau.h"
+#include "sndpcm.h"
+#include "sndmulaw.h"
+#include "vidbase.h"
+#if defined(__X__) || defined(__WXGTK__)
+#include "vidxanm.h"
+#endif
+#ifdef __WINDOWS__
+#include "sndwin.h"
+#include "cdwin.h"
+#include "vidwin.h"
+#endif
+#include "cdbase.h"
+#ifdef __UNIX__
+#include "cdunix.h"
+#endif
+#include "mmsolve.h"
+// #include "midfile.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+IMPLEMENT_ABSTRACT_CLASS(wxSound, wxObject)
+IMPLEMENT_ABSTRACT_CLASS(wxSndBuffer, wxObject)
+IMPLEMENT_DYNAMIC_CLASS(wxSndSimpleBuffer, wxSndBuffer)
+
+IMPLEMENT_ABSTRACT_CLASS(wxSoundCodec, wxObject)
+IMPLEMENT_DYNAMIC_CLASS(wxSoundPcmCodec, wxSoundCodec)
+IMPLEMENT_DYNAMIC_CLASS(wxSoundMulawCodec, wxSoundCodec)
+
+#ifdef __UNIX__
+IMPLEMENT_DYNAMIC_CLASS(wxUssSound, wxSound)
+#endif
+#ifdef __WINDOWS__
+IMPLEMENT_DYNAMIC_CLASS(wxWinSound, wxSound)
+#endif
+
+IMPLEMENT_ABSTRACT_CLASS(wxSndFileCodec, wxMMediaFile)
+IMPLEMENT_DYNAMIC_CLASS(wxSndWavCodec, wxSndFileCodec)
+IMPLEMENT_DYNAMIC_CLASS(wxSndAuCodec, wxSndFileCodec)
+IMPLEMENT_DYNAMIC_CLASS(wxSndAiffCodec, wxSndFileCodec)
+
+IMPLEMENT_ABSTRACT_CLASS(wxVideoBaseDriver, wxMMediaFile)
+IMPLEMENT_DYNAMIC_CLASS(wxVideoOutput, wxWindow)
+#if defined(__X__) || defined(__WXGTK__)
+IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
+#endif
+#ifdef __WINDOWS__
+IMPLEMENT_DYNAMIC_CLASS(wxVideoWindows, wxVideoBaseDriver)
+#endif
+
+IMPLEMENT_ABSTRACT_CLASS(wxCDAudio, wxObject)
+#ifdef linux
+IMPLEMENT_DYNAMIC_CLASS(wxCDAudioLinux, wxCDAudio)
+#else
+IMPLEMENT_DYNAMIC_CLASS(wxCDAudioWin, wxCDAudio)
+#endif
+
+// IMPLEMENT_ABSTRACT_CLASS(wxMidiFile, wxObject)
+
+wxMediaFileSolve::wxMFileList *wxMediaFileSolve::m_first = NULL;
+wxUint8 wxMediaFileSolve::m_devnum = 0;
+
+MMD_REGISTER_FILE("audio/x-wav", "Wav Player", wxSndWavCodec, "wav")
+MMD_REGISTER_FILE("audio/x-aiff", "Aiff Player", wxSndAiffCodec, "aif")
+MMD_REGISTER_FILE("audio/x-au", "Sun Audio File Player", wxSndAuCodec, "au")
+#if defined(__X__) || defined(__WXGTK__)
+MMD_REGISTER_FILE("video/*", "Video Player", wxVideoXANIM, "mov")
+#else
+MMD_REGISTER_FILE("video/avi", "AVI Player", wxVideoWindows, "avi")
+#endif
diff --git a/utils/wxMMedia/mmedia.h b/utils/wxMMedia/mmedia.h
new file mode 100644 (file)
index 0000000..a530b7b
--- /dev/null
@@ -0,0 +1,31 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       mmedia.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __MMEDIA_H__
+#define __MMEDIA_H__
+
+#ifdef __WINDOWS__
+
+#include "sndwin.h"
+#define wxSoundDevice wxWinSound
+
+#include "vidwin.h"
+#define wxVideoDevice wxVideoWindows
+
+#else
+
+#include "snduss.h"
+#define wxSoundDevice wxUssSound
+
+#include "vidxanm.h"
+#define wxVideoDevice wxVideoXANIM
+
+#endif
+
+#endif
diff --git a/utils/wxMMedia/mmfile.cpp b/utils/wxMMedia/mmfile.cpp
new file mode 100644 (file)
index 0000000..fa57adf
--- /dev/null
@@ -0,0 +1,194 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       mmfile.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <wx/stream.h>
+#include <wx/fstream.h>
+#include <wx/mstream.h>
+
+#include "mmfile.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxMMediaFile::wxMMediaFile()
+  : m_istream(NULL), m_i_temp(NULL), m_ostream(NULL), m_o_temp(NULL),
+    m_tmpfname((char *)NULL), m_mfname((char *)NULL),
+    m_seekable(FALSE)
+{
+}
+
+wxMMediaFile::wxMMediaFile(wxOutputStream& os, bool seekable)
+  : m_istream(NULL), m_i_temp(NULL), m_ostream(&os), m_o_temp(NULL),
+    m_tmpfname((char *)NULL), m_mfname((char *)NULL),
+    m_seekable(seekable)
+{
+}
+
+wxMMediaFile::wxMMediaFile(wxInputStream& is, bool preload, bool seekable)
+  : m_istream(&is), m_i_temp(NULL), m_ostream(NULL), m_o_temp(NULL),
+    m_tmpfname((char *)NULL), m_mfname((char *)NULL),
+    m_seekable(seekable)
+{
+/*
+  if (preload) {
+    wxMemoryStream *tmpstream = new wxMemoryStream();
+
+    m_o_temp = tmpstream;
+    m_i_temp = tmpstream;
+
+    m_o_temp->Write(is);
+  }
+*/
+}
+
+wxMMediaFile::wxMMediaFile(const wxString& fname)
+  : m_istream(NULL), m_i_temp(NULL), m_ostream(NULL), m_o_temp(NULL),
+    m_tmpfname((char *)NULL), m_mfname(fname),
+    m_seekable(TRUE)
+{
+  wxFileStream *s = new wxFileStream(fname);
+
+  m_mfname = fname;
+  m_istream = s;
+  m_ostream = s;
+}
+
+void wxMMediaFile::SetFile(wxInputStream& str, bool preload, bool seekable)
+{
+  CleanUpPrevious();
+  m_istream = &str;
+  m_ostream = NULL;
+  m_seekable = seekable;
+
+/*
+  if (preload) {
+    wxMemoryStream *tmpstream = new wxMemoryStream();
+
+    m_i_temp = tmpstream;
+    m_o_temp = tmpstream;
+
+    m_o_temp->Write(str);
+  }
+*/
+}
+
+void wxMMediaFile::SetFile(wxOutputStream& str, bool seekable)
+{
+  CleanUpPrevious();
+  m_ostream = &str;
+  m_istream = NULL;
+  m_seekable = seekable;
+}
+
+void wxMMediaFile::SetFile(const wxString& fname)
+{
+  CleanUpPrevious();
+
+  m_mfname = fname;
+  wxFileStream *f = new wxFileStream(fname);
+
+  SetFile(*f, FALSE, TRUE);
+}
+
+void wxMMediaFile::CleanUpPrevious()
+{
+  if (m_i_temp) {
+    m_i_temp->SeekI(0);
+
+    if (m_ostream)
+      m_ostream->Write(*m_i_temp);
+
+    delete m_i_temp; // Only one delete because m_tmpo* and m_tmpi* are linked
+
+    if (m_tmpfname)
+      wxRemoveFile(m_tmpfname);
+  }
+
+  if (!m_mfname.IsNull() && m_mfname != "")
+    delete m_istream;
+
+  m_i_temp = NULL;
+  m_o_temp = NULL;
+  m_istream = NULL;
+  m_ostream = NULL;
+}
+
+wxMMediaFile::~wxMMediaFile()
+{
+  CleanUpPrevious();
+}
+
+wxMMtime wxMMediaFile::GetLength()
+{
+  wxMMtime mm_time = {-1, 0, 0};
+  return mm_time;
+}
+
+wxMMtime wxMMediaFile::GetPosition()
+{
+  wxMMtime mm_time = {0, 0, 0};
+  return mm_time;
+}
+
+wxInputStream *wxMMediaFile::GetIRawData()
+{
+  if (!m_istream)
+    return NULL;
+
+  if (!m_seekable && !m_i_temp)
+    CacheIO();
+
+  return (m_i_temp) ? m_i_temp : m_istream;
+}
+
+wxOutputStream *wxMMediaFile::GetORawData()
+{
+  if (!m_ostream)
+    return NULL;
+
+  if (!m_seekable && !m_i_temp)
+    CacheIO();
+
+  return (m_o_temp) ? m_o_temp : m_ostream;
+}
+
+wxString wxMMediaFile::GetCurrentFile()
+{
+  if (!m_istream && !m_ostream)
+    return wxString((char *)NULL);
+
+  if (!m_mfname && !m_i_temp) 
+    CacheIO();
+
+  return (!m_tmpfname.IsEmpty()) ? m_tmpfname : m_mfname;
+}
+
+void wxMMediaFile::CacheIO()
+{
+  if ((!m_istream && !m_ostream) || m_i_temp)
+    return;
+
+  m_tmpfname = wxGetTempFileName("mmd");
+
+  wxFileStream *tmpstream = new wxFileStream(m_tmpfname);
+  m_i_temp = tmpstream;
+  m_o_temp = tmpstream;
+
+  if (m_istream)
+    tmpstream->wxOutputStream::Write(*m_istream);
+}
diff --git a/utils/wxMMedia/mmfile.h b/utils/wxMMedia/mmfile.h
new file mode 100644 (file)
index 0000000..29b3968
--- /dev/null
@@ -0,0 +1,94 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       mmfile.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __MMD_file_H__
+#define __MMD_file_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "wx/string.h"
+#include "wx/stream.h"
+#include "mmtype.h"
+
+///
+typedef enum {
+  wxMMFILE_NOERROR,
+  wxMMFILE_INVALID,
+  wxMMFILE_EOF
+} ///
+ wxMMFileError;
+
+typedef struct {
+  wxInt8 hours;
+  wxUint8 minutes, seconds;
+} wxMMtime;
+
+/// Common base class for multimedia file.
+class wxMMediaFile {
+public:
+  wxMMediaFile();
+  ///
+  wxMMediaFile(wxInputStream& is, bool preload, bool seekable);
+  ///
+  wxMMediaFile(wxOutputStream& is, bool seekable);
+  ///
+  wxMMediaFile(const wxString& fname);
+  ///
+  virtual ~wxMMediaFile();
+
+  ///
+  wxInputStream *GetIRawData();
+  wxOutputStream *GetORawData();
+  ///
+  wxString GetCurrentFile();
+
+  ///
+  virtual void SetFile(wxInputStream& is,
+                       bool preload = FALSE, bool seekable = FALSE);
+  ///
+  virtual void SetFile(wxOutputStream& is, bool seekable = FALSE);
+  ///
+  void SetFile(const wxString& fname);
+
+  ///
+  wxMMFileError GetFileError() const { return m_mmerror; }
+  ///
+  virtual wxMMtime GetLength();
+  ///
+  virtual wxMMtime GetPosition();
+  ///
+  virtual bool StartPlay() = 0;
+  ///
+  virtual void StopPlay() = 0;
+protected:
+  ///
+  wxMMFileError m_mmerror;
+  ///
+  wxInputStream *m_istream, *m_i_temp;
+  ///
+  wxOutputStream *m_ostream, *m_o_temp;
+  ///
+  wxString m_tmpfname, m_mfname;
+  ///
+  bool m_seekable;
+
+  ///
+  void CacheIO(); 
+  ///
+  void CleanUpPrevious();
+};
+
+#endif
diff --git a/utils/wxMMedia/mmriff.cpp b/utils/wxMMedia/mmriff.cpp
new file mode 100644 (file)
index 0000000..10c8188
--- /dev/null
@@ -0,0 +1,215 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       mmriff.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "mmriff.h"
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmfile.h"
+#include "mmriff.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxRiffCodec::wxRiffCodec() :
+  riff_i_stream(NULL), riff_o_stream(NULL), chunk_length(INVALID_CHUNK_LEN)
+{
+}
+
+wxRiffCodec::wxRiffCodec(wxInputStream& s) :
+  riff_i_stream(&s), riff_o_stream(NULL), chunk_length(INVALID_CHUNK_LEN)
+{
+}
+
+wxRiffCodec::wxRiffCodec(wxOutputStream& s) :
+  riff_i_stream(NULL), riff_o_stream(&s), chunk_length(INVALID_CHUNK_LEN)
+{
+}
+
+wxRiffCodec::~wxRiffCodec()
+{
+}
+
+bool wxRiffCodec::RiffReset(wxUint8 mode)
+{
+  switch (mode) {
+  case RIFF_READ:
+    if (!riff_i_stream)
+      return FALSE;
+    riff_i_stream->SeekI(0);
+    chunk_length = INVALID_CHUNK_LEN;
+    return TRUE;
+  case RIFF_WRITE:
+    if (!riff_o_stream)
+      return FALSE;
+    riff_o_stream->SeekO(0);
+    chunk_length = INVALID_CHUNK_LEN; 
+    return TRUE;
+  }
+  return FALSE;
+}
+
+bool wxRiffCodec::ReadData(void *data, wxUint32 size)
+{
+  if (!riff_i_stream)
+    return FALSE;
+
+  if (chunk_length != INVALID_CHUNK_LEN && (wxUint32)chunk_length < size) {
+    riff_error = wxMMFILE_EOF;
+    return FALSE;
+  }
+  if (chunk_length != INVALID_CHUNK_LEN)
+    chunk_length -= size;
+
+  bool ret = (riff_i_stream->Read((char *)data, size).LastRead() == size);
+
+  return ret;
+}
+
+bool wxRiffCodec::WriteData(void *data, wxUint32 size)
+{
+  if (!riff_o_stream)
+    return FALSE;
+
+  if (chunk_length < size) {
+    riff_error = wxMMFILE_EOF;
+    return FALSE;
+  }
+  chunk_length -= size;
+
+  riff_o_stream->Write(data, size);
+
+  return TRUE;
+}
+
+bool wxRiffCodec::Read32(wxUint32& i32)
+{
+  wxUint8 i8[4];
+
+  if (!ReadData(i8, 4))
+    return FALSE;
+
+  i32 = i8[0];
+  i32 |= ((wxUint32)i8[1]) << 8;
+  i32 |= ((wxUint32)i8[2]) << 16;
+  i32 |= ((wxUint32)i8[3]) << 24;
+  
+  return TRUE;
+}
+
+bool wxRiffCodec::Write32(wxUint32 i32)
+{
+  wxUint8 i8[4];
+
+  i8[0] = i32 & 0xff;
+  i8[1] = (i32 >> 8) & 0xff;
+  i8[2] = (i32 >> 16) & 0xff;
+  i8[3] = (i32 >> 24) & 0xff;
+
+  if (!WriteData(i8, 4))
+    return FALSE;
+
+  return TRUE;
+}
+
+bool wxRiffCodec::Read16(wxUint16& i16)
+{
+  wxUint8 i8[2];
+
+  if (!ReadData(i8, 2))
+    return FALSE;
+
+  i16 = i8[0];
+  i16 |= ((wxUint16)i8[1]) << 8;
+  
+  return TRUE;
+}
+
+bool wxRiffCodec::Write16(wxUint16 i16)
+{
+  wxUint8 i8[2];
+
+  i8[0] = i16 & 0xff;
+  i8[1] = (i16 >> 8) & 0xff;
+
+  if (!WriteData(i8, 2))
+    return FALSE;
+
+  return TRUE;
+}
+
+bool wxRiffCodec::Skip(wxUint32 skip)
+{
+  if (!riff_i_stream || (chunk_length != INVALID_CHUNK_LEN && (wxInt32)skip > chunk_length))
+    return FALSE;
+
+  if (chunk_length != INVALID_CHUNK_LEN)
+    chunk_length -= skip;
+  riff_i_stream->SeekI(skip, wxFromCurrent);
+
+  return TRUE;
+}
+
+bool wxRiffCodec::CreateChunk(const wxString& name, wxUint32 size)
+{
+  if (!riff_o_stream || name.Length() != 4)
+    return FALSE;
+
+  if (riff_o_stream->Write(name.GetData(), 4).LastError()) {
+    riff_error = wxMMFILE_EOF;
+    return FALSE;
+  }
+
+  chunk_length = size+4;
+
+  return Write32(size);
+}
+
+bool wxRiffCodec::FindChunk(const wxString& name, bool from_here)
+{
+  char buf[5];
+  wxString str2;
+
+  if (!riff_i_stream)
+    return FALSE;
+
+  if (chunk_length != INVALID_CHUNK_LEN && !from_here)
+    Skip(chunk_length);
+  while (1) {
+    if (riff_i_stream->Read(buf, 4).LastError()) {
+      riff_error = wxMMFILE_EOF;
+      return FALSE;
+    }
+
+    chunk_length = INVALID_CHUNK_LEN;
+    if (!Read32(chunk_length)) {
+      riff_error = wxMMFILE_EOF;
+      return FALSE;
+    }
+
+    buf[4] = 0;
+    str2 = buf;
+    if ((!name.IsNull()) && str2 != name) {
+      Skip(chunk_length);
+      continue;
+    }
+
+    m_chunk = str2;
+
+    return TRUE;
+  }
+
+  return TRUE;
+}
diff --git a/utils/wxMMedia/mmriff.h b/utils/wxMMedia/mmriff.h
new file mode 100644 (file)
index 0000000..5ea5395
--- /dev/null
@@ -0,0 +1,81 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       mmriff.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1998
+// Updated:
+// Copyright:  (C) 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __MM_riff_H__
+#define __MM_riff_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmtype.h"
+#include "mmfile.h"
+
+#define RIFF_READ 0
+#define RIFF_WRITE 1
+#define INVALID_CHUNK_LEN ((wxUint32)-1)
+
+///
+class wxRiffCodec {
+public:
+  ///
+  wxRiffCodec();
+  ///
+  wxRiffCodec(wxOutputStream& s);
+  ///
+  wxRiffCodec(wxInputStream& s);
+  ///
+  virtual ~wxRiffCodec();
+
+  ///
+  void SetFile(wxInputStream& s) { cout << "RIFF:SetFile(i)" << endl; riff_i_stream = &s; riff_o_stream = NULL; }
+  ///
+  void SetFile(wxOutputStream& s) { cout << "RIFF::SetFile(o)" << endl; riff_i_stream = NULL; riff_o_stream = &s; }
+
+  ///
+  bool Read32(wxUint32& i32);
+  ///
+  bool Read16(wxUint16& i16);
+  ///
+  bool ReadData(void *data, wxUint32 size);
+  ///
+  bool Skip(wxUint32 skip);
+
+  ///
+  bool Write32(wxUint32 i32);
+  ///
+  bool Write16(wxUint16 i16);
+  ///
+  bool WriteData(void *data, wxUint32 size);
+
+  ///
+  inline wxUint32 GetChunkLength() const { return chunk_length; }
+  ///
+  inline const wxString& GetChunkName() const { return m_chunk; }
+
+  ///
+  bool RiffReset(wxUint8 state);
+
+  ///
+  bool FindChunk(const wxString& name = "", bool from_here = FALSE);
+  ///
+  bool CreateChunk(const wxString& name, wxUint32 chunk_size);
+
+  ///
+  inline wxMMFileError GetError() const { return riff_error; }
+
+protected:
+  wxInputStream *riff_i_stream;
+  wxOutputStream *riff_o_stream;
+  wxUint32 chunk_length;
+  wxMMFileError riff_error;
+  wxString m_chunk;
+};
+
+#endif
diff --git a/utils/wxMMedia/mmsolve.cpp b/utils/wxMMedia/mmsolve.cpp
new file mode 100644 (file)
index 0000000..fd4fef2
--- /dev/null
@@ -0,0 +1,124 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       mmsolve.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "mmsolve.h"
+
+wxMMediaFile *wxMediaFileSolve::ByExtension(const wxString& filename)
+{
+  wxMFileList *list = m_first;
+  wxString tmp, f_ext;
+  int pos = filename.Find('.', TRUE)+1;
+
+  tmp = filename;
+  f_ext = tmp(pos, filename.Length()-pos);
+
+  printf("f_ext = %s\n", f_ext.GetData());
+  while (list) {
+    printf("list->ext = %s\n", list->ext.GetData());
+    if (list->ext.CompareTo(f_ext) == 0) {
+      wxMMediaFile *mmf = list->creator();
+      return mmf;
+    }
+    list = list->next;
+  }
+  return NULL;
+}
+
+wxMMediaFile *wxMediaFileSolve::ByName(const wxString& name)
+{
+  wxMFileList *list = m_first;
+
+  while (list) {
+    if (list->name == name)
+      return (wxMMediaFile *)(list->creator());
+    list = list->next;
+  }
+  return NULL;
+}
+
+bool wxMatchMimeType(const wxString& mime_obj, const wxString& type)
+{
+#ifdef USE_GNU_WXSTRING
+  wxString mime2_obj = mime_obj;
+  wxString type2 = type;
+#define mime_obj mime2_obj
+#define type type2
+#endif
+
+  if (mime_obj.Find('*') != -1) {
+    wxString part_str1[2], part_str2[2];
+
+    part_str1[0] = mime_obj.Left('/');
+    part_str1[1] = mime_obj.After('/');
+   
+    part_str2[0] = type.Left('/');
+    part_str2[1] = type.After('/');
+
+    if (part_str1[0] == "*" && part_str1[1] == "*")
+      return TRUE;
+
+    if (part_str1[0] == "*" && part_str1[1] == part_str2[1])
+      return TRUE;
+
+    if (part_str1[1] == "*" && part_str1[0] == part_str2[1])
+      return TRUE;
+      
+    return FALSE;
+  }
+  if (mime_obj == type)
+    return TRUE;
+  return FALSE;
+}
+
+wxMMediaFile *wxMediaFileSolve::ByType(const wxString& type)
+{
+  wxMFileList *list = m_first;
+
+  while (list) {
+    if (wxMatchMimeType(*(list->mime_type), type))
+      return (wxMMediaFile *)(list->creator());
+    list = list->next;
+  }
+  return NULL;
+}
+
+void wxMediaFileSolve::ListMDevice(wxString*& names, wxUint8& devices)
+{
+  wxMFileList *list = m_first;
+  wxUint8 d = 0;
+
+  if (!m_devnum) {
+    names = NULL;
+    return;
+  }
+  devices = m_devnum;
+  names = new wxString[devices];
+
+  while (list) {
+    names[d++] = list->name;
+    list = list->next;
+  }
+}
+
+wxMMDfileRegister::wxMMDfileRegister(wxMediaFileCreator cbk,
+                                    char *mtype, char *ext, char *name)
+{
+  wxMediaFileSolve::wxMFileList *entry = new wxMediaFileSolve::wxMFileList;
+
+  entry->next = wxMediaFileSolve::m_first;
+  entry->creator = cbk;
+  entry->mime_type = wxString(mtype);
+  entry->name = wxString(name);
+  entry->ext = wxString(ext);
+  wxMediaFileSolve::m_devnum++;
+  wxMediaFileSolve::m_first = entry;
+}
diff --git a/utils/wxMMedia/mmsolve.h b/utils/wxMMedia/mmsolve.h
new file mode 100644 (file)
index 0000000..04ef8f8
--- /dev/null
@@ -0,0 +1,92 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       mmsolve.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __MMD_solve_H__
+#define __MMD_solve_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmfile.h"
+
+/** @name Solver classes */
+//@{
+
+typedef wxMMediaFile *(*wxMediaFileCreator)();
+
+/** wxMediaFileSolve is a class to do name resolution on multimedia files
+  * @memo Multimedia file solver
+  * @author Guilhem Lavaux
+  */
+class WXDLLEXPORT wxMediaFileSolve : public wxObject {
+protected:
+  typedef struct wxMFileList {
+    wxMediaFileCreator creator;
+    wxString mime_type, name, ext;
+    wxMFileList *next;
+  } wxMFileList;
+
+  static wxMFileList *m_first;
+  static wxUint8 m_devnum;
+
+  friend class wxMMDfileRegister;
+public:
+  wxMediaFileSolve() : wxObject() {}
+  ~wxMediaFileSolve() {}
+
+  /** It resolves using the extension of the specified filename
+    * @memo
+    * @return the multimedia codec
+    * @param filename
+    */
+  static wxMMediaFile *ByExtension(const wxString& filename);
+
+  /** It resolves using the real name of a codec
+    * @memo
+    * @return the multimedia codec
+    * @param devname
+    */
+  static wxMMediaFile *ByName(const wxString& devname);
+
+  /** It resolves using a mime type
+    * @memo
+    * @return the multimedia codec
+    * @param mimetype
+    */
+  static wxMMediaFile *ByType(const wxString& mimetype);
+
+  /** It lists all codecs currently registered in "names". "names" is allocated
+    * by it and devices returns the number of codecs the list contains
+    * @memo
+    * @return nothing
+    * @param names an array
+    * @param devices
+    */
+  static void ListMDevice(wxString*& names, wxUint8& devices);
+};
+
+///
+class wxMMDfileRegister {
+public:
+  ///
+  wxMMDfileRegister(wxMediaFileCreator cbk, char *mtype, char *ext, char *name);
+};
+
+#define MMD_REGISTER_FILE(mtype, name, class, ext) \
+static wxMMediaFile *wxMediaFileConstructor_##class() { return new class(); } \
+wxMMDfileRegister mmd_##class(wxMediaFileConstructor_##class, mtype, ext, name);
+
+//@}
+
+#endif
diff --git a/utils/wxMMedia/mmtype.h b/utils/wxMMedia/mmtype.h
new file mode 100644 (file)
index 0000000..e65d00d
--- /dev/null
@@ -0,0 +1,41 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       mmtype.h
+// Purpose:    wxMMedia (imported from wxSocket)
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SOCKTYPEH__
+#define __SOCKTYPEH__
+
+#ifdef __UNIX__
+#include <stl_config.h>
+#endif
+
+/// Type to use for 8 bits unsigned integers
+typedef unsigned char wxUint8;
+/// Type to use for 16 bits unsigned integers
+typedef unsigned short wxUint16;
+/// Type to use for 32 bits unsigned integers
+typedef unsigned long wxUint32;
+#if HAVE_UINT64
+/// Type to use for 64 bits unsigned integers
+typedef unsigned long long wxUint64;
+#endif
+
+/// Type to use for 8 bits signed integers
+typedef char wxInt8;
+/// Type to use for 16 bits signed integers
+typedef short wxInt16;
+/// Type to use for 32 bits signed integers
+typedef long wxInt32;
+#if HAVE_UINT64
+/// Type to use for 64 bits signed integers
+typedef long long wxInt64;
+#endif
+
+#endif
+
diff --git a/utils/wxMMedia/sndaiff.cpp b/utils/wxMMedia/sndaiff.cpp
new file mode 100644 (file)
index 0000000..2e4b0cb
--- /dev/null
@@ -0,0 +1,218 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       sndaiff.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    February 1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndaiff.h"
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "wx/datstrm.h"
+#include "sndaiff.h"
+#include "sndpcm.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#define READ_DATA(n) m_istream->Read(tmp_buf,n)
+#define WRITE_DATA(n) m_ostream->Write(tmp_buf,n)
+
+#define READ_STRING(s,n) \
+  READ_DATA(n); \
+  tmp_buf[n] = 0; \
+  s = tmp_buf;
+
+#define WRITE_STRING(s,n) WRITE_DATA((const char *)s, n)
+
+#define READ32(i) \
+  READ_DATA(4); \
+  i = (unsigned long)tmp_buf[3] | \
+      ((unsigned long)tmp_buf[2] << 8) | \
+      ((unsigned long)tmp_buf[1] << 16) | \
+      ((unsigned long)tmp_buf[0] << 24);
+
+#define WRITE32(i) \
+  tmp_buf[3] = i & 0xFF; \
+  tmp_buf[2] = (i >> 8) & 0xFF; \
+  tmp_buf[1] = (i >> 16) & 0xFF; \
+  tmp_buf[0] = (i >> 24) & 0xFF; \
+  WRITE_DATA(4);
+
+#define READ16(i) \
+  READ_DATA(2); \
+  i = (unsigned short)tmp_buf[1] | \
+      ((unsigned short)tmp_buf[0] << 8);
+
+wxSndAiffCodec::wxSndAiffCodec()
+  : wxSndFileCodec()
+{
+  m_sndtime.hours = -1;
+}
+
+wxSndAiffCodec::wxSndAiffCodec(wxOutputStream& s, bool seekable)
+  : wxSndFileCodec(s, seekable)
+{
+  if (!seekable)
+    CacheIO();
+  m_sndtime.hours = -1;
+}
+
+wxSndAiffCodec::wxSndAiffCodec(wxInputStream& s, bool preload, bool seekable)
+  : wxSndFileCodec(s, preload, seekable)
+{
+  if (!seekable)
+    CacheIO();
+  m_sndtime.hours = -1;
+}
+
+wxSndAiffCodec::wxSndAiffCodec(const wxString& fname)
+  : wxSndFileCodec(fname)
+{
+  m_sndtime.hours = -1;
+}
+
+wxUint32 wxSndAiffCodec::PrepareToPlay()
+{
+  char tmp_buf[5];
+  wxString chunk_name;
+
+  m_istream->SeekI(0, wxFromStart);
+
+  wxSndFileCodec::m_mmerror = wxMMFILE_INVALID;
+
+  READ_STRING(chunk_name, 4);
+  if (chunk_name != "FORM")
+    return 0;
+  m_istream->SeekI(4, wxFromCurrent);
+
+  READ_STRING(chunk_name, 4);
+  if (chunk_name != "AIFF" && chunk_name != "AIFC")
+    return 0;
+
+  // To check whether the file is good
+  m_spos = 0;
+  m_slen = 0;
+  m_sndformat.SetSampleRate(0);
+  while (1) {
+    READ_STRING(chunk_name, 4);
+    READ32(m_chunksize);
+    
+    if (chunk_name == "SSND")
+      ParseSSND();
+    if (chunk_name == "COMM")
+      ParseCOMM();
+    else
+      m_istream->SeekI(m_chunksize, wxFromCurrent);
+
+    if (m_spos && m_sndformat.GetSampleRate())
+      break;
+  }
+
+  m_sndmode = wxSND_OUTPUT;
+
+  wxUint32 sec1 = m_slen / m_sndformat.GetCodec()->GetByteRate(),
+           sec2 = sec1 % 3600;
+
+  m_sndtime.hours = sec1 / 3600;
+  m_sndtime.minutes = sec2 / 60;
+  m_sndtime.seconds = sec2 % 60;
+
+  wxSndFileCodec::m_mmerror = wxMMFILE_NOERROR;
+
+  m_istream->SeekI(m_spos, wxFromStart);
+  return m_slen;
+}
+
+void wxSndAiffCodec::ParseCOMM()
+{
+  wxDataInputStream data_s(*m_istream);
+  char tmp_buf[10];
+  wxUint16 channels;
+  wxUint32 srate, num_samples;
+  wxUint16 bps;
+
+  READ16(channels);
+  READ32(num_samples);
+  READ16(bps);
+
+  srate  = (wxUint32)data_s.ReadDouble();
+  m_sndformat.SetSampleRate(srate);
+  m_sndformat.SetBps(bps);
+  m_sndformat.SetChannels(channels);
+  m_sndformat.SetByteOrder(wxSND_SAMPLE_BE);
+  m_sndformat.SetSign(wxSND_SAMPLE_UNSIGNED);
+  ChangeCodec(WXSOUND_PCM);
+
+  m_istream->SeekI(m_chunksize-18, wxFromCurrent);
+}
+
+void wxSndAiffCodec::ParseSSND()
+{
+  wxDataInputStream data_s(*m_istream);
+  char tmp_buf[10];
+
+  READ32(m_spos);
+  m_istream->SeekI(4, wxFromCurrent);
+
+  m_slen = m_chunksize - m_spos;
+  m_spos += m_istream->TellI();
+}
+
+wxSndAiffCodec::~wxSndAiffCodec()
+{
+}
+
+bool wxSndAiffCodec::OnNeedData(char *buf, wxUint32 size)
+{
+  m_istream->Read(buf, size);
+  return TRUE;
+}
+
+bool wxSndAiffCodec::OnWriteData(char *buf, wxUint32 size)
+{
+  return ( !(m_ostream->Write(buf, size).LastError()) );
+}
+
+bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize)
+{
+/*
+  wxUint32 total_size;
+  char tmp_buf[10];
+
+  m_ostream->SeekO(0, wxBeginPosition);
+
+  m_ostream->Write("FORM", 4);
+  WRITE32(total_size);
+
+  m_ostream->Write("AIFF", 4);
+
+  WriteCOMM();
+  WriteSSND(m_fsize);
+
+*/
+  return TRUE;
+}
+
+void wxSndAiffCodec::SetFile(wxInputStream& s, bool preload, bool seekable)
+{
+  wxMMediaFile::SetFile(s, preload, seekable);
+  if (!seekable)
+    CacheIO();
+}
+
+void wxSndAiffCodec::SetFile(wxOutputStream& s, bool seekable)
+{
+  wxMMediaFile::SetFile(s, seekable);
+  if (!seekable)
+    CacheIO();
+}
diff --git a/utils/wxMMedia/sndaiff.h b/utils/wxMMedia/sndaiff.h
new file mode 100644 (file)
index 0000000..0a574e8
--- /dev/null
@@ -0,0 +1,58 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndaiff.h
+// Purpose:    wxMMedia Aiff Codec
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    February 1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_aiff_H__
+#define __SND_aiff_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+
+///
+class wxSndAiffCodec : public wxSndFileCodec {
+  ///
+  DECLARE_DYNAMIC_CLASS(wxSndAiffCodec)
+public:
+  ///
+  wxSndAiffCodec();
+  ///
+  wxSndAiffCodec(wxInputStream& s, bool preload = FALSE, bool seekable = TRUE);
+  ///
+  wxSndAiffCodec(wxOutputStream& s, bool seekable = TRUE);
+  ///
+  wxSndAiffCodec(const wxString& fname);
+  ///
+  virtual ~wxSndAiffCodec();
+
+  virtual bool OnNeedData(char *buf, wxUint32 size);
+  virtual bool OnWriteData(char *buf, wxUint32 size);
+
+  virtual wxUint32 PrepareToPlay();
+  virtual bool PrepareToRecord(wxUint32 file_size);
+
+  virtual void SetFile(wxInputStream& s, bool preload = FALSE,
+                       bool seekable = FALSE);
+  virtual void SetFile(wxOutputStream& s,
+                       bool seekable = FALSE);
+protected:
+  void ParseCOMM();
+  void ParseSSND();
+
+  void WriteCOMM();
+  void WriteSSND(wxUint32 file_size);
+
+protected:
+  wxUint32 m_spos, m_slen;
+  wxUint32 m_chunksize;
+};
+
+#endif
diff --git a/utils/wxMMedia/sndau.cpp b/utils/wxMMedia/sndau.cpp
new file mode 100644 (file)
index 0000000..9c46880
--- /dev/null
@@ -0,0 +1,114 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndau.cpp
+// Purpose:    wxMMedia Sun Audio File Codec
+// Author:     Guilhem Lavaux
+// Created:    1998
+// Updated:
+// Copyright:  (C) 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndau.h"
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+#include "sndau.h"
+
+#define AU_ISDN_ULAW 1
+#define AU_PCM_8BITS 2
+#define AU_PCM_16BITS 3
+#define AU_ADPCM 23
+
+wxSndAuCodec::wxSndAuCodec()
+  : wxSndFileCodec()
+{
+}
+
+wxSndAuCodec::wxSndAuCodec(wxInputStream& s, bool preload, bool seekable)
+  : wxSndFileCodec(s, preload, seekable)
+{
+}
+
+wxSndAuCodec::wxSndAuCodec(wxOutputStream& s, bool seekable)
+  : wxSndFileCodec(s, seekable)
+{
+}
+
+wxSndAuCodec::wxSndAuCodec(const wxString& fname)
+  : wxSndFileCodec(fname)
+{
+}
+
+wxSndAuCodec::~wxSndAuCodec()
+{
+}
+
+wxUint32 wxSndAuCodec::PrepareToPlay()
+{
+  wxString id;
+  char temp_buf[5];
+  int offset, srate, codec, ch_count;
+  size_t len;
+
+  m_istream->SeekI(0);
+
+  m_istream->Read(temp_buf, 4);
+  temp_buf[4] = 0;
+
+  id = temp_buf;
+  if (id != ".snd") {
+    m_mmerror = wxMMFILE_INVALID;
+    return 0;
+  }
+
+#define READ_BE_32(i) \
+m_istream->Read(temp_buf, 4); \
+i = (unsigned long)temp_buf[0] << 24; \
+i |= (unsigned long)temp_buf[1] << 16; \
+i |= (unsigned long)temp_buf[2] << 8; \
+i |= (unsigned long)temp_buf[3];
+
+  READ_BE_32(offset);
+  READ_BE_32(len);
+  READ_BE_32(codec);
+  READ_BE_32(srate);
+  READ_BE_32(ch_count);
+
+  m_sndformat.SetSampleRate(srate);
+  m_sndformat.SetChannels(ch_count);
+  switch (codec) {
+  case AU_ISDN_ULAW:
+    ChangeCodec(WXSOUND_ULAW);
+    break;
+  case AU_PCM_8BITS:
+    ChangeCodec(WXSOUND_PCM);
+    m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+    m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+    break;
+  case AU_PCM_16BITS:
+    ChangeCodec(WXSOUND_PCM);
+    m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+    m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+    break;
+  case AU_ADPCM:
+    ChangeCodec(WXSOUND_ADPCM);
+    break;
+  }
+  return len;
+}
+
+bool wxSndAuCodec::OnNeedData(char *buf, wxUint32 size)
+{
+  return m_istream->Read(buf, size).LastError();
+}
+
+bool wxSndAuCodec::OnWriteData(char *buf, wxUint32 size)
+{
+  return m_ostream->Write(buf, size).LastError();
+}
+
+bool wxSndAuCodec::PrepareToRecord(wxUint32 file_size)
+{
+  return FALSE;
+}
diff --git a/utils/wxMMedia/sndau.h b/utils/wxMMedia/sndau.h
new file mode 100644 (file)
index 0000000..ee8a276
--- /dev/null
@@ -0,0 +1,47 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndau.h
+// Purpose:    wxMMedia Sun Audio File Codec
+// Author:     Guilhem Lavaux
+// Created:    1998
+// Updated:
+// Copyright:  (C) 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_au_H__
+#define __SND_au_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+
+///
+class wxSndAuCodec : public wxSndFileCodec {
+  ///
+  DECLARE_DYNAMIC_CLASS(wxSndAuCodec)
+public:
+  ///
+  wxSndAuCodec();
+  ///
+  wxSndAuCodec(wxInputStream& s, bool preload = FALSE, bool seekable = TRUE);
+  ///
+  wxSndAuCodec(wxOutputStream& s, bool seekable = TRUE);
+  ///
+  wxSndAuCodec(const wxString& fname);
+  ///
+  virtual ~wxSndAuCodec();
+
+  bool OnNeedData(char *buf, wxUint32 size);
+  bool OnWriteData(char *buf, wxUint32 size);
+
+  wxUint32 PrepareToPlay();
+  bool PrepareToRecord(wxUint32 file_size);
+
+protected:
+  wxUint32 m_spos, m_slen;
+  wxUint32 m_chunksize;
+};
+
+#endif
diff --git a/utils/wxMMedia/sndfile.cpp b/utils/wxMMedia/sndfile.cpp
new file mode 100644 (file)
index 0000000..798969a
--- /dev/null
@@ -0,0 +1,323 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       sndfile.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndfile.h"
+#endif
+
+#include "mmedia.h"
+#include "sndfile.h"
+#ifdef WX_PRECOMP
+#include <wx/wxprec.h>
+#else
+#include <wx/wx.h>
+#endif
+#include <wx/module.h>
+#include "sndfrmt.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxSndFileCodec::wxSndFileCodec()
+  : wxMMediaFile(), wxSndBuffer(),
+    m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::wxSndFileCodec(wxOutputStream& s, bool seekable)
+  : wxMMediaFile(s, seekable),
+    wxSndBuffer(),
+    m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::wxSndFileCodec(wxInputStream& s, bool preload, bool seekable)
+  : wxMMediaFile(s, preload, seekable),
+    wxSndBuffer(), 
+    m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::wxSndFileCodec(const wxString& fname)
+  : wxMMediaFile(fname), wxSndBuffer(),
+    m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::~wxSndFileCodec()
+{
+}
+
+void wxSndFileCodec::Play(wxSound& snd)
+{
+  if (m_fstate != wxSFILE_STOPPED || IsSet(wxSND_BUFLOCKED))
+    return;
+
+  if (!(m_fsize = PrepareToPlay()))
+    return;
+
+  m_fpos = 0;
+  m_fstate = wxSFILE_PLAYING;
+
+  Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
+  snd.QueueBuffer(*this);
+}
+
+void wxSndFileCodec::Stop(wxSound& snd)
+{
+  if (m_fstate == wxSFILE_STOPPED)
+    return;
+
+  snd.UnqueueBuffer(*this);
+  Clear(wxSND_BUFREADY | wxSND_KEEPQUEUED);
+  m_fstate = wxSFILE_STOPPED;
+}
+
+void wxSndFileCodec::Record(wxSound& snd,
+                            const wxSoundDataFormat& format,
+                            wxUint32 seconds)
+{
+  wxUint32 byterate;
+
+  if (m_fstate != wxSFILE_STOPPED)
+    return;
+
+  m_sndformat = format;
+  byterate = m_sndformat.GetCodec()->GetByteRate();
+
+  m_fsize = seconds*byterate;
+  if (!PrepareToRecord(m_fsize))
+    return;
+  if (IsSet(wxSND_BUFLOCKED))
+    return;
+  wxUint32 sec1 = m_fsize / byterate,
+           sec2 = sec1 % 3600;
+
+  m_sndtime.hours = sec1 / 3600;
+  m_sndtime.minutes = sec2 / 60;
+  m_sndtime.seconds = sec2 % 60;
+
+  m_fdone = m_fpos = 0;
+  m_fstate = wxSFILE_RECORDING;
+
+  m_sndmode = wxSND_INPUT;
+
+  Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
+  snd.QueueBuffer(*this);
+}
+
+void wxSndFileCodec::OnNeedOutputData(char *data, wxUint32& size)
+{
+  wxUint32 datas_left = m_fsize-m_fpos;
+
+  if (m_fstate != wxSFILE_PLAYING) {
+    size = 0;
+    return;
+  }
+
+  if (!datas_left) {
+    size = 0;
+    m_fpos = 0;
+    m_fstate = wxSFILE_STOPPED;
+    Clear(wxSND_KEEPQUEUED);
+    return;
+  }
+
+  if (size > datas_left)
+    size = datas_left;
+
+  if (!OnNeedData(data, size)) {
+    size = 0;
+    m_fpos = 0;
+    m_fstate = wxSFILE_STOPPED;
+    Clear(wxSND_KEEPQUEUED);
+    return;
+  }
+
+  m_fpos += size;
+}
+
+void wxSndFileCodec::OnBufferInFinished(char *iobuf, wxUint32& size)
+{
+  wxUint32 datas_left = m_fsize-m_fdone;
+
+  if (m_fstate != wxSFILE_RECORDING) {
+    size = 0;
+    return;
+  }
+
+  if (!datas_left) {
+    size = 0;
+    Clear(wxSND_KEEPQUEUED); // To be sure.
+    return;
+  }
+
+  if (size > datas_left)
+    size = datas_left;
+
+  OnWriteData(iobuf, size);
+  m_fdone += size;
+}
+
+wxMMtime wxSndFileCodec::GetPosition()
+{
+  wxMMtime mm_time;
+  wxUint32 sec1, sec2;
+  wxUint32 byterate;
+
+  byterate = m_sndformat.GetCodec()->GetByteRate();
+
+  if (m_fpos && byterate) {
+    sec1 = m_fpos / byterate;
+    sec2 = sec1 % 3600;
+    mm_time.hours = sec1 / 3600;
+    mm_time.minutes = sec2 / 60;
+    mm_time.seconds = sec2 % 60;
+  } else {
+    mm_time.hours = 0;
+    mm_time.minutes = 0;
+    mm_time.seconds = 0;
+  }
+
+  return mm_time;
+}
+
+wxMMtime wxSndFileCodec::GetLength()
+{
+  if (m_sndtime.hours == -1 && m_istream)
+    PrepareToPlay();
+
+  return m_sndtime;
+}
+
+bool wxSndFileCodec::TranslateBuffer(wxSndBuffer& buf)
+{
+#define TMP_BUFSIZE 10240
+
+  wxUint32 buf_size;
+  wxStreamBuffer *tmp_buf;
+  wxSoundCodec *codec_in, *codec_out;
+  wxSoundDataFormat std_format;
+
+  if (!m_ostream || !buf.RestartBuffer(wxSND_OUTPUT))
+    return FALSE;
+  m_sndformat = buf.GetFormat();
+  codec_in = buf.GetCurrentCodec();
+
+  m_fdone = 0;
+
+  if (!PrepareToRecord(m_fsize))
+    return FALSE;
+  codec_out = GetCurrentCodec();
+  m_fsize = (int)(((float)buf.GetSize() / codec_in->GetByteRate()) *
+             codec_out->GetByteRate());
+
+  if (!PrepareToRecord(m_fsize))
+    return FALSE;
+
+  codec_out = GetCurrentCodec();
+  codec_in->InitIO(m_sndformat);
+  codec_out->InitIO(m_sndformat);
+
+  tmp_buf = new wxStreamBuffer(wxStreamBuffer::read_write);
+  tmp_buf->Fixed(TRUE);
+  tmp_buf->Flushable(FALSE);
+  tmp_buf->SetBufferIO(TMP_BUFSIZE);
+
+  m_fstate = wxSFILE_RECORDING;
+
+  while (m_fdone < m_fsize) {
+    tmp_buf->ResetBuffer();
+    codec_in->SetOutStream(tmp_buf);
+    codec_in->Decode();
+
+    tmp_buf->ResetBuffer();
+    codec_out->SetInStream(tmp_buf);
+    codec_out->Encode();
+
+    buf.OnBufferOutFinished();
+  }
+  delete tmp_buf;
+
+  m_fstate = wxSFILE_STOPPED;
+
+  return TRUE;
+}
+
+bool wxSndFileCodec::RestartBuffer(wxSndMode mode)
+{
+  if (IsSet(wxSND_BUFLOCKED))
+    return FALSE;
+
+  m_fdone = 0;
+  m_fpos = 0;
+
+  if (mode == wxSND_OUTPUT && m_istream) {
+    m_fsize = PrepareToPlay();
+    m_fstate = wxSFILE_PLAYING;
+    return TRUE;
+  }
+  if (mode == wxSND_INPUT && m_ostream) {
+    m_fsize = 0;
+    m_fstate = wxSFILE_RECORDING;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+wxUint32 wxSndFileCodec::GetSize() const
+{
+  return m_fsize;
+}
+
+wxUint32 wxSndFileCodec::Available() const
+{
+  return m_fsize-m_fpos; 
+}
+
+//
+// Simple API
+//
+static wxSoundDevice *dev_snd = NULL;
+
+bool wxSndFileCodec::StartPlay()
+{
+  if (!dev_snd)
+    dev_snd = new wxSoundDevice;
+
+  Play(*dev_snd);
+
+  return TRUE;
+}
+
+void wxSndFileCodec::StopPlay()
+{
+  if (!dev_snd)
+    return;
+
+  Stop(*dev_snd);
+  m_fpos = 0;
+}
+
+class wxSoundModule : public wxModule {
+  DECLARE_DYNAMIC_CLASS(wxSoundModule)
+public:
+  virtual bool OnInit() { return TRUE; }
+  virtual void OnExit() {
+    if (dev_snd)
+      delete dev_snd;
+  }
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxSoundModule, wxModule)
diff --git a/utils/wxMMedia/sndfile.h b/utils/wxMMedia/sndfile.h
new file mode 100644 (file)
index 0000000..2a1c7e5
--- /dev/null
@@ -0,0 +1,91 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndfile.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_file_H__
+#define __SND_file_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmfile.h"
+#include "sndsnd.h"
+
+///
+class wxSndFileCodec : public wxMMediaFile, public wxSndBuffer {
+  ///
+  DECLARE_ABSTRACT_CLASS(wxSndFileCodec)
+public:
+
+  typedef enum {
+    wxSFILE_STOPPED,
+    wxSFILE_PLAYING,
+    wxSFILE_RECORDING
+  } FileState;
+
+protected:
+  wxUint32 m_fsize, m_fpos, m_fdone;
+  FileState m_fstate;
+  wxMMtime m_sndtime;
+public:
+
+  ///
+  wxSndFileCodec();
+  ///
+  wxSndFileCodec(wxInputStream& s, bool preload, bool seekable);
+  ///
+  wxSndFileCodec(wxOutputStream& s, bool seekable);
+  ///
+  wxSndFileCodec(const wxString& fname);
+  ///
+  virtual ~wxSndFileCodec();
+
+  ///
+  void Play(wxSound& snd);
+  ///
+  void Stop(wxSound& snd);
+  ///
+  void Record(wxSound& snd,
+              const wxSoundDataFormat& format, wxUint32 seconds);
+
+  ///
+  void OnNeedOutputData(char *data, wxUint32& size);
+  ///
+  void OnBufferInFinished(char *iobuf, wxUint32& size);
+
+  ///
+  virtual bool OnNeedData(char *buf, wxUint32 size) = 0;
+  ///
+  virtual bool OnWriteData(char *buf, wxUint32 size) = 0;
+  ///
+  virtual wxUint32 PrepareToPlay() = 0;
+  ///
+  virtual bool PrepareToRecord(wxUint32 file_size) = 0;
+  ///
+  virtual bool TranslateBuffer(wxSndBuffer& buf);
+  ///
+  virtual bool RestartBuffer(wxSndMode mode);
+  ///
+  virtual wxUint32 GetSize() const;
+  ///
+  virtual wxUint32 Available() const;
+  ///
+  virtual wxMMtime GetLength();
+
+  ///
+  wxMMtime GetPosition();
+
+  ///
+  virtual bool StartPlay();
+  ///
+  virtual void StopPlay();
+};
+
+#endif
diff --git a/utils/wxMMedia/sndfrag.cpp b/utils/wxMMedia/sndfrag.cpp
new file mode 100644 (file)
index 0000000..cd4a76b
--- /dev/null
@@ -0,0 +1,268 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       sndfrag.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndfrag.h"
+#endif
+#include <stdio.h>
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndfrag.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxFragmentBuffer::wxFragmentBuffer(wxSound& io_drv)
+ : m_iodrv(&io_drv), m_maxoq(0), m_maxiq(0),
+   m_optrs(NULL), m_iptrs(NULL), m_lstoptrs(NULL), m_lstiptrs(NULL),
+   m_buf2free(FALSE), m_dontq(FALSE), m_freeing(FALSE)
+{
+}
+
+wxFragmentBuffer::~wxFragmentBuffer()
+{
+}
+
+void wxFragmentBuffer::AbortBuffer(wxSndBuffer *buf)
+{
+  for (wxUint8 i=0;i<m_maxoq;i++)
+    if (m_lstoptrs[i].buffers->Member(buf)) {
+      if (m_lstoptrs[i].state == wxBUFFER_PLAYING)
+        // TODO: Do something.
+        ;
+      m_lstoptrs[i].state = wxBUFFER_TOFREE;
+    }
+
+  for (wxUint8 i=0;i<m_maxiq;i++)
+    if (m_lstiptrs[i].buffers->Member(buf)) {
+      if (m_lstiptrs[i].state == wxBUFFER_PLAYING)
+        // Do something.
+        ;
+      m_lstiptrs[i].state = wxBUFFER_TOFREE;
+    }
+}
+
+wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer(
+                         wxFragBufPtr *list, wxUint8 max_queue)
+{
+  if (!list)
+    return NULL;
+
+  for (wxUint8 i=0;i<max_queue;i++) {
+    if (list[i].state == wxBUFFER_FREE)
+      return &list[i];
+  }
+
+  return NULL;
+}
+
+bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
+{
+  wxFragBufPtr *ptr;
+  char *raw_buf;
+  wxUint32 rawbuf_size;
+
+  if (!m_iodrv->OnSetupDriver(*buf, wxSND_OUTPUT))
+    return FALSE;
+
+  while (1) {
+    // Find the first free (at least partly free) output buffer
+    ptr = FindFreeBuffer(m_lstoptrs, m_maxoq);
+    // No free : go out !
+    if (!ptr)
+      return FALSE;
+    
+    // Find the end of the buffer
+    raw_buf = ptr->data + ptr->ptr;
+    rawbuf_size = ptr->size - ptr->ptr;
+    
+    // Fill it up
+    buf->OnNeedOutputData(raw_buf, rawbuf_size);
+
+    // No data to fill the buffer: dequeue the current wxSndBuffer
+    if (!rawbuf_size) {
+      if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
+        buf->Set(wxSND_UNQUEUEING);
+        m_iodrv->m_buffers.DeleteObject(buf);
+      }
+      return TRUE;
+    }
+
+    // Data: append it to the list
+    ptr->buffers->Append(buf);
+
+    ptr->ptr += rawbuf_size;
+
+    // Output buffer full: send it to the driver
+    if (ptr->ptr == ptr->size) {
+      ptr->state = wxBUFFER_FFILLED;
+      OnBufferFilled(ptr, wxSND_OUTPUT);
+    }
+  }
+}
+
+bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf)
+{
+  wxFragBufPtr *ptr;
+  char *raw_buf;
+  wxUint32 rawbuf_size;
+
+  if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
+    return FALSE;
+
+  while (1) {
+    ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
+    if (!ptr)
+      return FALSE;
+    
+    raw_buf = ptr->data + ptr->ptr;
+    rawbuf_size = ptr->size - ptr->ptr;
+    
+    rawbuf_size = (buf->Available() < rawbuf_size) ? buf->Available() : rawbuf_size;
+
+    if (!rawbuf_size) {
+
+      if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
+        buf->Set(wxSND_UNQUEUEING);
+        m_iodrv->m_buffers.DeleteObject(buf);
+      }
+
+      // Get data now when there isn't anymore buffer in the queue
+      if (!LastBuffer() && ptr->ptr) {
+        ptr->state = wxBUFFER_FFILLED;
+        if (!OnBufferFilled(ptr, wxSND_INPUT))
+          return FALSE;
+      }
+      return TRUE;
+    }
+    ptr->buffers->Append(buf);
+
+    ptr->ptr += rawbuf_size;
+
+    // Input buffer full => get data
+    if (ptr->ptr == ptr->size) {
+      ptr->state = wxBUFFER_FFILLED;
+      if (!OnBufferFilled(ptr, wxSND_INPUT))
+        return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+void wxFragmentBuffer::FreeBufToFree(bool force)
+{
+  wxUint8 i;
+  // Garbage collecting
+
+  m_dontq = TRUE;
+  m_buf2free = FALSE;
+
+  for (i=0;i<m_maxoq;i++) {
+    if ((m_lstoptrs[i].state == wxBUFFER_TOFREE) ||
+       (force && m_lstoptrs[i].state == wxBUFFER_FFILLED))
+      ClearBuffer(&m_lstoptrs[i]);
+  }
+
+  for (i=0;i<m_maxiq;i++) {
+    if ((m_lstiptrs[i].state == wxBUFFER_TOFREE) ||
+       (force && m_lstoptrs[i].state == wxBUFFER_FFILLED))
+      ClearBuffer(&m_lstiptrs[i]);
+  }
+
+  m_dontq = FALSE;
+}
+
+void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr)
+{
+  wxNode *node;
+  wxSndBuffer *buf;
+  char *data;
+  wxUint32 size, data_read;
+
+  data = ptr->data;
+  size = ptr->size;
+
+  node = ptr->buffers->First();
+
+  while (node) {
+    buf = (wxSndBuffer *)node->Data();
+
+    if (buf->GetMode() == wxSND_OUTPUT) {
+      buf->OnBufferOutFinished();
+    } else {
+      data_read = buf->OnBufferInFinished(data, size);
+
+      data += data_read;
+      size -= data_read;
+    }
+
+    if (buf->IsSet(wxSND_UNQUEUEING))
+      buf->Clear(wxSND_UNQUEUEING | wxSND_BUFLOCKED | wxSND_BUFREADY);
+
+    delete node;
+    node = ptr->buffers->First();
+  }
+
+  ptr->ptr = 0;
+  ptr->state = wxBUFFER_FREE;
+}
+
+void wxFragmentBuffer::OnBufferFinished(wxFragBufPtr *ptr)
+{
+  wxNode *node;
+  wxSndBuffer *buf;
+  bool ret = TRUE;
+
+  if (m_freeing) {
+    ptr->state = wxBUFFER_TOFREE;
+    m_buf2free = TRUE;
+    return;
+  }
+  m_freeing = TRUE;
+
+  // Clean up the old buffer.
+  if (ptr && ptr->state != wxBUFFER_FREE)
+    ClearBuffer(ptr);
+
+  // Garbage collecting ...
+  if (m_buf2free)
+    FreeBufToFree();
+
+  // If we are queueing, return immediately.
+  if (m_dontq) {
+    m_freeing = FALSE;
+    return;
+  }
+
+  node = m_iodrv->m_buffers.First();
+
+  while (node && ret) {
+    buf = (wxSndBuffer *)node->Data();
+    node = node->Next();
+
+    buf->HardLock();
+
+    // Stop request on this buffer.
+    if (buf->IsSet(wxSND_BUFSTOP)) {
+      buf->Clear(wxSND_BUFSTOP);
+      continue;
+    }
+    if (buf->GetMode() == wxSND_OUTPUT)
+      ret = NotifyOutputBuffer(buf);
+    else
+      ret = NotifyInputBuffer(buf);
+
+    buf->HardUnlock();
+  }
+  m_freeing = FALSE;
+}
diff --git a/utils/wxMMedia/sndfrag.h b/utils/wxMMedia/sndfrag.h
new file mode 100644 (file)
index 0000000..8acb31f
--- /dev/null
@@ -0,0 +1,103 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndfrag.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __SND_frag_H__
+#define __SND_frag_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndsnd.h"
+
+///
+class wxFragmentBuffer {
+protected:
+  wxSound *m_iodrv;
+
+  ///
+  wxUint8 m_maxoq, m_maxiq;
+
+  ///
+  typedef enum {
+    wxBUFFER_FREE,
+    wxBUFFER_FFILLED,
+    wxBUFFER_TOFREE
+  } BufState;
+public: 
+  ///
+  typedef struct {
+    char *data;
+    ///
+    char *user_data;
+    ///
+    wxUint32 size, ptr;
+    ///
+    wxList *buffers;
+    ///
+    BufState state;
+  } wxFragBufPtr;
+protected:
+  ///
+  wxFragBufPtr *m_optrs, *m_iptrs;
+  ///
+  wxFragBufPtr *m_lstoptrs, *m_lstiptrs;
+  ///
+  bool m_buf2free, m_dontq, m_freeing;
+public:
+  ///
+  wxFragmentBuffer(wxSound& io_drv);
+  ///
+  virtual ~wxFragmentBuffer();
+
+  ///
+  virtual void AllocIOBuffer() = 0;
+  ///
+  virtual void FreeIOBuffer() = 0;
+
+  ///
+  void AbortBuffer(wxSndBuffer *buf);
+  
+  ///
+  wxFragBufPtr *FindFreeBuffer(wxFragBufPtr *list, wxUint8 max_queue);
+  ///
+  bool NotifyOutputBuffer(wxSndBuffer *buf);
+  ///
+  bool NotifyInputBuffer(wxSndBuffer *buf);
+
+  ///
+  void OnBufferFinished(wxFragBufPtr *ptr);
+
+  ///
+  virtual bool OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode) = 0;
+
+  ///
+  inline wxSndBuffer *LastBuffer() {
+    wxNode *node = m_iodrv->m_buffers.Last();
+
+    if (!node) return NULL;
+    return (wxSndBuffer *)node->Data();
+  }
+  ///
+  inline wxSndBuffer *FirstBuffer() {
+    wxNode *node = m_iodrv->m_buffers.First();
+
+    if (!node) return NULL;
+    return (wxSndBuffer *)node->Data();
+  }
+protected:
+  void FreeBufToFree(bool force = FALSE);
+  void ClearBuffer(wxFragBufPtr *ptr);
+};
+
+#endif
diff --git a/utils/wxMMedia/sndfrmt.cpp b/utils/wxMMedia/sndfrmt.cpp
new file mode 100644 (file)
index 0000000..fb933b4
--- /dev/null
@@ -0,0 +1,266 @@
+#ifdef __GNUG__
+#pragma implementation "sndfrmt.h"
+#endif
+#include "sndsnd.h"
+#include "sndfrmt.h"
+#include "sndpcm.h"
+#include <dmalloc.h>
+
+// ----------------------------------------------------------------------------
+// wxSoundDataFormat
+// ----------------------------------------------------------------------------
+
+wxSoundDataFormat::wxSoundDataFormat()
+{
+  m_srate = 22050;
+  m_bps = 8;
+  m_channels = 1;
+  m_codno = 1;
+  m_codec = NULL;
+  m_codchange = FALSE;
+  m_codcreate = TRUE;
+}
+
+wxSoundDataFormat::~wxSoundDataFormat()
+{
+  wxDELETE(m_codec);
+}
+
+void wxSoundDataFormat::SetChannels(int channels)
+{
+  m_channels = channels;
+}
+
+void wxSoundDataFormat::SetBps(int bps)
+{
+  m_bps = bps;
+  CodecChange();
+}
+
+void wxSoundDataFormat::SetSign(int sign)
+{
+  m_sign = sign;
+  CodecChange();
+}
+
+void wxSoundDataFormat::SetByteOrder(int byteorder)
+{
+  m_byteorder = byteorder;
+  CodecChange();
+}
+
+void wxSoundDataFormat::SetCodecNo(int codno)
+{
+  m_codno = codno;
+  m_codchange = TRUE;
+  CodecChange();
+}
+
+wxSoundCodec *wxSoundDataFormat::GetCodec()
+{
+  if (!m_codcreate)
+    return NULL;
+
+  if (m_codchange) 
+    wxDELETEA(m_codec);
+  
+  if (m_codec)
+    return m_codec;
+
+  m_codchange = FALSE;
+  m_codec = wxSoundCodec::Get(m_codno);
+
+  return m_codec;
+}
+
+void wxSoundDataFormat::CodecChange()
+{
+  wxSoundCodec *codec = GetCodec();
+
+  if (!codec)
+    return;
+
+  switch (m_codno) {
+  case WXSOUND_PCM: {
+      wxSoundPcmCodec *pcm_codec = (wxSoundPcmCodec *)codec;
+
+      pcm_codec->SetBits(m_bps);
+      pcm_codec->SetByteOrder(m_byteorder);
+      pcm_codec->SetSign(m_sign);
+      break;
+    }
+  default:
+      break;
+  }
+}
+
+wxSoundDataFormat& wxSoundDataFormat::operator =(const wxSoundDataFormat& format)
+{
+  wxDELETE(m_codec);
+
+  m_srate = format.m_srate;
+  m_bps = format.m_bps;
+  m_channels = format.m_channels;
+  m_codno = format.m_codno;
+  m_sign = format.m_sign;
+  m_byteorder = format.m_byteorder;
+
+  return *this;
+}
+
+bool wxSoundDataFormat::operator ==(const wxSoundDataFormat& format) const
+{
+  if (m_codno != format.m_codno || m_srate != format.m_srate ||
+      m_bps != format.m_bps || m_channels != format.m_channels)
+    return FALSE;
+
+  if (m_codno == WXSOUND_PCM &&
+      (m_sign != format.m_sign || m_byteorder != format.m_byteorder))
+    return FALSE;
+
+  return TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// wxSoundCodec
+// ----------------------------------------------------------------------------
+
+#include "sndpcm.h"
+//#include "sndadpcm.h"
+//#include "sndalaw.h"
+#include "sndmulaw.h"
+
+static wxClassInfo *l_sound_formats[] = {
+      NULL,
+      CLASSINFO(wxSoundPcmCodec),
+      NULL, //  CLASSINFO(wxSoundAdpcmCodec),
+      NULL,
+      NULL,
+      NULL,
+      NULL, // CLASSINFO(wxSoundAlawCodec),
+      NULL  // CLASSINFO(wxSoundMulawCodec)
+};
+
+static int l_nb_formats = WXSIZEOF(l_sound_formats);
+
+wxSoundCodec::wxSoundCodec()
+{
+  m_in_sound = NULL;
+  m_out_sound = NULL;
+  m_init = TRUE;
+}
+
+wxSoundCodec::~wxSoundCodec()
+{
+}
+
+void wxSoundCodec::InitIO(const wxSoundDataFormat& format)
+{
+  m_io_format = format;
+}
+
+void wxSoundCodec::InitMode(int mode)
+{
+  wxStreamBuffer *buf_snd;
+
+  m_mode = (mode == 0) ? ENCODING : DECODING;
+  if (!m_chain_codec) {
+    if (mode == ENCODING) {
+      m_out_sound = new wxStreamBuffer(*this, wxStreamBuffer::write);
+      m_out_sound->SetBufferIO(1024);
+    } else {
+      m_in_sound = new wxStreamBuffer(*this, wxStreamBuffer::read);
+      m_in_sound->SetBufferIO(1024);
+    }
+  }
+  if (m_chain_codec) {
+    if (m_chain_before) {
+      m_chain_codec->SetInStream(m_in_sound);
+      buf_snd = new wxStreamBuffer(wxStreamBuffer::read_write);
+      buf_snd->Fixed(FALSE);
+      m_chain_codec->SetOutStream(buf_snd);
+      m_chain_codec->Decode();
+      buf_snd->Seek(0, wxFromStart);
+      m_in_sound = buf_snd;
+    } else {
+      buf_snd = new wxStreamBuffer(wxStreamBuffer::read_write);
+      buf_snd->Fixed(FALSE);
+
+      m_chain_codec->SetInStream(buf_snd);
+      m_chain_codec->SetOutStream(m_out_sound);
+      m_out_sound = buf_snd;
+
+      buf_snd->Seek(0, wxFromStart);
+    }
+  }
+}
+
+void wxSoundCodec::ExitMode()
+{
+  if (m_chain_codec) {
+    if (m_chain_before) {
+      delete m_in_sound;
+      m_in_sound = m_chain_codec->GetInStream();
+    } else {
+      delete m_out_sound;
+      m_out_sound = m_chain_codec->GetOutStream();
+    }
+  }
+}
+
+bool wxSoundCodec::ChainCodecBefore(wxSoundDataFormat& format)
+{
+  m_chain_codec = format.GetCodec();
+
+  if (!m_chain_codec)
+    return FALSE;
+
+  m_chain_before = TRUE;
+  return TRUE;
+}
+
+bool wxSoundCodec::ChainCodecAfter(wxSoundDataFormat& format)
+{
+  m_chain_codec = format.GetCodec();
+
+  if (!m_chain_codec)
+    return FALSE;
+
+  m_chain_before = FALSE;
+  return TRUE;
+}
+
+void wxSoundCodec::CopyToOutput()
+{
+  m_out_sound->Write(m_in_sound);
+}
+
+size_t wxSoundCodec::Available()
+{
+  return m_io_sndbuf->Available();
+}
+
+size_t wxSoundCodec::OnSysRead(void *buffer, size_t bsize)
+{
+  wxUint32 s = bsize;
+  m_io_sndbuf->OnNeedOutputData((char *)buffer, s);
+  return bsize;
+}
+
+size_t wxSoundCodec::OnSysWrite(const void *buffer, size_t bsize)
+{
+  wxUint32 s = bsize;
+  m_io_sndbuf->OnBufferInFinished((char *)buffer, s);
+  return bsize;
+}
+
+wxSoundCodec *wxSoundCodec::Get(int no)
+{
+  if (no < 0 || no >= l_nb_formats)
+    return NULL;
+
+  if (!l_sound_formats[no])
+    return NULL;
+
+  return (wxSoundCodec *)l_sound_formats[no]->CreateObject();
+}
diff --git a/utils/wxMMedia/sndfrmt.h b/utils/wxMMedia/sndfrmt.h
new file mode 100644 (file)
index 0000000..feb0ad6
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef __SNDFRMT_H__
+#define __SNDFRMT_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <wx/object.h>
+
+class wxSndBuffer;
+
+// Standard Microsoft types (why change ?)
+#define WXSOUND_PCM   0x0001
+#define WXSOUND_ADPCM 0x0002
+#define WXSOUND_ALAW  0x0006
+#define WXSOUND_ULAW  0x0007
+
+class wxSoundCodec;
+class wxSoundDataFormat {
+ public:
+  wxSoundDataFormat();
+  ~wxSoundDataFormat();
+
+  void SetSampleRate(int srate) { m_srate = srate; }
+  void SetChannels(int channels);
+  void SetStereo(bool on);
+  void SetCodecNo(int no);
+  void SetCodecCreate(bool create) { m_codcreate = create; }
+
+  int GetSampleRate() const { return m_srate; }
+  int GetChannels()  const { return m_channels; }
+  bool GetStereo() const { return (m_channels == 2); }
+  int GetCodecNo() const { return m_codno; }
+
+  wxSoundCodec *GetCodec();
+
+  wxSoundDataFormat& operator =(const wxSoundDataFormat& format);
+  bool operator ==(const wxSoundDataFormat& format) const;
+  bool operator !=(const wxSoundDataFormat& format) const
+        { return !(operator ==(format)); }
+
+  /// PCM format
+  void SetByteOrder(int order);
+  void SetSign(int sign);
+  int GetByteOrder() const { return m_byteorder; }
+  int GetSign() const { return m_sign; }
+
+  void SetBps(int bps);
+  int GetBps() const { return m_bps; }
+
+ protected:
+  void CodecChange();
+
+ protected:
+  int m_srate, m_bps, m_channels, m_codno;
+  int m_byteorder, m_sign;
+  bool m_codchange, m_codcreate;
+  wxSoundCodec *m_codec;
+};
+
+class wxSoundCodec : public wxObject, public wxStreamBase {
+  DECLARE_ABSTRACT_CLASS(wxSoundCodec)
+ public:
+  wxSoundCodec();
+  virtual ~wxSoundCodec();
+
+  void SetIOBuffer(wxSndBuffer *sndbuf) { m_io_sndbuf = sndbuf; }
+  size_t Available();
+
+  void InitIO(const wxSoundDataFormat& format);
+  void InitMode(int mode);
+  void ExitMode();
+
+  inline void SetInStream(wxStreamBuffer *s)
+          { m_in_sound = s; }
+  inline void SetOutStream(wxStreamBuffer *s)
+          { m_out_sound = s; }
+  inline wxStreamBuffer *GetInStream() const { return m_in_sound; }
+  inline wxStreamBuffer *GetOutStream() const { return m_out_sound; }
+
+  inline bool Good() const { return (m_in_sound->Stream()->LastError() == wxStream_NOERROR) && (m_out_sound->Stream()->LastError() == wxStream_NOERROR); }
+
+  virtual size_t GetByteRate() const = 0; 
+  virtual wxSoundDataFormat GetPreferredFormat(int codec = 0) const = 0; 
+
+  virtual void Decode() = 0;
+  virtual void Encode() = 0;
+
+  static wxSoundCodec *Get(int no);
+
+ protected:
+  void CopyToOutput();
+
+  unsigned short Convert8_16(unsigned char s) { return (s & 0xff) << 8; }
+  unsigned char Convert16_8(unsigned short s) { return (s & 0xff00) >> 8; }
+
+  bool ChainCodecBefore(wxSoundDataFormat& cod_to);
+  bool ChainCodecAfter(wxSoundDataFormat& cod_to);
+
+  // -------------
+  // wxStream part
+  // -------------
+  size_t OnSysWrite(const void *buffer, size_t bsize);
+  size_t OnSysRead(void *buffer, size_t bsize);
+
+ protected:
+  wxSndBuffer *m_io_sndbuf;
+  wxSoundDataFormat m_io_format;
+  wxStreamBuffer *m_in_sound, *m_out_sound;
+  wxSoundCodec *m_chain_codec;
+  bool m_init, m_chain_before;
+
+  enum {
+    ENCODING = 0,
+    DECODING
+  } m_mode;
+};
+
+#endif
diff --git a/utils/wxMMedia/sndmulaw.cpp b/utils/wxMMedia/sndmulaw.cpp
new file mode 100644 (file)
index 0000000..f42e5a4
--- /dev/null
@@ -0,0 +1,85 @@
+#ifdef __GNUG__
+#pragma implementation "sndmulaw.h"
+#endif
+
+#include "sndsnd.h"
+#include "sndfrmt.h"
+#include "sndmulaw.h"
+#include "adpcm/g72x.h"
+
+wxSoundMulawCodec::wxSoundMulawCodec()
+  : wxSoundCodec()
+{
+}
+
+wxSoundMulawCodec::~wxSoundMulawCodec()
+{
+}
+
+void wxSoundMulawCodec::Decode()
+{
+  int smp;
+  wxSoundDataFormat pref_frmt;
+
+  pref_frmt = GetPreferredFormat(0);
+  if (m_io_format != pref_frmt)
+    ChainCodecAfter(pref_frmt);
+
+  InitMode(DECODING);
+
+  while (!Good()) {
+      smp = ulaw2linear(m_in_sound->GetChar());
+#ifdef USE_BE_MACH
+      m_out_sound->PutChar((smp & 0xff00) >> 8);
+      m_out_sound->PutChar(smp & 0xff);
+#else
+      m_out_sound->PutChar(smp & 0xff);
+      m_out_sound->PutChar((smp & 0xff00) >> 8);
+#endif
+  }
+}
+
+void wxSoundMulawCodec::Encode()
+{
+  int smp;
+  wxSoundDataFormat pref_frmt;
+
+  pref_frmt = GetPreferredFormat(0);
+  if (m_io_format != pref_frmt)
+    ChainCodecBefore(pref_frmt);
+
+  InitMode(ENCODING);
+
+  while (!Good()) {
+#ifdef USE_BE_MACH
+      smp = ((unsigned short)m_in_sound->GetChar()) << 8;
+      smp |= m_in_sound->GetChar() & 0xff;
+#else
+      smp = m_in_sound->GetChar() & 0xff;
+      smp |= ((unsigned short)m_in_sound->GetChar()) << 8;
+#endif
+      m_out_sound->PutChar(linear2ulaw(smp));
+  }
+}
+
+size_t wxSoundMulawCodec::GetByteRate() const
+{
+  return m_srate;
+}
+
+wxSoundDataFormat wxSoundMulawCodec::GetPreferredFormat(int WXUNUSED(no)) const
+{
+  wxSoundDataFormat format;
+
+  format.SetCodecNo(WXSOUND_PCM);
+  format.SetSampleRate(m_srate);
+  format.SetBps(16);
+  format.SetChannels(1);
+  format.SetSign(wxSND_SAMPLE_SIGNED);
+#ifdef USE_BE_MACH
+  format.SetByteOrder(wxSND_SAMPLE_BE);
+#else
+  format.SetByteOrder(wxSND_SAMPLE_LE);
+#endif
+  return format;
+}
diff --git a/utils/wxMMedia/sndmulaw.h b/utils/wxMMedia/sndmulaw.h
new file mode 100644 (file)
index 0000000..8405674
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __MEDIA_SNDMULAW_H__
+#define __MEDIA_SNDMULAW_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "sndfrmt.h"
+
+class wxSoundMulawCodec : public wxSoundCodec {
+  DECLARE_DYNAMIC_CLASS(wxSoundMulawCodec)
+ public:
+  wxSoundMulawCodec();
+  virtual ~wxSoundMulawCodec();
+
+  void SetSampleRate(int srate) { m_srate = srate; }
+
+  size_t GetByteRate() const;
+  wxSoundDataFormat GetPreferredFormat(int codec = 0) const;
+
+  void Decode();
+  void Encode();
+
+ protected:
+  int m_srate;
+};
+
+#endif
diff --git a/utils/wxMMedia/sndpcm.cpp b/utils/wxMMedia/sndpcm.cpp
new file mode 100644 (file)
index 0000000..a1c5be0
--- /dev/null
@@ -0,0 +1,216 @@
+#ifdef __GNUG__
+#pragma implementation "sndpcm.h"
+#endif
+#include "sndsnd.h"
+#include "sndpcm.h"
+#include <dmalloc.h>
+
+#define WX_BIG_ENDIAN 0
+
+wxSoundPcmCodec::wxSoundPcmCodec()
+  : wxSoundCodec()
+{
+  m_orig_format.SetCodecCreate(FALSE);
+  m_orig_format.SetCodecNo(1);
+  m_char_bool = FALSE;
+}
+
+wxSoundPcmCodec::~wxSoundPcmCodec()
+{
+}
+
+size_t wxSoundPcmCodec::GetByteRate() const
+{
+  return (m_orig_format.GetBps()/8)*
+          m_orig_format.GetSampleRate()*
+          m_orig_format.GetChannels();
+}
+
+wxSoundDataFormat wxSoundPcmCodec::GetPreferredFormat(int codec) const
+{
+  wxSoundDataFormat prefFormat;
+
+  prefFormat = m_orig_format;
+  prefFormat.SetCodecNo(WXSOUND_PCM);
+  return prefFormat;
+}
+
+// ---------------------------------------------------------------------------
+// Main part of the decoder
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::Decode()
+{
+  InitMode(DECODING);
+  if (m_io_format == m_orig_format) {
+    CopyToOutput();
+    ExitMode();
+    return;
+  }
+
+  // Swap bytes
+  switch (m_io_format.GetBps()) {
+  case 8:
+    InputSign8();
+    break;
+  case 16:
+    InputSwapAndSign16();
+    break;
+  case 32:
+  case 64:
+  default:
+    break;
+  }
+  ExitMode();
+}
+
+// ---------------------------------------------------------------------------
+// Change the sign of a 8-bit sample.
+
+#define GET() (m_in_sound->GetChar())
+#define PUT(c) (m_out_sound->PutChar(c))
+#define OUT_ERROR() (out->LastError() == wxStream_NOERROR)
+#define IN_ERROR() (in->LastError() == wxStream_NOERROR)
+
+void wxSoundPcmCodec::InputSign8()
+{
+  unsigned char signer = 0;
+  wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+
+  if (m_io_format.GetSign() != m_orig_format.GetSign())
+    signer = 128;
+
+  while (IN_ERROR() && OUT_ERROR())
+    PUT(GET() + signer);
+
+}
+
+// ---------------------------------------------------------------------------
+// Swap bytes and change the sign of a 16-bit sample.
+
+void wxSoundPcmCodec::InputSwapAndSign16()
+{
+  unsigned short signer1 = 0, signer2 = 0;
+  wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+  bool swap = (m_io_format.GetByteOrder() != m_orig_format.GetByteOrder());
+  char temp;
+
+  if (m_io_format.GetSign() != m_orig_format.GetSign()) {
+    if (m_io_format.GetByteOrder() == wxSND_SAMPLE_LE)
+      signer2 = 0x80;
+    else
+      signer1 = 0x80;
+  }
+
+  if (swap) {
+    while (IN_ERROR() && OUT_ERROR()) {
+      temp = GET() ^ signer1;
+      PUT(GET() ^ signer2);
+      if (OUT_ERROR()) {
+        m_char_bool = TRUE;
+        m_char_stack = temp;
+        break;
+      }
+      PUT(temp);
+    }
+  } else {
+    while (IN_ERROR() && OUT_ERROR()) {
+      PUT(GET() ^ signer1);
+      if (OUT_ERROR()) {
+        m_char_bool = TRUE;
+        m_char_stack = temp;
+        break;
+      }
+      PUT(GET() ^ signer2);
+    }
+  }
+}
+
+// ---------------------------------------------------------------------------
+// Encoder part.
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::OutputSign8()
+{
+  wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+  unsigned char signer = 0;
+
+  if (m_io_format.GetSign() != m_orig_format.GetSign())
+    signer = 128;
+
+  while (IN_ERROR() && OUT_ERROR())
+    PUT((char)(GET() + signer));
+}
+
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::OutputSwapAndSign16()
+{
+  bool swap = (m_io_format.GetByteOrder() != m_orig_format.GetByteOrder());
+  unsigned short signer1 = 0, signer2 = 0;
+  char temp;
+  wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+
+  if (m_char_bool) {
+    PUT(GET());
+    PUT(m_char_stack);
+    m_char_bool = FALSE;
+  }
+
+  if (m_io_format.GetSign() != m_orig_format.GetSign())
+    if (m_io_format.GetByteOrder() == wxSND_SAMPLE_LE)
+      signer1 = 0x80;
+    else
+      signer2 = 0x80;
+
+  if (swap) {
+    while (IN_ERROR()) {
+      temp = GET();
+      PUT(GET() ^ signer1);
+      if (OUT_ERROR()) {
+        m_char_stack = temp ^ signer2;
+        m_char_bool = TRUE;
+        break;
+      }
+      PUT(temp ^ signer2);
+    }
+  } else {
+    while (IN_ERROR()) {
+      PUT(GET() ^ signer1);
+      if (!OUT_ERROR()) {
+        m_char_stack = GET() ^ signer2;
+        m_char_bool = TRUE;
+        break;
+      }
+      PUT(GET() ^ signer2);
+    }
+  }
+
+}
+
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::Encode()
+{
+  InitMode(ENCODING);
+  if (m_io_format == m_orig_format) {
+    CopyToOutput();
+    ExitMode();
+    return;
+  }
+
+  // Swap bytes
+  switch (m_io_format.GetBps()) {
+  case 8:
+    OutputSign8();
+    break;
+  case 16:
+    OutputSwapAndSign16();
+    break;
+  case 32:
+  case 64:
+  default:
+    break;
+  }
+  ExitMode();
+}
diff --git a/utils/wxMMedia/sndpcm.h b/utils/wxMMedia/sndpcm.h
new file mode 100644 (file)
index 0000000..4c464dd
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __SNDPCM_H__
+#define __SNDPCM_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "sndfrmt.h"
+
+class wxSoundPcmCodec : public wxSoundCodec {
+  DECLARE_DYNAMIC_CLASS(wxSoundPcmCodec)
+ public:
+  wxSoundPcmCodec();
+  virtual ~wxSoundPcmCodec();
+
+  void SetSampleRate(int srate) { m_orig_format.SetSampleRate(srate); }
+  void SetBits(int bits) { m_orig_format.SetBps(bits); }
+  void SetByteOrder(int order) { m_orig_format.SetByteOrder(order); }
+  void SetSign(int sample_sign) { m_orig_format.SetSign(sample_sign); }
+
+  size_t GetByteRate() const;
+  wxSoundDataFormat GetPreferredFormat(int codec = 0) const;
+
+  void Decode();
+  void Encode();
+
+ protected:
+  void InputSign8();
+  void InputSwapAndSign16();
+  void OutputSign8();
+  void OutputSwapAndSign16();
+
+ protected:
+  wxSoundDataFormat m_orig_format;
+  char m_char_stack;
+  bool m_char_bool;
+};
+
+#endif
diff --git a/utils/wxMMedia/sndsnd.cpp b/utils/wxMMedia/sndsnd.cpp
new file mode 100644 (file)
index 0000000..3422b72
--- /dev/null
@@ -0,0 +1,264 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       sndsnd.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndsnd.h"
+#endif
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndsnd.h"
+#include "sndfrmt.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#define PROCESS_EVENT() wxYield()
+// #define PROCESS_EVENT()
+
+// ----------------------------------------------------------------------------
+// wxSndBuffer: base sound buffer class
+// ----------------------------------------------------------------------------
+
+
+wxSndBuffer::wxSndBuffer()
+  : m_sndmode(wxSND_OUTPUT), m_sndflags(0), m_sndoutput(NULL), m_sndcodec(NULL)
+{
+}
+
+wxSndBuffer::~wxSndBuffer()
+{
+}
+
+void wxSndBuffer::Set(wxSndFlags flags)
+{
+  m_sndflags |= flags;
+
+  if ((m_sndflags & wxSND_BUFAUTO) && (flags & wxSND_BUFREADY))
+    m_sndoutput->QueueBuffer(*this);
+}
+
+void wxSndBuffer::SetError(wxSndError error)
+{
+  if (error == wxSND_NOERROR)
+    Clear(wxSND_BUFERR);
+  else
+    Set(wxSND_BUFERR);
+
+  m_snderror = error;
+}
+
+wxSndError wxSndBuffer::GetError()
+{
+  if (IsNotSet(wxSND_BUFERR))
+    return wxSND_NOERROR;
+  Clear(wxSND_BUFERR);
+  return m_snderror;
+}
+
+void wxSndBuffer::OnPlayFinished()
+{
+}
+
+void wxSndBuffer::OnBufferOutFinished()
+{
+}
+
+void wxSndBuffer::OnBufferInFinished(char *WXUNUSED(iobuf),
+                                     wxUint32& WXUNUSED(size))
+{
+}
+
+bool wxSndBuffer::Wait()
+{
+  if (IsNotSet(wxSND_BUFLOCKED))
+    return FALSE;
+
+  while (IsSet(wxSND_BUFLOCKED))
+    PROCESS_EVENT();
+
+  return IsNotSet(wxSND_BUFERR);
+}
+
+void wxSndBuffer::HardLock()
+{
+  m_mutex.Lock();
+}
+
+void wxSndBuffer::HardUnlock()
+{
+  m_mutex.Unlock();
+}
+
+void wxSndBuffer::ChangeCodec(int no)
+{
+  wxDELETE(m_sndcodec);
+
+  m_sndformat.SetCodecNo(no);
+  m_sndcodec = m_sndformat.GetCodec();
+  m_sndcodec->SetIOBuffer(this);
+}
+
+// ----------------------------------------------------------------------------
+// wxSndSimpleBuffer: the simplest sound buffer
+// ----------------------------------------------------------------------------
+
+
+wxSndSimpleBuffer::wxSndSimpleBuffer(char *buffer, wxUint32 bufsize,
+                                    wxSndMode mode)
+  : wxSndBuffer()
+{
+  m_sndbuf = buffer;
+  m_sndsize = bufsize;
+  m_sndmode = mode;
+
+  m_sndptr = 0;
+}
+
+wxSndSimpleBuffer::~wxSndSimpleBuffer()
+{
+}
+
+void wxSndSimpleBuffer::OnNeedOutputData(char *iobuf, wxUint32& size)
+{
+  char *buf = m_sndbuf + m_sndptr;
+  wxUint32 nbdata_left = m_sndsize - m_sndptr;
+
+  if (m_sndptr >= m_sndsize) {
+    size = 0;
+    return;
+  }
+
+  if (size > nbdata_left)
+    size = nbdata_left;
+
+  m_sndptr += size;
+
+  memcpy(iobuf, buf, size);
+}
+
+void wxSndSimpleBuffer::OnBufferOutFinished()
+{
+  if (m_sndptr >= m_sndsize)
+    OnPlayFinished();
+}
+
+void wxSndSimpleBuffer::OnBufferInFinished(char *iobuf, wxUint32& size)
+{
+  char *raw_buf = m_sndbuf + m_sndptr;
+  wxUint32 data_left = m_sndsize - m_sndptr;
+
+  if (!data_left) {
+    size = 0;
+    return;
+  }
+
+  if (size > data_left)
+    size = data_left;
+
+  memcpy(raw_buf, iobuf, size);
+  m_sndptr += size;
+}
+
+void wxSndSimpleBuffer::SetData(char *buffer, wxUint32 bufsize,
+                               wxSndMode mode)
+{
+  m_sndbuf = buffer;
+  m_sndsize = bufsize;
+  m_sndmode = mode;
+}
+
+bool wxSndSimpleBuffer::RestartBuffer(wxSndMode mode)
+{
+  m_sndptr = 0;
+  return TRUE;
+}
+
+wxUint32 wxSndSimpleBuffer::GetSize() const
+{
+  return m_sndsize;
+}
+
+wxUint32 wxSndSimpleBuffer::Available() const
+{
+  return m_sndsize - m_sndptr;
+}
+
+// ----------------------------------------------------------------------------
+// wxSound: base sound driver implementation
+// ----------------------------------------------------------------------------
+
+wxSound::wxSound()
+  : wxObject(),
+    m_lastbuf(NULL), m_sndcbk(NULL), m_snderror(wxSND_NOERROR)
+{
+  m_buffers.Clear();
+}
+
+wxSound::~wxSound()
+{
+  wxNode *node = m_buffers.First();
+
+  while (node) {
+    wxSndBuffer *buf = (wxSndBuffer *)node->Data();
+
+    buf->Clear(wxSND_BUFLOCKED);
+  }
+}
+
+bool wxSound::QueueBuffer(wxSndBuffer& buf)
+{
+  if (buf.IsSet(wxSND_BUFLOCKED) || buf.IsNotSet(wxSND_BUFREADY))
+    return FALSE;
+
+  buf.Set(wxSND_BUFLOCKED);
+  buf.SetOutput(*this);
+
+  m_buffers.Append(&buf);
+  return Wakeup(buf);
+}
+
+bool wxSound::UnqueueBuffer(wxSndBuffer& buf)
+{
+  wxNode *node;
+
+  if (buf.IsNotSet(wxSND_BUFLOCKED))
+    return FALSE;
+
+  node = m_buffers.Member(&buf);
+  if (!node)
+    return FALSE;
+
+  StopBuffer(buf);
+  node = m_buffers.Member(&buf);
+  if (node)
+    delete node;
+
+  return TRUE;
+}
+
+void wxSound::Callback(wxSndCallback cbk)
+{
+  m_sndcbk = cbk;
+}
+
+void wxSound::SetClientData(char *cdata)
+{
+  m_cdata = cdata;
+}
+
+void wxSound::OnPlayBuffer(wxSndBuffer& buf)
+{
+  m_lastbuf = &buf;
+  if (m_sndcbk)
+    m_sndcbk(*this, buf, m_cdata);
+}
diff --git a/utils/wxMMedia/sndsnd.h b/utils/wxMMedia/sndsnd.h
new file mode 100644 (file)
index 0000000..9fae1a8
--- /dev/null
@@ -0,0 +1,275 @@
+/* Real -*- C++ -*- */
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndsnd.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __WX_SND_SOUND_H__
+#define __WX_SND_SOUND_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <wx/thread.h>
+#include "sndfrmt.h"
+#include "mmtype.h"
+
+class wxSound;
+class wxSndBuffer;
+
+typedef enum {
+  wxSND_OUTPUT,
+  wxSND_INPUT,
+  wxSND_DUPLEX,
+  wxSND_OTHER_IO
+} /// The possible sound output modes
+ wxSndMode;
+
+typedef enum {
+  wxSND_NOERROR = 0,
+  wxSND_NOCAPS,
+  wxSND_CANTOPEN,
+  wxSND_NOMEM,
+  wxSND_READERR,
+  wxSND_WRITEERR,
+  wxSND_CANTSET
+} /// Sound errors
+ wxSndError;
+
+/// Sound callback
+typedef void (*wxSndCallback)(wxSound&, wxSndBuffer&, char *);
+
+/// Sound flags
+typedef wxUint16 wxSndFlags;
+
+/** @name Sound buffer flags */
+/// buffer ready
+#define wxSND_BUFREADY   0x0001
+/// an error occured
+#define wxSND_BUFERR     0x0002
+/// buffer is in use
+#define wxSND_BUFLOCKED  0x0004
+/// the driver mustn't unqueue it
+#define wxSND_KEEPQUEUED 0x0008
+/// automatic: when BUFREADY is set play the buffer 
+#define wxSND_BUFAUTO    0x0010
+///
+#define wxSND_UNFINISHED 0x0020
+/// buffer is nearly being unqueued
+#define wxSND_UNQUEUEING 0x0040
+/// driver wants the buffer stop
+#define wxSND_BUFSTOP    0x0080
+/// buffer will loop
+#define wxSND_LOOP       0x0100
+
+/** @name Sound data format */
+/// little endian
+#define wxSND_SAMPLE_LE  0
+/// big endian
+#define wxSND_SAMPLE_BE  1
+/// unsigned samples
+#define wxSND_SAMPLE_UNSIGNED 0
+/// signed samples
+#define wxSND_SAMPLE_SIGNED   1
+
+/** @name wxSndBuffer
+  * @memo wxSndBuffer is the basic class for all the sound codec.
+  * @author Guilhem Lavaux
+  */
+class wxSndBuffer : public wxObject {
+  /// It is an abstract class
+  DECLARE_ABSTRACT_CLASS(wxSndBuffer)
+protected:
+  wxMutex m_mutex;
+  /// output mode
+  wxSndMode m_sndmode;
+  /// last error
+  wxSndError m_snderror;
+  /// some flag
+  wxSndFlags m_sndflags;
+  /// last sound driver used
+  wxSound *m_sndoutput;
+  /// sound data format
+  wxSoundDataFormat m_sndformat;
+  /// current sound codec
+  wxSoundCodec *m_sndcodec;
+public:
+  /** @name constructor and destructor */
+  //@{
+  /// Construct an uninitialized wxSndBuffer
+  wxSndBuffer();
+  /// Destroy
+  virtual ~wxSndBuffer();
+  //@}
+
+  /** @name Functions returning the current state */
+  //@{
+    /// @return current mode
+  inline wxSndMode GetMode() const { return m_sndmode; }
+    /// @return sound data format
+  inline wxSoundDataFormat& GetFormat() { return m_sndformat; }
+     /// @return the size of the buffer
+  virtual wxUint32 GetSize() const = 0;
+    /// @return bytes left
+  virtual wxUint32 Available() const = 0;
+    /** enable the specified flags
+      * @param flags
+      */
+  void Set(wxSndFlags flags);
+    /** disable the specified flags
+      * @param flags
+      */
+  inline void Clear(wxSndFlags flags)
+      { m_sndflags &= ~flags; }
+    /** Check if the specified flags is set
+      * @param flags
+      * @return TRUE if all flags is set
+      */
+  inline bool IsSet(wxSndFlags flags) const
+      { return ((m_sndflags & flags) == flags); }
+    /** Check if the specified flags is not set
+      * @param flags
+      * @return TRUE if at least one flag is not set
+      */
+  inline bool IsNotSet(wxSndFlags flags) const
+      { return ((m_sndflags & flags) != flags); }
+    /** Check if the buffer is currently being played
+      * @return TRUE
+       if the buffer is being played
+      */
+  inline bool IsPlaying() const
+      { return IsSet(wxSND_BUFLOCKED); }
+  //@}
+
+  ///
+  inline void SetOutput(wxSound& snd)
+      { m_sndoutput = &snd; }
+  ///
+  inline wxSoundCodec *GetCurrentCodec() const
+      { return m_sndcodec; }
+  ///
+  void HardLock();
+  ///
+  void HardUnlock();
+
+  ///
+  wxSndError GetError();
+  ///
+  void SetError(wxSndError err);
+
+  ///
+  virtual bool Wait();
+  ///
+  virtual bool RestartBuffer(wxSndMode mode) = 0;
+  ///
+  virtual bool Abort() { return TRUE; }
+
+  ///
+  virtual void OnPlayFinished();
+
+  /** Data exchanging functions */
+  //@{
+  ///
+  virtual void OnNeedOutputData(char *io_buf, wxUint32& size) = 0;
+  ///
+  virtual void OnBufferOutFinished();
+  ///
+  virtual void OnBufferInFinished(char *iobuf, wxUint32& size);
+  //@}
+
+protected:
+  void ChangeCodec(int no);
+};
+
+class wxSndSimpleBuffer : public wxSndBuffer {
+  DECLARE_DYNAMIC_CLASS(wxSndSimpleBuffer)
+protected:
+  /// sound buffer
+  char *m_sndbuf;
+  /// size of the sound buffer
+  wxUint32 m_sndsize;
+  /// current position in the sound buffer
+  wxUint32 m_sndptr;
+public:
+  wxSndSimpleBuffer(char *buffer = NULL, wxUint32 bufsize = 0,
+                    wxSndMode mode = wxSND_OUTPUT);
+  virtual ~wxSndSimpleBuffer();
+
+  void SetData(char *buffer, wxUint32 bufsize,
+               wxSndMode mode = wxSND_OUTPUT);
+  inline void SetSoundFormat(const wxSoundDataFormat& format);
+
+  void OnNeedOutputData(char *io_buf, wxUint32& size);
+  void OnNeedInputData(wxUint32& size);
+
+  void OnBufferOutFinished();
+  void OnBufferInFinished(char *iobuf, wxUint32& size);
+
+  bool RestartBuffer(wxSndMode mode);
+  wxUint32 GetSize() const;
+  wxUint32 Available() const;
+};
+
+///
+class wxSound : public wxObject {
+  ///
+  DECLARE_ABSTRACT_CLASS(wxSound)
+protected:
+  friend class wxFragmentBuffer;
+
+  ///
+  wxSndBuffer *m_lastbuf;
+  ///
+  wxList m_buffers;
+  ///
+  wxSndCallback m_sndcbk;
+  ///
+  wxSndError m_snderror;
+  ///
+  char *m_cdata;
+public:
+  ///
+  wxSound();
+  ///
+  virtual ~wxSound();
+
+  ///
+  virtual bool QueueBuffer(wxSndBuffer& buf);
+  ///
+  virtual bool UnqueueBuffer(wxSndBuffer& buf);
+  ///
+  inline wxSndBuffer *LastBufferPlayed()
+    { return m_lastbuf; }
+
+  ///
+  wxSndError GetError() { return m_snderror; }
+
+  ///
+  void Callback(wxSndCallback cbk);
+  ///
+  void SetClientData(char *cdata);
+  ///
+  virtual void OnPlayBuffer(wxSndBuffer& buf);
+protected:
+  ///
+  virtual bool Wakeup(wxSndBuffer& buf) = 0;
+  ///
+  virtual void StopBuffer(wxSndBuffer& buf) = 0;
+
+  ///
+  virtual inline bool OnSetupDriver(wxSndBuffer& WXUNUSED(buf),
+                                      wxSndMode WXUNUSED(mode))
+             { return TRUE; }
+};
+
+#endif
diff --git a/utils/wxMMedia/snduss.cpp b/utils/wxMMedia/snduss.cpp
new file mode 100644 (file)
index 0000000..c98a741
--- /dev/null
@@ -0,0 +1,268 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       snduss.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "snduss.h"
+#endif
+
+#include <sys/soundcard.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dmalloc.h>
+
+#include "wx/app.h"
+#include "wx/utils.h"
+
+#define WXMMEDIA_INTERNAL
+#include "snduss.h"
+#include "sndfrmt.h"
+
+wxUssSound::wxUssSound()
+  : wxSound(),
+    m_srate(0), m_bps(0), m_stereo(0),
+    m_mode(wxSND_OTHER_IO),
+    m_stop_thrd(TRUE), m_sleeping(FALSE)
+{
+  m_fd = -1;
+  m_ussformat.SetCodecNo(WXSOUND_PCM);
+  m_ussformat.SetSign(wxSND_SAMPLE_SIGNED);
+  m_ussformat.SetByteOrder(wxSND_SAMPLE_LE);
+
+  m_sndbuf = new wxStreamBuffer(wxStreamBuffer::read_write);
+  m_sndbuf->Flushable(FALSE);
+  m_sndbuf->Fixed(TRUE);
+}
+
+wxUssSound::~wxUssSound()
+{
+  if (!m_stop_thrd) {
+    m_stop_thrd = TRUE;
+    if (m_sleeping) {
+      m_sleep_mtx.Lock();
+      m_sleep_cond.Signal();
+      m_sleep_mtx.Unlock();
+    }
+    Join();
+  }
+
+  if (m_fd != -1)
+    close(m_fd);
+}
+
+bool wxUssSound::Wakeup(wxSndBuffer& WXUNUSED(buf))
+{
+  printf("Waking up (wxUssSound::Wakeup) ...\n");
+  if (m_stop_thrd) {
+    m_stop_thrd = FALSE; 
+    Entry();
+//    wxThread::Create();
+  }
+
+  if (m_sleeping) {
+    m_sleep_mtx.Lock();
+    m_sleep_cond.Signal();
+    m_sleep_mtx.Unlock();
+  }
+
+  return TRUE;
+}
+
+void wxUssSound::StopBuffer(wxSndBuffer& buf)
+{
+  buf.HardLock();
+  buf.Set(wxSND_BUFSTOP);
+  buf.HardUnlock();
+  while (buf.IsSet(wxSND_BUFSTOP))
+    wxYield();
+//    usleep(0);
+}
+
+void wxUssSound::USS_Sleep()
+{
+  bool ret;
+
+  printf("Asleeping ...\n");
+  m_sleeping = TRUE;
+  m_sleep_mtx.Lock();
+  ret = m_sleep_cond.Wait(m_sleep_mtx, 10, 0);
+  m_sleep_mtx.Unlock();
+  m_sleeping = FALSE;
+  
+  printf("Waking up ...\n");
+  if (!ret)
+    m_stop_thrd = TRUE;
+}
+
+bool wxUssSound::DoInput(wxSndBuffer *buf)
+{
+  wxUint32 bufsize;
+  wxSoundCodec *codec = buf->GetFormat().GetCodec();
+
+  m_sndbuf->ResetBuffer();
+  codec->SetInStream(m_sndbuf);
+  codec->InitIO(m_ussformat);
+
+  bufsize = codec->Available();
+  if (bufsize > m_max_bufsize)
+    bufsize = m_max_bufsize;
+
+  if (!bufsize) {
+    buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
+    return false;
+  }
+  read(m_fd, m_sndbuf, bufsize);
+  codec->Encode();
+
+  return true;
+}
+
+bool wxUssSound::DoOutput(wxSndBuffer *buf)
+{
+  wxSoundCodec *codec = buf->GetCurrentCodec();
+
+  m_sndbuf->ResetBuffer();
+  codec->SetOutStream(m_sndbuf);
+  codec->InitIO(m_ussformat);
+
+  if (!codec->Available()) {
+    buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
+    return false;
+  }
+  codec->Decode();
+  write(m_fd, m_sndbuf, m_sndbuf->GetIntPosition());
+
+  // Well ... it's not accurate ! :-|
+  buf->OnBufferOutFinished();
+
+  return true;
+}
+
+void *wxUssSound::Entry()
+{
+  wxNode *node;
+  wxSndBuffer *buf;
+
+  while (!m_stop_thrd) {
+    node = m_buffers.First();
+    if (!node) {
+      USS_Sleep();
+      continue;
+    }
+    buf = (wxSndBuffer *)node->Data();
+    if (!OnSetupDriver(*buf, buf->GetMode()))
+      continue;
+
+    buf->HardLock();
+    if (buf->IsSet(wxSND_BUFSTOP)) {
+      buf->HardUnlock();
+      delete node;
+      continue;
+    }
+    switch(m_mode) {
+    case wxSND_INPUT:
+      if (!DoInput(buf))
+        delete node;
+      break;
+    case wxSND_OUTPUT:
+      if (!DoOutput(buf))
+        delete node;
+      break;
+    case wxSND_DUPLEX:
+    case wxSND_OTHER_IO:
+      break;
+    }
+    buf->HardUnlock();
+  }
+  return NULL;
+}
+
+bool wxUssSound::OnSetupDriver(wxSndBuffer& buf, wxSndMode WXUNUSED(mode))
+{
+  wxSoundDataFormat format;
+  wxSoundCodec *codec;
+
+  codec = buf.GetFormat().GetCodec();
+  format = codec->GetPreferredFormat(WXSOUND_PCM);
+
+  if ((format.GetSampleRate() != m_srate) ||
+      (format.GetBps() != m_bps) ||
+      (format.GetStereo() != m_stereo)) {
+
+    if (!SetupSound(format.GetSampleRate(), format.GetBps(),
+                   format.GetStereo())) {
+      m_buffers.DeleteObject(&buf);
+      buf.Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
+      buf.SetError(wxSND_CANTSET);
+      return false;
+    }
+    m_mode = wxSND_OTHER_IO;
+  }
+
+  if (buf.GetMode() != m_mode) {
+    m_mode = buf.GetMode();
+    return false;
+  }
+
+  return true;
+}
+
+wxUint32 wxUssSound::GetNbFragments()
+{
+  struct audio_buf_info frag_info;
+
+  ioctl(m_fd, SNDCTL_DSP_GETOSPACE, &frag_info);
+
+  return frag_info.fragstotal;
+}
+
+wxUint32 wxUssSound::GetFragmentSize()
+{
+  return m_max_bufsize;
+}
+
+bool wxUssSound::SetupSound(wxUint16 srate, wxUint8 bps, bool stereo)
+{
+  int tmp;
+  unsigned long tmp_ul;
+
+  if (m_fd != -1) {
+    delete m_sndbuf;
+    fsync(m_fd);
+    close(m_fd);
+  }
+
+  m_fd = open("/dev/dsp", O_RDWR);
+
+  tmp = stereo;
+  if (ioctl(m_fd, SNDCTL_DSP_STEREO, &tmp) < 0)
+    return FALSE;
+  m_stereo = tmp;
+  tmp_ul = srate;
+  if (ioctl(m_fd, SNDCTL_DSP_SPEED, &tmp_ul) < 0)
+    return FALSE;
+  m_srate = tmp_ul;
+
+  tmp = bps;
+  if (ioctl(m_fd, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
+    return FALSE;
+  m_bps = tmp;
+
+  ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &tmp);
+  m_max_bufsize = tmp;
+  m_sndbuf->SetBufferIO(m_max_bufsize);
+
+  m_ussformat.SetBps(m_bps);
+  m_ussformat.SetChannels((m_stereo) ? 2 : 1);
+  m_ussformat.SetSampleRate(m_srate);
+
+  return TRUE;
+}
diff --git a/utils/wxMMedia/snduss.h b/utils/wxMMedia/snduss.h
new file mode 100644 (file)
index 0000000..59569dd
--- /dev/null
@@ -0,0 +1,85 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       snduss.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_ussnd_H__
+#define __SND_ussnd_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <wx/thread.h>
+#include "sndsnd.h"
+#include "sndfrag.h"
+#include "sndfrmt.h"
+
+///
+class wxUssSound : public wxSound, public wxThread {
+  ///
+  DECLARE_DYNAMIC_CLASS(wxUssSound)
+public:
+  wxUssSound();
+  ///
+  virtual ~wxUssSound();
+  
+  ///
+  void OnNeedBuffer();
+protected:
+  ///
+  virtual bool Wakeup(wxSndBuffer& buf);
+  ///
+  void USS_Sleep();
+  ///
+  virtual void StopBuffer(wxSndBuffer& buf);
+
+  ///
+  bool OnSetupDriver(wxSndBuffer& buf, wxSndMode mode);
+
+  ///
+  bool SetupSound(wxUint16 srate, wxUint8 bps, bool stereo);
+
+  ///
+  wxUint32 GetNbFragments();
+  ///
+  wxUint32 GetFragmentSize();
+  ///
+  void ThreadEntryPoint();
+
+protected:
+  ///
+  wxUint16 m_srate;
+  ///
+  wxUint8 m_bps;
+  ///
+  wxUint32 m_max_bufsize;
+  ///
+  bool m_stereo;
+  ///
+  wxSndMode m_mode;
+  ///
+  wxSoundDataFormat m_ussformat;
+  ///
+  wxStreamBuffer *m_sndbuf;
+  ///
+  bool m_stop_thrd, m_sleeping;
+  /// Sound file descriptor.
+  int m_fd;
+  /// Thread sleep mutexes and conditions.
+  wxMutex m_sleep_mtx;
+  wxCondition m_sleep_cond;
+
+  ///
+  bool DoInput(wxSndBuffer *buf);
+  bool DoOutput(wxSndBuffer *buf);
+
+  ///
+  virtual void *Entry();
+};
+
+#endif
diff --git a/utils/wxMMedia/sndwav.cpp b/utils/wxMMedia/sndwav.cpp
new file mode 100644 (file)
index 0000000..ad64191
--- /dev/null
@@ -0,0 +1,186 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       sndwav.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    February 1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndwav.h"
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndwav.h"
+#include "sndfrmt.h"
+#include "sndpcm.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxSndWavCodec::wxSndWavCodec()
+  : wxSndFileCodec(), riff_codec()
+{
+  m_sndtime.hours = -1;
+}
+
+wxSndWavCodec::wxSndWavCodec(wxOutputStream& s, bool seekable)
+  : wxSndFileCodec(s, seekable)
+{
+  if (!seekable)
+    CacheIO();
+  riff_codec = wxRiffCodec(*m_ostream);
+  m_sndtime.hours = -1;
+}
+
+wxSndWavCodec::wxSndWavCodec(wxInputStream& s, bool preload, bool seekable)
+  : wxSndFileCodec(s, preload, seekable)
+{
+  if (!seekable)
+    CacheIO();
+
+  riff_codec = wxRiffCodec(*m_istream);
+  m_sndtime.hours = -1;
+}
+
+wxSndWavCodec::wxSndWavCodec(const wxString& fname)
+  : wxSndFileCodec(fname)
+{
+  riff_codec = wxRiffCodec(*m_istream);
+  m_sndtime.hours = -1;
+}
+
+wxUint32 wxSndWavCodec::PrepareToPlay()
+{
+  if (!riff_codec.RiffReset(RIFF_READ))
+    return 0;
+
+  if (!riff_codec.FindChunk("RIFF", TRUE)) {
+    wxSndFileCodec::m_mmerror = wxMMFILE_INVALID;
+    return 0;
+  }
+
+  char tmp_buf[5];
+  riff_codec.ReadData(tmp_buf, 4);
+  tmp_buf[4] = 0;
+  if (wxString("WAVE") != tmp_buf) {
+    wxSndFileCodec::m_mmerror = wxMMFILE_INVALID;
+    return 0;
+  }
+  if (!riff_codec.FindChunk("fmt ", TRUE))
+    return 0;
+
+  riff_codec.Read16(wav_hdr.format);
+  riff_codec.Read16(wav_hdr.channels);
+  riff_codec.Read32(wav_hdr.sample_fq);
+  riff_codec.Read32(wav_hdr.byte_p_sec);
+  riff_codec.Read16(wav_hdr.byte_p_spl);
+  riff_codec.Read16(wav_hdr.bits_p_spl);
+
+  if (!riff_codec.FindChunk("data"))
+    return 0;
+
+  m_sndformat.SetSampleRate(wav_hdr.sample_fq);
+  m_sndformat.SetBps(wav_hdr.bits_p_spl);
+  m_sndformat.SetChannels(wav_hdr.channels);
+  m_sndmode = wxSND_OUTPUT;
+  ChangeCodec(wav_hdr.format);
+
+  m_sndformat.SetSampleRate(wav_hdr.sample_fq);
+  m_sndformat.SetBps(wav_hdr.bits_p_spl);
+  m_sndformat.SetChannels(wav_hdr.channels);
+
+  if (wav_hdr.format == WXSOUND_PCM) {
+    m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+    m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+  }
+
+  wxUint32 sec1 = riff_codec.GetChunkLength() / wav_hdr.byte_p_sec,
+           sec2 = sec1 % 3600;
+
+  m_sndtime.hours = sec1 / 3600;
+  m_sndtime.minutes = sec2 / 60;
+  m_sndtime.seconds = sec2 % 60;
+
+  wxSndFileCodec::m_mmerror = wxMMFILE_NOERROR;
+
+  return riff_codec.GetChunkLength();
+}
+
+wxSndWavCodec::~wxSndWavCodec()
+{
+}
+
+bool wxSndWavCodec::OnNeedData(char *buf, wxUint32 size)
+{
+  return riff_codec.ReadData(buf, size);
+}
+
+bool wxSndWavCodec::OnWriteData(char *buf, wxUint32 size)
+{
+  return riff_codec.WriteData(buf, size);
+}
+
+bool wxSndWavCodec::PrepareToRecord(wxUint32 m_fsize)
+{
+  wxUint32 total_size;
+
+  if (!riff_codec.RiffReset(RIFF_WRITE))
+    return FALSE;
+
+  total_size = 16 + sizeof(wav_hdr) + m_fsize;
+
+  if (!riff_codec.CreateChunk("RIFF", total_size))
+    return FALSE;
+  riff_codec.WriteData("WAVE", 4);
+  if (!riff_codec.CreateChunk("fmt ", sizeof(wav_hdr)))
+    return FALSE;
+
+  wav_hdr.format = 1; // PCM_WAV_FORMAT
+  wav_hdr.channels = m_sndformat.GetChannels();
+  wav_hdr.sample_fq = m_sndformat.GetSampleRate();
+  wav_hdr.byte_p_spl = (m_sndformat.GetBps() / 8) * wav_hdr.channels;
+  wav_hdr.byte_p_sec = m_sndformat.GetCodec()->GetByteRate();
+  wav_hdr.bits_p_spl = m_sndformat.GetBps();
+  ChangeCodec(WXSOUND_PCM);
+
+  if (wav_hdr.format == WXSOUND_PCM) {
+    m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+    m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+  }
+
+  riff_codec.Write16(wav_hdr.format);
+  riff_codec.Write16(wav_hdr.channels);
+  riff_codec.Write32(wav_hdr.sample_fq);
+  riff_codec.Write32(wav_hdr.byte_p_sec);
+  riff_codec.Write16(wav_hdr.byte_p_spl);
+  riff_codec.Write16(wav_hdr.bits_p_spl);
+
+  if (!riff_codec.CreateChunk("data", m_fsize))
+    return FALSE;
+  return TRUE;
+}
+
+void wxSndWavCodec::SetFile(wxInputStream& s, bool preload, bool seekable)
+{
+  wxMMediaFile::SetFile(s, preload, seekable);
+  if (!seekable)
+    CacheIO();
+
+  riff_codec.SetFile((seekable) ? s : *m_istream);
+}
+
+void wxSndWavCodec::SetFile(wxOutputStream& s, bool seekable)
+{
+  wxMMediaFile::SetFile(s, seekable);
+  if (!seekable)
+    CacheIO();
+
+  riff_codec.SetFile((seekable) ? s : *m_ostream);
+}
diff --git a/utils/wxMMedia/sndwav.h b/utils/wxMMedia/sndwav.h
new file mode 100644 (file)
index 0000000..b442e34
--- /dev/null
@@ -0,0 +1,59 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndwav.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    February 1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_wav_H__
+#define __SND_wav_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+
+///
+class wxSndWavCodec : public wxSndFileCodec {
+  ///
+  DECLARE_DYNAMIC_CLASS(wxSndWavCodec)
+public:
+  ///
+  wxSndWavCodec();
+  ///
+  wxSndWavCodec(wxInputStream& s, bool preload = FALSE, bool seekable = TRUE);
+  ///
+  wxSndWavCodec(wxOutputStream& s, bool seekable = TRUE);
+  ///
+  wxSndWavCodec(const wxString& fname);
+  ///
+  virtual ~wxSndWavCodec();
+
+  virtual bool OnNeedData(char *buf, wxUint32 size);
+  virtual bool OnWriteData(char *buf, wxUint32 size);
+
+  virtual wxUint32 PrepareToPlay();
+  virtual bool PrepareToRecord(wxUint32 file_size);
+
+  virtual void SetFile(wxInputStream& s, bool preload = FALSE,
+                       bool seekable = FALSE);
+  virtual void SetFile(wxOutputStream& s,
+                       bool seekable = FALSE);
+
+protected:
+  wxRiffCodec riff_codec;
+  struct {
+    wxUint16 format;
+    wxUint16 channels;
+    wxUint32 sample_fq;
+    wxUint32 byte_p_sec;
+    wxUint16 byte_p_spl;
+    wxUint16 bits_p_spl;
+  } wav_hdr;
+};
+
+#endif
diff --git a/utils/wxMMedia/sndwin.cpp b/utils/wxMMedia/sndwin.cpp
new file mode 100644 (file)
index 0000000..8161ed8
--- /dev/null
@@ -0,0 +1,384 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       sndwin.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <wx/msw/private.h>
+
+#define WXMMEDIA_INTERNAL
+#include "sndwin.h"
+
+#define MMD_WIN_IO_BSIZE 16384
+
+#include <mmsystem.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxSndWinFragment::wxSndWinFragment(wxSound& io_drv)
+  : wxFragmentBuffer(io_drv)
+{
+}
+
+wxSndWinFragment::~wxSndWinFragment(void)
+{
+}
+
+void wxSndWinFragment::AllocIOBuffer(void)
+{
+  wxWinSound *w_snd = (wxWinSound *) m_iodrv;
+  wxUint8 i;
+
+  m_maxoq = 5;
+  m_maxiq = 5;
+
+  m_lstoptrs = m_optrs = new wxFragBufPtr[m_maxoq];
+  m_lstiptrs = m_iptrs = new wxFragBufPtr[m_maxiq];
+
+  for (i=0;i<m_maxoq;i++) {
+    m_lstoptrs[i].size = MMD_WIN_IO_BSIZE;
+    m_lstoptrs[i].ptr = 0;
+    m_lstoptrs[i].buffers = new wxList();
+    m_lstoptrs[i].state = wxBUFFER_FREE;
+
+    w_snd->PrepareHeader(m_lstoptrs[i], wxSND_OUTPUT);
+  }
+
+  for (i=0;i<m_maxiq;i++) {
+    m_lstiptrs[i].size = MMD_WIN_IO_BSIZE;
+    m_lstiptrs[i].ptr = 0;
+    m_lstiptrs[i].buffers = new wxList();
+    m_lstiptrs[i].state = wxBUFFER_FREE;
+
+    w_snd->PrepareHeader(m_lstiptrs[i], wxSND_INPUT);
+  }
+}
+
+void wxSndWinFragment::FreeIOBuffer(void)
+{
+  wxWinSound *w_snd = (wxWinSound *)m_iodrv;
+  wxUint8 i;
+
+  if (!m_lstoptrs && !m_lstiptrs)
+    return;
+
+  for (i=0;i<m_maxoq;i++) {
+    w_snd->UnprepareHeader(m_lstoptrs[i], wxSND_OUTPUT);
+    delete m_lstoptrs[i].buffers;
+  }
+
+  for (i=0;i<m_maxiq;i++) {
+    w_snd->UnprepareHeader(m_lstiptrs[i], wxSND_INPUT);
+    delete m_lstiptrs[i].buffers;
+  }
+
+  delete[] m_lstoptrs;
+  delete[] m_lstiptrs;
+
+  m_lstoptrs = m_lstiptrs = NULL;
+  m_maxoq = m_maxiq = 0;
+}
+
+void wxSndWinFragment::WaitForAll()
+{
+  bool buf_busy = TRUE;
+  int i;
+
+  m_dontq = TRUE;
+
+  while (buf_busy) {
+    buf_busy = FALSE;
+
+    for (i=0;i<m_maxoq;i++) {
+      if (m_lstoptrs[i].state == wxBUFFER_FFILLED) {
+        buf_busy = TRUE;
+        break;
+      }
+    }
+    wxYield();
+  }
+
+  m_dontq = FALSE;
+  FreeBufToFree(TRUE);
+}
+
+bool wxSndWinFragment::OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode)
+{
+  wxSndWinInfo *info = (wxSndWinInfo *)ptr->user_data;
+  wxWinSound *w_snd = (wxWinSound *)m_iodrv;
+  MMRESULT result;
+
+  switch (mode) {
+  case wxSND_INPUT:
+    result = waveInAddBuffer(w_snd->internal->devin_id, info->hdr,
+                             sizeof(WAVEHDR));
+    break;
+  case wxSND_OUTPUT:
+    result = waveOutWrite(w_snd->internal->devout_id, info->hdr,
+                          sizeof(WAVEHDR));
+    printf("WINOUT: result=%d\n", result);
+    break;
+  }
+  return TRUE;
+}
+
+wxWinSound::wxWinSound(void)
+  : wxSound(),
+    fragments(*this)
+{
+  internal = new wxWinSoundInternal;
+  internal->devout_id = 0;
+  internal->devin_id = 0;
+  internal->sndWin = 0;
+
+  wout_opened = FALSE;
+  win_opened = FALSE;
+  curr_o_srate = (wxUint32)-1;
+  curr_o_bps = (wxUint8)-1;
+  curr_o_stereo = (bool)-1;
+  curr_i_srate = (wxUint32)-1;
+  curr_i_bps = (wxUint8)-1;
+  curr_i_stereo = (bool)-1;
+}
+
+wxWinSound::~wxWinSound(void)
+{
+  int i;
+
+  fragments.WaitForAll();
+
+  if (wout_opened)
+    waveOutReset(internal->devout_id);
+  if (win_opened)
+    waveInReset(internal->devout_id);
+
+  fragments.FreeIOBuffer();
+
+  if (wout_opened)
+    waveOutClose(internal->devout_id);
+  if (win_opened)
+    waveInClose(internal->devin_id);
+
+  if (internal->sndWin)
+    ::DestroyWindow(internal->sndWin);
+
+  delete internal;
+}
+
+bool wxWinSound::Wakeup(wxSndBuffer& buf)
+{
+  if (!Reopen(buf, FALSE)) {
+    buf.Clear(wxSND_BUFLOCKED);
+    return FALSE;
+  }
+
+  fragments.OnBufferFinished(NULL);
+  return TRUE;
+}
+
+void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
+                               wxSndMode mode)
+{
+  wxSndWinInfo *info;
+  WAVEHDR *hdr;
+
+  if ((mode == wxSND_INPUT && !win_opened) ||
+      (mode == wxSND_OUTPUT && !wout_opened))
+    return;
+
+  info = new wxSndWinInfo;
+
+  info->h_data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, frag.size);
+  info->h_hdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
+
+  info->data = (char *)GlobalLock(info->h_data);
+  hdr = info->hdr = (WAVEHDR *)GlobalLock(info->h_hdr);
+
+  memset(hdr, 0, sizeof(*hdr));
+  hdr->lpData = info->data;
+  hdr->dwBufferLength = frag.size;
+  hdr->dwUser = (DWORD)&frag;
+  hdr->dwFlags = WHDR_DONE;
+
+  if (mode == wxSND_INPUT) {
+    MMRESULT result = waveInPrepareHeader(internal->devin_id, hdr,
+                                          sizeof(WAVEHDR));
+
+    printf("prepareIn = %d\n", result);
+    if (result != MMSYSERR_NOERROR)
+      wxExit();
+  } else {
+    MMRESULT result = waveOutPrepareHeader(internal->devout_id, hdr,
+                                           sizeof(WAVEHDR));
+    printf("prepareOut = %d\n", result);
+    if (result != MMSYSERR_NOERROR)
+      wxExit();
+  }
+
+  frag.user_data = (char *)info;
+  frag.data = info->data;
+}
+
+void wxWinSound::UnprepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
+                                 wxSndMode mode)
+{
+  wxSndWinInfo *info = (wxSndWinInfo *)frag.user_data;
+
+  if ((mode == wxSND_INPUT && !win_opened) ||
+      (mode == wxSND_OUTPUT && !wout_opened))
+    return;
+
+  MMRESULT result;
+
+  if (mode == wxSND_INPUT) {
+    result = waveInUnprepareHeader(internal->devin_id, info->hdr, sizeof(*info->hdr));
+  } else {
+    result = waveOutUnprepareHeader(internal->devout_id, info->hdr, sizeof(*info->hdr));
+  }
+
+  printf("unprepare = %d\n", result);
+
+  GlobalUnlock(info->h_hdr);
+  GlobalUnlock(info->h_data);
+
+  GlobalFree(info->h_hdr);
+  GlobalFree(info->h_data);
+
+  delete info;
+}
+
+extern char wxCanvasClassName[];
+
+LRESULT APIENTRY _EXPORT wxSoundHandlerWndProc(HWND hWnd, UINT message,
+                 WPARAM wParam, LPARAM lParam)
+{
+  switch (message) {
+  case MM_WOM_DONE: {
+    wxWinSound *snd_drv = (wxWinSound *)GetWindowLong(hWnd, GWL_USERDATA);
+    WAVEHDR *hdr = (WAVEHDR *)lParam;
+    wxFragmentBuffer::wxFragBufPtr *buf =
+            (wxFragmentBuffer::wxFragBufPtr *)hdr->dwUser;
+
+    // To be sure ...
+    hdr->dwFlags |= WHDR_DONE;
+
+    snd_drv->fragments.OnBufferFinished(buf);
+    break;
+  }
+  case MM_WOM_OPEN:
+    printf("wave Open ack\n");
+    break;
+  case MM_WOM_CLOSE:
+    printf("wave Close ack\n");
+    break;
+  default:
+    return DefWindowProc(hWnd, message, wParam, lParam);
+  }
+  return (LRESULT)0;
+}
+
+void wxWinSound::StopBuffer(wxSndBuffer& buf)
+{
+  buf.HardLock();
+  buf.Set(wxSND_BUFSTOP);
+  fragments.AbortBuffer(buf);
+  buf.HardUnlock();
+
+  while (buf.IsSet(wxSND_BUFSTOP))
+    wxYield();
+}
+
+bool wxWinSound::Reopen(wxSndBuffer& buf, bool force)
+{
+  WAVEFORMATEX wformat;
+
+  if ((buf.GetSampleRate() != curr_o_srate) ||
+      (buf.GetBps() != curr_o_bps) ||
+      (buf.GetStereo() != curr_o_stereo) ||
+      (buf.GetMode() != curr_mode))
+    force = TRUE;
+
+  if (force) {
+    wxUint32 *curr_srate =
+       (buf.GetMode() == wxSND_OUTPUT) ? &curr_o_srate : &curr_i_srate;
+    wxUint8 *curr_bps =
+       (buf.GetMode() == wxSND_OUTPUT) ? &curr_o_bps : &curr_i_bps;
+    bool *curr_stereo =
+       (buf.GetMode() == wxSND_OUTPUT) ? &curr_o_stereo : &curr_i_stereo;
+
+    fragments.WaitForAll();
+    fragments.FreeIOBuffer();
+    if (!internal->sndWin) {
+        FARPROC proc = MakeProcInstance((FARPROC)wxSoundHandlerWndProc, wxGetInstance());
+
+        internal->sndWin = ::CreateWindow(wxCanvasClassName, NULL, 0,
+                               0, 0, 0, 0, NULL, (HMENU) NULL,
+                                wxGetInstance(), 0);
+
+        ::SetWindowLong(internal->sndWin, GWL_WNDPROC,
+                        (LONG)proc);
+       ::SetWindowLong(internal->sndWin, GWL_USERDATA, (LONG) this);
+    }
+
+    if (wout_opened) {
+      waveOutClose(internal->devout_id);
+      wout_opened = FALSE;
+    }
+    if (win_opened) {
+      waveInClose(internal->devin_id);
+      win_opened = FALSE;
+    }
+
+    *curr_srate = buf.GetSampleRate();
+    *curr_bps = buf.GetBps();
+    *curr_stereo = buf.GetStereo();
+    wformat.wFormatTag = WAVE_FORMAT_PCM;
+    wformat.nChannels = curr_o_stereo+1;
+
+    wformat.nSamplesPerSec = curr_o_srate;
+    wformat.nBlockAlign = curr_o_bps / 8 * wformat.nChannels;
+    wformat.nAvgBytesPerSec =
+                wformat.nSamplesPerSec * wformat.nBlockAlign;
+    wformat.wBitsPerSample = curr_o_bps;
+    wformat.cbSize = 0;
+
+    if (buf.GetMode() == wxSND_OUTPUT) {
+      MMRESULT result = waveOutOpen(&internal->devout_id,
+                                    WAVE_MAPPER, &wformat,
+                                    (DWORD)internal->sndWin, (DWORD)this,
+                                    CALLBACK_WINDOW);
+      if (result != MMSYSERR_NOERROR)
+        return FALSE;
+      internal->devin_id = 0;
+      wout_opened = TRUE;
+      curr_mode = wxSND_OUTPUT;
+
+      fragments.AllocIOBuffer();
+    }
+    else {
+      MMRESULT result = waveInOpen(&internal->devin_id,
+                                   WAVE_MAPPER, &wformat,
+                                   (DWORD)internal->sndWin, (DWORD)this,
+                                   CALLBACK_FUNCTION);
+      if (result != MMSYSERR_NOERROR)
+        return FALSE;
+      internal->devout_id = 0;
+      win_opened = TRUE;
+      curr_mode = wxSND_INPUT;
+
+      fragments.AllocIOBuffer();
+    }
+  }
+  return TRUE;
+}
diff --git a/utils/wxMMedia/sndwin.h b/utils/wxMMedia/sndwin.h
new file mode 100644 (file)
index 0000000..5ac3eb0
--- /dev/null
@@ -0,0 +1,108 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       sndwin.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_win_H__
+#define __SND_win_H__
+
+#include "sndsnd.h"
+#include "sndfrag.h"
+
+#ifdef WXMMEDIA_INTERNAL
+#include <wx/msw/private.h>
+#include <windows.h>
+#include <mmsystem.h>
+
+typedef struct wxWinSoundInternal {
+  HWAVEOUT devout_id;
+  HWAVEIN devin_id;
+  HWND sndWin;
+} wxWinSoundInternal;
+
+typedef struct wxSndWinInfo {
+  HGLOBAL h_data, h_hdr;
+
+  char *data;
+  WAVEHDR *hdr;
+} wxSndWinInfo;
+
+#endif
+
+/** Sound buffer fragmenter: windows specific implementation
+  * @author Guilhem Lavaux
+  */
+class wxSndWinFragment : public wxFragmentBuffer {
+public:
+  wxSndWinFragment(wxSound& io_drv);
+  virtual ~wxSndWinFragment(void);
+
+  virtual void AllocIOBuffer(void);
+  virtual void FreeIOBuffer(void);
+
+  virtual bool OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode);
+
+  void WaitForAll();
+};
+
+///
+class wxWinSound : public wxSound {
+  ///
+  DECLARE_DYNAMIC_CLASS(wxWinSound)
+protected:
+  struct wxWinSoundInternal *internal;
+
+  ///
+  bool wout_opened, win_opened;
+  ///
+  wxUint32 curr_o_srate, curr_i_srate;
+  ///
+  wxUint8 curr_o_bps, curr_i_bps;
+  ///
+  bool curr_o_stereo, curr_i_stereo;
+  ///
+  wxSndMode curr_mode;
+
+  ///
+  wxSndWinFragment fragments;
+
+#ifdef WXMMEDIA_INTERNAL
+  ///
+  friend LRESULT APIENTRY _EXPORT wxSoundHandlerWndProc(HWND win,
+                                             UINT message,
+                                             WPARAM wParam, LPARAM lParam);
+
+#endif
+
+public:
+  ///
+  wxWinSound(void);
+  ///
+  virtual ~wxWinSound(void);
+
+  ///
+  void OnNeedBuffer(wxSndMode mode);
+  ///
+  void StopBuffer(wxSndBuffer& buf);
+protected:
+  ///
+  virtual bool Wakeup(wxSndBuffer& buf);
+
+  ///
+  bool Reopen(wxSndBuffer& buf, bool force);
+
+  ///
+  friend class wxSndWinFragment;
+
+  ///
+  void PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag, wxSndMode mode);
+  ///
+  void UnprepareHeader(wxFragmentBuffer::wxFragBufPtr& frag, wxSndMode mode);
+};
+
+#endif
diff --git a/utils/wxMMedia/ulaw.h b/utils/wxMMedia/ulaw.h
new file mode 100644 (file)
index 0000000..0ff8c0a
--- /dev/null
@@ -0,0 +1,69 @@
+static unsigned char ulaw_dsp[] = {
+     3,    7,   11,   15,   19,   23,   27,   31,
+    35,   39,   43,   47,   51,   55,   59,   63,
+    66,   68,   70,   72,   74,   76,   78,   80,
+    82,   84,   86,   88,   90,   92,   94,   96,
+    98,   99,  100,  101,  102,  103,  104,  105,
+   106,  107,  108,  109,  110,  111,  112,  113,
+   113,  114,  114,  115,  115,  116,  116,  117,
+   117,  118,  118,  119,  119,  120,  120,  121,
+   121,  121,  122,  122,  122,  122,  123,  123,
+   123,  123,  124,  124,  124,  124,  125,  125,
+   125,  125,  125,  125,  126,  126,  126,  126,
+   126,  126,  126,  126,  127,  127,  127,  127,
+   127,  127,  127,  127,  127,  127,  127,  127,
+   128,  128,  128,  128,  128,  128,  128,  128,
+   128,  128,  128,  128,  128,  128,  128,  128,
+   128,  128,  128,  128,  128,  128,  128,  128,
+   253,  249,  245,  241,  237,  233,  229,  225,
+   221,  217,  213,  209,  205,  201,  197,  193,
+   190,  188,  186,  184,  182,  180,  178,  176,
+   174,  172,  170,  168,  166,  164,  162,  160,
+   158,  157,  156,  155,  154,  153,  152,  151,
+   150,  149,  148,  147,  146,  145,  144,  143,
+   143,  142,  142,  141,  141,  140,  140,  139,
+   139,  138,  138,  137,  137,  136,  136,  135,
+   135,  135,  134,  134,  134,  134,  133,  133,
+   133,  133,  132,  132,  132,  132,  131,  131,
+   131,  131,  131,  131,  130,  130,  130,  130,
+   130,  130,  130,  130,  129,  129,  129,  129,
+   129,  129,  129,  129,  129,  129,  129,  129,
+   128,  128,  128,  128,  128,  128,  128,  128,
+   128,  128,  128,  128,  128,  128,  128,  128,
+   128,  128,  128,  128,  128,  128,  128,  128,
+};
+
+static unsigned char dsp_ulaw[] = {
+     0,    0,    0,    0,    0,    1,    1,    1,
+     1,    2,    2,    2,    2,    3,    3,    3,
+     3,    4,    4,    4,    4,    5,    5,    5,
+     5,    6,    6,    6,    6,    7,    7,    7,
+     7,    8,    8,    8,    8,    9,    9,    9,
+     9,   10,   10,   10,   10,   11,   11,   11,
+    11,   12,   12,   12,   12,   13,   13,   13,
+    13,   14,   14,   14,   14,   15,   15,   15,
+    15,   16,   16,   17,   17,   18,   18,   19,
+    19,   20,   20,   21,   21,   22,   22,   23,
+    23,   24,   24,   25,   25,   26,   26,   27,
+    27,   28,   28,   29,   29,   30,   30,   31,
+    31,   32,   33,   34,   35,   36,   37,   38,
+    39,   40,   41,   42,   43,   44,   45,   46,
+    47,   49,   51,   53,   55,   57,   59,   61,
+    63,   66,   70,   74,   78,   84,   92,  104,
+   254,  231,  219,  211,  205,  201,  197,  193,
+   190,  188,  186,  184,  182,  180,  178,  176,
+   175,  174,  173,  172,  171,  170,  169,  168,
+   167,  166,  165,  164,  163,  162,  161,  160,
+   159,  159,  158,  158,  157,  157,  156,  156,
+   155,  155,  154,  154,  153,  153,  152,  152,
+   151,  151,  150,  150,  149,  149,  148,  148,
+   147,  147,  146,  146,  145,  145,  144,  144,
+   143,  143,  143,  143,  142,  142,  142,  142,
+   141,  141,  141,  141,  140,  140,  140,  140,
+   139,  139,  139,  139,  138,  138,  138,  138,
+   137,  137,  137,  137,  136,  136,  136,  136,
+   135,  135,  135,  135,  134,  134,  134,  134,
+   133,  133,  133,  133,  132,  132,  132,  132,
+   131,  131,  131,  131,  130,  130,  130,  130,
+   129,  129,  129,  129,  128,  128,  128,  128,
+};
diff --git a/utils/wxMMedia/vidbase.cpp b/utils/wxMMedia/vidbase.cpp
new file mode 100644 (file)
index 0000000..dbe8dae
--- /dev/null
@@ -0,0 +1,87 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       vidbdrv.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "vidbase.h"
+#endif
+#include <wx/fstream.h>
+#include "vidbase.h"
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxVideoOutput::wxVideoOutput()
+  : wxWindow()
+{
+  dyn_size = TRUE;
+}
+
+wxVideoOutput::wxVideoOutput(wxWindow *parent, const wxWindowID id, const wxPoint& position,
+                            const wxSize& size, const long style,
+                            const wxString& name)
+  : wxWindow(parent, id, position, size, style, name)
+{
+  dyn_size = TRUE;
+}
+
+///
+wxVideoOutput::~wxVideoOutput()
+{
+}
+
+wxVideoBaseDriver::wxVideoBaseDriver()
+  : wxMMediaFile()
+{
+}
+
+wxVideoBaseDriver::wxVideoBaseDriver(wxInputStream& str, bool seekable)
+  : wxMMediaFile(str, FALSE, seekable)
+{
+}
+
+wxVideoBaseDriver::wxVideoBaseDriver(const wxString& fname)
+  : wxMMediaFile(fname)
+{
+}
+
+wxVideoBaseDriver::~wxVideoBaseDriver()
+{
+}
+
+bool wxVideoBaseDriver::AttachOutput(wxVideoOutput& output)
+{
+  video_output = &output;
+  return TRUE;
+}
+
+void wxVideoBaseDriver::DetachOutput()
+{
+  video_output = NULL;
+}
+
+// Use an external frame for video output
+
+wxFrame *wxVideoCreateFrame(wxVideoBaseDriver *vid_drv)
+{
+  wxFrame *frame = new wxFrame(NULL, -1, "Video Output", wxDefaultPosition, wxSize(100, 100));
+  wxVideoOutput *vid_out = new wxVideoOutput(frame, -1);
+
+  vid_out->DynamicSize(TRUE);
+  vid_drv->AttachOutput(*vid_out);
+  frame->Layout();
+  frame->Show(TRUE);
+
+  return frame;
+}
diff --git a/utils/wxMMedia/vidbase.h b/utils/wxMMedia/vidbase.h
new file mode 100644 (file)
index 0000000..367b373
--- /dev/null
@@ -0,0 +1,105 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       vidbase.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// CVS:               $Id$
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __VID_bdrv_H__
+#define __VID_bdrv_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmtype.h"
+#include "mmfile.h"
+#include "wx/string.h"
+#include "wx/window.h"
+
+///
+typedef enum {
+  wxVIDEO_MSAVI,
+  wxVIDEO_MPEG,
+  wxVIDEO_QT,
+  wxVIDEO_GIF,
+  wxVIDEO_JMOV,
+  wxVIDEO_FLI,
+  wxVIDEO_IFF,
+  wxVIDEO_SGI,
+  wxVIDEO_MPEG2
+} ///
+ wxVideoType;
+
+///
+class wxVideoBaseDriver;
+class wxVideoOutput : public wxWindow {
+  ///
+  DECLARE_DYNAMIC_CLASS(wxVideoOutput)
+protected:
+  bool dyn_size;
+public:
+  ///
+  wxVideoOutput();
+  ///
+  wxVideoOutput(wxWindow *parent, const wxWindowID id,
+                const wxPoint& pos = wxDefaultPosition,
+               const wxSize& size = wxDefaultSize, const long style = 0,
+                const wxString& name = "video_output");
+  ///
+  virtual ~wxVideoOutput();
+  
+  ///
+  bool DynamicSize() { return dyn_size; }
+  ///
+  void DynamicSize(bool dyn) { dyn_size = dyn; }
+};
+
+///
+class wxVideoBaseDriver : public wxObject, public wxMMediaFile {
+  ///
+  DECLARE_ABSTRACT_CLASS(wxVideoBaseDriver)
+protected:
+  wxVideoOutput *video_output;
+public:
+  friend class wxVideoOutput;
+  ///
+  wxVideoBaseDriver();
+  ///
+  wxVideoBaseDriver(wxInputStream& str, bool seekable = FALSE);
+  ///
+  wxVideoBaseDriver(const wxString& fname);
+  ///
+  virtual ~wxVideoBaseDriver();
+
+  ///
+  virtual bool Pause() = 0;
+  ///
+  virtual bool Resume() = 0;
+
+  ///
+  virtual bool SetVolume(wxUint8 vol) = 0;
+  ///
+  virtual bool Resize(wxUint16 w, wxUint16 h) = 0;
+
+  ///
+  virtual bool IsCapable(wxVideoType WXUNUSED(v_type)) { return FALSE; }
+
+  ///
+  virtual void OnFinished() {}
+
+  ///
+  virtual bool AttachOutput(wxVideoOutput& output);
+  ///
+  virtual void DetachOutput();
+};
+
+extern wxFrame *wxVideoCreateFrame(wxVideoBaseDriver *vid_drv);
+
+
+#endif
diff --git a/utils/wxMMedia/vidwin.cpp b/utils/wxMMedia/vidwin.cpp
new file mode 100644 (file)
index 0000000..a8e83b2
--- /dev/null
@@ -0,0 +1,131 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       vidwin.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    February 1998
+// Updated:
+// Copyright:  (C) 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "vidwin.h"
+#endif
+
+#if 0
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+
+#define WXMMEDIA_INTERNAL
+#include <windows.h>
+#include <mmsystem.h>
+#include <digitalv.h>
+#include "mmtype.h"
+#include "mmfile.h"
+#include "vidwin.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxVideoWindows::wxVideoWindows(void)
+{
+}
+
+wxVideoWindows::wxVideoWindows(wxInputStream& str, bool seekable)
+  : wxVideoBaseDriver(str, seekable)
+{
+  OpenFile(GetCurrentFile());
+}
+
+wxVideoWindows::wxVideoWindows(const char *fname)
+  : wxVideoBaseDriver(fname)
+{
+  OpenFile(fname);
+}
+
+wxVideoWindows::~wxVideoWindows(void)
+{
+  mciSendCommand(internal->dev_id, MCI_CLOSE, 0, 0);
+
+  if (internal)
+    delete internal;
+}
+
+void wxVideoWindows::OpenFile(const char *fname)
+{
+  MCI_DGV_OPEN_PARMS open_struct;
+  DWORD ret;
+
+  internal = new VIDW_Internal;
+
+  open_struct.lpstrDeviceType = "avivideo";
+  open_struct.lpstrElementName = (LPSTR)fname;
+  open_struct.hWndParent = 0;
+
+  ret = mciSendCommand(0, MCI_OPEN,
+        MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_OPEN_TYPE|MCI_DGV_OPEN_32BIT,
+                       (DWORD)(LPVOID)&open_struct);
+  internal->dev_id = open_struct.wDeviceID;
+}
+
+bool wxVideoWindows::Pause(void)
+{
+  return (mciSendCommand(internal->dev_id, MCI_PAUSE, 0, 0) == 0);
+}
+
+bool wxVideoWindows::Resume(void)
+{
+  return (mciSendCommand(internal->dev_id, MCI_PAUSE, 0, 0) == 0);
+}
+
+bool wxVideoWindows::SetVolume(wxUint8 vol)
+{
+  return TRUE;
+}
+
+bool wxVideoWindows::Resize(wxUint16 w, wxUint16 h)
+{
+  return TRUE;
+}
+
+bool wxVideoWindows::IsCapable(wxVideoType v_type)
+{
+  return (v_type == wxVIDEO_MSAVI);
+}
+
+bool wxVideoWindows::AttachOutput(wxVideoOutput& output)
+{
+  MCI_DGV_WINDOW_PARMS win_struct;
+
+  if (!wxVideoBaseDriver::AttachOutput(output))
+    return FALSE;
+
+  win_struct.hWnd = (HWND)output.GetHWND();
+  mciSendCommand(internal->dev_id, MCI_WINDOW,
+                 MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&win_struct);
+  return TRUE;
+}
+
+void wxVideoWindows::DetachOutput(void)
+{
+  MCI_DGV_WINDOW_PARMS win_struct;
+
+  wxVideoBaseDriver::DetachOutput();
+
+  win_struct.hWnd = 0;
+  mciSendCommand(internal->dev_id, MCI_WINDOW,
+                 MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&win_struct);
+}
+
+bool wxVideoWindows::StartPlay(void)
+{
+  return (mciSendCommand(internal->dev_id, MCI_PLAY, 0, NULL) == 0);
+}
+
+void wxVideoWindows::StopPlay(void)
+{
+  mciSendCommand(internal->dev_id, MCI_STOP, 0, NULL);
+}
diff --git a/utils/wxMMedia/vidwin.h b/utils/wxMMedia/vidwin.h
new file mode 100644 (file)
index 0000000..784d72a
--- /dev/null
@@ -0,0 +1,62 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       vidwin.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    February 1998
+// Updated:
+// Copyright:  (C) 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __VID_windows_H__
+#define __VID_windows_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmtype.h"
+#include "mmfile.h"
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "vidbase.h"
+
+#ifdef WXMMEDIA_INTERNAL
+#include <windows.h>
+#include <mmsystem.h>
+
+typedef struct VIDW_Internal {
+  MCIDEVICEID dev_id;
+} VIDW_Internal;
+#endif
+
+class wxVideoWindows : public wxVideoBaseDriver {
+  DECLARE_DYNAMIC_CLASS(wxVideoWindows)
+protected:
+  struct VIDW_Internal *internal;
+
+  void OpenFile(const char *fname);
+public:
+  wxVideoWindows(void);
+  wxVideoWindows(wxInputStream& str, bool seekable = FALSE);
+  wxVideoWindows(const char *fname);
+  virtual ~wxVideoWindows(void);
+
+  virtual bool StartPlay(void);
+  virtual void StopPlay(void);
+  virtual bool Pause(void);
+  virtual bool Resume(void);
+
+  virtual bool SetVolume(wxUint8 vol);
+  virtual bool Resize(wxUint16 w, wxUint16 h);
+
+  virtual bool IsCapable(wxVideoType v_type);
+
+  virtual bool AttachOutput(wxVideoOutput& output);
+  virtual void DetachOutput(void);
+};
+
+#endif
diff --git a/utils/wxMMedia/vidxanm.cpp b/utils/wxMMedia/vidxanm.cpp
new file mode 100644 (file)
index 0000000..7a934c2
--- /dev/null
@@ -0,0 +1,231 @@
+////////////////////////////////////////////////////////////////////////////////
+// Name:       vidxanm.cpp
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "vidxanm.h"
+#endif
+#define WXMMEDIA_INTERNAL
+#ifdef __XT__
+#define Uses_XLib
+#define Uses_XtIntrinsic
+#endif
+#include "vidbase.h"
+#include "vidxanm.h"
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#ifdef __WXGTK__
+#include <gdk/gdk.h>
+#include <gdk/gdkprivate.h>
+#endif
+
+wxVideoXANIM::wxVideoXANIM()
+ : wxVideoBaseDriver()
+{
+  internal = new wxXANIMinternal;
+  xanim_started = false;
+  paused = false;
+}
+
+wxVideoXANIM::wxVideoXANIM(wxInputStream& str)
+  : wxVideoBaseDriver(str, false)
+{
+  internal = new wxXANIMinternal;
+  xanim_started = false;
+  paused = false;
+}
+
+wxVideoXANIM::wxVideoXANIM(const wxString& fname)
+  : wxVideoBaseDriver(fname)
+{
+  internal = new wxXANIMinternal;
+  xanim_started = false;
+}
+
+wxVideoXANIM::~wxVideoXANIM()
+{
+  if (xanim_started)
+    StopPlay();
+  delete internal;
+}
+
+bool wxVideoXANIM::StartPlay()
+{
+  if (!paused && xanim_started)
+    return true;
+  if (!video_output)
+    wxVideoCreateFrame(this);
+
+  if (SendCommand(" ")) {
+    paused = false;
+    return true;
+  }
+  return false;
+}
+
+bool wxVideoXANIM::Pause()
+{
+  if (!paused && SendCommand(" ")) {
+    paused = TRUE;
+    return TRUE;
+  }
+  return FALSE;
+}
+
+bool wxVideoXANIM::Resume()
+{
+  if (paused && SendCommand(" ")) {
+    paused = FALSE;
+    return TRUE;
+  }
+  return FALSE;
+}
+
+void wxVideoXANIM::StopPlay()
+{
+  if (!xanim_started)
+    return;
+
+  SendCommand("q");
+
+  xanim_started = FALSE;
+  paused = FALSE;
+}
+
+bool wxVideoXANIM::SetVolume(wxUint8 vol)
+{
+  if (vol > 100)
+    vol = 100;
+
+  wxString str_vol("v%d", vol);
+  return SendCommand(str_vol.GetData());
+}
+
+bool wxVideoXANIM::Resize(wxUint16 WXUNUSED(w), wxUint16 WXUNUSED(h))
+{
+  // Not implemented
+  //  Actually, I think that we just need to resize the output window ...
+  return FALSE;
+}
+
+bool wxVideoXANIM::IsCapable(wxVideoType v_type)
+{
+  if (v_type == wxVIDEO_MSAVI || v_type == wxVIDEO_MPEG ||
+      v_type == wxVIDEO_QT || v_type == wxVIDEO_GIF || v_type == wxVIDEO_JMOV ||
+      v_type == wxVIDEO_FLI || v_type == wxVIDEO_IFF || v_type == wxVIDEO_SGI)
+    return true;
+  else
+    return false;
+}
+
+bool wxVideoXANIM::AttachOutput(wxVideoOutput& out)
+{
+  if (!wxVideoBaseDriver::AttachOutput(out))
+    return false;
+
+  return RestartXANIM();
+}
+
+void wxVideoXANIM::DetachOutput()
+{
+  SendCommand("q");
+  xanim_started = false;
+  paused = false;
+
+  wxVideoBaseDriver::DetachOutput();
+}
+
+bool wxVideoXANIM::SendCommand(const char *command, char **ret,
+                                 wxUint32 *size)
+{
+  if (!xanim_started)
+    if (!RestartXANIM())
+      return false;
+
+  // Send a command to XAnim through X11 Property
+  XChangeProperty(internal->xanim_dpy, internal->xanim_window,
+                  internal->xanim_atom,
+                 XA_STRING, 8, PropModeReplace, (unsigned char *)command,
+                 strlen(command));
+  XFlush(internal->xanim_dpy);
+  if (ret) {
+    int prop_format;
+    Atom prop_type;
+    unsigned long extra;
+
+    XGetWindowProperty(internal->xanim_dpy, internal->xanim_window,
+                       internal->xanim_ret, 0, 16, True, AnyPropertyType,
+                       &prop_type, &prop_format, (unsigned long *)size,
+                       &extra, (unsigned char **)ret);
+  }
+  return true;
+}
+
+bool wxVideoXANIM::RestartXANIM()
+{
+  wxString xanim_command;
+  int ret;
+  Atom prop_type;
+  int prop_format;
+  unsigned long nitems;
+  unsigned long extra;
+  char prop[4];
+  bool xanim_chg_size;
+
+  if (!video_output || xanim_started || !GetCurrentFile())
+    return false;
+  
+  // Check if we can change the size of the window dynamicly
+  xanim_chg_size =  video_output->DynamicSize();
+  // Get current display
+#ifdef __XT__
+  internal->xanim_dpy = wxAPP_DISPLAY;
+#endif
+#ifdef __WXGTK__
+  internal->xanim_dpy = gdk_display;
+#endif
+  // Get the window id
+#ifdef __XT__
+  internal->xanim_window = XtWindow(video_output->FWidget());
+#else
+  internal->xanim_window =
+            ((GdkWindowPrivate *)video_output->m_widget->window)->xwindow;
+#endif
+  // Get the XANIM atom
+  internal->xanim_atom = XInternAtom(internal->xanim_dpy,
+                                     "XANIM_PROPERTY", False);
+
+  // Build the command
+  xanim_command.sprintf(__XANIM_COMMAND__ " +W%d +Wp +f +B -Zr +q +Zpe +Ae "
+                       "+Av70 %s %s", internal->xanim_window,
+                       (xanim_chg_size == true) ? "+Sr" : "",
+                       (const char *)GetCurrentFile());
+  // Execute it
+  if (!wxExecute(xanim_command, false))
+    return false;
+
+  // Wait for XAnim to be ready
+  nitems = 0;
+  while (nitems == 0) {
+    ret = XGetWindowProperty(internal->xanim_dpy, internal->xanim_window,
+                            internal->xanim_atom,
+                            0, 4, False, AnyPropertyType, &prop_type,
+                            &prop_format, &nitems, &extra,
+                            (unsigned char **)&prop);
+//    wxYield();
+  }
+
+  xanim_started = true;
+
+  return true;
+}
diff --git a/utils/wxMMedia/vidxanm.h b/utils/wxMMedia/vidxanm.h
new file mode 100644 (file)
index 0000000..28d0098
--- /dev/null
@@ -0,0 +1,69 @@
+// /////////////////////////////////////////////////////////////////////////////
+// Name:       vidxanm.h
+// Purpose:    wxMMedia
+// Author:     Guilhem Lavaux
+// Created:    1997
+// Updated:    1998
+// Copyright:  (C) 1997, 1998, Guilhem Lavaux
+// License:    wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __VID_xanim_H__
+#define __VID_xanim_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#if defined(WXMMEDIA_INTERNAL) && (defined(__X__) || defined(__WXGTK__))
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+
+#include "vidbase.h"
+
+#ifdef WXMMEDIA_INTERNAL
+typedef struct wxXANIMinternal {
+  Display *xanim_dpy;
+  Window xanim_window;
+  Atom xanim_atom, xanim_ret;
+} wxXANIMinternal;
+
+#ifndef __XANIM_COMMAND__
+#define __XANIM_COMMAND__ "/usr/X11R6/bin/xanim"
+#endif
+#endif
+
+class wxVideoXANIM : public wxVideoBaseDriver {
+  DECLARE_DYNAMIC_CLASS(wxVideoXANIM)
+protected:
+  bool xanim_started, paused;
+  struct wxXANIMinternal *internal;
+public:
+  wxVideoXANIM();
+  wxVideoXANIM(wxInputStream& str);
+  wxVideoXANIM(const wxString& fname);
+  virtual ~wxVideoXANIM();
+
+  virtual bool StartPlay();
+  virtual bool Pause();
+  virtual bool Resume();
+  virtual void StopPlay();
+
+  virtual bool SetVolume(wxUint8 vol);
+  virtual bool Resize(wxUint16 w, wxUint16 h);
+
+  virtual bool IsCapable(wxVideoType v_type);
+
+  virtual bool AttachOutput(wxVideoOutput& output);
+  virtual void DetachOutput();
+
+protected:
+  ///
+  bool RestartXANIM();
+  ///
+  bool SendCommand(const char *command, char **ret = NULL,
+                     wxUint32 *size = NULL);
+};
+
+#endif
diff --git a/utils/wxMMedia/wave.cpp b/utils/wxMMedia/wave.cpp
new file mode 100644 (file)
index 0000000..5f11afb
--- /dev/null
@@ -0,0 +1,65 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wave.cpp
+// Purpose:     wxWave class
+// Author:      Guilhem Lavaux / API by Julian Smart
+// Modified by:
+// Created:     04/23/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Guilhem Lavaux
+// Licence:    wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "wave.h"
+#endif
+
+#include <wx/fstream.h>
+#include "wave.h"
+
+wxWave::wxWave()
+{
+  m_wave = NULL;
+  m_iowave = NULL;
+}
+
+wxWave::wxWave(const wxString& fileName, bool isResource = FALSE)
+{
+  Create(fileName, isResource);
+}
+
+wxWave::~wxWave()
+{
+  Free();
+}
+
+bool wxWave::Create(const wxString& sFileName, bool isResource = FALSE)
+{
+  m_iowave = new wxFileInputStream(sFileName);
+  m_wave = new wxSndWavCodec(*m_iowave);
+
+  return TRUE;
+}
+
+bool wxWave::Play(bool async, bool looped) const
+{
+  if (!m_wave)
+    return FALSE;
+
+  if (looped)
+    m_wave->Set(wxSND_LOOP);
+  if (!m_wave->StartPlay());
+    return FALSE;
+  if (!async)
+    m_wave->Wait();
+
+  m_wave->Clear(wxSND_LOOP);
+  return TRUE;
+}
+
+bool wxWave::Free()
+{
+  if (m_wave) {
+    delete m_wave;
+    delete m_iowave;
+  }
+  return TRUE;
+}
diff --git a/utils/wxMMedia/wave.h b/utils/wxMMedia/wave.h
new file mode 100644 (file)
index 0000000..b91edf9
--- /dev/null
@@ -0,0 +1,43 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wave.h
+// Purpose:     wxWave class
+// Author:      Julian Smart
+// Modified by: Guilhem Lavaux for wxMMedia (02/05/1998)
+// Created:     01/02/97
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart and Markus Holzem
+// Licence:    wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __WAVEH__
+#define __WAVEH__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <wx/object.h>
+#include <wx/string.h>
+#include "sndwav.h"
+
+class wxWave : public wxObject
+{
+public:
+  wxWave();
+  wxWave(const wxString& fileName, bool isResource = FALSE);
+  ~wxWave();
+
+public:
+  bool  Create(const wxString& sFileName, bool isResource = FALSE);
+  bool  IsOk() const { return (m_wave ? TRUE : FALSE); };
+  bool  Play(bool async = TRUE, bool looped = FALSE) const;
+
+protected:
+  bool  Free();
+
+protected:
+  wxInputStream *m_iowave;
+  wxSndWavCodec *m_wave;
+};
+
+#endif