Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1097 lines
30 KiB

/****************************************************************************
* NCSA Mosaic for Microsoft Windows *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* 605 E. Springfield, Champaign, IL 61820 *
* [email protected] *
* *
* Copyright (C) 1993, 1994, Board of Trustees of the University of Illinois *
* *
* NCSA Mosaic software, both binary and source (hereafter, Software) is *
* copyrighted by The Board of Trustees of the University of Illinois *
* (UI), and ownership remains with the UI. *
* *
* The UI grants you (hereafter, Licensee) a license to use the Software *
* for academic, research and internal business purposes only, without a *
* fee. Licensee may distribute the binary and source code (if released) *
* to third parties provided that the copyright notice and this statement *
* appears on all copies and that no charge is associated with such *
* copies. *
* *
* Licensee may make derivative works. However, if Licensee distributes *
* any derivative work based on or derived from the Software, then *
* Licensee will (1) notify NCSA regarding its distributing of the *
* derivative work, and (2) clearly notify users that such derivative *
* work is a modified version and not the original NCSA Mosaic *
* distributed by the UI. *
* *
* Any Licensee wishing to make commercial use of the Software should *
* contact the UI, c/o NCSA, to negotiate an appropriate license for such *
* commercial use. Commercial use included (1) integration of all or *
* part of the source code into a product for sale or license by or on *
* behalf of Licensee to third parties, or (2) distribution of the binary *
* code or source code to third parties that need it to utilize a *
* commercial product sold or licensed by or on behalf of Licensee. *
* *
* UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR *
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED *
* WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE *
* USERS OF THIS SOFTWARE. *
* *
* By using or copying this Software, Licensee agrees to abide by the *
* copyright law and all other applicable laws of the U.S. including, but *
* not limited to, export control laws, and the terms of this license. *
* UI shall have the right to terminate this license immediately by *
* written notice upon Licensee's breach of, or non-compliance with, any *
* of its terms. Licensee may be held legally responsible for any *
* copyright infringement that is caused or encouraged by Licensee's *
* failure to abide by the terms of this license. *
* *
****************************************************************************/
/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Author(s):
Albert Lee [email protected]
Adapted from NCSA's AU.CPP. Significant changes have been made to code.
*/
#include "all.h"
#include "history.h"
#ifdef FEATURE_SOUND_PLAYER
#define BLOCK_SIZE 32768
int device_capability = DEVICE_8BIT;
static BOOL bInitialized = FALSE;
struct hash_table gSoundCache;
PRIVATE BOOL AuDecodeCharacter(struct SoundInfo *si, char c);
static short int ulaw_table[256] =
{
-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 };
void swapLongs(unsigned long *data, int n)
{
int idx;
unsigned char b;
unsigned char *bptr;
bptr = (unsigned char *) data;
for (idx = 0; idx < n; idx++, bptr += 4)
{
b = bptr[0];
bptr[0] = bptr[3];
bptr[3] = b;
b = bptr[1];
bptr[1] = bptr[2];
bptr[2] = b;
}
}
void swapShorts(unsigned short int *data, int n)
{
int idx;
unsigned char b;
unsigned char *bptr;
bptr = (unsigned char *) data;
for (idx = 0; idx < n; idx++, bptr += 2)
{
b = bptr[0];
bptr[0] = bptr[1];
bptr[1] = b;
}
}
BOOL AuProcess(struct SoundInfo *si, const char *pszURL)
{
int i;
FILE *fp;
char *buf;
long size;
char status[128];
#ifdef WIN32
GetSoundCapability(); /* determine if 16-bit sound can be played */
#endif
si->count = 0;
si->bValid = TRUE;
si->state = 0;
si->magic = 0;
si->buf = NULL;
si->style = SIGN2;
si->size = 0;
si->swap = 0;
si->buf_size = 0;
si->data_size = (unsigned long) -1;
si->loc = 0;
fp = fopen(si->fsOrig, "rb");
if (!fp)
return FALSE;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
buf = GTR_MALLOC(size);
if (buf == NULL)
{
fclose(fp);
return FALSE;
}
GTR_formatmsg(RES_STRING_AU1,status,sizeof(status));
WAIT_Push(si->tw_refer, waitNoInteract, status);
WAIT_SetRange(si->tw_refer, 0, 100, size);
// BUGBUG jcordell 06-23-95: fread failure not checked
fread(buf, 1, size, fp);
fclose(fp);
for (i = 0; i < size; i++)
{
if (si->bValid) {
if ( !AuDecodeCharacter(si, buf[i]) ) {
si->bValid = FALSE;
break;
}
} else
break;
}
WAIT_Pop(si->tw_refer);
GTR_FREE(buf);
si->bValid = (si->bValid &&
(si->channels == 1 || si->channels == 2) &&
si->sample_rate >= 1000 &&
(si->size == 1 || si->size == 2));
if (si->bValid)
CreateSoundPlayer(si, pszURL);
else
ERR_ReportError(si->tw_refer, errInvalidSoundFormat, "", "");
return (si->bValid);
}
PRIVATE BOOL AuDecodeCharacter(struct SoundInfo *si, char c)
{
static unsigned long hdr;
static unsigned long chunksize;
static unsigned short int wTmp;
short int *ibuf;
char *buf2;
char *pb;
si->count++;
// BUGBUG performance: jcordell -- we could do the WAIT_SetTherm less often
WAIT_SetTherm(si->tw_refer, si->count);
switch (si->state)
{
case STATE_SPIN:
/* In case our data is bad or our state machine is hosed, just forget any data that comes in. */
si->bValid = FALSE;
break;
/* Read in the magic number */
case 0:
hdr = 0;
chunksize = 0;
wTmp = 0;
si->magic = (unsigned long) c;
si->state++;
break;
case 1:
si->magic |= ((unsigned long) c) << 8;
si->state++;
break;
case 2:
si->magic |= ((unsigned long) c) << 16;
si->state++;
break;
case 3:
si->magic |= ((unsigned long) c) << 24;
si->state++;
if (si->magic == DEC_INV_MAGIC)
{
XX_DMsg(DBG_MM, ("Found inverted DEC magic word (AU)\n"));
si->type = SOUND_AU;
si->swap = 1;
}
else if (si->magic == SUN_INV_MAGIC)
{
XX_DMsg(DBG_MM, ("Found inverted Sun/NeXT magic word (AU)\n"));
si->type = SOUND_AU;
si->swap = 1;
}
else if (si->magic == SUN_MAGIC)
{
XX_DMsg(DBG_MM, ("Found Sun/NeXT magic word (AU)\n"));
si->type = SOUND_AU;
si->swap = 0;
}
else if (si->magic == DEC_MAGIC)
{
XX_DMsg(DBG_MM, ("Found DEC magic word (AU)\n"));
si->type = SOUND_AU;
si->swap = 0;
}
else if (si->magic == AIFF_MAGIC)
{
XX_DMsg(DBG_MM, ("Found AIFF magic word (AIFF)\n"));
si->type = SOUND_AIFF;
si->swap = 0;
}
else if (si->magic == AIFF_INV_MAGIC)
{
XX_DMsg(DBG_MM, ("Found inverted AIFF magic word (AIFF)\n"));
si->type = SOUND_AIFF;
si->swap = 1;
}
else
{
XX_DMsg(DBG_MM, ("No magic word - trouble!\n"));
si->state = STATE_SPIN;
}
break;
/* Read the header size */
case 4:
si->hdr_size = (unsigned long) c;
si->state++;
break;
case 5:
si->hdr_size |= ((unsigned long) c) << 8;
si->state++;
break;
case 6:
si->hdr_size |= ((unsigned long) c) << 16;
si->state++;
break;
case 7:
si->hdr_size |= ((unsigned long) c) << 24;
si->state++;
if (si->swap)
swapLongs((unsigned long *) &si->hdr_size, 1);
if ((si->type == SOUND_AU) && (si->hdr_size >= SUN_HDRSIZE))
{
XX_DMsg(DBG_MM, ("Sun/DEC/NeXT header size: 0x%lx = %ld\n", si->hdr_size, si->hdr_size));
break;
}
if (si->type == SOUND_AIFF)
{
XX_DMsg(DBG_MM, ("AIFF total size: 0x%lx = %ld\n", si->hdr_size, si->hdr_size));
si->state = -1;
break;
}
XX_DMsg(DBG_MM, ("Incorrect header size\n"));
si->state=STATE_SPIN;
break;
/* Negative cases are all AIFF handling */
case -1:
hdr = ((unsigned long) c) << 24;
si->state--;
break;
case -2:
hdr |= ((unsigned long) c) << 16;
si->state--;
break;
case -3:
hdr |= ((unsigned long) c) << 8;
si->state--;
break;
case -4:
hdr |= ((unsigned long) c);
if (hdr != 0x41494646)
{
XX_DMsg(DBG_MM, ("FORM chunk does not specify AIFF type\n"));
si->state = STATE_SPIN;
break;
}
XX_DMsg(DBG_MM, ("FORM chunk specifies AIFF type\n"));
si->state--;
break;
case -5:
hdr = ((unsigned long) c) << 24;
si->state--;
break;
case -6:
hdr |= ((unsigned long) c) << 16;
si->state--;
break;
case -7:
hdr |= ((unsigned long) c) << 8;
si->state--;
break;
case -8:
hdr |= ((unsigned long) c);
si->state--;
break;
case -9:
chunksize = (unsigned long) c;
si->state--;
break;
case -10:
chunksize |= ((unsigned long) c) << 8;
si->state--;
break;
case -11:
chunksize |= ((unsigned long) c) << 16;
si->state--;
break;
case -12:
chunksize |= ((unsigned long) c) << 24;
swapLongs((unsigned long *) &chunksize, 1);
if (hdr == 0x434f4d4d)
{
XX_DMsg(DBG_MM, ("COMM chunk found\n"));
if (chunksize != 18)
{
XX_DMsg(DBG_MM, ("COMM chunk has incorrect chunksize 0x%lx\n", chunksize));
/*
// si->state = STATE_SPIN;
// break;
*/
}
si->state = -20;
break;
}
if (hdr == 0x53534e44)
{
XX_DMsg(DBG_MM, ("SSND chunk found\n"));
si->state = -14;
break;
}
XX_DMsg(DBG_MM, ("Unrecognized chunk 0x%lx found. Skipping\n", hdr));
si->state--;
break;
case -13:
chunksize--;
if (chunksize == 0)
si->state = -5;
break;
/* SSND chunk - read the offset */
case -14:
si->offset = (unsigned long) c;
si->state--;
break;
case -15:
si->offset |= ((unsigned long) c ) << 8;
si->state--;
break;
case -16:
si->offset |= ((unsigned long) c ) << 16;
si->state--;
break;
case -17:
si->offset |= ((unsigned long) c) << 24;
XX_DMsg(DBG_MM, ("AIFF offset is %lu\n",si->offset));
si->state--;
si->idx=0;
break;
case -18:
XX_DMsg(DBG_MM, ("Blocksize byte\n"));
if (c != 0)
{
XX_DMsg(DBG_MM, ("Blocksize is not zero!\n"));
si->state=STATE_SPIN;
break;
}
si->idx++;
if (si->idx > 3)
{
if (si->offset != 0)
si->state--;
else
{
si->buf = GTR_MALLOC(DATABLOCKSIZE);
if (si->buf == NULL)
return FALSE;
si->buf_size = DATABLOCKSIZE;
si->loc = 0;
si->state = 25;
}
}
break;
case -19:
si->offset--;
if (si->offset == 0)
{
si->buf = GTR_MALLOC(DATABLOCKSIZE);
if (si->buf == NULL)
return FALSE;
si->buf_size = DATABLOCKSIZE;
si->loc = 0;
si->state=25;
}
break;
/* COMM chunk - Read the number of channels */
case -20:
wTmp = (unsigned short int) c;
si->state--;
break;
case -21:
wTmp |= ((unsigned short int) c) << 8;
swapShorts((unsigned short int *) &wTmp, 1);
si->channels = (unsigned long) wTmp;
XX_DMsg(DBG_MM, ("Number of channels: %ld\n",si->channels));
si->state--;
break;
/* Read the # of frames. (? Throw it away.) */
case -22:
case -23:
case -24:
case -25:
si->state--;
break;
case -26:
wTmp = (unsigned short int) c;
si->state--;
break;
case -27:
wTmp |= ((unsigned short int) c) << 8;
swapShorts((unsigned short int *) &wTmp, 1);
if (wTmp == 16)
si->size = SIZE_WORD;
else
si->size = SIZE_BYTE;
XX_DMsg(DBG_MM, ("Number of bits: %u\n", wTmp));
si->state--;
si->idx = 9;
break;
case -28:
si->temp[si->idx--] = (unsigned char) c;
if (si->idx < 0)
{
double dTmp = *((double *) si->temp);
si->sample_rate = (unsigned long) dTmp;
XX_DMsg(DBG_MM, ("Sample rate is %f\n", dTmp));
si->state = -5;
}
break;
/* 7<numbers>25 are AU handling */
/* Read the data size; may be ~0 meaning unspecified */
case 8:
si->data_size = (unsigned long) c;
si->state++;
break;
case 9:
si->data_size |= ((unsigned long) c) << 8;
si->state++;
break;
case 10:
si->data_size |= ((unsigned long) c) << 16;
si->state++;
break;
case 11:
si->data_size |= ((unsigned long) c) << 24;
si->state++;
if (si->swap)
swapLongs((unsigned long *) &si->data_size, 1);
XX_DMsg(DBG_MM, ("Data size: 0x%lx = %ld\n", si->data_size, si->data_size));
break;
/* Read the encoding; there are some more possibilities */
case 12:
si->encoding = (unsigned long) c;
si->state++;
break;
case 13:
si->encoding |= ((unsigned long) c) << 8;
si->state++;
break;
case 14:
si->encoding |= ((unsigned long) c) << 16;
si->state++;
break;
case 15:
si->encoding |= ((unsigned long) c) << 24;
si->state++;
if (si->swap)
swapLongs((unsigned long *) &si->encoding, 1);
/* Translate the encoding into style and size parameters */
switch (si->encoding)
{
case SUN_ULAW:
XX_DMsg(DBG_MM, ("Sun u-Law encoding\n"));
si->style = ULAW;
si->size = SIZE_BYTE;
break;
case SUN_LIN_8:
XX_DMsg(DBG_MM, ("Sun linear 8-bit encoding\n"));
si->style = SIGN2;
si->size = SIZE_BYTE;
break;
case SUN_LIN_16:
XX_DMsg(DBG_MM, ("Sun linear 16-bit encoding\n"));
si->style = SIGN2;
si->size = SIZE_WORD;
break;
default:
XX_DMsg(DBG_MM, ("Encoding: 0x%lx\n", si->encoding));
XX_DMsg(DBG_MM, ("Unsupported encoding in Sun/NeXT header. Only U-law, signed bytes, and signed words are supported\n"));
si->state = STATE_SPIN;
break;
}
break;
/* Read the sampling rate */
case 16:
si->sample_rate = (unsigned long) c;
si->state++;
break;
case 17:
si->sample_rate |= ((unsigned long) c) << 8;
si->state++;
break;
case 18:
si->sample_rate |= ((unsigned long) c) << 16;
si->state++;
break;
case 19:
si->sample_rate |= ((unsigned long) c) << 24;
si->state++;
if (si->swap)
swapLongs((unsigned long *) &si->sample_rate, 1);
XX_DMsg(DBG_MM, ("Sample rate: %ld Hz\n", si->sample_rate));
break;
/* Read the number of channels */
case 20:
si->channels = (unsigned long) c;
si->state++;
break;
case 21:
si->channels |= ((unsigned long) c) << 8;
si->state++;
break;
case 22:
si->channels |= ((unsigned long) c) << 16;
si->state++;
break;
case 23:
si->channels |= ((unsigned long) c) << 24;
si->state++;
if (si->swap)
swapLongs((unsigned long *) &si->channels, 1);
XX_DMsg(DBG_MM, ("Number of channels: %ld\n", si->channels));
si->hdr_size -= SUN_HDRSIZE; /* #bytes already read */
break;
/* Skip the info string in header */
case 24:
if (si->hdr_size > 0)
{
si->hdr_size--;
break;
}
else
si->state++;
if (si->data_size == -1)
{
si->buf = GTR_MALLOC(DATABLOCKSIZE);
if (si->buf == NULL)
return FALSE;
si->buf_size = DATABLOCKSIZE;
si->loc = 0;
if ((si->style == ULAW) && (device_capability != DEVICE_8BIT))
si->size = SIZE_WORD;
}
else
{
switch (si->size)
{
case SIZE_BYTE:
switch (si->style)
{
case SIGN2:
si->buf_size = si->data_size;
si->buf = GTR_MALLOC(si->buf_size);
if (si->buf == NULL)
return FALSE;
si->loc = 0;
break;
case ULAW:
si->buf_size = si->data_size * 2;
si->buf = GTR_MALLOC(si->buf_size);
if (si->buf == NULL)
return FALSE;
si->loc = 0;
if (device_capability != DEVICE_8BIT)
si->size = SIZE_WORD;
break;
default:
XX_DMsg(DBG_MM, ("Unsupported Format!\n"));
si->state = STATE_SPIN;
return FALSE;
}
break;
case SIZE_WORD:
switch (si->style)
{
case SIGN2:
si->buf_size = si->data_size * 2;
si->buf = GTR_MALLOC(si->buf_size);
if (si->buf == NULL)
return FALSE;
si->loc = 0;
break;
default:
XX_DMsg(DBG_MM, ("Unsupported Format!\n"));
return FALSE;
}
}
}
/* Go ahead and drop through to next case */
case 25:
/* Read the data */
if (si->loc >= si->buf_size)
{
/* The following check doesn't seem to be needed, and
it also prohibits 11khz sound files from playing.
if (si->data_size != -1)
{
XX_DMsg(DBG_MM, ("Too many bytes in stream!\n"));
si->state=STATE_SPIN;
return FALSE;
}
*/
pb = GTR_REALLOC(si->buf, si->buf_size + DATABLOCKSIZE);
if (pb == NULL)
return FALSE;
si->buf = pb;
si->buf_size += DATABLOCKSIZE;
}
buf2= si->buf + si->loc;
if (si->style == ULAW)
{
/* use table from Posk stuff */
if (device_capability != DEVICE_8BIT)
{
ibuf = (short int *) buf2;
*ibuf = (short) ulaw_table[(unsigned char) c];
si->loc += 2;
}
else
{
*buf2 = (char) (((short) ulaw_table[(unsigned char) c]) / 256);
*buf2 ^= 128;
si->loc++;
}
}
else
{
/* style == SIGN2 */
switch (si->size)
{
case SIZE_BYTE:
*buf2 = c;
*buf2 = *buf2 ^ 0x7F;
break;
case SIZE_WORD:
*buf2 = c;
if (si->loc & 0x01)
{
if (si->swap)
{
c = buf2[0];
buf2[0] = buf2[1];
buf2[1] = c;
}
}
break;
default:
XX_DMsg(DBG_MM, ("Unsupported option - not 8- or 16-bit size for SIGN2 encoding!\n"));
si->state = STATE_SPIN;
break;
}
si->loc++;
}
break;
}
return TRUE;
}
static void Sound_Callback( void *param,
const char *pszURL,
BOOL bAbort,
const char *pszFileHREF,
BOOL fDCache,
DCACHETIME dctExpires,
DCACHETIME dctLastModif)
{
struct SoundInfo *si;
si = (struct SoundInfo *) param;
Hash_FindOrAdd(&gSoundCache, (char *) pszURL, NULL, si);
if (bAbort) goto abortExit;
// if its a bksound, then don't show up in history
if ( ! si->fHidden )
GHist_Add((char *) pszURL, NULL, time(NULL), TRUE);
GTR_strncpy(si->szURL, pszURL, MAX_URL_STRING);
// if pszFileHREF is not NULL, then file wasn't copied, but passed as path
if (pszFileHREF)
{
if (si->fsOrig)
{
if (!si->bNoDeleteFile)
{
if (!si->fDCached)
remove(si->fsOrig); // remove the file if not cached to disk
}
GTR_FREE(si->fsOrig);
}
si->bNoDeleteFile = TRUE;
if (!(si->fsOrig = GTR_MALLOC(_MAX_PATH + 1)))
goto abortExit;
GTR_strncpy(si->fsOrig, pszFileHREF, _MAX_PATH);
}
switch (si->type)
{
case SOUND_AU:
si->fDCached = ( fDCache
&& gPrefs.bEnableDiskCache
&& FUpdateBuiltinDCache(WWW_AUDIO, pszURL, &si->fsOrig, dctExpires, dctLastModif, TRUE, si->tw));
AuProcess(si, pszURL);
break;
case SOUND_AIFF:
si->fDCached = ( fDCache
&& gPrefs.bEnableDiskCache
&& FUpdateBuiltinDCache(WWW_AIFF, pszURL, &si->fsOrig, dctExpires, dctLastModif, TRUE, si->tw));
AiffProcess(si, pszURL);
break;
}
ResetCIFEntryCurDoc(pszURL);
return;
abortExit:
if (bAbort)
{
if (si->fsOrig)
{
if ((!si->bNoDeleteFile) && (!si->fDCached))
{
remove(si->fsOrig); // remove the file if not cached to disk
}
GTR_FREE(si->fsOrig);
}
GTR_FREE(si);
}
}
HTStream *SoundPlayer_Present(struct Mwin *tw, HTRequest *request, void *param, HTFormat input_format, HTFormat output_format, HTStream *output_stream)
{
struct SoundInfo *si;
HTStream *me;
char path[_MAX_PATH + 1];
int format;
#ifdef WIN32
{
int available_device = 0;
available_device = waveOutGetNumDevs();
if (available_device == 0)
{
/* Can't play sound on this machine. Tell user. */
ERR_ReportError(tw, errNoSoundDevice, "", "");
return NULL;
}
}
#endif /* WIN32 */
if (!bInitialized)
{
Hash_Init(&gSoundCache);
bInitialized = TRUE;
}
if (input_format == HTAtom_for("audio/basic"))
format = SOUND_AU;
else if (input_format == HTAtom_for("audio/aiff") ||
input_format == HTAtom_for("audio/x-aiff"))
format = SOUND_AIFF;
else
format = SOUND_INVALID;
if (format == SOUND_INVALID)
return NULL;
if (!(si = GTR_MALLOC(sizeof(struct SoundInfo))))
goto LError;
memset(si, 0, sizeof(struct SoundInfo));
si->type = format;
si->tw_refer = tw;
si->bNoDeleteFile = TRUE;
if (request->szLocalFileName)
{
if (!(si->fsOrig = GTR_MALLOC(_MAX_PATH + 1)))
goto LError;
strcpy(si->fsOrig, request->szLocalFileName);
request->nosavedlg = TRUE;
request->savefile = NULL;
}
else
{
if (!request->fImgFromDCache)
{
// Get a temporary file name to pass to SaveLocally
if (!(si->fsOrig = GTR_MALLOC(_MAX_PATH + 1)))
goto LError;
if ( GetTempFileName(gPrefs.szCacheLocation, "A", 0, si->fsOrig) == 0 ) {
path[0] = 0;
PREF_GetTempPath(_MAX_PATH, path);
GetTempFileName(path, "A", 0, si->fsOrig);
}
request->savefile = si->fsOrig;
si->bNoDeleteFile = FALSE;
}
else
si->fsOrig = request->savefile;
}
request->nosavedlg = TRUE;
me = HTSaveWithCallback(tw, request, si, input_format, Sound_Callback);
return me;
LError:
if (si)
{
if (si->fsOrig)
GTR_FREE(si->fsOrig);
GTR_FREE(si);
}
return NULL;
}
BOOL SoundPlayer_ShowCachedFile(const char *pszURL)
{
char *pURL;
struct SoundInfo *si;
if (!bInitialized)
return FALSE;
/* Check if a window with the given URL exists */
if (Hash_Find(&gSoundCache, (char *) pszURL, &pURL, (void **)&si) != -1)
{
#ifdef WIN32
if (IsWindow(si->hwnd))
{
/* If the window exists then check its enabled status. If it is
not enabled, it means that the error dialog is up. In this
case, let the error dialog become active. */
if (IsWindowEnabled(si->hwnd))
TW_RestoreWindow(si->hwnd);
else
TW_EnableModalChild(si->hwnd);
return TRUE;
}
#endif
}
return FALSE;
}
void SoundPlayer_CleanUp(void)
{
int count, i;
struct SoundInfo *si;
if (!bInitialized)
return;
#ifdef WIN32
SoundPlayer_FreeBitmaps();
#endif
/* Destroy all open windows */
count = Hash_Count(&gSoundCache);
for (i = 0; i < count; i++)
{
Hash_GetIndexedEntry(&gSoundCache, i, NULL, NULL, (void **)&si);
#ifdef WIN32
if (IsWindow(si->hwnd))
DestroyWindow(si->hwnd);
GTR_FREE(si);
#endif
}
Hash_FreeContents(&gSoundCache);
}
#ifdef WIN32
HWND SoundPlayer_GetNextWindow(BOOL bStart)
{
static int current_index = 0;
struct SoundInfo *si;
if (bStart)
current_index = 0;
if (current_index >= Hash_Count(&gSoundCache))
return NULL;
if (!bStart)
current_index++;
if (current_index >= Hash_Count(&gSoundCache))
return NULL;
Hash_GetIndexedEntry(&gSoundCache, current_index, NULL, NULL, (void **) &si);
return (si->hwnd);
}
BOOL SoundPlayer_IsWindow(HWND hwnd)
{
int i;
struct SoundInfo *si;
for (i = 0; i < Hash_Count(&gSoundCache); i++)
{
Hash_GetIndexedEntry(&gSoundCache, i, NULL, NULL, (void **) &si);
if (si->hwnd == hwnd)
return TRUE;
}
return FALSE;
}
#endif
#endif