# HG changeset patch # User William Pitcock # Date 1184945428 18000 # Node ID fbeb9446aa2e626eb1944fd872c4995cf3182b43 # Parent cbccccf7ea8465265f4f25e0ebc50f27939917ea# Parent f34112ab9101aa6c16b39136f6c199eb1e1c6e3c Automated merge with ssh://hg.atheme.org//hg/audacious-plugins diff -r f34112ab9101 -r fbeb9446aa2e src/madplug/Makefile --- a/src/madplug/Makefile Fri Jul 20 05:39:56 2007 +0200 +++ b/src/madplug/Makefile Fri Jul 20 10:30:28 2007 -0500 @@ -20,6 +20,6 @@ CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) $(ARCH_DEFINES) $(SIMD_CFLAGS) -I../../intl -I../.. -Wall LDFLAGS += $(AUDLDFLAGS) -LIBADD = -L/opt/local/lib -L$(plugindir) -laudid3tag -lmad $(GTK_LIBS) $(GLIB_LIBS) $(PANGO_LIBS) +LIBADD = -L/opt/local/lib -L$(plugindir) -Wl,-rpath=$(plugindir) -laudid3tag -lmad $(GTK_LIBS) $(GLIB_LIBS) $(PANGO_LIBS) include ../../mk/objective.mk diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/Makefile Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,30 @@ +include ../../mk/rules.mk +include ../../mk/init.mk + +OBJECTIVE_LIBS = libshnplug$(SHARED_SUFFIX) + +LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR) + +SOURCES = \ + array.c \ + convert.c \ + fixio.c \ + gtk.c \ + id3v2.c \ + misc.c \ + output.c \ + seek.c \ + shn.c \ + shorten.c \ + sulawalaw.c \ + vario.c \ + wave.c + +OBJECTS = ${SOURCES:.c=.o} + +CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) $(ARCH_DEFINES) $(SIMD_CFLAGS) -I../../intl -I../.. -Wall + +LDFLAGS += $(AUDLDFLAGS) +LIBADD = -L/opt/local/lib -L$(plugindir) -Wl,-rpath=$(plugindir) -laudid3tag $(GTK_LIBS) $(GLIB_LIBS) $(PANGO_LIBS) + +include ../../mk/objective.mk diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/array.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/array.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,40 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: array.c,v 1.7 2003/08/26 05:34:04 jason Exp $ + */ + +#include +#include +#include "shorten.h" + +void *pmalloc(ulong size, shn_file *this_shn) { + void *ptr; + + ptr = malloc(size); + + if(ptr == NULL) + shn_error_fatal(this_shn,"Call to malloc(%ld) failed in pmalloc() -\nyour system may be low on memory", size); + + return(ptr); +} + +slong **long2d(ulong n0, ulong n1, shn_file *this_shn) { + slong **array0 = NULL; + + if((array0 = (slong**) pmalloc((ulong) (n0 * sizeof(slong*) + + n0 * n1 * sizeof(slong)),this_shn)) != NULL ) { + slong *array1 = (slong*) (array0 + n0); + int i; + + for(i = 0; i < n0; i++) + array0[i] = array1 + i * n1; + } + return(array0); +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/bitshift.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/bitshift.h Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,33 @@ +char ulaw_maxshift[256] = {12,8,7,9,7,8,7,10,7,8,7,9,7,8,7,11,6,7,6,8,6,7,6,9,6,7,6,8,6,7,6,10,5,6,5,7,5,6,5,8,5,6,5,7,5,6,5,9,5,4,6,4,5,4,7,4,5,4,6,4,5,4,8,4,3,5,3,4,3,6,3,4,3,5,3,4,3,7,3,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,0,7,8,7,9,7,8,7,10,7,8,7,9,7,8,7,11,6,7,6,8,6,7,6,9,6,7,6,8,6,7,6,10,5,6,5,7,5,6,5,8,5,6,5,7,5,6,5,9,5,4,6,4,5,4,7,4,5,4,6,4,5,4,8,4,3,5,3,4,3,6,3,4,3,5,3,4,3,7,3,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,12}; + +schar ulaw_inward[13][256] = { +{-127,-126,-125,-124,-123,-122,-121,-120,-119,-118,-117,-116,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,-128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}, +{-119,-118,-117,-116,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-128,-7,-127,-6,-126,-5,-125,-4,-124,-3,-123,-2,-122,-1,-121,-120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,127,7,126,6,125,5,124,4,123,3,122,2,121,1,120,0}, +{-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-128,-11,-127,-10,-126,-9,-125,-8,-124,-7,-123,-6,-122,-5,-121,-4,-120,-119,-118,-3,-117,-116,-115,-2,-114,-113,-112,-1,-111,-110,-109,-108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,127,11,126,10,125,9,124,8,123,7,122,6,121,5,120,4,119,118,117,3,116,115,114,2,113,112,111,1,110,109,108,0}, +{-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-128,-13,-127,-12,-126,-11,-125,-10,-124,-9,-123,-8,-122,-7,-121,-6,-120,-119,-118,-5,-117,-116,-115,-4,-114,-113,-112,-3,-111,-110,-109,-2,-108,-107,-106,-105,-104,-103,-102,-1,-101,-100,-99,-98,-97,-96,-95,-94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,127,13,126,12,125,11,124,10,123,9,122,8,121,7,120,6,119,118,117,5,116,115,114,4,113,112,111,3,110,109,108,2,107,106,105,104,103,102,101,1,100,99,98,97,96,95,94,0}, +{-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-128,-14,-127,-13,-126,-12,-125,-11,-124,-10,-123,-9,-122,-8,-121,-7,-120,-119,-118,-6,-117,-116,-115,-5,-114,-113,-112,-4,-111,-110,-109,-3,-108,-107,-106,-105,-104,-103,-102,-2,-101,-100,-99,-98,-97,-96,-95,-1,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,127,14,126,13,125,12,124,11,123,10,122,9,121,8,120,7,119,118,117,6,116,115,114,5,113,112,111,4,110,109,108,3,107,106,105,104,103,102,101,2,100,99,98,97,96,95,94,1,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,0}, +{-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-128,-14,-127,-13,-126,-12,-125,-11,-124,-10,-123,-9,-122,-8,-121,-120,-7,-119,-118,-117,-6,-116,-115,-114,-5,-113,-112,-111,-4,-110,-109,-108,-107,-106,-3,-105,-104,-103,-102,-101,-100,-99,-2,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-1,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,127,14,126,13,125,12,124,11,123,10,122,9,121,8,120,119,7,118,117,116,6,115,114,113,5,112,111,110,4,109,108,107,106,105,3,104,103,102,101,100,99,98,2,97,96,95,94,93,92,91,90,89,88,87,1,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,0}, +{-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-128,-15,-127,-14,-126,-13,-125,-12,-124,-11,-123,-10,-122,-9,-121,-8,-120,-119,-7,-118,-117,-116,-6,-115,-114,-113,-5,-112,-111,-110,-4,-109,-108,-107,-106,-105,-104,-3,-103,-102,-101,-100,-99,-98,-97,-2,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-1,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,7,117,116,115,6,114,113,112,5,111,110,109,4,108,107,106,105,104,103,3,102,101,100,99,98,97,96,2,95,94,93,92,91,90,89,88,87,86,85,84,83,1,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,0}, +{-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-128,-15,-127,-14,-126,-13,-125,-12,-124,-11,-123,-10,-122,-9,-121,-8,-120,-119,-118,-7,-117,-116,-115,-6,-114,-113,-112,-5,-111,-110,-109,-4,-108,-107,-106,-105,-104,-103,-3,-102,-101,-100,-99,-98,-97,-96,-2,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-1,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,117,7,116,115,114,6,113,112,111,5,110,109,108,4,107,106,105,104,103,102,3,101,100,99,98,97,96,95,2,94,93,92,91,90,89,88,87,86,85,84,83,82,81,1,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,0}, +{-16,-15,-128,-14,-127,-13,-126,-12,-125,-11,-124,-10,-123,-9,-122,-8,-121,-120,-119,-7,-118,-117,-116,-6,-115,-114,-113,-5,-112,-111,-110,-4,-109,-108,-107,-106,-105,-104,-103,-3,-102,-101,-100,-99,-98,-97,-96,-2,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-1,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,127,15,126,14,125,13,124,12,123,11,122,10,121,9,120,8,119,118,117,7,116,115,114,6,113,112,111,5,110,109,108,4,107,106,105,104,103,102,101,3,100,99,98,97,96,95,94,2,93,92,91,90,89,88,87,86,85,84,83,82,81,80,1,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,0}, +{-8,-128,-127,-7,-126,-125,-124,-6,-123,-122,-121,-5,-120,-119,-118,-4,-117,-116,-115,-114,-113,-112,-111,-3,-110,-109,-108,-107,-106,-105,-104,-2,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-1,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,127,126,125,7,124,123,122,6,121,120,119,5,118,117,116,4,115,114,113,112,111,110,109,3,108,107,106,105,104,103,102,2,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,1,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,0}, +{-4,-128,-127,-126,-125,-124,-123,-3,-122,-121,-120,-119,-118,-117,-116,-2,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-1,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,127,126,125,124,123,122,121,3,120,119,118,117,116,115,114,2,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,1,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,0}, +{-2,-128,-127,-126,-125,-124,-123,-122,-121,-120,-119,-118,-117,-116,-115,-1,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,1,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,0}, +{-1,-128,-127,-126,-125,-124,-123,-122,-121,-120,-119,-118,-117,-116,-115,-114,-113,-112,-111,-110,-109,-108,-107,-106,-105,-104,-103,-102,-101,-100,-99,-98,-97,-96,-95,-94,-93,-92,-91,-90,-89,-88,-87,-86,-85,-84,-83,-82,-81,-80,-79,-78,-77,-76,-75,-74,-73,-72,-71,-70,-69,-68,-67,-66,-65,-64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0} +}; + +uchar ulaw_outward[13][256] = { +{127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,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,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128}, +{112,114,116,118,120,122,124,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,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,113,115,117,119,121,123,125,255,253,251,249,247,245,243,241,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,252,250,248,246,244,242,240}, +{96,98,100,102,104,106,108,110,112,113,114,116,117,118,120,121,122,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,97,99,101,103,105,107,109,111,115,119,123,255,251,247,243,239,237,235,233,231,229,227,225,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,250,249,248,246,245,244,242,241,240,238,236,234,232,230,228,226,224}, +{80,82,84,86,88,90,92,94,96,97,98,100,101,102,104,105,106,108,109,110,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,81,83,85,87,89,91,93,95,99,103,107,111,119,255,247,239,235,231,227,223,221,219,217,215,213,211,209,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,246,245,244,243,242,241,240,238,237,236,234,233,232,230,229,228,226,225,224,222,220,218,216,214,212,210,208}, +{64,66,68,70,72,74,76,78,80,81,82,84,85,86,88,89,90,92,93,94,96,97,98,99,100,101,102,104,105,106,107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,65,67,69,71,73,75,77,79,83,87,91,95,103,111,255,239,231,223,219,215,211,207,205,203,201,199,197,195,193,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,238,237,236,235,234,233,232,230,229,228,227,226,225,224,222,221,220,218,217,216,214,213,212,210,209,208,206,204,202,200,198,196,194,192}, +{49,51,53,55,57,59,61,63,64,66,67,68,70,71,72,74,75,76,78,79,80,81,82,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,50,52,54,56,58,60,62,65,69,73,77,83,91,103,255,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,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,210,209,208,207,206,204,203,202,200,199,198,196,195,194,192,191,189,187,185,183,181,179,177}, +{32,34,36,38,40,42,44,46,48,49,51,52,53,55,56,57,59,60,61,63,64,65,66,67,68,70,71,72,73,74,75,76,78,79,80,81,82,83,84,85,86,87,88,89,90,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,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,33,35,37,39,41,43,45,47,50,54,58,62,69,77,91,255,219,205,197,190,186,182,178,175,173,171,169,167,165,163,161,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,196,195,194,193,192,191,189,188,187,185,184,183,181,180,179,177,176,174,172,170,168,166,164,162,160}, +{16,18,20,22,24,26,28,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,51,52,53,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,78,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,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,19,21,23,25,27,29,31,35,39,43,47,54,62,77,255,205,190,182,175,171,167,163,159,157,155,153,151,149,147,145,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,181,180,179,178,177,176,174,173,172,170,169,168,166,165,164,162,161,160,158,156,154,152,150,148,146,144}, +{2,4,6,8,10,12,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,35,36,37,38,40,41,42,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,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,0,1,3,5,7,9,11,13,15,19,23,27,31,39,47,62,255,190,175,167,159,155,151,147,143,141,139,137,135,133,131,129,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,166,165,164,163,162,161,160,158,157,156,154,153,152,150,149,148,146,145,144,142,140,138,136,134,132,130,128}, +{1,2,4,5,6,8,9,10,12,13,14,16,17,18,19,20,21,22,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,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,0,3,7,11,15,23,31,47,255,175,159,151,143,139,135,131,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,150,149,148,147,146,145,144,142,141,140,138,137,136,134,133,132,130,129,128}, +{1,2,3,4,5,6,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,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,0,7,15,31,255,159,143,135,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,134,133,132,131,130,129,128}, +{1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,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,0,15,255,143,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128}, +{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,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,0,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128} +}; diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/convert.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/convert.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,42 @@ +/* convert.c - functions to convert little-endian data to endian of host + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: convert.c,v 1.9 2007/03/23 05:49:48 jason Exp $ + */ + +#include +#include "shorten.h" + +ulong shn_uchar_to_ulong_le(uchar *buf) +/* converts 4 bytes stored in little-endian format to a ulong */ +{ + return (ulong)((buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]); +} + +slong shn_uchar_to_slong_le(uchar *buf) +/* converts 4 bytes stored in little-endian format to an slong */ +{ + return (slong)shn_uchar_to_ulong_le(buf); +} + +ushort shn_uchar_to_ushort_le(uchar *buf) +/* converts 4 bytes stored in little-endian format to a ushort */ +{ + return (ushort)((buf[1] << 8) + buf[0]); +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/fixio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/fixio.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,279 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: fixio.c,v 1.7 2003/08/26 05:34:04 jason Exp $ + */ + +#include +#include +#include +#include +#include "shorten.h" +#include "bitshift.h" + +void swab(const void *from, void *to, ssize_t n); + +#define CAPMAXSCHAR(x) ((x > 127) ? 127 : x) +#define CAPMAXUCHAR(x) ((x > 255) ? 255 : x) +#define CAPMAXSHORT(x) ((x > 32767) ? 32767 : x) +#define CAPMAXUSHORT(x) ((x > 65535) ? 65535 : x) + +static int sizeof_sample[TYPE_EOF]; + +void init_sizeof_sample() { + sizeof_sample[TYPE_AU1] = sizeof(uchar); + sizeof_sample[TYPE_S8] = sizeof(schar); + sizeof_sample[TYPE_U8] = sizeof(uchar); + sizeof_sample[TYPE_S16HL] = sizeof(ushort); + sizeof_sample[TYPE_U16HL] = sizeof(ushort); + sizeof_sample[TYPE_S16LH] = sizeof(ushort); + sizeof_sample[TYPE_U16LH] = sizeof(ushort); + sizeof_sample[TYPE_ULAW] = sizeof(uchar); + sizeof_sample[TYPE_AU2] = sizeof(uchar); + sizeof_sample[TYPE_AU3] = sizeof(uchar); + sizeof_sample[TYPE_ALAW] = sizeof(uchar); +} + +/***************/ +/* fixed write */ +/***************/ + +void fwrite_type_init(shn_file *this_shn) { + init_sizeof_sample(); + this_shn->decode_state->writebuf = (schar*) NULL; + this_shn->decode_state->writefub = (schar*) NULL; + this_shn->decode_state->nwritebuf = 0; +} + +void fwrite_type_quit(shn_file *this_shn) { + if(this_shn->decode_state->writebuf != NULL) { + free(this_shn->decode_state->writebuf); + this_shn->decode_state->writebuf = NULL; + } + if(this_shn->decode_state->writefub != NULL) { + free(this_shn->decode_state->writefub); + this_shn->decode_state->writefub = NULL; + } +} + +/* convert from signed ints to a given type and write */ +void fwrite_type(slong **data,int ftype,int nchan,int nitem,shn_file *this_shn) +{ + int hiloint = 1, hilo = !(*((char*) &hiloint)); + int i, nwrite = 0, datasize = sizeof_sample[ftype], chan; + slong *data0 = data[0]; + int bufAvailable = OUT_BUFFER_SIZE - this_shn->vars.bytes_in_buf; + + if(this_shn->decode_state->nwritebuf < nchan * nitem * datasize) { + this_shn->decode_state->nwritebuf = nchan * nitem * datasize; + if(this_shn->decode_state->writebuf != NULL) free(this_shn->decode_state->writebuf); + if(this_shn->decode_state->writefub != NULL) free(this_shn->decode_state->writefub); + this_shn->decode_state->writebuf = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn); + if (!this_shn->decode_state->writebuf) + return; + this_shn->decode_state->writefub = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn); + if (!this_shn->decode_state->writefub) + return; + } + + switch(ftype) { + case TYPE_AU1: /* leave the conversion to fix_bitshift() */ + case TYPE_AU2: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = data0[i]; + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = data[chan][i]; + break; + } + case TYPE_U8: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXUCHAR(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXUCHAR(data[chan][i]); + break; + } + case TYPE_S8: { + schar *writebufp = (schar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXSCHAR(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXSCHAR(data[chan][i]); + break; + } + case TYPE_S16HL: + case TYPE_S16LH: { + short *writebufp = (short*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXSHORT(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXSHORT(data[chan][i]); + break; + } + case TYPE_U16HL: + case TYPE_U16LH: { + ushort *writebufp = (ushort*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXUSHORT(data0[i]); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = CAPMAXUSHORT(data[chan][i]); + break; + } + case TYPE_ULAW: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = Slinear2ulaw(CAPMAXSHORT((data0[i] << 3))); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = Slinear2ulaw(CAPMAXSHORT((data[chan][i] << 3))); + break; + } + case TYPE_AU3: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + if(data0[i] < 0) + *writebufp++ = (127 - data0[i]) ^ 0xd5; + else + *writebufp++ = (data0[i] + 128) ^ 0x55; + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + if(data[chan][i] < 0) + *writebufp++ = (127 - data[chan][i]) ^ 0xd5; + else + *writebufp++ = (data[chan][i] + 128) ^ 0x55; + break; + } + case TYPE_ALAW: { + uchar *writebufp = (uchar*) this_shn->decode_state->writebuf; + if(nchan == 1) + for(i = 0; i < nitem; i++) + *writebufp++ = Slinear2alaw(CAPMAXSHORT((data0[i] << 3))); + else + for(i = 0; i < nitem; i++) + for(chan = 0; chan < nchan; chan++) + *writebufp++ = Slinear2alaw(CAPMAXSHORT((data[chan][i] << 3))); + break; + } + } + + switch(ftype) { + case TYPE_AU1: + case TYPE_S8: + case TYPE_U8: + case TYPE_ULAW: + case TYPE_AU2: + case TYPE_AU3: + case TYPE_ALAW: + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 1]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + break; + case TYPE_S16HL: + case TYPE_U16HL: + if(hilo) + { + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 2]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + else + { + swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem); + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 3]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + break; + case TYPE_S16LH: + case TYPE_U16LH: + if(hilo) + { + swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem); + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 4]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + else + { + if (datasize*nchan*nitem <= bufAvailable) { + memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem); + this_shn->vars.bytes_in_buf += datasize*nchan*nitem; + nwrite = nitem; + } + else + shn_debug("Buffer overrun in fwrite_type() [case 5]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable); + } + break; + } + + if(nwrite != nitem) + shn_error_fatal(this_shn,"Failed to write decompressed stream -\npossible corrupt or truncated file"); +} + +/*************/ +/* bitshifts */ +/*************/ + +void fix_bitshift(buffer, nitem, bitshift, ftype) slong *buffer; int nitem, + bitshift, ftype; { + int i; + + if(ftype == TYPE_AU1) + for(i = 0; i < nitem; i++) + buffer[i] = ulaw_outward[bitshift][buffer[i] + 128]; + else if(ftype == TYPE_AU2) + for(i = 0; i < nitem; i++) { + if(buffer[i] >= 0) + buffer[i] = ulaw_outward[bitshift][buffer[i] + 128]; + else if(buffer[i] == -1) + buffer[i] = NEGATIVE_ULAW_ZERO; + else + buffer[i] = ulaw_outward[bitshift][buffer[i] + 129]; + } + else + if(bitshift != 0) + for(i = 0; i < nitem; i++) + buffer[i] <<= bitshift; +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/gtk.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/gtk.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,860 @@ +/* gtk.c - functions to build and display GTK windows + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: gtk.c,v 1.27 2007/03/29 00:40:40 jason Exp $ + */ + +#include +#include +#include +#include +#include "shorten.h" + +#undef XMMS_SHN_LOAD_TEXTFILES +#ifdef HAVE_DIRENT_H +# include +# include +# ifdef HAVE_OPENDIR +# ifdef HAVE_READDIR +# ifdef HAVE_CLOSEDIR +# define XMMS_SHN_LOAD_TEXTFILES 1 +# endif +# endif +# endif +#endif + +static GtkWidget *shn_configurewin = NULL, + *about_box, + *vbox, + *options_vbox, + *miscellaneous_vbox, + *seektables_vbox, + *bbox, + *notebook, + *output_frame, + *output_vbox, + *output_label, + *output_error_stderr, + *output_error_window, + *output_error_devnull, + *misc_frame, + *misc_vbox, + *swap_bytes_toggle, + *verbose_toggle, + *textfile_toggle, + *textfile_extensions_entry, + *textfile_extensions_label, + *textfile_extensions_hbox, + *path_frame, + *path_vbox, + *path_label, + *path_entry, + *path_entry_hbox, + *path_browse, + *relative_path_label, + *relative_path_entry, + *relative_path_entry_hbox, + *ok, + *cancel, + *apply; + +void shn_display_about(void) +{ + if (about_box != NULL) + { + gdk_window_raise(about_box->window); + return; + } + + about_box = xmms_show_message( + (gchar *) "About " PACKAGE, + (gchar *) PACKAGE " version " VERSION "\n" + "Copyright (C) 2000-2007 Jason Jordan \n" + "Portions Copyright (C) 1992-1995 Tony Robinson\n" + "\n" + "shorten utilities pages:\n" + "\n" + "http://www.etree.org/shnutils/\n" + "http://shnutils.freeshell.org/", + (gchar *) "Cool", + FALSE, NULL, NULL); + g_signal_connect_swapped(GTK_OBJECT(about_box), "destroy", + gtk_widget_destroyed, &about_box); +} + +void shn_configurewin_save(void) +{ + ConfigDb *cfg; + gchar *filename; + + shn_cfg.error_output_method = ERROR_OUTPUT_DEVNULL; + if (GTK_TOGGLE_BUTTON(output_error_stderr)->active) + shn_cfg.error_output_method = ERROR_OUTPUT_STDERR; + else if (GTK_TOGGLE_BUTTON(output_error_window)->active) + shn_cfg.error_output_method = ERROR_OUTPUT_WINDOW; + + g_free(shn_cfg.seek_tables_path); + shn_cfg.seek_tables_path = g_strdup(gtk_entry_get_text(GTK_ENTRY(path_entry))); + + g_free(shn_cfg.relative_seek_tables_path); + shn_cfg.relative_seek_tables_path = g_strdup(gtk_entry_get_text(GTK_ENTRY(relative_path_entry))); + + shn_cfg.verbose = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(verbose_toggle)); + + shn_cfg.swap_bytes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(swap_bytes_toggle)); + + shn_cfg.load_textfiles = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(textfile_toggle)); + + g_free(shn_cfg.textfile_extensions); + shn_cfg.textfile_extensions = g_strdup(gtk_entry_get_text(GTK_ENTRY(textfile_extensions_entry))); + + filename = g_strconcat(g_get_home_dir(), "/.xmms/config", NULL); + cfg = bmp_cfg_db_open(); + bmp_cfg_db_set_int(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.error_output_method_config_name, shn_cfg.error_output_method); + bmp_cfg_db_set_bool(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.verbose_config_name, shn_cfg.verbose); + bmp_cfg_db_set_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.seek_tables_path_config_name, shn_cfg.seek_tables_path); + bmp_cfg_db_set_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.relative_seek_tables_path_config_name, shn_cfg.relative_seek_tables_path); + bmp_cfg_db_set_bool(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.swap_bytes_config_name, shn_cfg.swap_bytes); + bmp_cfg_db_set_bool(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.load_textfiles_config_name, shn_cfg.load_textfiles); + bmp_cfg_db_set_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.textfile_extensions_config_name, shn_cfg.textfile_extensions); + + bmp_cfg_db_close(cfg); + g_free(filename); +} + +void shn_configurewin_apply() +{ + shn_configurewin_save(); +} + +void shn_configurewin_ok(void) +{ + shn_configurewin_save(); + gtk_widget_destroy(shn_configurewin); +} + +void shn_display_configure(void) +{ + if (shn_configurewin != NULL) + { + gdk_window_raise(shn_configurewin->window); + return; + } + + shn_configurewin = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_signal_connect(GTK_OBJECT(shn_configurewin), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &shn_configurewin); + gtk_window_set_title(GTK_WINDOW(shn_configurewin), (gchar *)"SHN Player Configuration"); + gtk_window_set_policy(GTK_WINDOW(shn_configurewin), FALSE, FALSE, FALSE); + gtk_container_border_width(GTK_CONTAINER(shn_configurewin), 10); + + vbox = gtk_vbox_new(FALSE, 10); + gtk_container_add(GTK_CONTAINER(shn_configurewin), vbox); + + notebook = gtk_notebook_new(); + + gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + + options_vbox = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(options_vbox), 5); + + seektables_vbox = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(seektables_vbox), 5); + + miscellaneous_vbox = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(miscellaneous_vbox), 5); + +/* begin error output box */ + + output_frame = gtk_frame_new((gchar *)" Error display options "); + gtk_container_set_border_width(GTK_CONTAINER(output_frame), 5); + + output_vbox = gtk_vbox_new(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(output_vbox), 5); + gtk_container_add(GTK_CONTAINER(output_frame), output_vbox); + + output_label = gtk_label_new((gchar *)"When an error occurs, display it to:"); + gtk_misc_set_alignment(GTK_MISC(output_label), 0, 0); + gtk_label_set_justify(GTK_LABEL(output_label), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(output_vbox), output_label, FALSE, FALSE, 0); + gtk_widget_show(output_label); + + output_error_window = gtk_radio_button_new_with_label(NULL, (gchar *)"a window"); + if (shn_cfg.error_output_method == ERROR_OUTPUT_WINDOW) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(output_error_window), TRUE); + gtk_box_pack_start(GTK_BOX(output_vbox), output_error_window, FALSE, FALSE, 0); + gtk_widget_show(output_error_window); + + output_error_stderr = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(output_error_window)), (gchar *)"stderr"); + if (shn_cfg.error_output_method == ERROR_OUTPUT_STDERR) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(output_error_stderr), TRUE); + gtk_box_pack_start(GTK_BOX(output_vbox), output_error_stderr, FALSE, FALSE, 0); + gtk_widget_show(output_error_stderr); + + output_error_devnull = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(output_error_window)), (gchar *)"/dev/null"); + if (shn_cfg.error_output_method == ERROR_OUTPUT_DEVNULL) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(output_error_devnull), TRUE); + gtk_box_pack_start(GTK_BOX(output_vbox), output_error_devnull, FALSE, FALSE, 0); + gtk_widget_show(output_error_devnull); + + gtk_widget_show(output_vbox); + gtk_widget_show(output_frame); + +/* end error output box */ + +/* begin misc box */ + + misc_frame = gtk_frame_new((gchar *)" Miscellaneous options "); + gtk_container_set_border_width(GTK_CONTAINER(misc_frame), 5); + + misc_vbox = gtk_vbox_new(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(misc_vbox), 5); + gtk_container_add(GTK_CONTAINER(misc_frame), misc_vbox); + + swap_bytes_toggle = gtk_check_button_new_with_label((gchar *)"Swap audio bytes (toggle if all you hear is static)"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(swap_bytes_toggle), shn_cfg.swap_bytes); + gtk_box_pack_start(GTK_BOX(misc_vbox), swap_bytes_toggle, FALSE, FALSE, 0); + gtk_widget_show(swap_bytes_toggle); + + verbose_toggle = gtk_check_button_new_with_label((gchar *)"Display debug info to stderr"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(verbose_toggle), shn_cfg.verbose); + gtk_box_pack_start(GTK_BOX(misc_vbox), verbose_toggle, FALSE, FALSE, 0); + gtk_widget_show(verbose_toggle); + + textfile_toggle = gtk_check_button_new_with_label((gchar *)"Load text files in file information box"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(textfile_toggle), shn_cfg.load_textfiles); + gtk_box_pack_start(GTK_BOX(misc_vbox), textfile_toggle, FALSE, FALSE, 0); + gtk_widget_show(textfile_toggle); + + textfile_extensions_hbox = gtk_hbox_new(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(textfile_extensions_hbox), 5); + gtk_box_pack_start(GTK_BOX(misc_vbox), textfile_extensions_hbox, FALSE, FALSE, 0); + + textfile_extensions_label = gtk_label_new((gchar *)" Text file extensions:"); + gtk_misc_set_alignment(GTK_MISC(textfile_extensions_label), 0, 0); + gtk_label_set_justify(GTK_LABEL(textfile_extensions_label), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(textfile_extensions_hbox), textfile_extensions_label, FALSE, FALSE, 0); + gtk_widget_show(textfile_extensions_label); + + textfile_extensions_entry = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(textfile_extensions_entry), shn_cfg.textfile_extensions); + gtk_box_pack_start(GTK_BOX(textfile_extensions_hbox), textfile_extensions_entry, TRUE, TRUE, 0); + gtk_widget_show(textfile_extensions_entry); + + gtk_widget_show(textfile_extensions_hbox); + gtk_widget_show(misc_vbox); + gtk_widget_show(misc_frame); + +/* end misc box */ + +/* begin seek table path box */ + + path_frame = gtk_frame_new((gchar *)" Alternate seek table file locations "); + gtk_container_set_border_width(GTK_CONTAINER(path_frame), 5); + + path_vbox = gtk_vbox_new(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(path_vbox), 5); + gtk_container_add(GTK_CONTAINER(path_frame), path_vbox); + + relative_path_label = gtk_label_new((gchar *)"Relative seek table path:"); + gtk_misc_set_alignment(GTK_MISC(relative_path_label), 0, 0); + gtk_label_set_justify(GTK_LABEL(relative_path_label), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(path_vbox), relative_path_label, FALSE, FALSE, 0); + gtk_widget_show(relative_path_label); + + relative_path_entry_hbox = gtk_hbox_new(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(relative_path_entry_hbox), 5); + gtk_box_pack_start(GTK_BOX(path_vbox), relative_path_entry_hbox, TRUE, TRUE, 0); + + relative_path_entry = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(relative_path_entry), shn_cfg.relative_seek_tables_path); + gtk_box_pack_start(GTK_BOX(relative_path_entry_hbox), relative_path_entry, TRUE, TRUE, 0); + gtk_widget_show(relative_path_entry); + + path_label = gtk_label_new((gchar *)"\nAbsolute seek table path:"); + gtk_misc_set_alignment(GTK_MISC(path_label), 0, 0); + gtk_label_set_justify(GTK_LABEL(path_label), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(path_vbox), path_label, FALSE, FALSE, 0); + gtk_widget_show(path_label); + + path_entry_hbox = gtk_hbox_new(FALSE, 5); + gtk_container_set_border_width(GTK_CONTAINER(path_entry_hbox), 5); + gtk_box_pack_start(GTK_BOX(path_vbox), path_entry_hbox, TRUE, TRUE, 0); + + path_entry = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(path_entry), shn_cfg.seek_tables_path); + gtk_box_pack_start(GTK_BOX(path_entry_hbox), path_entry, TRUE, TRUE, 0); + gtk_widget_show(path_entry); + +#if 0 + path_browse = gtk_button_new_with_label("Browse"); + gtk_signal_connect(GTK_OBJECT(path_browse), "clicked", GTK_SIGNAL_FUNC(path_browse_cb), NULL); + gtk_box_pack_start(GTK_BOX(path_entry_hbox), path_browse, FALSE, FALSE, 0); + gtk_widget_show(path_browse); +#endif + + gtk_widget_show(relative_path_entry_hbox); + gtk_widget_show(path_entry_hbox); + gtk_widget_show(path_vbox); + gtk_widget_show(path_frame); + +/* end seek table path box */ + + gtk_box_pack_start(GTK_BOX(options_vbox), output_frame, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(seektables_vbox), path_frame, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(miscellaneous_vbox), misc_frame, TRUE, TRUE, 0); + + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), options_vbox, gtk_label_new((gchar *)"Error Display")); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), seektables_vbox, gtk_label_new((gchar *)"Seek Tables")); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), miscellaneous_vbox, gtk_label_new((gchar *)"Miscellaneous")); + + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); + gtk_box_pack_start(GTK_BOX(vbox), bbox, TRUE, TRUE, 0); + + ok = gtk_button_new_with_label((gchar *)"OK"); + gtk_signal_connect(GTK_OBJECT(ok), "clicked", GTK_SIGNAL_FUNC(shn_configurewin_ok), NULL); + GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0); + gtk_widget_show(ok); + gtk_widget_grab_default(ok); + + cancel = gtk_button_new_with_label((gchar *)"Cancel"); + gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(shn_configurewin)); + GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0); + gtk_widget_show(cancel); + + apply = gtk_button_new_with_label((gchar *)"Apply"); + gtk_signal_connect_object(GTK_OBJECT(apply), "clicked", GTK_SIGNAL_FUNC(shn_configurewin_apply), NULL); + GTK_WIDGET_SET_FLAGS(apply, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), apply, TRUE, TRUE, 0); + gtk_widget_show(apply); + + gtk_widget_show(bbox); + gtk_widget_show(options_vbox); + gtk_widget_show(seektables_vbox); + gtk_widget_show(miscellaneous_vbox); + gtk_widget_show(notebook); + gtk_widget_show(vbox); + gtk_widget_show(shn_configurewin); +} + +void shn_message_box(char *message) +{ + GtkWidget *mbox_win, + *mbox_vbox1, + *mbox_vbox2, + *mbox_frame, + *mbox_label, + *mbox_bbox, + *mbox_ok; + + mbox_win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_signal_connect(GTK_OBJECT(mbox_win), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &mbox_win); + gtk_window_set_title(GTK_WINDOW(mbox_win), (gchar *)"Shorten file information"); + gtk_window_set_policy(GTK_WINDOW(mbox_win), FALSE, FALSE, FALSE); + gtk_container_border_width(GTK_CONTAINER(mbox_win), 10); + + mbox_vbox1 = gtk_vbox_new(FALSE, 10); + gtk_container_add(GTK_CONTAINER(mbox_win), mbox_vbox1); + + mbox_frame = gtk_frame_new((gchar *)" " PACKAGE " error "); + gtk_container_set_border_width(GTK_CONTAINER(mbox_frame), 5); + gtk_box_pack_start(GTK_BOX(mbox_vbox1), mbox_frame, FALSE, FALSE, 0); + + mbox_vbox2 = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(mbox_vbox2), 5); + gtk_container_add(GTK_CONTAINER(mbox_frame), mbox_vbox2); + + mbox_label = gtk_label_new((gchar *)message); + gtk_misc_set_alignment(GTK_MISC(mbox_label), 0, 0); + gtk_label_set_justify(GTK_LABEL(mbox_label), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mbox_vbox2), mbox_label, TRUE, TRUE, 0); + gtk_widget_show(mbox_label); + + mbox_bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(mbox_bbox), GTK_BUTTONBOX_SPREAD); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(mbox_bbox), 5); + gtk_box_pack_start(GTK_BOX(mbox_vbox2), mbox_bbox, FALSE, FALSE, 0); + + mbox_ok = gtk_button_new_with_label((gchar *)"OK"); + gtk_signal_connect_object(GTK_OBJECT(mbox_ok), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(mbox_win)); + GTK_WIDGET_SET_FLAGS(mbox_ok, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(mbox_bbox), mbox_ok, TRUE, TRUE, 0); + gtk_widget_show(mbox_ok); + gtk_widget_grab_default(mbox_ok); + + gtk_widget_show(mbox_bbox); + gtk_widget_show(mbox_vbox2); + gtk_widget_show(mbox_frame); + gtk_widget_show(mbox_vbox1); + gtk_widget_show(mbox_win); +} + +void load_shntextfile(char *filename,int num,GtkWidget *shntxt_notebook) +{ + FILE *f; + char buffer[1024],*shortfilename; + int nchars; + GtkWidget *shntxt_frame, + *shntxt_vbox, + *shntxt_vbox_inner, +// *shntxt_text, +// *shntxt_table, +// *shntxt_vscrollbar, + *shntxt_filename_hbox, + *shntxt_filename_entry, + *shntxt_filename_label; + + shn_debug("Loading text file '%s'",filename); + + if ((shortfilename = strrchr(filename,'/'))) + shortfilename++; + else + shortfilename = filename; + + shntxt_vbox = gtk_vbox_new(FALSE, 10); + + shn_snprintf(buffer,1024," %s ",shortfilename); + + shntxt_frame = gtk_frame_new((gchar *)buffer); + gtk_container_set_border_width(GTK_CONTAINER(shntxt_frame), 10); + gtk_box_pack_start(GTK_BOX(shntxt_vbox), shntxt_frame, TRUE, TRUE, 0); + + shntxt_vbox_inner = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(shntxt_vbox_inner), 5); + gtk_container_add(GTK_CONTAINER(shntxt_frame), shntxt_vbox_inner); + +/* begin filename */ + shntxt_filename_hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(shntxt_vbox_inner), shntxt_filename_hbox, FALSE, TRUE, 0); + + shntxt_filename_label = gtk_label_new((gchar *)"Filename:"); + gtk_box_pack_start(GTK_BOX(shntxt_filename_hbox), shntxt_filename_label, FALSE, TRUE, 0); + shntxt_filename_entry = gtk_entry_new(); + gtk_editable_set_editable(GTK_EDITABLE(shntxt_filename_entry), FALSE); + gtk_box_pack_start(GTK_BOX(shntxt_filename_hbox), shntxt_filename_entry, TRUE, TRUE, 0); + + gtk_entry_set_text(GTK_ENTRY(shntxt_filename_entry), filename); + gtk_editable_set_position(GTK_EDITABLE(shntxt_filename_entry), -1); +/* end filename */ + +#if 0 + shntxt_text = gtk_text_new(NULL,NULL); + + shntxt_table = gtk_table_new(2,2,FALSE); + gtk_container_add(GTK_CONTAINER(shntxt_vbox_inner), shntxt_table); + + shntxt_vscrollbar = gtk_vscrollbar_new(GTK_TEXT(shntxt_text)->vadj); + + gtk_text_set_editable(GTK_TEXT(shntxt_text),FALSE); + gtk_text_set_word_wrap(GTK_TEXT(shntxt_text),TRUE); + + gtk_table_attach(GTK_TABLE(shntxt_table),shntxt_text, 0, 1, 0, 1, GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(shntxt_table),shntxt_vscrollbar, 1, 2, 0, 1, GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0); + + gtk_widget_show(shntxt_vscrollbar); + gtk_widget_show(shntxt_text); + gtk_widget_show(shntxt_table); +#endif + gtk_widget_show(shntxt_frame); + gtk_widget_show(shntxt_vbox); + gtk_widget_show(shntxt_vbox_inner); + gtk_widget_show(shntxt_filename_hbox); + gtk_widget_show(shntxt_filename_entry); + gtk_widget_show(shntxt_filename_label); + + if ((f = fopen(filename,"rb"))) + { + nchars = fread(buffer,1,1024,f); + while (nchars > 0) + { +// gtk_text_insert(GTK_TEXT(shntxt_text),NULL,NULL,NULL,buffer,nchars); + nchars = fread(buffer,1,1024,f); + } + fclose(f); + } + else + { + shn_snprintf(buffer,1024,"error loading file: '%s'",filename); +// gtk_text_insert(GTK_TEXT(shntxt_text),NULL,NULL,NULL,buffer,strlen(buffer)); + } + + shn_snprintf(buffer,1024,"Text file %d",num); + + gtk_notebook_append_page(GTK_NOTEBOOK(shntxt_notebook), shntxt_vbox, gtk_label_new((gchar *)buffer)); +} + +void scan_for_textfiles(GtkWidget *this_notebook,char *dirname,int *filenum) +{ + char *ext,*textfile_exts,buffer[2048]; + gchar *exts; + DIR *dp; + struct dirent *entry; + + shn_debug("Searching for text files in directory '%s'",dirname); + + if (NULL == (dp = opendir(dirname))) + { + shn_debug("Could not open directory '%s'",dirname); + return; + } + + while ((entry = readdir(dp))) + { + exts = g_strdup(shn_cfg.textfile_extensions); + + if ((ext = strrchr(entry->d_name,'.'))) + ext++; + else + ext = ""; + + textfile_exts = strtok(exts,","); + while (textfile_exts) + { + if ((0 == strcmp(textfile_exts,ext)) || (0 == strcmp(textfile_exts,""))) + { + shn_snprintf(buffer,2048,"%s/%s",dirname,entry->d_name); + + load_shntextfile(buffer,*filenum,this_notebook); + *filenum = *filenum + 1; + break; + } + + textfile_exts = strtok(NULL,","); + } + + g_free(exts); + } + + closedir(dp); +} + +void load_shntextfiles(GtkWidget *this_notebook,char *filename) +{ +#ifdef XMMS_SHN_LOAD_TEXTFILES + char *basedir,*uponedir; + int filenum = 1; + + basedir = shn_get_base_directory(filename); + + if (NULL == (uponedir = malloc((strlen(basedir) + 5) * sizeof(char)))) + { + shn_debug("Could not allocate memory for search directories"); + return; + } + + shn_snprintf(uponedir,strlen(basedir) + 4,"%s/..",basedir); + + scan_for_textfiles(this_notebook,basedir,&filenum); + scan_for_textfiles(this_notebook,uponedir,&filenum); + + free(basedir); + free(uponedir); +#else + shn_debug("Text file support is disabled on your platform because the\n" + "appropriate functions were not found. Please email me with\n" + "the specifics of your platform, and I will try to support it."); +#endif +} + + +void shn_display_info(shn_file *tmp_file) +{ + char props[BUF_SIZE]; + char details[BUF_SIZE]; + char props_label[BUF_SIZE]; + char details_label[BUF_SIZE]; + char misalignment[8]; + char seektable_revision[8]; + char id3v2_info[32]; + GtkWidget *info_win, + *info_notebook, + *props_hbox, + *props_vbox, + *props_vbox_inner, + *props_frame, + *props_label_left, + *props_label_right, + *props_filename_hbox, + *props_filename_label, + *props_filename_entry, + *details_hbox, + *details_vbox, + *details_vbox_inner, + *details_frame, + *details_label_left, + *details_label_right, + *details_filename_hbox, + *details_filename_label, + *details_filename_entry, + *main_vbox, + *info_bbox, + *info_ok; + + shn_snprintf(props_label,BUF_SIZE," Properties for %s ", + strrchr(tmp_file->wave_header.filename,'/') ? + strrchr(tmp_file->wave_header.filename,'/') + 1 : + tmp_file->wave_header.filename); + + shn_snprintf(details_label,BUF_SIZE," Details for %s ", + strrchr(tmp_file->wave_header.filename,'/') ? + strrchr(tmp_file->wave_header.filename,'/') + 1 : + tmp_file->wave_header.filename); + + shn_snprintf(misalignment,8,"%d",tmp_file->wave_header.data_size % CD_BLOCK_SIZE); + + if (NO_SEEK_TABLE != tmp_file->seek_header.version) + shn_snprintf(seektable_revision,8,"%d",tmp_file->seek_header.version); + + shn_snprintf(id3v2_info,32,"yes (%ld bytes)",tmp_file->wave_header.id3v2_tag_size); + + shn_snprintf(props,BUF_SIZE, + "%s\n" + "%s\n" + "%s\n" + "%0.4f\n" + "\n" + "%s\n" + "%s\n" + "%s bytes\n" + "%s\n" + "\n" + "%s\n" + "%s\n" + "\n" + "%s", + tmp_file->wave_header.m_ss, + (tmp_file->vars.seek_table_entries == NO_SEEK_TABLE)?"no":"yes", + (tmp_file->seek_header.version == NO_SEEK_TABLE)?"n/a":seektable_revision, + (double)tmp_file->wave_header.actual_size/(double)tmp_file->wave_header.total_size, + (PROB_NOT_CD(tmp_file->wave_header))?"no":"yes", + (PROB_NOT_CD(tmp_file->wave_header))?"n/a":((PROB_BAD_BOUND(tmp_file->wave_header))?"no":"yes"), + (PROB_NOT_CD(tmp_file->wave_header))?"n/a":misalignment, + (PROB_NOT_CD(tmp_file->wave_header))?"n/a":((PROB_TOO_SHORT(tmp_file->wave_header))?"no":"yes"), + (PROB_HDR_NOT_CANONICAL(tmp_file->wave_header))?"yes":"no", + (PROB_EXTRA_CHUNKS(tmp_file->wave_header))?"yes":"no", + (tmp_file->wave_header.file_has_id3v2_tag)?id3v2_info:"no" + ); + + shn_snprintf(details,BUF_SIZE, + "\n" + "0x%04x (%s)\n" + "%hu\n" + "%hu\n" + "%lu\n" + "%lu\n" + "%lu bytes/sec\n" + "%hu\n" + "%d bytes\n" + "%lu bytes\n" + "%lu bytes\n" + "%lu bytes\n" + "%lu bytes", + tmp_file->wave_header.wave_format, + shn_format_to_str(tmp_file->wave_header.wave_format), + tmp_file->wave_header.channels, + tmp_file->wave_header.bits_per_sample, + tmp_file->wave_header.samples_per_sec, + tmp_file->wave_header.avg_bytes_per_sec, + tmp_file->wave_header.rate, + tmp_file->wave_header.block_align, + tmp_file->wave_header.header_size, + tmp_file->wave_header.data_size, + tmp_file->wave_header.chunk_size, + tmp_file->wave_header.total_size, + tmp_file->wave_header.actual_size + ); + + info_win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_signal_connect(GTK_OBJECT(info_win), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &info_win); + gtk_window_set_title(GTK_WINDOW(info_win), (gchar *)"Shorten file information"); + gtk_window_set_policy(GTK_WINDOW(info_win), FALSE, FALSE, FALSE); + gtk_container_border_width(GTK_CONTAINER(info_win), 10); + + main_vbox = gtk_vbox_new(FALSE, 10); + gtk_container_add(GTK_CONTAINER(info_win), main_vbox); + + info_notebook = gtk_notebook_new(); + gtk_container_add(GTK_CONTAINER(main_vbox), info_notebook); + +/* begin properties page */ + + props_vbox = gtk_vbox_new(FALSE, 10); + + props_frame = gtk_frame_new((gchar *)props_label); + gtk_container_set_border_width(GTK_CONTAINER(props_frame), 10); + gtk_box_pack_start(GTK_BOX(props_vbox), props_frame, TRUE, TRUE, 0); + + props_vbox_inner = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(props_vbox_inner), 5); + gtk_container_add(GTK_CONTAINER(props_frame), props_vbox_inner); + +/* begin filename */ + props_filename_hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(props_vbox_inner), props_filename_hbox, FALSE, TRUE, 0); + + props_filename_label = gtk_label_new((gchar *)"Filename:"); + gtk_box_pack_start(GTK_BOX(props_filename_hbox), props_filename_label, FALSE, TRUE, 0); + props_filename_entry = gtk_entry_new(); + gtk_editable_set_editable(GTK_EDITABLE(props_filename_entry), FALSE); + gtk_box_pack_start(GTK_BOX(props_filename_hbox), props_filename_entry, TRUE, TRUE, 0); + + gtk_entry_set_text(GTK_ENTRY(props_filename_entry), tmp_file->wave_header.filename); + gtk_editable_set_position(GTK_EDITABLE(props_filename_entry), -1); +/* end filename */ + + props_hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(props_vbox_inner), props_hbox, TRUE, TRUE, 0); + + props_label_left = gtk_label_new((gchar *) + "Length:\n" + "Seekable:\n" + "Seek table revision:\n" + "Compression ratio:\n" + "CD-quality properties:\n" + " CD-quality:\n" + " Cut on sector boundary:\n" + " Sector misalignment:\n" + " Long enough to be burned:\n" + "WAVE properties:\n" + " Non-canonical header:\n" + " Extra RIFF chunks:\n" + "Possible problems:\n" + " File contains ID3v2 tag:" + ); + + props_label_right = gtk_label_new((gchar *)props); + + gtk_misc_set_alignment(GTK_MISC(props_label_left), 0, 0); + gtk_label_set_justify(GTK_LABEL(props_label_left), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(props_hbox), props_label_left, TRUE, TRUE, 0); + gtk_widget_show(props_label_left); + + gtk_misc_set_alignment(GTK_MISC(props_label_right), 0, 0); + gtk_label_set_justify(GTK_LABEL(props_label_right), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(props_hbox), props_label_right, TRUE, TRUE, 0); + gtk_widget_show(props_label_right); + +/* end properties page */ + +/* begin details page */ + + details_vbox = gtk_vbox_new(FALSE, 10); + + details_frame = gtk_frame_new((gchar *)details_label); + gtk_container_set_border_width(GTK_CONTAINER(details_frame), 10); + gtk_box_pack_start(GTK_BOX(details_vbox), details_frame, TRUE, TRUE, 0); + + details_vbox_inner = gtk_vbox_new(FALSE, 10); + gtk_container_set_border_width(GTK_CONTAINER(details_vbox_inner), 5); + gtk_container_add(GTK_CONTAINER(details_frame), details_vbox_inner); + +/* begin filename */ + details_filename_hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(details_vbox_inner), details_filename_hbox, FALSE, TRUE, 0); + + details_filename_label = gtk_label_new((gchar *)"Filename:"); + gtk_box_pack_start(GTK_BOX(details_filename_hbox), details_filename_label, FALSE, TRUE, 0); + details_filename_entry = gtk_entry_new(); + gtk_editable_set_editable(GTK_EDITABLE(details_filename_entry), FALSE); + gtk_box_pack_start(GTK_BOX(details_filename_hbox), details_filename_entry, TRUE, TRUE, 0); + + gtk_entry_set_text(GTK_ENTRY(details_filename_entry), tmp_file->wave_header.filename); + gtk_editable_set_position(GTK_EDITABLE(details_filename_entry), -1); +/* end filename */ + + details_hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(details_vbox_inner), details_hbox, TRUE, TRUE, 0); + + details_label_left = gtk_label_new((gchar *) + "\n" + "WAVE format:\n" + "Channels:\n" + "Bits per sample:\n" + "Samples per second:\n" + "Average bytes per second:\n" + "Rate (calculated):\n" + "Block align:\n" + "Header size:\n" + "WAVE data size:\n" + "Chunk size:\n" + "Total size (chunk size + 8):\n" + "Actual file size:" + ); + + details_label_right = gtk_label_new((gchar *)details); + + gtk_misc_set_alignment(GTK_MISC(details_label_left), 0, 0); + gtk_label_set_justify(GTK_LABEL(details_label_left), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(details_hbox), details_label_left, TRUE, TRUE, 0); + gtk_widget_show(details_label_left); + + gtk_misc_set_alignment(GTK_MISC(details_label_right), 0, 0); + gtk_label_set_justify(GTK_LABEL(details_label_right), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(details_hbox), details_label_right, TRUE, TRUE, 0); + gtk_widget_show(details_label_right); + +/* end details page */ + + info_bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(info_bbox), GTK_BUTTONBOX_SPREAD); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(info_bbox), 5); + gtk_box_pack_start(GTK_BOX(main_vbox), info_bbox, FALSE, FALSE, 0); + + info_ok = gtk_button_new_with_label((gchar *)"OK"); + gtk_signal_connect_object(GTK_OBJECT(info_ok), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(info_win)); + GTK_WIDGET_SET_FLAGS(info_ok, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(info_bbox), info_ok, TRUE, TRUE, 0); + gtk_widget_show(info_ok); + gtk_widget_grab_default(info_ok); + + gtk_notebook_append_page(GTK_NOTEBOOK(info_notebook), props_vbox, gtk_label_new((gchar *)"Properties")); + gtk_notebook_append_page(GTK_NOTEBOOK(info_notebook), details_vbox, gtk_label_new((gchar *)"Details")); + + gtk_widget_show(props_frame); + gtk_widget_show(props_hbox); + gtk_widget_show(props_vbox_inner); + gtk_widget_show(props_vbox); + gtk_widget_show(props_filename_hbox); + gtk_widget_show(props_filename_entry); + gtk_widget_show(props_filename_label); + gtk_widget_show(details_frame); + gtk_widget_show(details_hbox); + gtk_widget_show(details_vbox_inner); + gtk_widget_show(details_vbox); + gtk_widget_show(details_filename_hbox); + gtk_widget_show(details_filename_entry); + gtk_widget_show(details_filename_label); + +/* begin any text files pages */ + + if (shn_cfg.load_textfiles) + load_shntextfiles(info_notebook,tmp_file->wave_header.filename); + +/* end any text files pages */ + + gtk_notebook_set_page(GTK_NOTEBOOK(info_notebook), 0); + + gtk_widget_show(info_notebook); + gtk_widget_show(main_vbox); + gtk_widget_show(info_bbox); + gtk_widget_show(info_win); +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/id3v2.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/id3v2.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,120 @@ +/* id3v2.c - functions to handle ID3v2 tags prepended to shn files + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: id3v2.c,v 1.6 2007/03/23 05:49:48 jason Exp $ + */ + +#include +#include "shorten.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define ID3V2_MAGIC "ID3" + +typedef struct { + char magic[3]; + unsigned char version[2]; + unsigned char flags[1]; + unsigned char size[4]; +} _id3v2_header; + +int tagcmp(char *got,char *expected) +/* compare got against expected, up to the length of expected */ +{ + int i; + + for (i=0;*(expected+i);i++) { + if (*(got+i) != *(expected+i)) + return i+1; + } + + return 0; +} + +unsigned long synchsafe_int_to_ulong(unsigned char *buf) +/* converts 4 bytes stored in synchsafe integer format to an unsigned long */ +{ + return (unsigned long)(((buf[0] & 0x7f) << 21) | ((buf[1] & 0x7f) << 14) | ((buf[2] & 0x7f) << 7) | (buf[3] & 0x7f)); +} + +static unsigned long check_for_id3v2_tag(VFSFile *f) +{ + _id3v2_header id3v2_header; + unsigned long tag_size; + + /* read an ID3v2 header's size worth of data */ + if (sizeof(_id3v2_header) != vfs_fread(&id3v2_header,1,sizeof(_id3v2_header),f)) { + return 0; + } + + /* verify this is an ID3v2 header */ + if (tagcmp(id3v2_header.magic,ID3V2_MAGIC) || + 0xff == id3v2_header.version[0] || 0xff == id3v2_header.version[1] || + 0x80 <= id3v2_header.size[0] || 0x80 <= id3v2_header.size[1] || + 0x80 <= id3v2_header.size[2] || 0x80 <= id3v2_header.size[3]) + { + return 0; + } + + /* calculate and return ID3v2 tag size */ + tag_size = synchsafe_int_to_ulong(id3v2_header.size); + + return tag_size; +} + +VFSFile *shn_open_and_discard_id3v2_tag(char *filename,int *file_has_id3v2_tag,long *id3v2_tag_size) +/* opens a file, and if it contains an ID3v2 tag, skips past it */ +{ + VFSFile *f; + unsigned long tag_size; + + if (NULL == (f = vfs_fopen(filename,"rb"))) { + return NULL; + } + + if (file_has_id3v2_tag) + *file_has_id3v2_tag = 0; + + if (id3v2_tag_size) + *id3v2_tag_size = 0; + + /* check for ID3v2 tag on input */ + if (0 == (tag_size = check_for_id3v2_tag(f))) { + vfs_fclose(f); + return vfs_fopen(filename,"rb"); + } + + if (file_has_id3v2_tag) + *file_has_id3v2_tag = 2; + + if (id3v2_tag_size) + *id3v2_tag_size = (long)(tag_size + sizeof(_id3v2_header)); + + shn_debug("Discarding %lu-byte ID3v2 tag at beginning of file '%s'.",tag_size+sizeof(_id3v2_header),filename); + + if (0 != vfs_fseek(f,(long)tag_size,SEEK_CUR)) { + shn_debug("Error while discarding ID3v2 tag in file '%s'.",filename); + vfs_fclose(f); + return vfs_fopen(filename,"rb"); + } + + return f; +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/misc.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,148 @@ +/* misc.c - miscellaneous functions + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: misc.c,v 1.14 2007/03/23 05:49:48 jason Exp $ + */ + +#include +#include +#include "shorten.h" + +void shn_snprintf(char *dest,int maxlen,char *formatstr, ...) +/* acts like snprintf, but makes 100% sure the string is NULL-terminated */ +{ + va_list args; + + va_start(args,formatstr); + + shn_vsnprintf(dest,maxlen,formatstr,args); + + dest[maxlen-1] = 0; + + va_end(args); +} + +int shn_filename_contains_a_dot(char *filename) +{ + char *slash,*dot; + + dot = strrchr(filename,'.'); + if (!dot) + return 0; + + slash = strrchr(filename,'/'); + if (!slash) + return 1; + + if (slash < dot) + return 1; + else + return 0; +} + +char *shn_get_base_filename(char *filename) +{ + char *b,*e,*p,*base; + + b = strrchr(filename,'/'); + + if (b) + b++; + else + b = filename; + + e = strrchr(filename,'.'); + + if (e < b) + e = filename + strlen(filename); + + if (NULL == (base = malloc((e - b + 1) * sizeof(char)))) + { + shn_debug("Could not allocate memory for base filename"); + return NULL; + } + + for (p=b;pwave_header)) { + newlength = (ulong)info->wave_header.exact_length; + + tmp = info->wave_header.exact_length - (double)((ulong)info->wave_header.exact_length); + ms = (ulong)((tmp * 1000.0) + 0.5); + + if (1000 == ms) { + ms = 0; + newlength++; + } + + shn_snprintf(info->wave_header.m_ss,16,"%lu:%02lu.%03lu",newlength/60,newlength%60,ms); + } + else { + newlength = info->wave_header.length; + + rem1 = info->wave_header.data_size % CD_RATE; + rem2 = rem1 % CD_BLOCK_SIZE; + + frames = rem1 / CD_BLOCK_SIZE; + if (rem2 >= (CD_BLOCK_SIZE / 2)) + frames++; + + if (frames == CD_BLOCKS_PER_SEC) { + frames = 0; + newlength++; + } + + shn_snprintf(info->wave_header.m_ss,16,"%lu:%02lu.%02lu",newlength/60,newlength%60,frames); + } +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/output.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/output.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,101 @@ +/* output.c - functions for message and error output + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: output.c,v 1.11 2007/03/23 05:49:48 jason Exp $ + */ + +#include +#include +#include "shorten.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +void print_lines(char *prefix,char *message) +{ + char *head, *tail; + + head = tail = message; + while (*head != '\0') { + if (*head == '\n') { + *head = '\0'; + fprintf(stderr,"%s%s\n",prefix,tail); + tail = head + 1; + } + head++; + } + fprintf(stderr,"%s%s\n",prefix,tail); +} + +void shn_error(char *msg, ...) +{ + va_list args; + char msgbuf[BUF_SIZE]; + + va_start(args,msg); + + shn_vsnprintf(msgbuf,BUF_SIZE,msg,args); + + switch (shn_cfg.error_output_method) { + case ERROR_OUTPUT_STDERR: + print_lines(PACKAGE ": ",msgbuf); + break; + case ERROR_OUTPUT_WINDOW: + shn_message_box(msgbuf); + break; + default: + if (0 != shn_cfg.verbose) + print_lines(PACKAGE " [error]: ",msgbuf); + } + + va_end(args); +} + +void shn_debug(char *msg, ...) +{ + va_list args; + char msgbuf[BUF_SIZE]; + + va_start(args,msg); + + shn_vsnprintf(msgbuf,BUF_SIZE,msg,args); + + if (0 != shn_cfg.verbose) + print_lines(PACKAGE " [debug]: ",msgbuf); + + va_end(args); +} + +void shn_error_fatal(shn_file *this_shn,char *complaint, ...) +{ + va_list args; + + va_start(args,complaint); + + if (NULL != this_shn) { + if (0 == this_shn->vars.fatal_error) { + this_shn->vars.fatal_error = 1; + this_shn->vars.going = 0; + shn_vsnprintf(this_shn->vars.fatal_error_msg,BUF_SIZE,complaint,args); + } + } + + va_end(args); +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/seek.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/seek.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,279 @@ +/* seek.c - functions related to real-time seeking + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: seek.c,v 1.18 2007/03/23 05:49:48 jason Exp $ + */ + +#include +#include +#include +#include "shorten.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define ID3V1_TAG_SIZE 128 + +shn_seek_entry *shn_seek_entry_search(shn_seek_entry *table,ulong goal,ulong min,ulong max,ulong resolution) +{ + ulong med = (min + max) / 2; + shn_seek_entry *middle = table + med; + ulong sample = shn_uchar_to_ulong_le(middle->data); + + shn_debug("Examining seek table entry %lu with sample %lu (min/max = %lu/%lu, goal sample is %lu, resolution is %lu samples)",med,sample,min,max,goal,resolution); + + if (goal < sample) + return shn_seek_entry_search(table,goal,min,med-1,resolution); + if (goal > sample + resolution) + return shn_seek_entry_search(table,goal,med+1,max,resolution); + return middle; +} + +int load_separate_seek_table_generic(char *filename,shn_file *this_shn) +{ + VFSFile *f; + slong seek_table_len; + + shn_debug("Looking for seek table in separate file: '%s'",filename); + + if (!(f=vfs_fopen(filename,"rb"))) + { + return 0; + } + + vfs_fseek(f,0,SEEK_END); + seek_table_len = (slong)vfs_ftell(f) - SEEK_HEADER_SIZE; + vfs_fseek(f,0,SEEK_SET); + + if (vfs_fread((void *)this_shn->seek_header.data,1,SEEK_HEADER_SIZE,f) == SEEK_HEADER_SIZE) + { + this_shn->seek_header.version = (slong)shn_uchar_to_ulong_le(this_shn->seek_header.data+4); + this_shn->seek_header.shnFileSize = shn_uchar_to_ulong_le(this_shn->seek_header.data+8); + if (memcmp(this_shn->seek_header.data,SEEK_HEADER_SIGNATURE,strlen(SEEK_HEADER_SIGNATURE)) == 0) + { + if (this_shn->seek_header.shnFileSize != this_shn->wave_header.actual_size) + { + shn_debug("warning: Seek table expected .shn file size %lu differs from actual .shn file size %lu - seek table might not belong to this file", + this_shn->seek_header.shnFileSize,this_shn->wave_header.actual_size); + } + + if ((this_shn->seek_table = malloc(seek_table_len))) + { + if (vfs_fread((void *)this_shn->seek_table,1,seek_table_len,f) == seek_table_len) + { + shn_debug("Successfully loaded seek table in separate file: '%s'",filename); + + this_shn->vars.seek_table_entries = seek_table_len / SEEK_ENTRY_SIZE; + + if (this_shn->vars.seek_table_entries > 1) + this_shn->vars.seek_resolution = shn_uchar_to_ulong_le(this_shn->seek_table->data+SEEK_ENTRY_SIZE); + else + this_shn->vars.seek_resolution = SEEK_RESOLUTION; + + vfs_fclose(f); + + return 1; + } + } + } + } + + vfs_fclose(f); + return 0; +} + +int load_appended_seek_table(shn_file *this_shn,char *filename,long bytes_from_end) +{ + switch (bytes_from_end) + { + case 0: + shn_debug("Looking for seek table appended to file: '%s'",filename); + break; + case ID3V1_TAG_SIZE: + shn_debug("Looking for seek table hidden behind an ID3v1 tag at the end of file: '%s'",filename); + break; + default: + shn_debug("Looking for seek table located %ld bytes from the end of file: '%s'",bytes_from_end,filename); + break; + } + + vfs_fseek(this_shn->vars.fd,-(SEEK_TRAILER_SIZE+bytes_from_end),SEEK_END); + if (vfs_fread((void *)this_shn->seek_trailer.data,1,SEEK_TRAILER_SIZE,this_shn->vars.fd) == SEEK_TRAILER_SIZE) + { + this_shn->seek_trailer.seekTableSize = shn_uchar_to_ulong_le(this_shn->seek_trailer.data); + if (memcmp(this_shn->seek_trailer.data+4,SEEK_TRAILER_SIGNATURE,strlen(SEEK_TRAILER_SIGNATURE)) == 0) + { + vfs_fseek(this_shn->vars.fd,-(this_shn->seek_trailer.seekTableSize+bytes_from_end),SEEK_END); + this_shn->seek_trailer.seekTableSize -= (SEEK_HEADER_SIZE + SEEK_TRAILER_SIZE); + if (vfs_fread((void *)this_shn->seek_header.data,1,SEEK_HEADER_SIZE,this_shn->vars.fd) == SEEK_HEADER_SIZE) + { + this_shn->seek_header.version = (slong)shn_uchar_to_ulong_le(this_shn->seek_header.data+4); + this_shn->seek_header.shnFileSize = shn_uchar_to_ulong_le(this_shn->seek_header.data+8); + if ((this_shn->seek_table = malloc(this_shn->seek_trailer.seekTableSize))) + { + if (vfs_fread((void *)this_shn->seek_table,1,this_shn->seek_trailer.seekTableSize,this_shn->vars.fd) == this_shn->seek_trailer.seekTableSize) + { + shn_debug("Successfully loaded seek table appended to file: '%s'",filename); + + this_shn->vars.seek_table_entries = this_shn->seek_trailer.seekTableSize / SEEK_ENTRY_SIZE; + + if (this_shn->vars.seek_table_entries > 1) + this_shn->vars.seek_resolution = shn_uchar_to_ulong_le(this_shn->seek_table->data+SEEK_ENTRY_SIZE); + else + this_shn->vars.seek_resolution = SEEK_RESOLUTION; + + return 1; + } + } + } + } + } + + return 0; +} + +int load_separate_seek_table_samedir(shn_file *this_shn,char *filename) +{ + char *altfilename,*basefile,*basedir; + + if (!(basefile = shn_get_base_filename(filename))) + { + return 0; + } + + if (!(basedir = shn_get_base_directory(filename))) + { + free(basefile); + return 0; + } + + if (!(altfilename = malloc(strlen(basedir)+strlen(basefile)+sizeof(SEEK_SUFFIX)+3))) + { + shn_debug("Could not allocate memory for same dir filename"); + free(basefile); + free(basedir); + return 0; + } + + sprintf(altfilename,"%s/%s.%s",basedir,basefile,SEEK_SUFFIX); + + free(basefile); + free(basedir); + + if (load_separate_seek_table_generic(altfilename,this_shn)) + { + free(altfilename); + return 1; + } + + free(altfilename); + return 0; +} + +int load_separate_seek_table_relative(shn_file *this_shn,char *filename) +{ + char *altfilename,*basefile,*basedir; + + if (0 == strcmp(shn_cfg.relative_seek_tables_path,"")) + return 0; + + if (!(basefile = shn_get_base_filename(filename))) + { + return 0; + } + + if (!(basedir = shn_get_base_directory(filename))) + { + free(basefile); + return 0; + } + + if (!(altfilename = malloc(strlen(basedir)+strlen(shn_cfg.relative_seek_tables_path)+strlen(basefile)+sizeof(SEEK_SUFFIX)+4))) + { + shn_debug("Could not allocate memory for absolute filename"); + free(basefile); + free(basedir); + return 0; + } + + sprintf(altfilename,"%s/%s/%s.%s",basedir,shn_cfg.relative_seek_tables_path,basefile,SEEK_SUFFIX); + + free(basefile); + free(basedir); + + if (load_separate_seek_table_generic(altfilename,this_shn)) + { + free(altfilename); + return 1; + } + + free(altfilename); + return 0; +} + +int load_separate_seek_table_absolute(shn_file *this_shn,char *filename) +{ + char *altfilename,*basefile; + + if (!(basefile = shn_get_base_filename(filename))) + { + return 0; + } + + if (!(altfilename = malloc(strlen(shn_cfg.seek_tables_path)+strlen(basefile)+sizeof(SEEK_SUFFIX)+3))) + { + shn_debug("Could not allocate memory for same dir filename"); + free(basefile); + return 0; + } + + sprintf(altfilename,"%s/%s.%s",shn_cfg.seek_tables_path,basefile,SEEK_SUFFIX); + + free(basefile); + + if (load_separate_seek_table_generic(altfilename,this_shn)) + { + free(altfilename); + return 1; + } + + free(altfilename); + return 0; +} + +void shn_load_seek_table(shn_file *this_shn,char *filename) +{ + if (load_appended_seek_table(this_shn,filename,0)) + return; + + if (load_appended_seek_table(this_shn,filename,ID3V1_TAG_SIZE)) + return; + + if (load_separate_seek_table_samedir(this_shn,filename)) + return; + + if (load_separate_seek_table_relative(this_shn,filename)) + return; + + if (load_separate_seek_table_absolute(this_shn,filename)) + return; + + shn_debug("Could not find any seek tables"); +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/shn.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/shn.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,1379 @@ +/* shn.c - main functions for xmms-shn + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: shn.c,v 1.38 2007/03/23 05:49:48 jason Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include "shorten.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +static void shn_about(void); +static void shn_configure(void); +static void shn_init(void); +static int shn_is_our_fd(char *, VFSFile *fd); +static void shn_play(InputPlayback *); +static void shn_stop(InputPlayback *); +static void shn_seek(InputPlayback *, int); +static void shn_pause(InputPlayback *, short); +static void shn_get_file_info(char *,char **,int *); +static void shn_display_file_info(char *); + +gchar *shn_fmts[] = { "shn", NULL }; + +InputPlugin shn_ip = +{ + NULL, + NULL, + "SHN Player " VERSION, + shn_init, + shn_about, + shn_configure, + NULL, + NULL, + shn_play, + shn_stop, + shn_pause, + shn_seek, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + shn_get_file_info, + shn_display_file_info, + NULL, + NULL, + NULL, + NULL, + shn_is_our_fd, + shn_fmts, +}; + +InputPlugin *shn_iplist[] = { &shn_ip, NULL }; + +DECLARE_PLUGIN(shnplug, NULL, NULL, shn_iplist, NULL, NULL, NULL, NULL); + +shn_file *shnfile; +shn_config shn_cfg; + +static pthread_t decode_thread; +static gboolean audio_error = FALSE; + +static void shn_init() +{ + ConfigDb *cfg; + + shn_cfg.error_output_method = ERROR_OUTPUT_DEVNULL; + shn_cfg.error_output_method_config_name = "error_output_method"; + shn_cfg.seek_tables_path = NULL; + shn_cfg.seek_tables_path_config_name = "seek_tables_path"; + shn_cfg.relative_seek_tables_path = NULL; + shn_cfg.relative_seek_tables_path_config_name = "relative_seek_tables_path"; + shn_cfg.verbose = 0; + shn_cfg.verbose_config_name = "verbose"; + shn_cfg.swap_bytes = 0; + shn_cfg.swap_bytes_config_name = "swap_bytes"; + shn_cfg.load_textfiles = FALSE; + shn_cfg.load_textfiles_config_name = "load_textfiles"; + shn_cfg.textfile_extensions = NULL; + shn_cfg.textfile_extensions_config_name = "textfile_extensions"; + + if ((cfg = bmp_cfg_db_open()) != 0) + { + bmp_cfg_db_get_int(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.error_output_method_config_name, &shn_cfg.error_output_method); + bmp_cfg_db_get_bool(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.verbose_config_name, &shn_cfg.verbose); + if (!bmp_cfg_db_get_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.seek_tables_path_config_name, &shn_cfg.seek_tables_path)) + shn_cfg.seek_tables_path = g_strdup(g_get_home_dir()); + if (!bmp_cfg_db_get_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.relative_seek_tables_path_config_name, &shn_cfg.relative_seek_tables_path)) + shn_cfg.relative_seek_tables_path = g_strdup(""); + bmp_cfg_db_get_bool(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.swap_bytes_config_name, &shn_cfg.swap_bytes); + bmp_cfg_db_get_bool(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.load_textfiles_config_name, &shn_cfg.load_textfiles); + if (!bmp_cfg_db_get_string(cfg, XMMS_SHN_VERSION_TAG, shn_cfg.textfile_extensions_config_name, &shn_cfg.textfile_extensions)) + shn_cfg.textfile_extensions = g_strdup("txt,nfo"); + bmp_cfg_db_close(cfg); + } +} + +static void shn_about() +{ + shn_display_about(); +} + +static void shn_configure() +{ + shn_display_configure(); +} + +int init_decode_state(shn_file *this_shn) +{ + if (this_shn->decode_state) + { + if (this_shn->decode_state->getbuf) + { + free(this_shn->decode_state->getbuf); + this_shn->decode_state->getbuf = NULL; + } + + if (this_shn->decode_state->writebuf) + { + free(this_shn->decode_state->writebuf); + this_shn->decode_state->writebuf = NULL; + } + + if (this_shn->decode_state->writefub) + { + free(this_shn->decode_state->writefub); + this_shn->decode_state->writefub = NULL; + } + + free(this_shn->decode_state); + this_shn->decode_state = NULL; + } + + if (!(this_shn->decode_state = malloc(sizeof(shn_decode_state)))) + { + shn_debug("Could not allocate memory for decode state data structure"); + return 0; + } + + this_shn->decode_state->getbuf = NULL; + this_shn->decode_state->getbufp = NULL; + this_shn->decode_state->nbitget = 0; + this_shn->decode_state->nbyteget = 0; + this_shn->decode_state->gbuffer = 0; + this_shn->decode_state->writebuf = NULL; + this_shn->decode_state->writefub = NULL; + this_shn->decode_state->nwritebuf = 0; + + this_shn->vars.bytes_in_buf = 0; + + return 1; +} + +int get_wave_header(shn_file *this_shn) +{ + slong **buffer = NULL, **offset = NULL; + slong lpcqoffset = 0; + int version = FORMAT_VERSION, bitshift = 0; + int ftype = TYPE_EOF; + char *magic = MAGIC; + int blocksize = DEFAULT_BLOCK_SIZE, nchan = DEFAULT_NCHAN; + int i, chan, nwrap, nskip = DEFAULT_NSKIP; + int *qlpc = NULL, maxnlpc = DEFAULT_MAXNLPC, nmean = UNDEFINED_UINT; + int cmd; + int internal_ftype; + int cklen; + int retval = 0; + + if (!init_decode_state(this_shn)) + return 0; + + /***********************/ + /* EXTRACT starts here */ + /***********************/ + + /* read magic number */ +#ifdef STRICT_FORMAT_COMPATABILITY + if(FORMAT_VERSION < 2) + { + for(i = 0; i < strlen(magic); i++) { + if(getc_exit(this_shn->vars.fd) != magic[i]) + return 0; + this_shn->vars.bytes_read++; + } + + /* get version number */ + version = getc_exit(this_shn->vars.fd); + this_shn->vars.bytes_read++; + } + else +#endif /* STRICT_FORMAT_COMPATABILITY */ + { + int nscan = 0; + + version = MAX_VERSION + 1; + while(version > MAX_VERSION) + { + int byte = vfs_getc(this_shn->vars.fd); + this_shn->vars.bytes_read++; + if(byte == EOF) + return 0; + if(magic[nscan] != '\0' && byte == magic[nscan]) + nscan++; + else + if(magic[nscan] == '\0' && byte <= MAX_VERSION) + version = byte; + else + { + if(byte == magic[0]) + nscan = 1; + else + { + nscan = 0; + } + version = MAX_VERSION + 1; + } + } + } + + /* check version number */ + if(version > MAX_SUPPORTED_VERSION) + return 0; + + /* set up the default nmean, ignoring the command line state */ + nmean = (version < 2) ? DEFAULT_V0NMEAN : DEFAULT_V2NMEAN; + + /* initialise the variable length file read for the compressed stream */ + var_get_init(this_shn); + if (this_shn->vars.fatal_error) + return 0; + + /* initialise the fixed length file write for the uncompressed stream */ + fwrite_type_init(this_shn); + + /* get the internal file type */ + internal_ftype = UINT_GET(TYPESIZE, this_shn); + + /* has the user requested a change in file type? */ + if(internal_ftype != ftype) { + if(ftype == TYPE_EOF) { + ftype = internal_ftype; /* no problems here */ + } + else { /* check that the requested conversion is valid */ + if(internal_ftype == TYPE_AU1 || internal_ftype == TYPE_AU2 || + internal_ftype == TYPE_AU3 || ftype == TYPE_AU1 ||ftype == TYPE_AU2 || ftype == TYPE_AU3) + { + retval = 0; + goto got_enough_data; + } + } + } + + nchan = UINT_GET(CHANSIZE, this_shn); + this_shn->vars.actual_nchan = nchan; + + /* get blocksize if version > 0 */ + if(version > 0) + { + int byte; + blocksize = UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),this_shn); + maxnlpc = UINT_GET(LPCQSIZE, this_shn); + this_shn->vars.actual_maxnlpc = maxnlpc; + nmean = UINT_GET(0, this_shn); + this_shn->vars.actual_nmean = nmean; + nskip = UINT_GET(NSKIPSIZE, this_shn); + for(i = 0; i < nskip; i++) + { + byte = uvar_get(XBYTESIZE,this_shn); + } + } + else + blocksize = DEFAULT_BLOCK_SIZE; + + nwrap = MAX(NWRAP, maxnlpc); + + /* grab some space for the input buffer */ + buffer = long2d((ulong) nchan, (ulong) (blocksize + nwrap),this_shn); + if (this_shn->vars.fatal_error) + return 0; + offset = long2d((ulong) nchan, (ulong) MAX(1, nmean),this_shn); + if (this_shn->vars.fatal_error) { + if (buffer) { + free(buffer); + buffer = NULL; + } + return 0; + } + + for(chan = 0; chan < nchan; chan++) + { + for(i = 0; i < nwrap; i++) + buffer[chan][i] = 0; + buffer[chan] += nwrap; + } + + if(maxnlpc > 0) { + qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc)),this_shn); + if (this_shn->vars.fatal_error) { + if (buffer) { + free(buffer); + buffer = NULL; + } + if (offset) { + free(offset); + buffer = NULL; + } + return 0; + } + } + + if(version > 1) + lpcqoffset = V2LPCQOFFSET; + + init_offset(offset, nchan, MAX(1, nmean), internal_ftype); + + /* get commands from file and execute them */ + chan = 0; + while(1) + { + this_shn->vars.reading_function_code = 1; + cmd = uvar_get(FNSIZE,this_shn); + this_shn->vars.reading_function_code = 0; + + switch(cmd) + { + case FN_ZERO: + case FN_DIFF0: + case FN_DIFF1: + case FN_DIFF2: + case FN_DIFF3: + case FN_QLPC: + { + slong coffset, *cbuffer = buffer[chan]; + int resn = 0, nlpc, j; + + if(cmd != FN_ZERO) + { + resn = uvar_get(ENERGYSIZE,this_shn); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + /* this is a hack as version 0 differed in definition of var_get */ + if(version == 0) + resn--; + } + + /* find mean offset : N.B. this code duplicated */ + if(nmean == 0) + coffset = offset[chan][0]; + else + { + slong sum = (version < 2) ? 0 : nmean / 2; + for(i = 0; i < nmean; i++) + sum += offset[chan][i]; + if(version < 2) + coffset = sum / nmean; + else + coffset = ROUNDEDSHIFTDOWN(sum / nmean, bitshift); + } + + switch(cmd) + { + case FN_ZERO: + for(i = 0; i < blocksize; i++) + cbuffer[i] = 0; + break; + case FN_DIFF0: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + coffset; + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_DIFF1: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + cbuffer[i - 1]; + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_DIFF2: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + (2 * cbuffer[i - 1] - cbuffer[i - 2]); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_DIFF3: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + 3 * (cbuffer[i - 1] - cbuffer[i - 2]) + cbuffer[i - 3]; + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + break; + case FN_QLPC: + nlpc = uvar_get(LPCQSIZE,this_shn); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + + for(i = 0; i < nlpc; i++) { + qlpc[i] = var_get(LPCQUANT,this_shn); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + for(i = 0; i < nlpc; i++) + cbuffer[i - nlpc] -= coffset; + for(i = 0; i < blocksize; i++) + { + slong sum = lpcqoffset; + + for(j = 0; j < nlpc; j++) + sum += qlpc[j] * cbuffer[i - j - 1]; + cbuffer[i] = var_get(resn,this_shn) + (sum >> LPCQUANT); + if (this_shn->vars.fatal_error) { + retval = 0; + goto got_enough_data; + } + } + if(coffset != 0) + for(i = 0; i < blocksize; i++) + cbuffer[i] += coffset; + break; + } + + /* store mean value if appropriate : N.B. Duplicated code */ + if(nmean > 0) + { + slong sum = (version < 2) ? 0 : blocksize / 2; + + for(i = 0; i < blocksize; i++) + sum += cbuffer[i]; + + for(i = 1; i < nmean; i++) + offset[chan][i - 1] = offset[chan][i]; + if(version < 2) + offset[chan][nmean - 1] = sum / blocksize; + else + offset[chan][nmean - 1] = (sum / blocksize) << bitshift; + } + + if (0 == chan) { + this_shn->vars.initial_file_position = this_shn->vars.last_file_position_no_really; + goto got_enough_data; + } + + /* do the wrap */ + for(i = -nwrap; i < 0; i++) + cbuffer[i] = cbuffer[i + blocksize]; + + fix_bitshift(cbuffer, blocksize, bitshift, internal_ftype); + + if(chan == nchan - 1) + { + fwrite_type(buffer, ftype, nchan, blocksize, this_shn); + this_shn->vars.bytes_in_buf = 0; + } + + chan = (chan + 1) % nchan; + break; + } + break; + + case FN_BLOCKSIZE: + UINT_GET((int) (log((double) blocksize) / M_LN2), this_shn); + break; + + case FN_VERBATIM: + cklen = uvar_get(VERBATIM_CKSIZE_SIZE,this_shn); + + while (cklen--) { + if (this_shn->vars.bytes_in_header >= OUT_BUFFER_SIZE) { + shn_debug("Unexpectedly large header - " PACKAGE " can only handle a maximum of %d bytes",OUT_BUFFER_SIZE); + goto got_enough_data; + } + this_shn->vars.bytes_in_buf = 0; + this_shn->vars.header[this_shn->vars.bytes_in_header++] = (char)uvar_get(VERBATIM_BYTE_SIZE,this_shn); + } + retval = 1; + break; + + case FN_BITSHIFT: + bitshift = uvar_get(BITSHIFTSIZE,this_shn); + this_shn->vars.actual_bitshift = bitshift; + break; + + default: + goto got_enough_data; + } + } + +got_enough_data: + + /* wind up */ + var_get_quit(this_shn); + fwrite_type_quit(this_shn); + + if (buffer) free((void *) buffer); + if (offset) free((void *) offset); + if(maxnlpc > 0 && qlpc) + free((void *) qlpc); + + this_shn->vars.bytes_in_buf = 0; + + return retval; +} + +void shn_unload(shn_file *this_shn) +{ + int this_shn_is_shnfile = (this_shn == shnfile) ? 1 : 0; + + if (this_shn) + { + if (this_shn->vars.fd) + { + vfs_fclose(this_shn->vars.fd); + this_shn->vars.fd = NULL; + } + + if (this_shn->decode_state) + { + if (this_shn->decode_state->getbuf) + { + free(this_shn->decode_state->getbuf); + this_shn->decode_state->getbuf = NULL; + } + + if (this_shn->decode_state->writebuf) + { + free(this_shn->decode_state->writebuf); + this_shn->decode_state->writebuf = NULL; + } + + if (this_shn->decode_state->writefub) + { + free(this_shn->decode_state->writefub); + this_shn->decode_state->writefub = NULL; + } + + free(this_shn->decode_state); + this_shn->decode_state = NULL; + } + + if (this_shn->seek_table) + { + free(this_shn->seek_table); + this_shn->seek_table = NULL; + } + + free(this_shn); + this_shn = NULL; + if (this_shn_is_shnfile) + shnfile = NULL; + } +} + +shn_file *load_shn(InputPlayback *playback, char *filename, VFSFile *fd) +{ + shn_file *tmp_file; + shn_seek_entry *first_seek_table; + + shn_debug("Loading file: '%s'", filename); + + if (!(tmp_file = malloc(sizeof(shn_file)))) + { + shn_debug("Could not allocate memory for SHN data structure"); + return NULL; + } + + memset(tmp_file, 0, sizeof(shn_file)); + + tmp_file->vars.fd = NULL; + tmp_file->vars.seek_to = -1; + tmp_file->vars.eof = 0; + tmp_file->vars.going = 0; + tmp_file->vars.playback = playback; + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + tmp_file->vars.bytes_in_buf = 0; + tmp_file->vars.bytes_in_header = 0; + tmp_file->vars.reading_function_code = 0; + tmp_file->vars.initial_file_position = 0; + tmp_file->vars.last_file_position = 0; + tmp_file->vars.last_file_position_no_really = 0; + tmp_file->vars.bytes_read = 0; + tmp_file->vars.actual_bitshift = 0; + tmp_file->vars.actual_maxnlpc = 0; + tmp_file->vars.actual_nmean = 0; + tmp_file->vars.actual_nchan = 0; + tmp_file->vars.seek_offset = 0; + + tmp_file->decode_state = NULL; + + tmp_file->wave_header.filename = filename; + tmp_file->wave_header.wave_format = 0; + tmp_file->wave_header.channels = 0; + tmp_file->wave_header.block_align = 0; + tmp_file->wave_header.bits_per_sample = 0; + tmp_file->wave_header.samples_per_sec = 0; + tmp_file->wave_header.avg_bytes_per_sec = 0; + tmp_file->wave_header.rate = 0; + tmp_file->wave_header.header_size = 0; + tmp_file->wave_header.data_size = 0; + tmp_file->wave_header.file_has_id3v2_tag = 0; + tmp_file->wave_header.id3v2_tag_size = 0; + + tmp_file->seek_header.version = NO_SEEK_TABLE; + tmp_file->seek_header.shnFileSize = 0; + + tmp_file->seek_trailer.seekTableSize = 0; + + tmp_file->seek_table = NULL; + + if (!fd) + { + if (!(tmp_file->vars.fd = shn_open_and_discard_id3v2_tag(filename,&tmp_file->wave_header.file_has_id3v2_tag,&tmp_file->wave_header.id3v2_tag_size))) + { + shn_debug("Could not open file: '%s'",filename); + shn_unload(tmp_file); + return NULL; + } + } + else + tmp_file->vars.fd = fd; + + if (0 == get_wave_header(tmp_file)) + { + shn_debug("Unable to read WAVE header from file '%s'",filename); + shn_unload(tmp_file); + return NULL; + } + + if (tmp_file->wave_header.file_has_id3v2_tag) + { + vfs_fseek(tmp_file->vars.fd,tmp_file->wave_header.id3v2_tag_size,SEEK_SET); + tmp_file->vars.bytes_read += tmp_file->wave_header.id3v2_tag_size; + tmp_file->vars.seek_offset = tmp_file->wave_header.id3v2_tag_size; + } + else + { + vfs_fseek(tmp_file->vars.fd,0,SEEK_SET); + } + + if (0 == shn_verify_header(tmp_file)) + { + shn_debug("Invalid WAVE header in file: '%s'",filename); + shn_unload(tmp_file); + return NULL; + } + + if (tmp_file->decode_state) + { + free(tmp_file->decode_state); + tmp_file->decode_state = NULL; + } + + shn_load_seek_table(tmp_file,filename); + + if (NO_SEEK_TABLE != tmp_file->vars.seek_table_entries) + { + /* verify seek tables */ + + first_seek_table = (shn_seek_entry *)tmp_file->seek_table; + + if (tmp_file->vars.actual_bitshift != shn_uchar_to_ushort_le(first_seek_table->data+22)) + { + /* initial bitshift value in the file does not match the first bitshift value of the first seektable entry - seeking is broken */ + shn_debug("Broken seek table detected (invalid bitshift) - seeking disabled for this file."); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else if (tmp_file->vars.actual_nchan > 2) + { + /* nchan is greater than the number of such entries stored in a seek table entry - seeking won't work */ + shn_debug("Broken seek table detected (nchan %d not in range [1 .. 2]) - seeking disabled for this file.",tmp_file->vars.actual_nchan); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else if (tmp_file->vars.actual_maxnlpc > 3) + { + /* maxnlpc is greater than the number of such entries stored in a seek table entry - seeking won't work */ + shn_debug("Broken seek table detected (maxnlpc %d not in range [0 .. 3]) - seeking disabled for this file.",tmp_file->vars.actual_maxnlpc); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else if (tmp_file->vars.actual_nmean > 4) + { + /* nmean is greater than the number of such entries stored in a seek table entry - seeking won't work */ + shn_debug("Broken seek table detected (nmean %d not in range [0 .. 4]) - seeking disabled for this file.",tmp_file->vars.actual_nmean); + tmp_file->vars.seek_table_entries = NO_SEEK_TABLE; + } + else + { + /* seek table appears to be valid - now adjust byte offsets in seek table to match the file */ + tmp_file->vars.seek_offset += tmp_file->vars.initial_file_position - shn_uchar_to_ulong_le(first_seek_table->data+8); + + if (0 != tmp_file->vars.seek_offset) + { + shn_debug("Adjusting seek table offsets by %ld bytes due to mismatch between seek table values and input file - seeking might not work correctly.", + tmp_file->vars.seek_offset); + } + } + } + + shn_debug("Successfully loaded file: '%s'",filename); + + return tmp_file; +} + +static int shn_is_our_fd(char *fn, VFSFile *fd) +{ + char data[4]; + + if (vfs_fread((void *)data,1,4,fd) != 4) + return FALSE; + + if (memcmp(data,MAGIC,4)) + return FALSE; + +#if 0 + if (!(tmp_file = load_shn(NULL, filename, fd))) + return FALSE; + + shn_unload(tmp_file); +#endif + + return TRUE; +} + +void swap_bytes(shn_file *this_shn,int bytes) +{ + int i; + uchar tmp; + + for (i=0;ivars.buffer[i+1]; + this_shn->vars.buffer[i+1] = this_shn->vars.buffer[i]; + this_shn->vars.buffer[i] = tmp; + } +} + +void write_and_wait(shn_file *this_shn,int block_size) +{ + int bytes_to_write,bytes_in_block,i; + InputPlayback *playback = this_shn->vars.playback; + + if (this_shn->vars.bytes_in_buf < block_size) + return; + + bytes_in_block = min(this_shn->vars.bytes_in_buf, block_size); + + if (bytes_in_block <= 0) + return; + + bytes_to_write = bytes_in_block; + while ((bytes_to_write + bytes_in_block) <= this_shn->vars.bytes_in_buf) + bytes_to_write += bytes_in_block; + + shn_ip.add_vis_pcm(shn_ip.output->written_time(), (this_shn->wave_header.bits_per_sample == 16) ? FMT_S16_LE : FMT_U8, + this_shn->wave_header.channels, bytes_to_write, this_shn->vars.buffer); + + while(shn_ip.output->buffer_free() < bytes_to_write && playback->playing && this_shn->vars.seek_to == -1) + xmms_usleep(10000); + + if(playback->playing && this_shn->vars.seek_to == -1) { + if (shn_cfg.swap_bytes) + swap_bytes(this_shn, bytes_to_write); + shn_ip.output->write_audio(this_shn->vars.buffer, bytes_to_write); + } else + return; + + /* shift data from end of buffer to the front */ + this_shn->vars.bytes_in_buf -= bytes_to_write; + + for(i=0;ivars.bytes_in_buf;i++) + this_shn->vars.buffer[i] = this_shn->vars.buffer[i+bytes_to_write]; +} + +static void *play_loop_shn(void *arg) +{ + slong **buffer = NULL, **offset = NULL; + slong lpcqoffset = 0; + int version = FORMAT_VERSION, bitshift = 0; + int ftype = TYPE_EOF; + char *magic = MAGIC; + int blocksize = DEFAULT_BLOCK_SIZE, nchan = DEFAULT_NCHAN; + int i, chan, nwrap, nskip = DEFAULT_NSKIP; + int *qlpc = NULL, maxnlpc = DEFAULT_MAXNLPC, nmean = UNDEFINED_UINT; + int cmd; + int internal_ftype; + shn_file *this_shn = shnfile; + int blk_size; + int cklen; + uchar tmp; + ulong seekto_offset; + InputPlayback *playback = this_shn->vars.playback; + +restart: + + this_shn->vars.bytes_in_buf = 0; + + if (!init_decode_state(this_shn)) + goto exit_thread; + + blk_size = 512 * (this_shn->wave_header.bits_per_sample / 8) * this_shn->wave_header.channels; + + /***********************/ + /* EXTRACT starts here */ + /***********************/ + + /* read magic number */ +#ifdef STRICT_FORMAT_COMPATABILITY + if(FORMAT_VERSION < 2) + { + for(i = 0; i < strlen(magic); i++) + if(getc_exit(this_shn->vars.fd) != magic[i]) { + shn_error_fatal(this_shn,"Bad magic number"); + goto exit_thread; + } + + /* get version number */ + version = getc_exit(this_shn->vars.fd); + } + else +#endif /* STRICT_FORMAT_COMPATABILITY */ + { + int nscan = 0; + + version = MAX_VERSION + 1; + while(version > MAX_VERSION) + { + int byte = vfs_getc(this_shn->vars.fd); + if(byte == EOF) { + shn_error_fatal(this_shn,"No magic number"); + goto exit_thread; + } + if(magic[nscan] != '\0' && byte == magic[nscan]) + nscan++; + else + if(magic[nscan] == '\0' && byte <= MAX_VERSION) + version = byte; + else + { + if(byte == magic[0]) + nscan = 1; + else + { + nscan = 0; + } + version = MAX_VERSION + 1; + } + } + } + + /* check version number */ + if(version > MAX_SUPPORTED_VERSION) { + shn_error_fatal(this_shn,"Can't decode version %d", version); + goto exit_thread; + } + + /* set up the default nmean, ignoring the command line state */ + nmean = (version < 2) ? DEFAULT_V0NMEAN : DEFAULT_V2NMEAN; + + /* initialise the variable length file read for the compressed stream */ + var_get_init(this_shn); + if (this_shn->vars.fatal_error) + goto exit_thread; + + /* initialise the fixed length file write for the uncompressed stream */ + fwrite_type_init(this_shn); + + /* get the internal file type */ + internal_ftype = UINT_GET(TYPESIZE, this_shn); + + /* has the user requested a change in file type? */ + if(internal_ftype != ftype) { + if(ftype == TYPE_EOF) + ftype = internal_ftype; /* no problems here */ + else /* check that the requested conversion is valid */ + if(internal_ftype == TYPE_AU1 || internal_ftype == TYPE_AU2 || + internal_ftype == TYPE_AU3 || ftype == TYPE_AU1 ||ftype == TYPE_AU2 || ftype == TYPE_AU3) { + shn_error_fatal(this_shn,"Not able to perform requested output format conversion"); + goto cleanup; + } + } + + nchan = UINT_GET(CHANSIZE, this_shn); + + /* get blocksize if version > 0 */ + if(version > 0) + { + int byte; + blocksize = UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),this_shn); + maxnlpc = UINT_GET(LPCQSIZE, this_shn); + nmean = UINT_GET(0, this_shn); + nskip = UINT_GET(NSKIPSIZE, this_shn); + for(i = 0; i < nskip; i++) + { + byte = uvar_get(XBYTESIZE,this_shn); + } + } + else + blocksize = DEFAULT_BLOCK_SIZE; + + nwrap = MAX(NWRAP, maxnlpc); + + /* grab some space for the input buffer */ + buffer = long2d((ulong) nchan, (ulong) (blocksize + nwrap),this_shn); + if (this_shn->vars.fatal_error) + goto exit_thread; + offset = long2d((ulong) nchan, (ulong) MAX(1, nmean),this_shn); + if (this_shn->vars.fatal_error) { + if (buffer) { + free(buffer); + buffer = NULL; + } + goto exit_thread; + } + + for(chan = 0; chan < nchan; chan++) + { + for(i = 0; i < nwrap; i++) + buffer[chan][i] = 0; + buffer[chan] += nwrap; + } + + if(maxnlpc > 0) { + qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc)),this_shn); + if (this_shn->vars.fatal_error) { + if (buffer) { + free(buffer); + buffer = NULL; + } + if (offset) { + free(offset); + buffer = NULL; + } + goto exit_thread; + } + } + + if(version > 1) + lpcqoffset = V2LPCQOFFSET; + + init_offset(offset, nchan, MAX(1, nmean), internal_ftype); + + /* get commands from file and execute them */ + chan = 0; + while(1) + { + cmd = uvar_get(FNSIZE,this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + + switch(cmd) + { + case FN_ZERO: + case FN_DIFF0: + case FN_DIFF1: + case FN_DIFF2: + case FN_DIFF3: + case FN_QLPC: + { + slong coffset, *cbuffer = buffer[chan]; + int resn = 0, nlpc, j; + + if(cmd != FN_ZERO) + { + resn = uvar_get(ENERGYSIZE,this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + /* this is a hack as version 0 differed in definition of var_get */ + if(version == 0) + resn--; + } + + /* find mean offset : N.B. this code duplicated */ + if(nmean == 0) + coffset = offset[chan][0]; + else + { + slong sum = (version < 2) ? 0 : nmean / 2; + for(i = 0; i < nmean; i++) + sum += offset[chan][i]; + if(version < 2) + coffset = sum / nmean; + else + coffset = ROUNDEDSHIFTDOWN(sum / nmean, bitshift); + } + + switch(cmd) + { + case FN_ZERO: + for(i = 0; i < blocksize; i++) + cbuffer[i] = 0; + break; + case FN_DIFF0: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + coffset; + if (this_shn->vars.fatal_error) + goto cleanup; + } + break; + case FN_DIFF1: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + cbuffer[i - 1]; + if (this_shn->vars.fatal_error) + goto cleanup; + } + break; + case FN_DIFF2: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + (2 * cbuffer[i - 1] - cbuffer[i - 2]); + if (this_shn->vars.fatal_error) + goto cleanup; + } + break; + case FN_DIFF3: + for(i = 0; i < blocksize; i++) { + cbuffer[i] = var_get(resn,this_shn) + 3 * (cbuffer[i - 1] - cbuffer[i - 2]) + cbuffer[i - 3]; + if (this_shn->vars.fatal_error) + goto cleanup; + } + break; + case FN_QLPC: + nlpc = uvar_get(LPCQSIZE,this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + + for(i = 0; i < nlpc; i++) { + qlpc[i] = var_get(LPCQUANT,this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + } + for(i = 0; i < nlpc; i++) + cbuffer[i - nlpc] -= coffset; + for(i = 0; i < blocksize; i++) + { + slong sum = lpcqoffset; + + for(j = 0; j < nlpc; j++) + sum += qlpc[j] * cbuffer[i - j - 1]; + cbuffer[i] = var_get(resn,this_shn) + (sum >> LPCQUANT); + if (this_shn->vars.fatal_error) + goto cleanup; + } + if(coffset != 0) + for(i = 0; i < blocksize; i++) + cbuffer[i] += coffset; + break; + } + + /* store mean value if appropriate : N.B. Duplicated code */ + if(nmean > 0) + { + slong sum = (version < 2) ? 0 : blocksize / 2; + + for(i = 0; i < blocksize; i++) + sum += cbuffer[i]; + + for(i = 1; i < nmean; i++) + offset[chan][i - 1] = offset[chan][i]; + if(version < 2) + offset[chan][nmean - 1] = sum / blocksize; + else + offset[chan][nmean - 1] = (sum / blocksize) << bitshift; + } + + /* do the wrap */ + for(i = -nwrap; i < 0; i++) + cbuffer[i] = cbuffer[i + blocksize]; + + fix_bitshift(cbuffer, blocksize, bitshift, internal_ftype); + + if(chan == nchan - 1) + { + if (!playback->playing || this_shn->vars.fatal_error) + goto cleanup; + + fwrite_type(buffer, ftype, nchan, blocksize, this_shn); + + write_and_wait(this_shn,blk_size); + + if (this_shn->vars.seek_to != -1) + { + shn_seek_entry *seek_info; + int j; + + shn_debug("Seeking to %d:%02d",this_shn->vars.seek_to/60,this_shn->vars.seek_to%60); + + seek_info = shn_seek_entry_search(this_shn->seek_table,this_shn->vars.seek_to * (ulong)this_shn->wave_header.samples_per_sec,0, + (ulong)(this_shn->vars.seek_table_entries - 1),this_shn->vars.seek_resolution); + + /* loop through number of channels in this file */ + for (i=0;idata+32+12*i-4*j); + + /* load the variable number of offset history values for this channel */ + for (j=0;jdata+48+16*i+4*j); + } + + bitshift = shn_uchar_to_ushort_le(seek_info->data+22); + + seekto_offset = shn_uchar_to_ulong_le(seek_info->data+8) + this_shn->vars.seek_offset; + + vfs_fseek(this_shn->vars.fd,(slong)seekto_offset,SEEK_SET); + vfs_fread((uchar*) this_shn->decode_state->getbuf, 1, BUFSIZ, this_shn->vars.fd); + + this_shn->decode_state->getbufp = this_shn->decode_state->getbuf + shn_uchar_to_ushort_le(seek_info->data+14); + this_shn->decode_state->nbitget = shn_uchar_to_ushort_le(seek_info->data+16); + this_shn->decode_state->nbyteget = shn_uchar_to_ushort_le(seek_info->data+12); + this_shn->decode_state->gbuffer = shn_uchar_to_ulong_le(seek_info->data+18); + + this_shn->vars.bytes_in_buf = 0; + + shn_ip.output->flush(this_shn->vars.seek_to * 1000); + this_shn->vars.seek_to = -1; + } + + } + chan = (chan + 1) % nchan; + break; + } + + break; + + case FN_QUIT: + /* empty out last of buffer */ + write_and_wait(this_shn,this_shn->vars.bytes_in_buf); + + playback->eof = TRUE; + + while (1) + { + if (!playback->playing) + goto finish; + if (this_shn->vars.seek_to != -1) + { + var_get_quit(this_shn); + fwrite_type_quit(this_shn); + + if (buffer) free((void *) buffer); + if (offset) free((void *) offset); + if(maxnlpc > 0 && qlpc) + free((void *) qlpc); + + vfs_fseek(this_shn->vars.fd,0,SEEK_SET); + goto restart; + } + else + xmms_usleep(10000); + } + + goto cleanup; + break; + + case FN_BLOCKSIZE: + blocksize = UINT_GET((int) (log((double) blocksize) / M_LN2), this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + break; + case FN_BITSHIFT: + bitshift = uvar_get(BITSHIFTSIZE,this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + break; + case FN_VERBATIM: + cklen = uvar_get(VERBATIM_CKSIZE_SIZE,this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + + while (cklen--) { + tmp = (uchar)uvar_get(VERBATIM_BYTE_SIZE,this_shn); + if (this_shn->vars.fatal_error) + goto cleanup; + } + + break; + + default: + shn_error_fatal(this_shn,"Sanity check fails trying to decode function: %d",cmd); + goto cleanup; + } + } + +cleanup: + + write_and_wait(this_shn,this_shn->vars.bytes_in_buf); + shn_ip.output->buffer_free(); + shn_ip.output->buffer_free(); + xmms_usleep(10000); + +finish: + + this_shn->vars.seek_to = -1; + playback->eof = TRUE; + + /* wind up */ + var_get_quit(this_shn); + fwrite_type_quit(this_shn); + + if (buffer) free((void *) buffer); + if (offset) free((void *) offset); + if(maxnlpc > 0 && qlpc) + free((void *) qlpc); + +exit_thread: + + pthread_exit(NULL); +} + +static void shn_play(InputPlayback *playback) +{ + char *name, *temp; + char *filename = playback->filename; + + audio_error = FALSE; + + if (!(shnfile = load_shn(playback, playback->filename, NULL))) + { + shn_debug("Could not load file for playing: '%s'", playback->filename); + return; + } + + vfs_fseek(shnfile->vars.fd,0,SEEK_SET); + + playback->playing = TRUE; + + if (shn_ip.output->open_audio((shnfile->wave_header.bits_per_sample == 16) ? FMT_S16_LE : FMT_U8, shnfile->wave_header.samples_per_sec, shnfile->wave_header.channels) == 0) + { + audio_error = TRUE; + shn_debug("Could not open audio device for playback (check your output plugin configuration)"); + return; + } + temp = strrchr(filename, '/'); + if (!temp) + temp = filename; + else + temp++; + name = malloc(strlen(temp) + 1); + strcpy(name, temp); + if (shn_filename_contains_a_dot(name)) + *(strrchr(name,'.')) = '\0'; + shn_ip.set_info(name, 1000 * shnfile->wave_header.length, 8 * shnfile->wave_header.rate, shnfile->wave_header.samples_per_sec, shnfile->wave_header.channels); + free(name); + shnfile->vars.seek_to = -1; + pthread_create(&decode_thread, NULL, play_loop_shn, NULL); +} + +static void shn_stop(InputPlayback *playback) +{ + int was_fatal; + char error_msg[BUF_SIZE]; + + if (!shnfile) + return; + + if ((was_fatal = shnfile->vars.fatal_error)) + shn_snprintf(error_msg,BUF_SIZE,"%s.\nAffected file was:\n%s",shnfile->vars.fatal_error_msg,shnfile->wave_header.filename); + + if (playback->playing || was_fatal) + { + playback->playing = FALSE; + pthread_join(decode_thread, NULL); + shn_ip.output->close_audio(); + shn_unload(shnfile); + } + + if (was_fatal) + shn_error(error_msg); +} + +static void shn_pause(InputPlayback *playback, short p) +{ + playback->output->pause(p); +} + +static void shn_seek(InputPlayback *playback, int time) +{ + if (NULL == shnfile) + return; + + if (shnfile->vars.seek_table_entries == NO_SEEK_TABLE) + { + shn_error("Cannot seek to %d:%02d because there is no seek information for this file.",time/60,time%60); + return; + } + + shnfile->vars.seek_to = time; + + while (shnfile->vars.seek_to != -1) + xmms_usleep(10000); +} + +static void shn_get_file_info(char *filename, char **title, int *length) +{ + char *name, *temp; + shn_file *tmp_file; + + temp = strrchr(filename, '/'); + if (!temp) + temp = filename; + else + temp++; + + name = g_malloc(strlen(temp) + 1); + strcpy(name, temp); + + if (shn_filename_contains_a_dot(name)) + *(strrchr(name,'.')) = '\0'; + + *title = name; + + *length = 0; + + if (!(tmp_file = load_shn(NULL, filename, NULL))) + { + shn_debug("Could not get information from file: '%s'",filename); + return; + } + + *length = 1000 * tmp_file->wave_header.length; + + shn_unload(tmp_file); +} + +static void shn_display_file_info(char *filename) +{ + shn_file *tmp_file; + + if (!(tmp_file = load_shn(NULL, filename, NULL))) + { + shn_debug("Could not get information from file: '%s'",filename); + return; + } + + shn_display_info(tmp_file); + + shn_unload(tmp_file); +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/shn.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/shn.h Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,293 @@ +/* xmms-shn - a shorten (.shn) plugin for XMMS + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: shn.h,v 1.27 2007/03/23 05:49:48 jason Exp $ + */ + +#ifndef _SHN_H +#define _SHN_H + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define shn_vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) + +#define min(a,b) (((a)<(b))?(a):(b)) + +#define XMMS_SHN_VERSION_TAG "xmms-shn_v2" + +/* surely no headers will be this large. right? RIGHT? */ +#define OUT_BUFFER_SIZE 16384 + +#define BUF_SIZE 4096 + +#define ERROR_OUTPUT_DEVNULL 0 +#define ERROR_OUTPUT_STDERR 1 +#define ERROR_OUTPUT_WINDOW 2 + +#define SEEK_SUFFIX "skt" + +#define NO_SEEK_TABLE -1 + +#define SEEK_HEADER_SIGNATURE "SEEK" +#define SEEK_TRAILER_SIGNATURE "SHNAMPSK" + +#define SEEK_HEADER_SIZE 12 +#define SEEK_TRAILER_SIZE 12 +#define SEEK_ENTRY_SIZE 80 +#define SEEK_RESOLUTION 25600 + +#define WAVE_RIFF (0x46464952) /* 'RIFF' in little-endian */ +#define WAVE_WAVE (0x45564157) /* 'WAVE' in little-endian */ +#define WAVE_FMT (0x20746d66) /* ' fmt' in little-endian */ +#define WAVE_DATA (0x61746164) /* 'data' in little-endian */ + +#define AIFF_FORM (0x4D524F46) /* 'FORM' in little-endian */ + +#define WAVE_FORMAT_UNKNOWN (0x0000) +#define WAVE_FORMAT_PCM (0x0001) +#define WAVE_FORMAT_ADPCM (0x0002) +#define WAVE_FORMAT_IEEE_FLOAT (0x0003) +#define WAVE_FORMAT_ALAW (0x0006) +#define WAVE_FORMAT_MULAW (0x0007) +#define WAVE_FORMAT_OKI_ADPCM (0x0010) +#define WAVE_FORMAT_IMA_ADPCM (0x0011) +#define WAVE_FORMAT_DIGISTD (0x0015) +#define WAVE_FORMAT_DIGIFIX (0x0016) +#define WAVE_FORMAT_DOLBY_AC2 (0x0030) +#define WAVE_FORMAT_GSM610 (0x0031) +#define WAVE_FORMAT_ROCKWELL_ADPCM (0x003b) +#define WAVE_FORMAT_ROCKWELL_DIGITALK (0x003c) +#define WAVE_FORMAT_G721_ADPCM (0x0040) +#define WAVE_FORMAT_G728_CELP (0x0041) +#define WAVE_FORMAT_MPEG (0x0050) +#define WAVE_FORMAT_MPEGLAYER3 (0x0055) +#define WAVE_FORMAT_G726_ADPCM (0x0064) +#define WAVE_FORMAT_G722_ADPCM (0x0065) + +#define CD_BLOCK_SIZE (2352) +#define CD_BLOCKS_PER_SEC (75) +#define CD_MIN_BURNABLE_SIZE (705600) +#define CD_CHANNELS (2) +#define CD_SAMPLES_PER_SEC (44100) +#define CD_BITS_PER_SAMPLE (16) +#define CD_RATE (176400) + +#define CANONICAL_HEADER_SIZE (44) + +#define PROBLEM_NOT_CD_QUALITY (0x00000001) +#define PROBLEM_CD_BUT_BAD_BOUND (0x00000002) +#define PROBLEM_CD_BUT_TOO_SHORT (0x00000004) +#define PROBLEM_HEADER_NOT_CANONICAL (0x00000008) +#define PROBLEM_EXTRA_CHUNKS (0x00000010) +#define PROBLEM_HEADER_INCONSISTENT (0x00000020) + +#define PROB_NOT_CD(f) ((f.problems) & (PROBLEM_NOT_CD_QUALITY)) +#define PROB_BAD_BOUND(f) ((f.problems) & (PROBLEM_CD_BUT_BAD_BOUND)) +#define PROB_TOO_SHORT(f) ((f.problems) & (PROBLEM_CD_BUT_TOO_SHORT)) +#define PROB_HDR_NOT_CANONICAL(f) ((f.problems) & (PROBLEM_HEADER_NOT_CANONICAL)) +#define PROB_EXTRA_CHUNKS(f) ((f.problems) & (PROBLEM_EXTRA_CHUNKS)) +#define PROB_HDR_INCONSISTENT(f) ((f.problems) & (PROBLEM_HEADER_INCONSISTENT)) + +typedef struct _shn_config +{ + gint error_output_method; + gchar *error_output_method_config_name; + gchar *seek_tables_path; + gchar *seek_tables_path_config_name; + gchar *relative_seek_tables_path; + gchar *relative_seek_tables_path_config_name; + gboolean verbose; + gchar *verbose_config_name; + gboolean swap_bytes; + gchar *swap_bytes_config_name; + gboolean load_textfiles; + gchar *load_textfiles_config_name; + gchar *textfile_extensions; + gchar *textfile_extensions_config_name; +} shn_config; + +typedef struct _shn_decode_state +{ + uchar *getbuf; + uchar *getbufp; + int nbitget; + int nbyteget; + ulong gbuffer; + schar *writebuf; + schar *writefub; + int nwritebuf; +} shn_decode_state; + +typedef struct _shn_seek_header +{ + uchar data[SEEK_HEADER_SIZE]; + slong version; + ulong shnFileSize; +} shn_seek_header; + +typedef struct _shn_seek_trailer +{ + uchar data[SEEK_TRAILER_SIZE]; + ulong seekTableSize; +} shn_seek_trailer; + +typedef struct _shn_seek_entry +{ + uchar data[SEEK_ENTRY_SIZE]; +} shn_seek_entry; + +/* old way, kept for reference. + (changed because some compilers apparently don't support #pragma pack(1)) + +typedef struct _shn_seek_header +{ + char signature[4]; + unsigned long version; + unsigned long shnFileSize; +} shn_seek_header; + +typedef struct _shn_seek_trailer +{ + unsigned long seekTableSize; + char signature[8]; +} shn_seek_trailer; + +typedef struct _shn_seek_entry +{ + unsigned long shnSample; + unsigned long shnByteOffset; + unsigned long shnLastPosition; + unsigned short shnByteGet; + unsigned short shnBufferOffset; + unsigned short shnBitOffset; + unsigned long shnGBuffer; + unsigned short shnBitShift; + long cbuf0[3]; + long cbuf1[3]; + long offset0[4]; + long offset1[4]; +} shn_seek_entry; +*/ + +typedef struct _shn_wave_header +{ + char *filename, + m_ss[16]; + + uint header_size; + + ushort channels, + block_align, + bits_per_sample, + wave_format; + + ulong samples_per_sec, + avg_bytes_per_sec, + rate, + length, + data_size, + total_size, + chunk_size, + actual_size; + + double exact_length; + + int file_has_id3v2_tag; + long id3v2_tag_size; + + ulong problems; +} shn_wave_header; + +typedef struct _shn_vars +{ + VFSFile *fd; + int seek_to; + int eof; + int going; + slong seek_table_entries; + ulong seek_resolution; + int bytes_in_buf; + uchar buffer[OUT_BUFFER_SIZE]; + int bytes_in_header; + uchar header[OUT_BUFFER_SIZE]; + int fatal_error; + schar fatal_error_msg[BUF_SIZE]; + int reading_function_code; + ulong last_file_position; + ulong last_file_position_no_really; + ulong initial_file_position; + ulong bytes_read; + unsigned short actual_bitshift; + int actual_maxnlpc; + int actual_nmean; + int actual_nchan; + long seek_offset; + InputPlayback *playback; +} shn_vars; + +typedef struct _shn_file +{ + shn_vars vars; + shn_decode_state *decode_state; + shn_wave_header wave_header; + shn_seek_header seek_header; + shn_seek_trailer seek_trailer; + shn_seek_entry *seek_table; +} shn_file; + +extern InputPlugin shn_ip; +extern shn_file *shnfile; +extern shn_config shn_cfg; + +extern shn_seek_entry *shn_seek_entry_search(shn_seek_entry *,ulong,ulong,ulong,ulong); +extern void shn_load_seek_table(shn_file *,char *); +extern void shn_unload(shn_file *); +extern void shn_display_about(void); +extern void shn_display_configure(void); +extern void shn_display_info(shn_file *); +extern int shn_verify_header(shn_file *); +extern int shn_filename_contains_a_dot(char *); +extern char *shn_get_base_filename(char *); +extern char *shn_get_base_directory(char *); +extern void shn_length_to_str(shn_file *); +extern ulong shn_uchar_to_ulong_le(uchar *); +extern slong shn_uchar_to_slong_le(uchar *); +extern ushort shn_uchar_to_ushort_le(uchar *); +extern char *shn_format_to_str(ushort); +extern void shn_message_box(char *); +extern void shn_debug(char *, ...); +extern void shn_error(char *, ...); +extern void shn_error_fatal(shn_file *,char *, ...); +extern void shn_snprintf(char *,int,char *, ...); +extern VFSFile *shn_open_and_discard_id3v2_tag(char *,int *,long *); + +#endif diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/shorten.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/shorten.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,54 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: shorten.c,v 1.7 2003/08/26 05:34:04 jason Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include "shorten.h" + +void init_offset(slong **offset,int nchan,int nblock,int ftype) +{ + slong mean = 0; + int chan, i; + + /* initialise offset */ + switch(ftype) + { + case TYPE_AU1: + case TYPE_S8: + case TYPE_S16HL: + case TYPE_S16LH: + case TYPE_ULAW: + case TYPE_AU2: + case TYPE_AU3: + case TYPE_ALAW: + mean = 0; + break; + case TYPE_U8: + mean = 0x80; + break; + case TYPE_U16HL: + case TYPE_U16LH: + mean = 0x8000; + break; + default: + shn_debug("Unknown file type: %d", ftype); + } + + for(chan = 0; chan < nchan; chan++) + for(i = 0; i < nblock; i++) + offset[chan][i] = mean; +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/shorten.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/shorten.h Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,222 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: shorten.h,v 1.4 2001/12/30 05:12:04 jason Exp $ + */ + +#ifndef _SHORTEN_H +#define _SHORTEN_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef HAVE_INTTYPES_H +# include +#else +# if SIZEOF_UNSIGNED_LONG == 4 +# define uint32_t unsigned long +# define int32_t long +# else +# define uint32_t unsigned int +# define int32_t int +# endif +# define uint16_t unsigned short +# define uint8_t unsigned char +# define int16_t short +# define int8_t char +#endif + +#undef ulong +#undef ushort +#undef uchar +#undef slong +#undef sshort +#undef schar +#define ulong uint32_t +#define ushort uint16_t +#define uchar uint8_t +#define slong int32_t +#define sshort int16_t +#define schar int8_t + +#include "shn.h" + +extern shn_file *shnfile; + +#define MAGIC "ajkg" +#define FORMAT_VERSION 2 +#define MIN_SUPPORTED_VERSION 1 +#define MAX_SUPPORTED_VERSION 3 +#define MAX_VERSION 7 + +#define UNDEFINED_UINT -1 +#define DEFAULT_BLOCK_SIZE 256 +#define DEFAULT_V0NMEAN 0 +#define DEFAULT_V2NMEAN 4 +#define DEFAULT_MAXNLPC 0 +#define DEFAULT_NCHAN 1 +#define DEFAULT_NSKIP 0 +#define DEFAULT_NDISCARD 0 +#define NBITPERLONG 32 +#define DEFAULT_MINSNR 256 +#define DEFAULT_MAXRESNSTR "32.0" +#define DEFAULT_QUANTERROR 0 +#define MINBITRATE 2.5 + +#define MAX_LPC_ORDER 64 +#define CHANSIZE 0 +#define ENERGYSIZE 3 +#define BITSHIFTSIZE 2 +#define NWRAP 3 + +#define FNSIZE 2 +#define FN_DIFF0 0 +#define FN_DIFF1 1 +#define FN_DIFF2 2 +#define FN_DIFF3 3 +#define FN_QUIT 4 +#define FN_BLOCKSIZE 5 +#define FN_BITSHIFT 6 +#define FN_QLPC 7 +#define FN_ZERO 8 +#define FN_VERBATIM 9 + +#define VERBATIM_CKSIZE_SIZE 5 /* a var_put code size */ +#define VERBATIM_BYTE_SIZE 8 /* code size 8 on single bytes means + * no compression at all */ +#define VERBATIM_CHUNK_MAX 256 /* max. size of a FN_VERBATIM chunk */ + +#define ULONGSIZE 2 +#define NSKIPSIZE 1 +#define LPCQSIZE 2 +#define LPCQUANT 5 +#define XBYTESIZE 7 + +#define TYPESIZE 4 +#define TYPE_AU1 0 /* original lossless ulaw */ +#define TYPE_S8 1 /* signed 8 bit characters */ +#define TYPE_U8 2 /* unsigned 8 bit characters */ +#define TYPE_S16HL 3 /* signed 16 bit shorts: high-low */ +#define TYPE_U16HL 4 /* unsigned 16 bit shorts: high-low */ +#define TYPE_S16LH 5 /* signed 16 bit shorts: low-high */ +#define TYPE_U16LH 6 /* unsigned 16 bit shorts: low-high */ +#define TYPE_ULAW 7 /* lossy ulaw: internal conversion to linear */ +#define TYPE_AU2 8 /* new ulaw with zero mapping */ +#define TYPE_AU3 9 /* lossless alaw */ +#define TYPE_ALAW 10 /* lossy alaw: internal conversion to linear */ +#define TYPE_RIFF_WAVE 11 /* Microsoft .WAV files */ +#define TYPE_EOF 12 +#define TYPE_GENERIC_ULAW 128 +#define TYPE_GENERIC_ALAW 129 + +#define POSITIVE_ULAW_ZERO 0xff +#define NEGATIVE_ULAW_ZERO 0x7f + +#ifndef MAX_PATH +#define MAX_PATH 2048 +#endif + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#if defined(unix) && !defined(linux) +#define labs abs +#endif + +#define ROUNDEDSHIFTDOWN(x, n) (((n) == 0) ? (x) : ((x) >> ((n) - 1)) >> 1) + +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +/* BUFSIZ must be a multiple of four to contain a whole number of words */ +#ifdef BUFSIZ +#undef BUFSIZ +#endif + +#define BUFSIZ 512 + +#define V2LPCQOFFSET (1 << LPCQUANT); + +#define UINT_GET(nbit, shnfile) \ + ((version == 0) ? uvar_get(nbit, shnfile) : ulong_get(shnfile)) + +#define putc_exit(val, stream)\ +{ char rval;\ + if((rval = putc((val), (stream))) != (char) (val))\ + complain("FATALERROR: write failed: putc returns EOF");\ +} + +extern int getc_exit_val; +#define getc_exit(stream)\ +(((getc_exit_val = vfs_getc(stream)) == EOF) ? \ + complain("FATALERROR: read failed: getc returns EOF"), 0: getc_exit_val) + +/************************/ +/* defined in shorten.c */ +extern void init_offset(slong**, int, int, int); +extern int shorten(FILE*, FILE*, int, char**); + +/**************************/ +/* defined in Sulawalaw.c */ +extern int Sulaw2lineartab[]; +#define Sulaw2linear(i) (Sulaw2lineartab[i]) +#ifndef Sulaw2linear +extern int Sulaw2linear(uchar); +#endif +extern uchar Slinear2ulaw(int); + +extern int Salaw2lineartab[]; +#define Salaw2linear(i) (Salaw2lineartab[i]) +#ifndef Salaw2linear +extern int Salaw2linear(uchar); +#endif +extern uchar Slinear2alaw(int); + +/**********************/ +/* defined in fixio.c */ +extern void init_sizeof_sample(void); +extern void fwrite_type_init(shn_file*); +extern void fwrite_type(slong**,int,int,int,shn_file*); +extern void fwrite_type_quit(shn_file*); +extern void fix_bitshift(slong*, int, int, int); + +/**********************/ +/* defined in vario.c */ +extern void var_get_init(shn_file*); +extern slong uvar_get(int, shn_file*); +extern slong var_get(int, shn_file*); +extern ulong ulong_get(shn_file*); +extern void var_get_quit(shn_file*); + +extern int sizeof_uvar(ulong, int); +extern int sizeof_var(slong, int); + +extern void mkmasktab(void); +extern ulong word_get(shn_file*); + +/**********************/ +/* defined in array.c */ +extern void* pmalloc(ulong, shn_file*); +extern slong** long2d(ulong, ulong, shn_file*); + +#endif diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/sulawalaw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/sulawalaw.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,192 @@ +/* + * $Id: sulawalaw.c,v 1.5 2001/12/30 05:12:04 jason Exp $ + */ + +#include +#include +#include +#include +#include "shorten.h" + +int Sulaw2lineartab[] = {-32124, -31100, -30076, -29052, -28028, -27004, + -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, + -17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436, + -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, + -8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, + -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644, + -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, + -2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500, + -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876, + -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, + -492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276, + -260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112, + -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, + 21884, 20860, 19836, 18812, 17788, 16764, 15996, 15484, 14972, 14460, + 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, + 8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, + 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900, 3772, 3644, 3516, + 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, + 1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, + 1244, 1180, 1116, 1052, 988, 924, 876, 844, 812, 780, 748, 716, 684, + 652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 356, 340, 324, 308, + 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104, + 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0}; + +#ifndef Sulaw2linear +#ifdef __STDC__ +int Sulaw2linear(uchar ulaw) { +#else +int Sulaw2linear(ulaw) uchar ulaw; { +#endif + return(Sulaw2lineartab[ulaw]); +} +#endif + +/* adapted by ajr for int input */ +#ifdef __STDC__ +uchar Slinear2ulaw(int sample) { +#else +uchar Slinear2ulaw(sample) int sample; { +#endif +/* +** This routine converts from linear to ulaw. +** +** Craig Reese: IDA/Supercomputing Research Center +** Joe Campbell: Department of Defense +** 29 September 1989 +** +** References: +** 1) CCITT Recommendation G.711 (very difficult to follow) +** 2) "A New Digital Technique for Implementation of Any +** Continuous PCM Companding Law," Villeret, Michel, +** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, +** 1973, pg. 11.12-11.17 +** 3) MIL-STD-188-113,"Interoperability and Performance Standards +** for Analog-to_Digital Conversion Techniques," +** 17 February 1987 +** +** Input: Signed 16 bit linear sample +** Output: 8 bit ulaw sample +*/ + +#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ +#define CLIP 32635 + + static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; + int sign, exponent, mantissa; + uchar ulawbyte; + + /* Get the sample into sign-magnitude. */ + if(sample < 0) { + sign = 0x80; + sample = -sample; + } + else + sign = 0; + + /* clip the magnitude */ + if(sample > CLIP) sample = CLIP; + + /* Convert from 16 bit linear to ulaw. */ + sample = sample + BIAS; + exponent = exp_lut[( sample >> 7 ) & 0xFF]; + mantissa = (sample >> (exponent + 3)) & 0x0F; + ulawbyte = ~(sign | (exponent << 4) | mantissa); + + return(ulawbyte); +} + + +/****************** + * ALAW starts here + */ + +int Salaw2lineartab[] = {-5504, -5248, -6016, -5760, -4480, -4224, + -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, + -4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064, + -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, + -31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032, + -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, + -13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264, + -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72, + -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, + -184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656, + -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, + -784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, + 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, + 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, + 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, + 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, + 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, + 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, + 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, + 816, 784, 880, 848}; + +#ifndef Salaw2linear +#ifdef __STDC__ +int Salaw2linear(uchar alaw) { +#else +int Salaw2linear(alaw) uchar alaw; { +#endif + return(Salaw2lineartab[alaw]); +} +#endif + +/* this is derived from the Sun code - it is a bit simpler and has int input */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#ifdef __STDC__ +uchar Slinear2alaw(int linear) { +#else +uchar Slinear2alaw(linear) int linear; { +#endif + int seg; + uchar aval, mask; + static sshort seg_aend[NSEGS] = {0x1f,0x3f,0x7f,0xff,0x1ff,0x3ff,0x7ff,0xfff}; + + linear = linear >> 3; + + if(linear >= 0) { + mask = 0xd5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + linear = -linear - 1; + } + + /* Convert the scaled magnitude to segment number. */ + for(seg = 0; seg < NSEGS && linear > seg_aend[seg]; seg++); + + /* Combine the sign, segment, and quantization bits. */ + if(seg >= NSEGS) /* out of range, return maximum value. */ + return (uchar) (0x7F ^ mask); + else { + aval = (uchar) seg << SEG_SHIFT; + if (seg < 2) + aval |= (linear >> 1) & QUANT_MASK; + else + aval |= (linear >> seg) & QUANT_MASK; + return (aval ^ mask); + } +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/vario.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/vario.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,146 @@ +/****************************************************************************** +* * +* Copyright (C) 1992-1995 Tony Robinson * +* * +* See the file doc/LICENSE.shorten for conditions on distribution and usage * +* * +******************************************************************************/ + +/* + * $Id: vario.c,v 1.10 2004/05/04 02:26:36 jason Exp $ + */ + +#include +#include +#include +#include "shorten.h" + +#define MASKTABSIZE 33 +ulong masktab[MASKTABSIZE]; + +void mkmasktab() { + int i; + ulong val = 0; + + masktab[0] = val; + for(i = 1; i < MASKTABSIZE; i++) { + val <<= 1; + val |= 1; + masktab[i] = val; + } +} + +void var_get_init(shn_file *this_shn) +{ + mkmasktab(); + + this_shn->decode_state->getbuf = (uchar*) pmalloc((ulong) BUFSIZ,this_shn); + this_shn->decode_state->getbufp = this_shn->decode_state->getbuf; + this_shn->decode_state->nbyteget = 0; + this_shn->decode_state->gbuffer = 0; + this_shn->decode_state->nbitget = 0; +} + +ulong word_get(shn_file *this_shn) +{ + ulong buffer; + int bytes; + + if(this_shn->decode_state->nbyteget < 4) + { + this_shn->vars.last_file_position = this_shn->vars.bytes_read; + + bytes = vfs_fread((uchar*) this_shn->decode_state->getbuf, 1, BUFSIZ, this_shn->vars.fd); + this_shn->decode_state->nbyteget += bytes; + + if(this_shn->decode_state->nbyteget < 4) { + shn_error_fatal(this_shn,"Premature EOF on compressed stream -\npossible corrupt or truncated file"); + return (ulong)0; + } + + this_shn->vars.bytes_read += bytes; + + this_shn->decode_state->getbufp = this_shn->decode_state->getbuf; + } + + buffer = (((slong) (this_shn->decode_state->getbufp[0])) << 24) | (((slong) (this_shn->decode_state->getbufp[1])) << 16) | + (((slong) (this_shn->decode_state->getbufp[2])) << 8) | ((slong) (this_shn->decode_state->getbufp[3])); + + this_shn->decode_state->getbufp += 4; + this_shn->decode_state->nbyteget -= 4; + + return(buffer); +} + +slong uvar_get(int nbin,shn_file *this_shn) +{ + slong result; + + if (this_shn->vars.reading_function_code) { + this_shn->vars.last_file_position_no_really = this_shn->vars.last_file_position; + } + + if(this_shn->decode_state->nbitget == 0) + { + this_shn->decode_state->gbuffer = word_get(this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + this_shn->decode_state->nbitget = 32; + } + + for(result = 0; !(this_shn->decode_state->gbuffer & (1L << --(this_shn->decode_state->nbitget))); result++) + { + if(this_shn->decode_state->nbitget == 0) + { + this_shn->decode_state->gbuffer = word_get(this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + this_shn->decode_state->nbitget = 32; + } + } + + while(nbin != 0) + { + if(this_shn->decode_state->nbitget >= nbin) + { + result = (result << nbin) | ((this_shn->decode_state->gbuffer >> (this_shn->decode_state->nbitget-nbin)) &masktab[nbin]); + this_shn->decode_state->nbitget -= nbin; + nbin = 0; + } + else + { + result = (result << this_shn->decode_state->nbitget) | (this_shn->decode_state->gbuffer & masktab[this_shn->decode_state->nbitget]); + this_shn->decode_state->gbuffer = word_get(this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + nbin -= this_shn->decode_state->nbitget; + this_shn->decode_state->nbitget = 32; + } + } + + return(result); +} + +ulong ulong_get(shn_file *this_shn) +{ + unsigned int nbit = uvar_get(ULONGSIZE,this_shn); + if (this_shn->vars.fatal_error) + return (ulong)0; + return(uvar_get(nbit,this_shn)); +} + +slong var_get(int nbin,shn_file *this_shn) +{ + ulong uvar = uvar_get(nbin + 1,this_shn); + if (this_shn->vars.fatal_error) + return (slong)0; + + if(uvar & 1) return((slong) ~(uvar >> 1)); + else return((slong) (uvar >> 1)); +} + +void var_get_quit(shn_file *this_shn) +{ + free((void *) this_shn->decode_state->getbuf); + this_shn->decode_state->getbuf = NULL; +} diff -r f34112ab9101 -r fbeb9446aa2e src/shnplug/wave.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shnplug/wave.c Fri Jul 20 10:30:28 2007 -0500 @@ -0,0 +1,268 @@ +/* wave.c - functions to parse and verify WAVE headers + * Copyright (C) 2000-2007 Jason Jordan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * $Id: wave.c,v 1.13 2007/03/23 05:49:48 jason Exp $ + */ + +#include +#include +#include +#include +#include +#include "shorten.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +int is_valid_file(shn_file *info) +/* determines whether the given filename (info->filename) is a regular file, and is readable */ +{ + struct stat sz; + FILE *f; + + if (0 != stat(info->wave_header.filename,&sz)) { + if (errno == ENOENT) + shn_error("cannot open '%s' because it does not exist",info->wave_header.filename); + else if (errno == EACCES) + shn_error("cannot open '%s' due to insufficient permissions",info->wave_header.filename); + else if (errno == EFAULT) + shn_error("cannot open '%s' due to bad address",info->wave_header.filename); + else if (errno == ENOMEM) + shn_error("cannot open '%s' because the kernel ran out of memory",info->wave_header.filename); + else if (errno == ENAMETOOLONG) + shn_error("cannot open '%s' because the file name is too long",info->wave_header.filename); + else + shn_error("cannot open '%s' due to an unknown problem",info->wave_header.filename); + return 0; + } + if (0 == S_ISREG(sz.st_mode)) { + if (S_ISLNK(sz.st_mode)) + shn_error("'%s' is a symbolic link, not a regular file",info->wave_header.filename); + else if (S_ISDIR(sz.st_mode)) + shn_error("'%s' is a directory, not a regular file",info->wave_header.filename); + else if (S_ISCHR(sz.st_mode)) + shn_error("'%s' is a character device, not a regular file",info->wave_header.filename); + else if (S_ISBLK(sz.st_mode)) + shn_error("'%s' is a block device, not a regular file",info->wave_header.filename); + else if (S_ISFIFO(sz.st_mode)) + shn_error("'%s' is a fifo, not a regular file",info->wave_header.filename); + else if (S_ISSOCK(sz.st_mode)) + shn_error("'%s' is a socket, not a regular file",info->wave_header.filename); + return 0; + } + info->wave_header.actual_size = (ulong)sz.st_size; + + if (NULL == (f = fopen(info->wave_header.filename,"rb"))) { + shn_error("could not open '%s': %s",info->wave_header.filename,strerror(errno)); + return 0; + } + fclose(f); + + return 1; +} + +int shn_verify_header(shn_file *this_shn) +{ + ulong l; + int cur = 0; + + if (0 == is_valid_file(this_shn)) + { + shn_debug("while processing '%s': something went wrong while opening this file, see above",this_shn->wave_header.filename); + return 0; + } + + if (this_shn->vars.bytes_in_header < CANONICAL_HEADER_SIZE) { + shn_debug("while processing '%s': header is only %d bytes (should be at least %d bytes)", + this_shn->wave_header.filename,this_shn->vars.bytes_in_header,CANONICAL_HEADER_SIZE); + return 0; + } + + if (WAVE_RIFF != shn_uchar_to_ulong_le(this_shn->vars.header+cur)) + { + if (AIFF_FORM == shn_uchar_to_ulong_le(this_shn->vars.header+cur)) + shn_debug("while processing '%s': file contains AIFF data, which is currently not supported",this_shn->wave_header.filename); + else + shn_debug("while processing '%s': WAVE header is missing RIFF tag - possible corrupt file",this_shn->wave_header.filename); + return 0; + } + cur += 4; + + this_shn->wave_header.chunk_size = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + + if (WAVE_WAVE != shn_uchar_to_ulong_le(this_shn->vars.header+cur)) + { + shn_debug("while processing '%s': WAVE header is missing WAVE tag",this_shn->wave_header.filename); + return 0; + } + cur += 4; + + for (;;) + { + cur += 4; + + l = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + + if (WAVE_FMT == shn_uchar_to_ulong_le(this_shn->vars.header+cur-8)) + break; + + cur += l; + } + + if (l < 16) + { + shn_debug("while processing '%s': fmt chunk in WAVE header was too short",this_shn->wave_header.filename); + return 0; + } + + this_shn->wave_header.wave_format = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + + switch (this_shn->wave_header.wave_format) + { + case WAVE_FORMAT_PCM: + break; + default: + shn_debug("while processing '%s': unsupported format 0x%04x (%s) - only PCM data is supported at this time", + this_shn->wave_header.filename,this_shn->wave_header.wave_format,shn_format_to_str(this_shn->wave_header.wave_format)); + return 0; + } + + this_shn->wave_header.channels = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + this_shn->wave_header.samples_per_sec = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + this_shn->wave_header.avg_bytes_per_sec = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + this_shn->wave_header.block_align = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + this_shn->wave_header.bits_per_sample = shn_uchar_to_ushort_le(this_shn->vars.header+cur); + cur += 2; + + if (this_shn->wave_header.bits_per_sample != 8 && this_shn->wave_header.bits_per_sample != 16) + { + shn_debug("while processing '%s': bits per sample is neither 8 nor 16",this_shn->wave_header.filename); + return 0; + } + + l -= 16; + + if (l > 0) + cur += l; + + for (;;) + { + cur += 4; + + l = shn_uchar_to_ulong_le(this_shn->vars.header+cur); + cur += 4; + + if (WAVE_DATA == shn_uchar_to_ulong_le(this_shn->vars.header+cur-8)) + break; + + cur += l; + } + + this_shn->wave_header.rate = ((uint)this_shn->wave_header.samples_per_sec * + (uint)this_shn->wave_header.channels * + (uint)this_shn->wave_header.bits_per_sample) / 8; + this_shn->wave_header.header_size = cur; + this_shn->wave_header.data_size = l; + this_shn->wave_header.total_size = this_shn->wave_header.chunk_size + 8; + this_shn->wave_header.length = this_shn->wave_header.data_size / this_shn->wave_header.rate; + this_shn->wave_header.exact_length = (double)this_shn->wave_header.data_size / (double)this_shn->wave_header.rate; + + if (this_shn->wave_header.channels == CD_CHANNELS && + this_shn->wave_header.bits_per_sample == CD_BITS_PER_SAMPLE && + this_shn->wave_header.samples_per_sec == CD_SAMPLES_PER_SEC && + this_shn->wave_header.avg_bytes_per_sec == CD_RATE && + this_shn->wave_header.rate == CD_RATE) + { + if (this_shn->wave_header.data_size < CD_MIN_BURNABLE_SIZE) + this_shn->wave_header.problems |= PROBLEM_CD_BUT_TOO_SHORT; + if (this_shn->wave_header.data_size % CD_BLOCK_SIZE != 0) + this_shn->wave_header.problems |= PROBLEM_CD_BUT_BAD_BOUND; + } + else + this_shn->wave_header.problems |= PROBLEM_NOT_CD_QUALITY; + + if (this_shn->wave_header.header_size != CANONICAL_HEADER_SIZE) + this_shn->wave_header.problems |= PROBLEM_HEADER_NOT_CANONICAL; + + if ((ulong)this_shn->wave_header.header_size + this_shn->wave_header.data_size > this_shn->wave_header.total_size) + this_shn->wave_header.problems |= PROBLEM_HEADER_INCONSISTENT; + + if ((ulong)this_shn->wave_header.header_size + this_shn->wave_header.data_size < this_shn->wave_header.total_size) + this_shn->wave_header.problems |= PROBLEM_EXTRA_CHUNKS; + + shn_length_to_str(this_shn); + + /* header looks ok */ + return 1; +} + +char *shn_format_to_str(ushort format) +{ + switch (format) { + case WAVE_FORMAT_UNKNOWN: + return "Microsoft Official Unknown"; + case WAVE_FORMAT_PCM: + return "Microsoft PCM"; + case WAVE_FORMAT_ADPCM: + return "Microsoft ADPCM"; + case WAVE_FORMAT_IEEE_FLOAT: + return "IEEE Float"; + case WAVE_FORMAT_ALAW: + return "Microsoft A-law"; + case WAVE_FORMAT_MULAW: + return "Microsoft U-law"; + case WAVE_FORMAT_OKI_ADPCM: + return "OKI ADPCM format"; + case WAVE_FORMAT_IMA_ADPCM: + return "IMA ADPCM"; + case WAVE_FORMAT_DIGISTD: + return "Digistd format"; + case WAVE_FORMAT_DIGIFIX: + return "Digifix format"; + case WAVE_FORMAT_DOLBY_AC2: + return "Dolby AC2"; + case WAVE_FORMAT_GSM610: + return "GSM 6.10"; + case WAVE_FORMAT_ROCKWELL_ADPCM: + return "Rockwell ADPCM"; + case WAVE_FORMAT_ROCKWELL_DIGITALK: + return "Rockwell DIGITALK"; + case WAVE_FORMAT_G721_ADPCM: + return "G.721 ADPCM"; + case WAVE_FORMAT_G728_CELP: + return "G.728 CELP"; + case WAVE_FORMAT_MPEG: + return "MPEG"; + case WAVE_FORMAT_MPEGLAYER3: + return "MPEG Layer 3"; + case WAVE_FORMAT_G726_ADPCM: + return "G.726 ADPCM"; + case WAVE_FORMAT_G722_ADPCM: + return "G.722 ADPCM"; + } + return "Unknown"; +}