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.
 
 
 
 
 
 

762 lines
19 KiB

/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Author(s):
Albert Lee [email protected]
*/
#include "all.h"
#ifdef MAC
#include "AIFF.h"
#endif
#ifdef FEATURE_SOUND_PLAYER
#ifdef MAC
/* FIXME "min" macro inherently unsafe */
#define min(fix, me) ((fix < me) ? fix : me)
#endif /* def MAC */
#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 };
static 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;
}
}
static 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;
}
}
#ifndef UNIX
/* we may eventually want to move this to a shared header */
typedef struct _AUHEADER
{
unsigned long magic;
unsigned long header_size;
unsigned long data_size;
unsigned long encoding;
unsigned long sample_rate;
unsigned long channels;
} AUHEADER;
static BOOL AuReadHeader(struct SoundInfo *si, FILE *fp)
{
AUHEADER header;
if (fread(&header, 1, sizeof(AUHEADER), fp) != sizeof(AUHEADER))
{
XX_DMsg(DBG_MM, ("Premature end of AU file\n"));
return FALSE;
}
/* set the swap flag */
switch(header.magic)
{
case DEC_INV_MAGIC:
XX_DMsg(DBG_MM, ("Found inverted DEC magic word\n"));
si->swap = TRUE;
break;
case SUN_INV_MAGIC:
XX_DMsg(DBG_MM, ("Found inverted Sun/NeXT magic word\n"));
si->swap = TRUE;
break;
case SUN_MAGIC:
XX_DMsg(DBG_MM, ("Found Sun/NeXT magic word\n"));
break;
case DEC_MAGIC:
XX_DMsg(DBG_MM, ("Found DEC magic word\n"));
break;
default:
XX_DMsg(DBG_MM, ("Invalid AU magic word found\n"));
return FALSE;
}
/* Assign variables */
si->magic = header.magic;
si->hdr_size = header.header_size;
si->data_size = header.data_size;
si->encoding = header.encoding;
si->sample_rate = header.sample_rate;
si->channels = header.channels;
/* swap if necessary */
if (si->swap)
{
swapLongs(&si->hdr_size, 1);
swapLongs(&si->data_size, 1);
swapLongs(&si->encoding, 1);
swapLongs(&si->sample_rate, 1);
swapLongs(&si->channels, 1);
}
/* Translate encoding into style and size */
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, ("Unsupported encoding: 0x%lx = %ld\n", si->encoding, si->encoding));
return FALSE;
}
XX_DMsg(DBG_MM, ("Header size: 0x%lx = %ld\n", si->hdr_size, si->hdr_size));
if (si->hdr_size < SUN_HDRSIZE)
{
XX_DMsg(DBG_MM, ("Incorrect header size\n"));
return FALSE;
}
XX_DMsg(DBG_MM, ("Data size: 0x%lx = %ld\n", si->data_size, si->data_size));
XX_DMsg(DBG_MM, ("Encoding: 0x%lx = %ld\n", si->encoding, si->encoding));
XX_DMsg(DBG_MM, ("Sample rate: 0x%lx = %ld\n", si->sample_rate, si->sample_rate));
XX_DMsg(DBG_MM, ("Channels: 0x%lx = %ld\n", si->channels, si->channels));
/* Ignore string info at the end of the header */
si->hdr_size -= SUN_HDRSIZE;
if (fseek(fp, si->hdr_size, SEEK_CUR))
{
XX_DMsg(DBG_MM, ("Premature end of AU file\n"));
return FALSE;
}
if (si->data_size == -1 || si->data_size == 0) /* data_size was not given, compute it */
{
long curpos, endpos;
curpos = ftell(fp);
fseek(fp, 0, SEEK_END);
endpos = ftell(fp);
si->data_size = endpos - curpos; /* don't count current byte */
fseek(fp, curpos, SEEK_SET);
}
return TRUE;
}
static BOOL AuAllocateMemory(struct SoundInfo *si, FILE *fp)
{
si->loc = 0;
switch(si->size)
{
case SIZE_BYTE:
if (si->style == SIGN2)
si->buf_size = si->data_size;
else
si->buf_size = si->data_size * 2; /* must be ulaw */
si->buf = GTR_MALLOC(si->buf_size);
if (!si->buf)
return FALSE;
break;
case SIZE_WORD:
si->buf_size = si->data_size * 2;
si->buf = GTR_MALLOC(si->buf_size);
if (!si->buf)
return FALSE;
break;
}
return TRUE;
}
#ifdef MAC
/* Mac au file processor. Converts an au file into an AIFF file. */
BOOL AuProcess(struct SoundInfo *si, const char *pszURL)
{
FILE *fp;
long size;
int c;
FILE *aiffOut;
ContainerChunk myContainer;
CommonChunk myCommon;
SoundDataChunk mySoundData;
const long headerSize = sizeof (ContainerChunk)
+ sizeof (CommonChunk) + sizeof (SoundDataChunk);
FSSpec tempSpec;
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;
if (!AuReadHeader(si, fp))
{
ERR_ReportError(si->tw_refer, SID_ERR_INVALID_SOUND_FORMAT, NULL, NULL);
return FALSE;
}
MakeTempFile(&tempSpec, "Procd");
si->fsPlayBack = PathNameFromFSSpec(tempSpec);
aiffOut = fopen(si->fsPlayBack, "wb");
if (aiffOut == NULL)
return FALSE; /* FIXME -- dispose of fp */
/* skip over header */
fseek(aiffOut, headerSize, SEEK_SET);
WAIT_Push(si->tw_refer, waitNoInteract, GTR_GetString(SID_INF_PROCESSING_AU_FILE));
WAIT_SetRange(si->tw_refer, 0, 100, size);
/* read in the buffer and process */
if (si->style == ULAW)
{
if (si->size == SIZE_WORD)
{
unsigned short sample;
while ((c = getc(fp)) != EOF)
{
sample = ulaw_table[c] ^0x8000u;
fwrite(&sample, 2, 1, aiffOut);
}
}
else
{
unsigned char incode;
signed char outcode;
while(fread(&incode, 1, 1, fp))
{
outcode = (ulaw_table[incode] / 256);
fwrite(&outcode, 1, 1, aiffOut);
}
}
}
else
{
if (si->size == SIZE_BYTE)
{
unsigned char sample;
while(fread(&sample, 1, 1, fp))
{
/* sample ^= 0x80u; */
fwrite(&sample, 1, 1, aiffOut);
}
}
else
{
/* SIZE_WORD - Read only even bytes */
unsigned char sample[2];
while(fread(sample, 2, 1, fp))
{
/* sample ^= 0x8000u; */
fwrite(sample, 2, 1, aiffOut);
}
}
}
fclose(fp);
/* now go back and write the AIFF header info */
size = ftell(aiffOut);
fseek(aiffOut, 0, SEEK_SET);
myContainer.ckID = FORMID;
myContainer.ckSize = size - sizeof(ChunkHeader); /* is this right? */
myContainer.formType = AIFFID;
fwrite(&myContainer, sizeof(ContainerChunk), 1, aiffOut);
myCommon.ckID = CommonID;
myCommon.ckSize = sizeof(CommonChunk) - sizeof(ChunkHeader);
myCommon.numChannels = si->channels;
myCommon.numSampleFrames = (size - headerSize) / (si->size * si->channels);
myCommon.sampleSize = si->size * 8;
#ifdef powerc
{
long double convert;
convert = si->sample_rate;
ldtox80(&convert, &(myCommon.sampleRate));
}
#else
myCommon.sampleRate = si->sample_rate;
#endif
fwrite(&myCommon, sizeof(CommonChunk), 1, aiffOut);
mySoundData.ckID = SoundDataID;
mySoundData.ckSize = size - headerSize
+ sizeof (SoundDataChunk) - sizeof (ChunkHeader);
mySoundData.offset = 0;
mySoundData.blockSize = 0;
fwrite(&mySoundData, sizeof(SoundDataChunk), 1, aiffOut);
fclose (aiffOut);
WAIT_Pop(si->tw_refer);
CreateSoundPlayer(si, pszURL);
return (TRUE);
}
#else /* !MAC */
BOOL AuProcess(struct SoundInfo *si, const char *pszURL)
{
FILE *fp;
long size = 0;
long actual, even;
int c, i;
char *buf;
short *sbuf;
#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;
if (!AuReadHeader(si, fp))
{
ERR_ReportError(si->tw_refer, SID_ERR_INVALID_SOUND_FORMAT, NULL, NULL);
return FALSE;
}
if (!AuAllocateMemory(si, fp))
{
ERR_ReportError(si->tw_refer, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
return FALSE;
}
WAIT_Push(si->tw_refer, waitNoInteract, GTR_GetString(SID_INF_PROCESSING_AU_FILE));
WAIT_SetRange(si->tw_refer, 0, 100, size);
/* read in the buffer and process */
if (si->style == ULAW)
{
if (si->size == SIZE_WORD)
{
sbuf = (short *) si->buf;
while (((c = getc(fp)) != EOF) &&
(si->loc < si->data_size))
{
*sbuf++ = ulaw_table[c];
si->loc++;
}
}
else
{
buf = (char *) si->buf;
while (((c = getc(fp)) != EOF) &&
(si->loc < si->data_size))
{
*buf++ = (ulaw_table[c] / 256) ^ 0x80;
si->loc++;
}
}
}
else
{
if (si->size == SIZE_BYTE)
{
actual = fread(si->buf, 1, si->buf_size, fp);
si->loc = min(actual, si->buf_size);
if (actual != si->buf_size)
{
/* There should be a warning here that says that the file
is smaller than described in the header */
}
buf = si->buf;
/* Invert sign bit */
for (i = 0; i < actual; i++)
*buf++ ^= 0x80;
}
else
{
/* SIZE_WORD - Read only even bytes */
even = si->buf_size;
if ((even % 2) == 1)
even--;
actual = fread(si->buf, 1, even, fp);
si->loc = min(actual, even);
if (actual != si->buf_size)
{
/* There should be a warning here that says that the file
is smaller than described in the header */
}
swapShorts((unsigned short *) si->buf, actual / 2);
sbuf = (short *) si->buf;
for (i = 0; i < actual / 2; i++)
*sbuf++ ^= 0x8000;
}
}
fclose(fp);
WAIT_Pop(si->tw_refer);
CreateSoundPlayer(si, pszURL);
return (TRUE);
}
#endif /* !MAC */
#endif
static void Sound_Callback(void *param, const char *pszURL, BOOL bAbort)
{
struct SoundInfo *si;
si = (struct SoundInfo *) param;
if (bAbort)
{
GTR_FREE(si->fsOrig);
GTR_FREE(si);
return;
}
switch (si->type)
{
case SOUND_AU:
if (!AuProcess(si, pszURL))
return;
else
break;
case SOUND_AIFF:
if (!AiffProcess(si, pszURL))
return;
else
break;
}
Hash_FindOrAdd(&gSoundCache, (char *) pszURL, NULL, si);
GHist_Add((char *) pszURL, NULL, time(NULL));
GTR_strncpy(si->szURL, pszURL, MAX_URL_STRING);
}
HTStream *SoundPlayer_Present(struct Mwin *tw, HTRequest *request, void *param, HTFormat input_format, HTFormat output_format, HTStream *output_stream)
{
struct SoundInfo *si;
HTStream *me;
#ifdef WIN32
char path[_MAX_PATH + 1];
#endif
enum sound_formats 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, SID_ERR_NO_SOUND_DEVICE, NULL, NULL);
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/x-aiff"))
format = SOUND_AIFF;
else
format = SOUND_INVALID;
if (format == SOUND_INVALID)
return NULL;
si = GTR_MALLOC(sizeof(struct SoundInfo));
memset(si, 0, sizeof(struct SoundInfo));
si->fsOrig = GTR_MALLOC(_MAX_PATH + 1);
si->type = format;
si->tw_refer = tw;
if (request->szLocalFileName)
{
strcpy(si->fsOrig, request->szLocalFileName);
si->bNoDeleteFile = TRUE;
request->nosavedlg = TRUE;
request->savefile = NULL;
}
else
{
#ifdef WIN32
path[0] = '\0';
PREF_GetTempPath(_MAX_PATH, path);
GetTempFileName(path, "A", 0, si->fsOrig);
#endif
#ifdef UNIX
xgtr_build_tempfile ( (char *)NULL, (char *)NULL,
(char *)HTFileSuffix (input_format), si->fsOrig);
tw->pSoundInfo = si;
#endif
#ifdef MAC
{
FSSpec tempSpec;
MakeTempFile(&tempSpec, "Orig");
si->fsOrig = PathNameFromFSSpec(tempSpec);
}
#endif
si->bNoDeleteFile = FALSE;
request->nosavedlg = TRUE;
request->savefile = si->fsOrig;
}
me = HTSaveWithCallback(tw, request, si, input_format, Sound_Callback);
return me;
}
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 UNIX
if (si->tw)
{
unHideWindow(si->tw);
return TRUE;
}
#endif
#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