diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3841a63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +colorchord2/windows/colorchord.def +colorchord2/colorchord.def \ No newline at end of file diff --git a/colorchord2/DisplayHIDAPI.c b/colorchord2/DisplayHIDAPI.c new file mode 100644 index 0000000..5e4dd70 --- /dev/null +++ b/colorchord2/DisplayHIDAPI.c @@ -0,0 +1,241 @@ +//Copyright 2015 <>< Charles Lohr under the ColorChord License. + +#include "outdrivers.h" +#include "notefinder.h" +#include +#include +#include "parameters.h" +#include +#include "hidapi.h" +#include "color.h" +#include + +struct HIDAPIOutDriver +{ + hid_device *devh; + int did_init; + int zigzag; + int total_leds; + int array; + float outamp; + uint8_t * last_leds; + int buffersize; + volatile int readyFlag; + int xn; + int yn; + int rot90; + int is_rgby; + int bank_size[4]; + int bank_id[4]; +}; + + +static void * LEDOutThread( void * v ) +{ + struct HIDAPIOutDriver * led = (struct HIDAPIOutDriver*)v; + while(1) + { + int total_bytes = led->buffersize; + total_bytes = ((total_bytes-2)&0xffc0) + 0x41; //Round up. + if( led->readyFlag ) + { +/* + int i; + printf( "%d -- ", total_bytes ); + for( i = 0; i < total_bytes; i++ ) + { + if( !( i & 0x0f ) ) printf( "\n" ); + printf( "%02x ", led->last_leds[i] ); + } + printf( "\n" ); +*/ + int r = hid_send_feature_report( led->devh, led->last_leds, total_bytes ); + if( r < 0 ) + { + led->did_init = 0; + printf( "Fault sending LEDs.\n" ); + } + led->readyFlag = 0; + } + OGUSleep(100); + } + return 0; +} + +static void LEDUpdate(void * id, struct NoteFinder*nf) +{ + int i; + struct HIDAPIOutDriver * led = (struct HIDAPIOutDriver*)id; + + + if( !led->did_init ) + { + led->did_init = 1; + hid_init(); + + led->devh = hid_open( 0xabcd, 0xf104, 0 ); + + if( !led->devh ) + { + fprintf( stderr, "Error: Cannot find device.\n" ); +// exit( -98 ); + } + } + + int leds_this_round = 0; + int ledbid = 0; + + while( led->readyFlag ) OGUSleep(100); + + int lastledplace = 1; + led->last_leds[0] = 0; + + int k = 0; + + //Advance the LEDs to this position when outputting the values. + for( i = 0; i < led->total_leds; i++ ) + { + int source = i; + if( !led->array ) + { + int sx, sy; + if( led->rot90 ) + { + sy = i % led->yn; + sx = i / led->yn; + } + else + { + sx = i % led->xn; + sy = i / led->xn; + } + + if( led->zigzag ) + { + if( led->rot90 ) + { + if( sx & 1 ) + { + sy = led->yn - sy - 1; + } + } + else + { + if( sy & 1 ) + { + sx = led->xn - sx - 1; + } + } + } + + if( led->rot90 ) + { + source = sx + sy * led->xn; + } + else + { + source = sx + sy * led->yn; + } + } + + + if( led->is_rgby ) + { + int r = OutLEDs[k++]; + int g = OutLEDs[k++]; + int b = OutLEDs[k++]; + int y = 0; + int rg_common; + if( r/2 > g ) rg_common = g; + else rg_common = r/2; + + if( rg_common > 255 ) rg_common = 255; + y = rg_common; + r -= rg_common; + g -= rg_common; + if( r < 0 ) r = 0; + if( g < 0 ) g = 0; + + + if( (lastledplace % 64) == 1 ) led->last_leds[lastledplace++] = led->bank_id[ledbid]; + led->last_leds[lastledplace++] = g * led->outamp; + if( (lastledplace % 64) == 1 ) led->last_leds[lastledplace++] = led->bank_id[ledbid]; + led->last_leds[lastledplace++] = r * led->outamp; + if( (lastledplace % 64) == 1 ) led->last_leds[lastledplace++] = led->bank_id[ledbid]; + led->last_leds[lastledplace++] = b * led->outamp; + if( (lastledplace % 64) == 1 ) led->last_leds[lastledplace++] = led->bank_id[ledbid]; + led->last_leds[lastledplace++] = y * led->outamp; + } + else + { + if( (lastledplace % 64) == 1 ) led->last_leds[lastledplace++] = led->bank_id[ledbid]; + led->last_leds[lastledplace++] = OutLEDs[source*3+1] * led->outamp; + if( (lastledplace % 64) == 1 ) led->last_leds[lastledplace++] = led->bank_id[ledbid]; + led->last_leds[lastledplace++] = OutLEDs[source*3+0] * led->outamp; + if( (lastledplace % 64) == 1 ) led->last_leds[lastledplace++] = led->bank_id[ledbid]; + led->last_leds[lastledplace++] = OutLEDs[source*3+2] * led->outamp; + } + //printf( "%3d -- %3d [%3d] == %d %d %d\n", ledbid, source, lastledplace, OutLEDs[source*3+1], OutLEDs[source*3+0], OutLEDs[source*3+2] ); + leds_this_round++; + while( leds_this_round >= led->bank_size[ledbid] ) + { + while( (lastledplace % 64) != 1 ) led->last_leds[lastledplace++] = 0; + ledbid++; + if( ledbid > 3 ) break; + if( led->bank_size[ledbid] != 0 ) + led->last_leds[lastledplace++] = led->bank_id[ledbid]; + else + continue; + leds_this_round = 0; + } + if( ledbid > 3 ) break; + } + led->buffersize = lastledplace; + + led->readyFlag = 1; +} + +static void LEDParams(void * id ) +{ + struct HIDAPIOutDriver * led = (struct HIDAPIOutDriver*)id; + + led->total_leds = GetParameterI( "leds", 300 ); + led->last_leds = malloc( led->total_leds * 5 + 4 ); + led->outamp = .1; RegisterValue( "ledoutamp", PAFLOAT, &led->outamp, sizeof( led->outamp ) ); + led->zigzag = 0; RegisterValue( "zigzag", PAINT, &led->zigzag, sizeof( led->zigzag ) ); + led->xn = 16; RegisterValue( "lightx", PAINT, &led->xn, sizeof( led->xn ) ); + led->yn = 9; RegisterValue( "lighty", PAINT, &led->yn, sizeof( led->yn ) ); + led->rot90 = 0; RegisterValue( "rot90", PAINT, &led->rot90, sizeof( led->rot90 ) ); + led->array = 0; RegisterValue( "ledarray", PAINT, &led->array, sizeof( led->array ) ); + led->is_rgby = 0; RegisterValue( "ledisrgby", PAINT, &led->is_rgby, sizeof( led->is_rgby ) ); + + led->bank_size[0] = 0; RegisterValue( "bank1_size", PAINT, &led->bank_size[0], sizeof( led->bank_size[0] ) ); + led->bank_size[1] = 0; RegisterValue( "bank2_size", PAINT, &led->bank_size[1], sizeof( led->bank_size[1] ) ); + led->bank_size[2] = 0; RegisterValue( "bank3_size", PAINT, &led->bank_size[2], sizeof( led->bank_size[2] ) ); + led->bank_size[3] = 0; RegisterValue( "bank4_size", PAINT, &led->bank_size[3], sizeof( led->bank_size[3] ) ); + led->bank_id[0] = 0; RegisterValue( "bank1_id", PAINT, &led->bank_id[0], sizeof( led->bank_id[0] ) ); + led->bank_id[1] = 0; RegisterValue( "bank2_id", PAINT, &led->bank_id[1], sizeof( led->bank_id[1] ) ); + led->bank_id[2] = 0; RegisterValue( "bank3_id", PAINT, &led->bank_id[2], sizeof( led->bank_id[2] ) ); + led->bank_id[3] = 0; RegisterValue( "bank4_id", PAINT, &led->bank_id[3], sizeof( led->bank_id[3] ) ); + + led->did_init = 0; +} + + +static struct DriverInstances * DisplayHIDAPI() +{ + struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) ); + memset( ret, 0, sizeof( struct DriverInstances ) ); + struct HIDAPIOutDriver * led = ret->id = malloc( sizeof( struct HIDAPIOutDriver ) ); + ret->Func = LEDUpdate; + ret->Params = LEDParams; + OGCreateThread( LEDOutThread, led ); + led->readyFlag = 0; + LEDParams( led ); + return ret; + +} + +REGISTER_OUT_DRIVER(DisplayHIDAPI); + + diff --git a/colorchord2/DisplayNetwork.c b/colorchord2/DisplayNetwork.c index 6ea00c9..b30ac5d 100644 --- a/colorchord2/DisplayNetwork.c +++ b/colorchord2/DisplayNetwork.c @@ -9,10 +9,12 @@ #include #include "color.h" #include "DrawFunctions.h" -#include -#ifdef WIN32 +#if defined(WIN32) || defined(WINDOWS) #include +#ifdef TCC +#include +#endif #define MSG_NOSIGNAL 0 #else #include diff --git a/colorchord2/DisplaySHM.c b/colorchord2/DisplaySHM.c new file mode 100644 index 0000000..e4eb3e1 --- /dev/null +++ b/colorchord2/DisplaySHM.c @@ -0,0 +1,121 @@ +//Copyright 2015 <>< Charles Lohr under the ColorChord License. + +#include "outdrivers.h" +#include "notefinder.h" +#include +#include "parameters.h" +#include +#include +#include +#include "color.h" +#include "DrawFunctions.h" +#include +#include /* For mode constants */ +#include /* For O_* constants */ +#include + +extern struct NoteFinder * nf; + + +struct SHMDriver +{ + int lights_file; + int dft_file; + int notes_file; + + uint8_t * dft_ptr; + uint8_t * lights_ptr; + uint8_t * notes_ptr; + + int total_dft; + int total_leds; +}; + + +static void SHMUpdate(void * id, struct NoteFinder*nf) +{ + struct SHMDriver * d = (struct SHMDriver*)id; + + if( !d->lights_file ) + { + const char * shmname = GetParameterS( "shm_lights", 0 ); + if( shmname ) + { + d->lights_file = shm_open(shmname, O_CREAT | O_RDWR, 0644); + ftruncate( d->lights_file, 16384 ); + d->lights_ptr = mmap(0,16384, PROT_READ | PROT_WRITE, MAP_SHARED, d->lights_file, 0); + } + } + + + if( !d->dft_file ) + { + const char * shmname = GetParameterS( "shm_dft", 0 ); + if( shmname ) + { + d->dft_file = shm_open(shmname, O_CREAT | O_RDWR, 0644); + ftruncate( d->dft_file, 16384 ); + d->dft_ptr = mmap(0,16384, PROT_READ | PROT_WRITE, MAP_SHARED, d->dft_file, 0); + } + } + + + if( !d->notes_file ) + { + const char * shmname = GetParameterS( "shm_notes", 0 ); + if( shmname ) + { + d->notes_file = shm_open(shmname, O_CREAT | O_RDWR, 0644); + ftruncate( d->notes_file, 16384 ); + d->notes_ptr = mmap(0,16384, PROT_READ | PROT_WRITE, MAP_SHARED, d->notes_file, 0); + } + } + + + if( d->dft_ptr ) + { + + d->total_dft = nf->octaves * nf->freqbins; + memcpy( d->dft_ptr+0, &nf->octaves, 4 ); + memcpy( d->dft_ptr+4, &nf->freqbins, 4 ); + memcpy( d->dft_ptr+8, nf->folded_bins, nf->freqbins * sizeof(float) ); + memcpy( d->dft_ptr+8+nf->freqbins * sizeof(float), + nf->outbins, d->total_dft * sizeof(float) ); + } + + if( d->lights_ptr ) + { + memcpy( d->lights_ptr, &d->total_leds, 4 ); + memcpy( d->lights_ptr + 4, OutLEDs, d->total_leds*3 ); + } + + + if( d->notes_ptr ) + { + memcpy( d->notes_ptr, &nf->dists_count, 4 ); + memcpy( d->notes_ptr+4, nf->dists, sizeof( nf->dists[0] ) * nf->dists_count ); + } + +} + +static void SHMParams(void * id ) +{ + struct SHMDriver * d = (struct SHMDriver*)id; + + d->total_leds = 300; RegisterValue( "leds", PAINT, &d->total_leds, sizeof( d->total_leds )); +} + +static struct DriverInstances * DisplaySHM(const char * parameters) +{ + struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) ); + struct SHMDriver * d = ret->id = malloc( sizeof( struct SHMDriver ) ); + memset( d, 0, sizeof( struct SHMDriver ) ); + ret->Func = SHMUpdate; + ret->Params = SHMParams; + SHMParams( d ); + return ret; +} + +REGISTER_OUT_DRIVER(DisplaySHM); + + diff --git a/colorchord2/Makefile b/colorchord2/Makefile index 2a74f53..64d16a8 100644 --- a/colorchord2/Makefile +++ b/colorchord2/Makefile @@ -3,14 +3,15 @@ all : colorchord RAWDRAW:=DrawFunctions.o XDriver.o SOUND:=sound.o sound_alsa.o sound_pulse.o sound_null.o -OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayDMX.o OutputProminent.o RecorderPlugin.o OutputCells.o +OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayDMX.o OutputProminent.o RecorderPlugin.o DisplayHIDAPI.o hidapi.o OutputCells.o DisplaySHM.o WINGCC:= i686-w64-mingw32-gcc -WINGCCFLAGS:= -s -DICACHE_FLASH_ATTR= -I../embeddedcommon -I. -O1 #-O2 -Wl,--relax -Wl,--gc-sections -ffunction-sections -fdata-sections -WINLDFLAGS:=-lwinmm -lgdi32 -lws2_32 + +WINGCCFLAGS:= -g -DICACHE_FLASH_ATTR= -I../embeddedcommon -I. -O1 #-O2 -Wl,--relax -Wl,--gc-sections -ffunction-sections -fdata-sections +WINLDFLAGS:=-lwinmm -lgdi32 -lws2_32 -lsetupapi RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext -LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse +LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse -ludev -lrt CFLAGS:=-g -O0 -flto -Wall -ffast-math -I../embeddedcommon -I. -DICACHE_FLASH_ATTR= @@ -19,7 +20,8 @@ EXTRALIBS:=-lusb-1.0 colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o hook.o ../embeddedcommon/DFT32.o configs.o gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS) -colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c OutputProminent.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c hook.c RecorderPlugin.c ../embeddedcommon/DFT32.c OutputCells.c configs.c + +colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c OutputProminent.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c hook.c RecorderPlugin.c ../embeddedcommon/DFT32.c OutputCells.c configs.c hidapi.c DisplayHIDAPI.c $(WINGCC) $(WINGCCFLAGS) -o $@ $^ $(WINLDFLAGS) diff --git a/colorchord2/OutputCells.c b/colorchord2/OutputCells.c index 502f985..4f5bee6 100644 --- a/colorchord2/OutputCells.c +++ b/colorchord2/OutputCells.c @@ -12,7 +12,6 @@ #include "color.h" #include #include -#include extern float DeltaFrameTime; extern double Now; diff --git a/colorchord2/OutputLinear.c b/colorchord2/OutputLinear.c index bac98ae..5c3d334 100644 --- a/colorchord2/OutputLinear.c +++ b/colorchord2/OutputLinear.c @@ -12,7 +12,6 @@ #include "color.h" #include #include -#include struct LEDOutDriver { diff --git a/colorchord2/OutputProminent.c b/colorchord2/OutputProminent.c index a9cfb6c..c9f1792 100644 --- a/colorchord2/OutputProminent.c +++ b/colorchord2/OutputProminent.c @@ -11,7 +11,6 @@ #include "color.h" #include #include -#include struct ProminentDriver { diff --git a/colorchord2/default.conf b/colorchord2/default.conf index 6bc9161..41f76a5 100644 --- a/colorchord2/default.conf +++ b/colorchord2/default.conf @@ -18,7 +18,7 @@ play = 0 rec = 1 channels = 2 samplerate = 44100 -wininput = 0 +wininput = 1 #Compiled version will default this. #sound_source = ALSA diff --git a/colorchord2/dft.c b/colorchord2/dft.c index 2ee7174..a28a758 100644 --- a/colorchord2/dft.c +++ b/colorchord2/dft.c @@ -420,7 +420,9 @@ uint16_t Sdatspace[FIXBINS*4]; //(advances,places,isses,icses) static uint8_t Sdo_this_octave[BINCYCLE]; static int16_t Saccum_octavebins[OCTAVES]; static uint8_t Swhichoctaveplace; +#ifndef INCLUDING_EMBEDDED uint16_t embeddedbins[FIXBINS]; //This is updated every time the DFT hits the octavecount, or 1/32 updates. +#endif //From: http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 /** diff --git a/colorchord2/hidapi.c b/colorchord2/hidapi.c new file mode 100644 index 0000000..ceb7832 --- /dev/null +++ b/colorchord2/hidapi.c @@ -0,0 +1,2918 @@ +#ifdef _WIN32 + +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + + +/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) + + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. +*/ + +#include + +#ifndef _NTDEF_ +typedef LONG NTSTATUS; +#endif + +#ifdef __MINGW32__ +#include +#include +#endif + +#ifdef __CYGWIN__ +#include +#define _wcsdup wcsdup +#endif + +/* The maximum number of characters that can be passed into the + HidD_Get*String() functions without it failing.*/ +#define MAX_STRING_WCHARS 0xFFF + +/*#define HIDAPI_USE_DDK*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TCC + typedef struct _SP_DEVINFO_DATA { + DWORD cbSize; + GUID ClassGuid; + DWORD DevInst; + ULONG_PTR Reserved; + } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA; + typedef struct _SP_DEVICE_INTERFACE_DATA { + DWORD cbSize; + GUID InterfaceClassGuid; + DWORD Flags; + ULONG_PTR Reserved; + } SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA; + typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA { + DWORD cbSize; + CHAR DevicePath[ANYSIZE_ARRAY]; + } SP_DEVICE_INTERFACE_DETAIL_DATA_A, *PSP_DEVICE_INTERFACE_DETAIL_DATA_A; + typedef PVOID HDEVINFO; + + HDEVINFO WINAPI SetupDiGetClassDevsA(CONST GUID*,PCSTR,HWND,DWORD); + + #define DIGCF_PRESENT 0x00000002 + #define DIGCF_DEVICEINTERFACE 0x00000010 + #define SPDRP_CLASS 7 + #define SPDRP_DRIVER 9 + #define FILE_DEVICE_KEYBOARD 0x0000000b + #define METHOD_OUT_DIRECT 2 + enum + { FILE_ANY_ACCESS = 0x00000000UL, + FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS, + FILE_READ_ACCESS = 0x00000001UL, + FILE_WRITE_ACCESS = 0x00000002UL + }; + #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) + +#else + #include + #include +#endif + #ifdef HIDAPI_USE_DDK + #include + #endif + + /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ + #define HID_OUT_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include +#include + + +#include "hidapi.h" + +#undef MIN +#define MIN(x,y) ((x) < (y)? (x): (y)) + +#ifdef _MSC_VER + /* Thanks Microsoft, but I know how to use strncpy(). */ + #pragma warning(disable:4996) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HIDAPI_USE_DDK + /* Since we're not building with the DDK, and the HID header + files aren't part of the SDK, we have to define all this + stuff here. In lookup_functions(), the function pointers + defined below are set. */ + typedef struct _HIDD_ATTRIBUTES{ + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + + typedef USHORT USAGE; + typedef struct _HIDP_CAPS { + USAGE Usage; + USAGE UsagePage; + USHORT InputReportByteLength; + USHORT OutputReportByteLength; + USHORT FeatureReportByteLength; + USHORT Reserved[17]; + USHORT fields_not_used_by_hidapi[10]; + } HIDP_CAPS, *PHIDP_CAPS; + typedef void* PHIDP_PREPARSED_DATA; + #define HIDP_STATUS_SUCCESS 0x110000 + + typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); + typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); + typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); + typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); + typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); + typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); + + static HidD_GetAttributes_ HidD_GetAttributes; + static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; + static HidD_GetManufacturerString_ HidD_GetManufacturerString; + static HidD_GetProductString_ HidD_GetProductString; + static HidD_SetFeature_ HidD_SetFeature; + static HidD_GetFeature_ HidD_GetFeature; + static HidD_GetIndexedString_ HidD_GetIndexedString; + static HidD_GetPreparsedData_ HidD_GetPreparsedData; + static HidD_FreePreparsedData_ HidD_FreePreparsedData; + static HidP_GetCaps_ HidP_GetCaps; + static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; + + static HMODULE lib_handle = NULL; + static BOOLEAN initialized = FALSE; +#endif /* HIDAPI_USE_DDK */ + +struct hid_device_ { + HANDLE device_handle; + BOOL blocking; + USHORT output_report_length; + size_t input_report_length; + void *last_error_str; + DWORD last_error_num; + BOOL read_pending; + char *read_buf; + OVERLAPPED ol; +}; + +static hid_device *new_hid_device() +{ + hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + dev->device_handle = INVALID_HANDLE_VALUE; + dev->blocking = TRUE; + dev->output_report_length = 0; + dev->input_report_length = 0; + dev->last_error_str = NULL; + dev->last_error_num = 0; + dev->read_pending = FALSE; + dev->read_buf = NULL; + memset(&dev->ol, 0, sizeof(dev->ol)); + dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + CloseHandle(dev->ol.hEvent); + CloseHandle(dev->device_handle); + LocalFree(dev->last_error_str); + free(dev->read_buf); + free(dev); +} + +static void register_error(hid_device *device, const char *op) +{ + WCHAR *ptr, *msg; + + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPVOID)&msg, 0/*sz*/, + NULL); + + /* Get rid of the CR and LF that FormatMessage() sticks at the + end of the message. Thanks Microsoft! */ + ptr = msg; + while (*ptr) { + if (*ptr == '\r') { + *ptr = 0x0000; + break; + } + ptr++; + } + + /* Store the message off in the Device entry so that + the hid_error() function can pick it up. */ + LocalFree(device->last_error_str); + device->last_error_str = msg; +} + +#ifndef HIDAPI_USE_DDK +static int lookup_functions() +{ + lib_handle = LoadLibraryA("hid.dll"); + if (lib_handle) { +#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; + RESOLVE(HidD_GetAttributes); + RESOLVE(HidD_GetSerialNumberString); + RESOLVE(HidD_GetManufacturerString); + RESOLVE(HidD_GetProductString); + RESOLVE(HidD_SetFeature); + RESOLVE(HidD_GetFeature); + RESOLVE(HidD_GetIndexedString); + RESOLVE(HidD_GetPreparsedData); + RESOLVE(HidD_FreePreparsedData); + RESOLVE(HidP_GetCaps); + RESOLVE(HidD_SetNumInputBuffers); +#undef RESOLVE + } + else + return -1; + + return 0; +} +#endif + +static HANDLE open_device(const char *path, BOOL enumerate) +{ + HANDLE handle; + DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); + DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + + handle = CreateFileA(path, + desired_access, + share_mode, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/ + 0); + + return handle; +} + +int HID_API_EXPORT hid_init(void) +{ +#ifndef HIDAPI_USE_DDK + if (!initialized) { + if (lookup_functions() < 0) { + hid_exit(); + return -1; + } + initialized = TRUE; + } +#endif + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ +#ifndef HIDAPI_USE_DDK + if (lib_handle) + FreeLibrary(lib_handle); + lib_handle = NULL; + initialized = FALSE; +#endif + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + BOOL res; + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + + /* Windows objects for interacting with the driver. */ + GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; + SP_DEVINFO_DATA devinfo_data; + SP_DEVICE_INTERFACE_DATA device_interface_data; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; + HDEVINFO device_info_set = INVALID_HANDLE_VALUE; + int device_index = 0; + int i; + + if (hid_init() < 0) + return NULL; + + /* Initialize the Windows objects. */ + memset(&devinfo_data, 0x0, sizeof(devinfo_data)); + devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); + device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + /* Get information for all the devices belonging to the HID class. */ + device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + /* Iterate over each device in the HID class, looking for the right one. */ + + for (;;) { + HANDLE write_handle = INVALID_HANDLE_VALUE; + DWORD required_size = 0; + HIDD_ATTRIBUTES attrib; + + res = SetupDiEnumDeviceInterfaces(device_info_set, + NULL, + &InterfaceClassGuid, + device_index, + &device_interface_data); + + if (!res) { + /* A return of FALSE from this function means that + there are no more devices. */ + break; + } + + /* Call with 0-sized detail size, and let the function + tell us how long the detail struct needs to be. The + size is put in &required_size. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + NULL, + 0, + &required_size, + NULL); + + /* Allocate a long enough structure for device_interface_detail_data. */ + device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); + device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + + /* Get the detailed data for this device. The detail data gives us + the device path for this device, which is then passed into + CreateFile() to get a handle to the device. */ + res = SetupDiGetDeviceInterfaceDetailA(device_info_set, + &device_interface_data, + device_interface_detail_data, + required_size, + NULL, + NULL); + + if (!res) { + /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); + Continue to the next device. */ + goto cont; + } + + /* Make sure this device is of Setup Class "HIDClass" and has a + driver bound to it. */ + for (i = 0; ; i++) { + char driver_name[256]; + + /* Populate devinfo_data. This function will return failure + when there are no more interfaces left. */ + res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); + if (!res) + goto cont; + + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (!res) + goto cont; + + if (strcmp(driver_name, "HIDClass") == 0) { + /* See if there's a driver bound. */ + res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, + SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); + if (res) + break; + } + } + + //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); + + /* Open a handle to the device */ + write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); + + /* Check validity of write_handle. */ + if (write_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + //register_error(dev, "CreateFile"); + goto cont_close; + } + + + /* Get the Vendor ID and Product ID for this device. */ + attrib.Size = sizeof(HIDD_ATTRIBUTES); + HidD_GetAttributes(write_handle, &attrib); + //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); + + /* Check the VID/PID to see if we should add this + device to the enumeration list. */ + if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && + (product_id == 0x0 || attrib.ProductID == product_id)) { + + #define WSTR_LEN 512 + const char *str; + struct hid_device_info *tmp; + PHIDP_PREPARSED_DATA pp_data = NULL; + HIDP_CAPS caps; + BOOLEAN res; + NTSTATUS nt_res; + wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ + size_t len; + + /* VID/PID match. Create the record. */ + tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + res = HidD_GetPreparsedData(write_handle, &pp_data); + if (res) { + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res == HIDP_STATUS_SUCCESS) { + cur_dev->usage_page = caps.UsagePage; + cur_dev->usage = caps.Usage; + } + + HidD_FreePreparsedData(pp_data); + } + + /* Fill out the record */ + cur_dev->next = NULL; + str = device_interface_detail_data->DevicePath; + if (str) { + len = strlen(str); + cur_dev->path = (char*) calloc(len+1, sizeof(char)); + strncpy(cur_dev->path, str, len+1); + cur_dev->path[len] = '\0'; + } + else + cur_dev->path = NULL; + + /* Serial Number */ + res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->serial_number = _wcsdup(wstr); + } + + /* Manufacturer String */ + res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->manufacturer_string = _wcsdup(wstr); + } + + /* Product String */ + res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); + wstr[WSTR_LEN-1] = 0x0000; + if (res) { + cur_dev->product_string = _wcsdup(wstr); + } + + /* VID/PID */ + cur_dev->vendor_id = attrib.VendorID; + cur_dev->product_id = attrib.ProductID; + + /* Release Number */ + cur_dev->release_number = attrib.VersionNumber; + + /* Interface Number. It can sometimes be parsed out of the path + on Windows if a device has multiple interfaces. See + http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or + search for "Hardware IDs for HID Devices" at MSDN. If it's not + in the path, it's set to -1. */ + cur_dev->interface_number = -1; + if (cur_dev->path) { + char *interface_component = strstr(cur_dev->path, "&mi_"); + if (interface_component) { + char *hex_str = interface_component + 4; + char *endptr = NULL; + cur_dev->interface_number = strtol(hex_str, &endptr, 16); + if (endptr == hex_str) { + /* The parsing failed. Set interface_number to -1. */ + cur_dev->interface_number = -1; + } + } + } + } + +cont_close: + CloseHandle(write_handle); +cont: + /* We no longer need the detail data. It can be freed */ + free(device_interface_detail_data); + + device_index++; + + } + + /* Close the device information handle. */ + SetupDiDestroyDeviceInfoList(device_info_set); + + return root; + +} + +void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) +{ + /* TODO: Merge this with the Linux version. This function is platform-independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + + +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* TODO: Merge this functions with the Linux version. This function should be platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) +{ + hid_device *dev; + HIDP_CAPS caps; + PHIDP_PREPARSED_DATA pp_data = NULL; + BOOLEAN res; + NTSTATUS nt_res; + + if (hid_init() < 0) { + return NULL; + } + + dev = new_hid_device(); + + /* Open a handle to the device */ + dev->device_handle = open_device(path, FALSE); + + /* Check validity of write_handle. */ + if (dev->device_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + register_error(dev, "CreateFile"); + goto err; + } + + /* Set the Input Report buffer size to 64 reports. */ + res = HidD_SetNumInputBuffers(dev->device_handle, 64); + if (!res) { + register_error(dev, "HidD_SetNumInputBuffers"); + goto err; + } + + /* Get the Input Report length for the device. */ + res = HidD_GetPreparsedData(dev->device_handle, &pp_data); + if (!res) { + register_error(dev, "HidD_GetPreparsedData"); + goto err; + } + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res != HIDP_STATUS_SUCCESS) { + register_error(dev, "HidP_GetCaps"); + goto err_pp_data; + } + dev->output_report_length = caps.OutputReportByteLength; + dev->input_report_length = caps.InputReportByteLength; + HidD_FreePreparsedData(pp_data); + + dev->read_buf = (char*) malloc(dev->input_report_length); + + return dev; + +err_pp_data: + HidD_FreePreparsedData(pp_data); +err: + free_hid_device(dev); + return NULL; +} + +int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + DWORD bytes_written; + BOOL res; + + OVERLAPPED ol; + unsigned char *buf; + memset(&ol, 0, sizeof(ol)); + + /* Make sure the right number of bytes are passed to WriteFile. Windows + expects the number of bytes which are in the _longest_ report (plus + one for the report number) bytes even if the data is a report + which is shorter than that. Windows gives us this value in + caps.OutputReportByteLength. If a user passes in fewer bytes than this, + create a temporary buffer which is the proper size. */ + if (length >= dev->output_report_length) { + /* The user passed the right number of bytes. Use the buffer as-is. */ + buf = (unsigned char *) data; + } else { + /* Create a temporary buffer and copy the user's data + into it, padding the rest with zeros. */ + buf = (unsigned char *) malloc(dev->output_report_length); + memcpy(buf, data, length); + memset(buf + length, 0, dev->output_report_length - length); + length = dev->output_report_length; + } + + res = WriteFile(dev->device_handle, buf, (DWORD)length, NULL, &ol); + int err = GetLastError(); + + if (!res) { + if (err != ERROR_IO_PENDING) { + /* WriteFile() failed. Return error. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + } + + /* Wait here until the write is done. This makes + hid_write() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); + if (!res) { + /* The Write operation failed. */ + register_error(dev, "WriteFile"); + bytes_written = -1; + goto end_of_function; + } + +end_of_function: + if (buf != data) + free(buf); + + return bytes_written; +} + + +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + DWORD bytes_read = 0; + size_t copy_len = 0; + BOOL res; + + /* Copy the handle for convenience. */ + HANDLE ev = dev->ol.hEvent; + + if (!dev->read_pending) { + /* Start an Overlapped I/O read. */ + dev->read_pending = TRUE; + memset(dev->read_buf, 0, dev->input_report_length); + ResetEvent(ev); + res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* ReadFile() has failed. + Clean up and return error. */ + CancelIo(dev->device_handle); + dev->read_pending = FALSE; + goto end_of_function; + } + } + } + + if (milliseconds >= 0) { + /* See if there is any data yet. */ + res = WaitForSingleObject(ev, milliseconds); + if (res != WAIT_OBJECT_0) { + /* There was no data this time. Return zero bytes available, + but leave the Overlapped I/O running. */ + return 0; + } + } + + /* Either WaitForSingleObject() told us that ReadFile has completed, or + we are in non-blocking mode. Get the number of bytes read. The actual + data has been copied to the data[] array which was passed to ReadFile(). */ + res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); + + /* Set pending back to false, even if GetOverlappedResult() returned error. */ + dev->read_pending = FALSE; + + if (res && bytes_read > 0) { + if (dev->read_buf[0] == 0x0) { + /* If report numbers aren't being used, but Windows sticks a report + number (0x0) on the beginning of the report anyway. To make this + work like the other platforms, and to make it work more like the + HID spec, we'll skip over this byte. */ + bytes_read--; + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf+1, copy_len); + } + else { + /* Copy the whole buffer, report number and all. */ + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf, copy_len); + } + } + +end_of_function: + if (!res) { + register_error(dev, "GetOverlappedResult"); + return -1; + } + + return (int)copy_len; +} + +int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + return 0; /* Success */ +} + +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length); + if (!res) { + register_error(dev, "HidD_SetFeature"); + return -1; + } + + return (int)length; +} + + +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + BOOL res; +#if 0 + res = HidD_GetFeature(dev->device_handle, data, length); + if (!res) { + register_error(dev, "HidD_GetFeature"); + return -1; + } + return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */ +#else + DWORD bytes_returned; + + OVERLAPPED ol; + memset(&ol, 0, sizeof(ol)); + + res = DeviceIoControl(dev->device_handle, + IOCTL_HID_GET_FEATURE, + data, (DWORD)length, + data, (DWORD)length, + &bytes_returned, &ol); + + if (!res) { + if (GetLastError() != ERROR_IO_PENDING) { + /* DeviceIoControl() failed. Return error. */ + register_error(dev, "Send Feature Report DeviceIoControl"); + return -1; + } + } + + /* Wait here until the write is done. This makes + hid_get_feature_report() synchronous. */ + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/); + if (!res) { + /* The operation failed. */ + register_error(dev, "Send Feature Report GetOverLappedResult"); + return -1; + } + + /* bytes_returned does not include the first byte which contains the + report ID. The data buffer actually contains one more byte than + bytes_returned. */ + bytes_returned++; + + return bytes_returned; +#endif +} + +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) +{ + if (!dev) + return; + CancelIo(dev->device_handle); + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetManufacturerString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetManufacturerString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetProductString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetProductString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetSerialNumberString(dev->device_handle, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetSerialNumberString"); + return -1; + } + + return 0; +} + +int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + BOOL res; + + res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)(sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS))); + if (!res) { + register_error(dev, "HidD_GetIndexedString"); + return -1; + } + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return (wchar_t*)dev->last_error_str; +} + + +/*#define PICPGM*/ +/*#define S11*/ +#define P32 +#ifdef S11 + unsigned short VendorID = 0xa0a0; + unsigned short ProductID = 0x0001; +#endif + +#ifdef P32 + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x3f; +#endif + + +#ifdef PICPGM + unsigned short VendorID = 0x04d8; + unsigned short ProductID = 0x0033; +#endif + + +#if 0 +int __cdecl main(int argc, char* argv[]) +{ + int res; + unsigned char buf[65]; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + /* Set up the command buffer. */ + memset(buf,0x00,sizeof(buf)); + buf[0] = 0; + buf[1] = 0x81; + + + /* Open the device. */ + int handle = open(VendorID, ProductID, L"12345"); + if (handle < 0) + printf("unable to open device\n"); + + + /* Toggle LED (cmd 0x80) */ + buf[1] = 0x80; + res = write(handle, buf, 65); + if (res < 0) + printf("Unable to write()\n"); + + /* Request state (cmd 0x81) */ + buf[1] = 0x81; + write(handle, buf, 65); + if (res < 0) + printf("Unable to write() (2)\n"); + + /* Read requested state */ + read(handle, buf, 65); + if (res < 0) + printf("Unable to read()\n"); + + /* Print out the returned buffer. */ + for (int i = 0; i < 4; i++) + printf("buf[%d]: %d\n", i, buf[i]); + + return 0; +} +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#elif defined( __MACOSX__ ) + +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 2010-07-03 + + Copyright 2010, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* See Apple Technical Note TN2187 for details on IOHidManager. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hidapi.h" + +/* Barrier implementation because Mac OSX doesn't have pthread_barrier. + It also doesn't have clock_gettime(). So much for POSIX and SUSv2. + This implementation came from Brent Priddy and was posted on + StackOverflow. It is used with his permission. */ +typedef int pthread_barrierattr_t; +typedef struct pthread_barrier { + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int trip_count; +} pthread_barrier_t; + +static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) { + errno = EINVAL; + return -1; + } + + if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->trip_count = count; + barrier->count = 0; + + return 0; +} + +static int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +static int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->trip_count) + { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else + { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +static int return_data(hid_device *dev, unsigned char *data, size_t length); + +/* Linked List of input reports received from the device. */ +struct input_report { + uint8_t *data; + size_t len; + struct input_report *next; +}; + +struct hid_device_ { + IOHIDDeviceRef device_handle; + int blocking; + int uses_numbered_reports; + int disconnected; + CFStringRef run_loop_mode; + CFRunLoopRef run_loop; + CFRunLoopSourceRef source; + uint8_t *input_report_buf; + CFIndex max_input_report_len; + struct input_report *input_reports; + + pthread_t thread; + pthread_mutex_t mutex; /* Protects input_reports */ + pthread_cond_t condition; + pthread_barrier_t barrier; /* Ensures correct startup sequence */ + pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ + int shutdown_thread; +}; + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->device_handle = NULL; + dev->blocking = 1; + dev->uses_numbered_reports = 0; + dev->disconnected = 0; + dev->run_loop_mode = NULL; + dev->run_loop = NULL; + dev->source = NULL; + dev->input_report_buf = NULL; + dev->input_reports = NULL; + dev->shutdown_thread = 0; + + /* Thread objects */ + pthread_mutex_init(&dev->mutex, NULL); + pthread_cond_init(&dev->condition, NULL); + pthread_barrier_init(&dev->barrier, NULL, 2); + pthread_barrier_init(&dev->shutdown_barrier, NULL, 2); + + return dev; +} + +static void free_hid_device(hid_device *dev) +{ + if (!dev) + return; + + /* Delete any input reports still left over. */ + struct input_report *rpt = dev->input_reports; + while (rpt) { + struct input_report *next = rpt->next; + free(rpt->data); + free(rpt); + rpt = next; + } + + /* Free the string and the report buffer. The check for NULL + is necessary here as CFRelease() doesn't handle NULL like + free() and others do. */ + if (dev->run_loop_mode) + CFRelease(dev->run_loop_mode); + if (dev->source) + CFRelease(dev->source); + free(dev->input_report_buf); + + /* Clean up the thread objects */ + pthread_barrier_destroy(&dev->shutdown_barrier); + pthread_barrier_destroy(&dev->barrier); + pthread_cond_destroy(&dev->condition); + pthread_mutex_destroy(&dev->mutex); + + /* Free the structure itself. */ + free(dev); +} + +static IOHIDManagerRef hid_mgr = 0x0; + + +#if 0 +static void register_error(hid_device *device, const char *op) +{ + +} +#endif + + +static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) +{ + CFTypeRef ref; + int32_t value; + + ref = IOHIDDeviceGetProperty(device, key); + if (ref) { + if (CFGetTypeID(ref) == CFNumberGetTypeID()) { + CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value); + return value; + } + } + return 0; +} + +static unsigned short get_vendor_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDVendorIDKey)); +} + +static unsigned short get_product_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDProductIDKey)); +} + +static int32_t get_max_report_length(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey)); +} + +static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len) +{ + CFStringRef str; + + if (!len) + return 0; + + str = IOHIDDeviceGetProperty(device, prop); + + buf[0] = 0; + + if (str) { + CFIndex str_len = CFStringGetLength(str); + CFRange range; + CFIndex used_buf_len; + CFIndex chars_copied; + + len --; + + range.location = 0; + range.length = ((size_t)str_len > len)? len: (size_t)str_len; + chars_copied = CFStringGetBytes(str, + range, + kCFStringEncodingUTF32LE, + (char)'?', + FALSE, + (UInt8*)buf, + len * sizeof(wchar_t), + &used_buf_len); + + if (chars_copied == len) + buf[len] = 0; /* len is decremented above */ + else + buf[chars_copied] = 0; + + return 0; + } + else + return -1; + +} + +static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); +} + +static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len); +} + +static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len); +} + + +/* Implementation of wcsdup() for Mac. */ +static wchar_t *dup_wcs(const wchar_t *s) +{ + size_t len = wcslen(s); + wchar_t *ret = malloc((len+1)*sizeof(wchar_t)); + wcscpy(ret, s); + + return ret; +} + +/* hidapi_IOHIDDeviceGetService() + * + * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by: + * - on OS X 10.6 and above, calling IOHIDDeviceGetService() + * - on OS X 10.5, extract it from the IOHIDDevice struct + */ +static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device) +{ + static void *iokit_framework = NULL; + static io_service_t (*dynamic_IOHIDDeviceGetService)(IOHIDDeviceRef device) = NULL; + + /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists. + * If any of these steps fail, dynamic_IOHIDDeviceGetService will be left NULL + * and the fallback method will be used. + */ + if (iokit_framework == NULL) { + iokit_framework = dlopen("/System/Library/IOKit.framework/IOKit", RTLD_LAZY); + + if (iokit_framework != NULL) + dynamic_IOHIDDeviceGetService = dlsym(iokit_framework, "IOHIDDeviceGetService"); + } + + if (dynamic_IOHIDDeviceGetService != NULL) { + /* Running on OS X 10.6 and above: IOHIDDeviceGetService() exists */ + return dynamic_IOHIDDeviceGetService(device); + } + else + { + /* Running on OS X 10.5: IOHIDDeviceGetService() doesn't exist. + * + * Be naughty and pull the service out of the IOHIDDevice. + * IOHIDDevice is an opaque struct not exposed to applications, but its + * layout is stable through all available versions of OS X. + * Tested and working on OS X 10.5.8 i386, x86_64, and ppc. + */ + struct IOHIDDevice_internal { + /* The first field of the IOHIDDevice struct is a + * CFRuntimeBase (which is a private CF struct). + * + * a, b, and c are the 3 fields that make up a CFRuntimeBase. + * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h + * + * The second field of the IOHIDDevice is the io_service_t we're looking for. + */ + uintptr_t a; + uint8_t b[4]; +#if __LP64__ + uint32_t c; +#endif + io_service_t service; + }; + struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device; + + return tmp->service; + } +} + +/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ +static int init_hid_manager(void) +{ + /* Initialize all the HID Manager Objects */ + hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_mgr) { + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); + IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + return 0; + } + + return -1; +} + +/* Initialize the IOHIDManager if necessary. This is the public function, and + it is safe to call this function repeatedly. Return 0 for success and -1 + for failure. */ +int HID_API_EXPORT hid_init(void) +{ + if (!hid_mgr) { + return init_hid_manager(); + } + + /* Already initialized. */ + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + if (hid_mgr) { + /* Close the HID manager. */ + IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone); + CFRelease(hid_mgr); + hid_mgr = NULL; + } + + return 0; +} + +static void process_pending_events(void) { + SInt32 res; + do { + res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE); + } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); +} + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + CFIndex num_devices; + int i; + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* give the IOHIDManager a chance to update itself */ + process_pending_events(); + + /* Get a list of the Devices */ + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); + CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); + + /* Convert the list into a C array so we can iterate easily. */ + num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + /* Iterate over each device, making an entry for it. */ + for (i = 0; i < num_devices; i++) { + unsigned short dev_vid; + unsigned short dev_pid; + #define BUF_LEN 256 + wchar_t buf[BUF_LEN]; + + IOHIDDeviceRef dev = device_array[i]; + + if (!dev) { + continue; + } + dev_vid = get_vendor_id(dev); + dev_pid = get_product_id(dev); + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + io_object_t iokit_dev; + kern_return_t res; + io_string_t path; + + /* VID/PID match. Create the record. */ + tmp = malloc(sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + cur_dev = tmp; + + /* Get the Usage Page and Usage for this device. */ + cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); + cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); + + /* Fill out the record */ + cur_dev->next = NULL; + + /* Fill in the path (IOService plane) */ + iokit_dev = hidapi_IOHIDDeviceGetService(dev); + res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path); + if (res == KERN_SUCCESS) + cur_dev->path = strdup(path); + else + cur_dev->path = strdup(""); + + /* Serial Number */ + get_serial_number(dev, buf, BUF_LEN); + cur_dev->serial_number = dup_wcs(buf); + + /* Manufacturer and Product strings */ + get_manufacturer_string(dev, buf, BUF_LEN); + cur_dev->manufacturer_string = dup_wcs(buf); + get_product_string(dev, buf, BUF_LEN); + cur_dev->product_string = dup_wcs(buf); + + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Release Number */ + cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); + + /* Interface Number (Unsupported on Mac)*/ + cur_dev->interface_number = -1; + } + } + + free(device_array); + CFRelease(device_set); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device * handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +static void hid_device_removal_callback(void *context, IOReturn result, + void *sender) +{ + /* Stop the Run Loop for this device. */ + hid_device *d = context; + + d->disconnected = 1; + CFRunLoopStop(d->run_loop); +} + +/* The Run Loop calls this function for each input report received. + This function puts the data into a linked list to be picked up by + hid_read(). */ +static void hid_report_callback(void *context, IOReturn result, void *sender, + IOHIDReportType report_type, uint32_t report_id, + uint8_t *report, CFIndex report_length) +{ + struct input_report *rpt; + hid_device *dev = context; + + /* Make a new Input Report object */ + rpt = calloc(1, sizeof(struct input_report)); + rpt->data = calloc(1, report_length); + memcpy(rpt->data, report, report_length); + rpt->len = report_length; + rpt->next = NULL; + + /* Lock this section */ + pthread_mutex_lock(&dev->mutex); + + /* Attach the new report object to the end of the list. */ + if (dev->input_reports == NULL) { + /* The list is empty. Put it at the root. */ + dev->input_reports = rpt; + } + else { + /* Find the end of the list and attach. */ + struct input_report *cur = dev->input_reports; + int num_queued = 0; + while (cur->next != NULL) { + cur = cur->next; + num_queued++; + } + cur->next = rpt; + + /* Pop one off if we've reached 30 in the queue. This + way we don't grow forever if the user never reads + anything from the device. */ + if (num_queued > 30) { + return_data(dev, NULL, 0); + } + } + + /* Signal a waiting thread that there is data. */ + pthread_cond_signal(&dev->condition); + + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + +} + +/* This gets called when the read_thread's run loop gets signaled by + hid_close(), and serves to stop the read_thread's run loop. */ +static void perform_signal_callback(void *context) +{ + hid_device *dev = context; + CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/ +} + +static void *read_thread(void *param) +{ + hid_device *dev = param; + SInt32 code; + + /* Move the device's run loop to this thread. */ + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); + + /* Create the RunLoopSource which is used to signal the + event loop to stop when hid_close() is called. */ + CFRunLoopSourceContext ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.version = 0; + ctx.info = dev; + ctx.perform = &perform_signal_callback; + dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx); + CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode); + + /* Store off the Run Loop so it can be stopped from hid_close() + and on device disconnection. */ + dev->run_loop = CFRunLoopGetCurrent(); + + /* Notify the main thread that the read thread is up and running. */ + pthread_barrier_wait(&dev->barrier); + + /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input + reports into the hid_report_callback(). */ + while (!dev->shutdown_thread && !dev->disconnected) { + code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); + /* Return if the device has been disconnected */ + if (code == kCFRunLoopRunFinished) { + dev->disconnected = 1; + break; + } + + + /* Break if The Run Loop returns Finished or Stopped. */ + if (code != kCFRunLoopRunTimedOut && + code != kCFRunLoopRunHandledSource) { + /* There was some kind of error. Setting + shutdown seems to make sense, but + there may be something else more appropriate */ + dev->shutdown_thread = 1; + break; + } + } + + /* Now that the read thread is stopping, Wake any threads which are + waiting on data (in hid_read_timeout()). Do this under a mutex to + make sure that a thread which is about to go to sleep waiting on + the condition actually will go to sleep before the condition is + signaled. */ + pthread_mutex_lock(&dev->mutex); + pthread_cond_broadcast(&dev->condition); + pthread_mutex_unlock(&dev->mutex); + + /* Wait here until hid_close() is called and makes it past + the call to CFRunLoopWakeUp(). This thread still needs to + be valid when that function is called on the other thread. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + return NULL; +} + +/* hid_open_path() + * + * path must be a valid path to an IOHIDDevice in the IOService plane + * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver" + */ +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + hid_device *dev = NULL; + io_registry_entry_t entry = MACH_PORT_NULL; + + dev = new_hid_device(); + + /* Set up the HID Manager if it hasn't been done */ + if (hid_init() < 0) + return NULL; + + /* Get the IORegistry entry for the given path */ + entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); + if (entry == MACH_PORT_NULL) { + /* Path wasn't valid (maybe device was removed?) */ + goto return_error; + } + + /* Create an IOHIDDevice for the entry */ + dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); + if (dev->device_handle == NULL) { + /* Error creating the HID device */ + goto return_error; + } + + /* Open the IOHIDDevice */ + IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + if (ret == kIOReturnSuccess) { + char str[32]; + + /* Create the buffers for receiving data */ + dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); + dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); + + /* Create the Run Loop Mode for this device. + printing the reference seems to work. */ + sprintf(str, "HIDAPI_%p", dev->device_handle); + dev->run_loop_mode = + CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); + + /* Attach the device to a Run Loop */ + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + &hid_report_callback, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); + + /* Start the read thread */ + pthread_create(&dev->thread, NULL, read_thread, dev); + + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); + + IOObjectRelease(entry); + return dev; + } + else { + goto return_error; + } + +return_error: + if (dev->device_handle != NULL) + CFRelease(dev->device_handle); + + if (entry != MACH_PORT_NULL) + IOObjectRelease(entry); + + free_hid_device(dev); + return NULL; +} + +static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) +{ + const unsigned char *data_to_send; + size_t length_to_send; + IOReturn res; + + /* Return if the device has been disconnected. */ + if (dev->disconnected) + return -1; + + if (data[0] == 0x0) { + /* Not using numbered Reports. + Don't send the report number. */ + data_to_send = data+1; + length_to_send = length-1; + } + else { + /* Using numbered Reports. + Send the Report Number */ + data_to_send = data; + length_to_send = length; + } + + if (!dev->disconnected) { + res = IOHIDDeviceSetReport(dev->device_handle, + type, + data[0], /* Report ID*/ + data_to_send, length_to_send); + + if (res == kIOReturnSuccess) { + return length; + } + else + return -1; + } + + return -1; +} + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeOutput, data, length); +} + +/* Helper function, so that this isn't duplicated in hid_read(). */ +static int return_data(hid_device *dev, unsigned char *data, size_t length) +{ + /* Copy the data out of the linked list item (rpt) into the + return buffer (data), and delete the liked list item. */ + struct input_report *rpt = dev->input_reports; + size_t len = (length < rpt->len)? length: rpt->len; + memcpy(data, rpt->data, len); + dev->input_reports = rpt->next; + free(rpt->data); + free(rpt); + return len; +} + +static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + while (!dev->input_reports) { + int res = pthread_cond_wait(cond, mutex); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; +} + +static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +{ + while (!dev->input_reports) { + int res = pthread_cond_timedwait(cond, mutex, abstime); + if (res != 0) + return res; + + /* A res of 0 means we may have been signaled or it may + be a spurious wakeup. Check to see that there's acutally + data in the queue before returning, and if not, go back + to sleep. See the pthread_cond_timedwait() man page for + details. */ + + if (dev->shutdown_thread || dev->disconnected) + return -1; + } + + return 0; + +} + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read = -1; + + /* Lock the access to the report list. */ + pthread_mutex_lock(&dev->mutex); + + /* There's an input report queued up. Return it. */ + if (dev->input_reports) { + /* Return the first one */ + bytes_read = return_data(dev, data, length); + goto ret; + } + + /* Return if the device has been disconnected. */ + if (dev->disconnected) { + bytes_read = -1; + goto ret; + } + + if (dev->shutdown_thread) { + /* This means the device has been closed (or there + has been an error. An error code of -1 should + be returned. */ + bytes_read = -1; + goto ret; + } + + /* There is no data. Go to sleep and wait for data. */ + + if (milliseconds == -1) { + /* Blocking */ + int res; + res = cond_wait(dev, &dev->condition, &dev->mutex); + if (res == 0) + bytes_read = return_data(dev, data, length); + else { + /* There was an error, or a device disconnection. */ + bytes_read = -1; + } + } + else if (milliseconds > 0) { + /* Non-blocking, but called with timeout. */ + int res; + struct timespec ts; + struct timeval tv; + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, &ts); + ts.tv_sec += milliseconds / 1000; + ts.tv_nsec += (milliseconds % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000L; + } + + res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); + if (res == 0) + bytes_read = return_data(dev, data, length); + else if (res == ETIMEDOUT) + bytes_read = 0; + else + bytes_read = -1; + } + else { + /* Purely non-blocking */ + bytes_read = 0; + } + +ret: + /* Unlock */ + pthread_mutex_unlock(&dev->mutex); + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + /* All Nonblocking operation is handled by the library. */ + dev->blocking = !nonblock; + + return 0; +} + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeFeature, data, length); +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + CFIndex len = length; + IOReturn res; + + /* Return if the device has been unplugged. */ + if (dev->disconnected) + return -1; + + res = IOHIDDeviceGetReport(dev->device_handle, + kIOHIDReportTypeFeature, + data[0], /* Report ID */ + data, &len); + if (res == kIOReturnSuccess) + return len; + else + return -1; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Disconnect the report callback before close. */ + if (!dev->disconnected) { + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + NULL, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev); + IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode); + IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode); + } + + /* Cause read_thread() to stop. */ + dev->shutdown_thread = 1; + + /* Wake up the run thread's event loop so that the thread can exit. */ + CFRunLoopSourceSignal(dev->source); + CFRunLoopWakeUp(dev->run_loop); + + /* Notify the read thread that it can shut down now. */ + pthread_barrier_wait(&dev->shutdown_barrier); + + /* Wait for read_thread() to end. */ + pthread_join(dev->thread, NULL); + + /* Close the OS handle to the device, but only if it's not + been unplugged. If it's been unplugged, then calling + IOHIDDeviceClose() will crash. */ + if (!dev->disconnected) { + IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); + } + + /* Clear out the queue of received reports. */ + pthread_mutex_lock(&dev->mutex); + while (dev->input_reports) { + return_data(dev, NULL, 0); + } + pthread_mutex_unlock(&dev->mutex); + CFRelease(dev->device_handle); + + free_hid_device(dev); +} + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_manufacturer_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_product_string(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_serial_number(dev->device_handle, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + /* TODO: */ + + return 0; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + /* TODO: */ + + return NULL; +} + + + + + + + +#if 0 +static int32_t get_location_id(IOHIDDeviceRef device) +{ + return get_int_property(device, CFSTR(kIOHIDLocationIDKey)); +} + +static int32_t get_usage(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey)); + return res; +} + +static int32_t get_usage_page(IOHIDDeviceRef device) +{ + int32_t res; + res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey)); + if (!res) + res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey)); + return res; +} + +static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len) +{ + return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len); +} + + +int main(void) +{ + IOHIDManagerRef mgr; + int i; + + mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + IOHIDManagerSetDeviceMatching(mgr, NULL); + IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); + + CFSetRef device_set = IOHIDManagerCopyDevices(mgr); + + CFIndex num_devices = CFSetGetCount(device_set); + IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + + for (i = 0; i < num_devices; i++) { + IOHIDDeviceRef dev = device_array[i]; + printf("Device: %p\n", dev); + printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev)); + + wchar_t serial[256], buf[256]; + char cbuf[256]; + get_serial_number(dev, serial, 256); + + + printf(" Serial: %ls\n", serial); + printf(" Loc: %ld\n", get_location_id(dev)); + get_transport(dev, buf, 256); + printf(" Trans: %ls\n", buf); + make_path(dev, cbuf, 256); + printf(" Path: %s\n", cbuf); + + } + + return 0; +} +#endif + + +#else //Linux + +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + Linux Version - 6/2/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* C */ +#include +#include +#include +#include +#include + +/* Unix */ +#include +#include +#include +#include +#include +#include +#include + +/* Linux */ +#include +#include +#include +#include + +#include "hidapi.h" + +/* Definitions from linux/hidraw.h. Since these are new, some distros + may not have header files which contain them. */ +#ifndef HIDIOCSFEATURE +#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) +#endif +#ifndef HIDIOCGFEATURE +#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) +#endif + + +/* USB HID device property names */ +const char *device_string_names[] = { + "manufacturer", + "product", + "serial", +}; + +/* Symbolic names for the properties above */ +enum device_string_id { + DEVICE_STRING_MANUFACTURER, + DEVICE_STRING_PRODUCT, + DEVICE_STRING_SERIAL, + + DEVICE_STRING_COUNT, +}; + +struct hid_device_ { + int device_handle; + int blocking; + int uses_numbered_reports; +}; + + +static __u32 kernel_version = 0; + +static __u32 detect_kernel_version(void) +{ + struct utsname name; + int major, minor, release; + int ret; + + uname(&name); + ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release); + if (ret == 3) { + return KERNEL_VERSION(major, minor, release); + } + + ret = sscanf(name.release, "%d.%d", &major, &minor); + if (ret == 2) { + return KERNEL_VERSION(major, minor, 0); + } + + printf("Couldn't determine kernel version from version string \"%s\"\n", name.release); + return 0; +} + +static hid_device *new_hid_device(void) +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->device_handle = -1; + dev->blocking = 1; + dev->uses_numbered_reports = 0; + + return dev; +} + + +/* The caller must free the returned string with free(). */ +static wchar_t *utf8_to_wchar_t(const char *utf8) +{ + wchar_t *ret = NULL; + + if (utf8) { + size_t wlen = mbstowcs(NULL, utf8, 0); + if ((size_t) -1 == wlen) { + return wcsdup(L""); + } + ret = calloc(wlen+1, sizeof(wchar_t)); + mbstowcs(ret, utf8, wlen+1); + ret[wlen] = 0x0000; + } + + return ret; +} + +/* Get an attribute value from a udev_device and return it as a whar_t + string. The returned string must be freed with free() when done.*/ +static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name) +{ + return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name)); +} + +/* uses_numbered_reports() returns 1 if report_descriptor describes a device + which contains numbered reports. */ +static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) { + unsigned int i = 0; + int size_code; + int data_len, key_size; + + while (i < size) { + int key = report_descriptor[i]; + + /* Check for the Report ID key */ + if (key == 0x85/*Report ID*/) { + /* This device has a Report ID, which means it uses + numbered reports. */ + return 1; + } + + //printf("key: %02hhx\n", key); + + if ((key & 0xf0) == 0xf0) { + /* This is a Long Item. The next byte contains the + length of the data section (value) for this key. + See the HID specification, version 1.11, section + 6.2.2.3, titled "Long Items." */ + if (i+1 < size) + data_len = report_descriptor[i+1]; + else + data_len = 0; /* malformed report */ + key_size = 3; + } + else { + /* This is a Short Item. The bottom two bits of the + key contain the size code for the data section + (value) for this key. Refer to the HID + specification, version 1.11, section 6.2.2.2, + titled "Short Items." */ + size_code = key & 0x3; + switch (size_code) { + case 0: + case 1: + case 2: + data_len = size_code; + break; + case 3: + data_len = 4; + break; + default: + /* Can't ever happen since size_code is & 0x3 */ + data_len = 0; + break; + }; + key_size = 1; + } + + /* Skip over this key and it's associated data */ + i += data_len + key_size; + } + + /* Didn't find a Report ID key. Device doesn't use numbered reports. */ + return 0; +} + +/* + * The caller is responsible for free()ing the (newly-allocated) character + * strings pointed to by serial_number_utf8 and product_name_utf8 after use. + */ +static int +parse_uevent_info(const char *uevent, int *bus_type, + unsigned short *vendor_id, unsigned short *product_id, + char **serial_number_utf8, char **product_name_utf8) +{ + char *tmp = strdup(uevent); + char *saveptr = NULL; + char *line; + char *key; + char *value; + + int found_id = 0; + int found_serial = 0; + int found_name = 0; + + line = strtok_r(tmp, "\n", &saveptr); + while (line != NULL) { + /* line: "KEY=value" */ + key = line; + value = strchr(line, '='); + if (!value) { + goto next_line; + } + *value = '\0'; + value++; + + if (strcmp(key, "HID_ID") == 0) { + /** + * type vendor product + * HID_ID=0003:000005AC:00008242 + **/ + int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id); + if (ret == 3) { + found_id = 1; + } + } else if (strcmp(key, "HID_NAME") == 0) { + /* The caller has to free the product name */ + *product_name_utf8 = strdup(value); + found_name = 1; + } else if (strcmp(key, "HID_UNIQ") == 0) { + /* The caller has to free the serial number */ + *serial_number_utf8 = strdup(value); + found_serial = 1; + } + +next_line: + line = strtok_r(NULL, "\n", &saveptr); + } + + free(tmp); + return (found_id && found_name && found_serial); +} + + +static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen) +{ + struct udev *udev; + struct udev_device *udev_dev, *parent, *hid_dev; + struct stat s; + int ret = -1; + char *serial_number_utf8 = NULL; + char *product_name_utf8 = NULL; + + /* Create the udev object */ + udev = udev_new(); + if (!udev) { + printf("Can't create udev\n"); + return -1; + } + + /* Get the dev_t (major/minor numbers) from the file handle. */ + ret = fstat(dev->device_handle, &s); + if (-1 == ret) + return ret; + /* Open a udev device from the dev_t. 'c' means character device. */ + udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); + if (udev_dev) { + hid_dev = udev_device_get_parent_with_subsystem_devtype( + udev_dev, + "hid", + NULL); + if (hid_dev) { + unsigned short dev_vid; + unsigned short dev_pid; + int bus_type; + size_t retm; + + ret = parse_uevent_info( + udev_device_get_sysattr_value(hid_dev, "uevent"), + &bus_type, + &dev_vid, + &dev_pid, + &serial_number_utf8, + &product_name_utf8); + + if (bus_type == BUS_BLUETOOTH) { + switch (key) { + case DEVICE_STRING_MANUFACTURER: + wcsncpy(string, L"", maxlen); + ret = 0; + break; + case DEVICE_STRING_PRODUCT: + retm = mbstowcs(string, product_name_utf8, maxlen); + ret = (retm == (size_t)-1)? -1: 0; + break; + case DEVICE_STRING_SERIAL: + retm = mbstowcs(string, serial_number_utf8, maxlen); + ret = (retm == (size_t)-1)? -1: 0; + break; + case DEVICE_STRING_COUNT: + default: + ret = -1; + break; + } + } + else { + /* This is a USB device. Find its parent USB Device node. */ + parent = udev_device_get_parent_with_subsystem_devtype( + udev_dev, + "usb", + "usb_device"); + if (parent) { + const char *str; + const char *key_str = NULL; + + if (key >= 0 && key < DEVICE_STRING_COUNT) { + key_str = device_string_names[key]; + } else { + ret = -1; + goto end; + } + + str = udev_device_get_sysattr_value(parent, key_str); + if (str) { + /* Convert the string from UTF-8 to wchar_t */ + retm = mbstowcs(string, str, maxlen); + ret = (retm == (size_t)-1)? -1: 0; + goto end; + } + } + } + } + } + +end: + free(serial_number_utf8); + free(product_name_utf8); + + udev_device_unref(udev_dev); + /* parent and hid_dev don't need to be (and can't be) unref'd. + I'm not sure why, but they'll throw double-free() errors. */ + udev_unref(udev); + + return ret; +} + +int HID_API_EXPORT hid_init(void) +{ + const char *locale; + + /* Set the locale if it's not set. */ + locale = setlocale(LC_CTYPE, NULL); + if (!locale) + setlocale(LC_CTYPE, ""); + + kernel_version = detect_kernel_version(); + + return 0; +} + +int HID_API_EXPORT hid_exit(void) +{ + /* Nothing to do for this in the Linux/hidraw implementation. */ + return 0; +} + + +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + + struct hid_device_info *root = NULL; /* return object */ + struct hid_device_info *cur_dev = NULL; + struct hid_device_info *prev_dev = NULL; /* previous device */ + + hid_init(); + + /* Create the udev object */ + udev = udev_new(); + if (!udev) { + printf("Can't create udev\n"); + return NULL; + } + + /* Create a list of the devices in the 'hidraw' subsystem. */ + enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(enumerate, "hidraw"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + /* For each item, see if it matches the vid/pid, and if so + create a udev_device record for it */ + udev_list_entry_foreach(dev_list_entry, devices) { + const char *sysfs_path; + const char *dev_path; + const char *str; + struct udev_device *raw_dev; /* The device's hidraw udev node. */ + struct udev_device *hid_dev; /* The device's HID udev node. */ + struct udev_device *usb_dev; /* The device's USB udev node. */ + struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ + unsigned short dev_vid; + unsigned short dev_pid; + char *serial_number_utf8 = NULL; + char *product_name_utf8 = NULL; + int bus_type; + int result; + + /* Get the filename of the /sys entry for the device + and create a udev_device object (dev) representing it */ + sysfs_path = udev_list_entry_get_name(dev_list_entry); + raw_dev = udev_device_new_from_syspath(udev, sysfs_path); + dev_path = udev_device_get_devnode(raw_dev); + + hid_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "hid", + NULL); + + if (!hid_dev) { + /* Unable to find parent hid device. */ + goto next; + } + + result = parse_uevent_info( + udev_device_get_sysattr_value(hid_dev, "uevent"), + &bus_type, + &dev_vid, + &dev_pid, + &serial_number_utf8, + &product_name_utf8); + + if (!result) { + /* parse_uevent_info() failed for at least one field. */ + goto next; + } + + if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) { + /* We only know how to handle USB and BT devices. */ + goto next; + } + + /* Check the VID/PID against the arguments */ + if ((vendor_id == 0x0 || vendor_id == dev_vid) && + (product_id == 0x0 || product_id == dev_pid)) { + struct hid_device_info *tmp; + + /* VID/PID match. Create the record. */ + tmp = malloc(sizeof(struct hid_device_info)); + if (cur_dev) { + cur_dev->next = tmp; + } + else { + root = tmp; + } + prev_dev = cur_dev; + cur_dev = tmp; + + /* Fill out the record */ + cur_dev->next = NULL; + cur_dev->path = dev_path? strdup(dev_path): NULL; + + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Serial Number */ + cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); + + /* Release Number */ + cur_dev->release_number = 0x0; + + /* Interface Number */ + cur_dev->interface_number = -1; + + switch (bus_type) { + case BUS_USB: + /* The device pointed to by raw_dev contains information about + the hidraw device. In order to get information about the + USB device, get the parent device with the + subsystem/devtype pair of "usb"/"usb_device". This will + be several levels up the tree, but the function will find + it. */ + usb_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "usb", + "usb_device"); + + if (!usb_dev) { + /* Free this device */ + free(cur_dev->serial_number); + free(cur_dev->path); + free(cur_dev); + + /* Take it off the device list. */ + if (prev_dev) { + prev_dev->next = NULL; + cur_dev = prev_dev; + } + else { + cur_dev = root = NULL; + } + + goto next; + } + + /* Manufacturer and Product strings */ + cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]); + cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]); + + /* Release Number */ + str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); + cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; + + /* Get a handle to the interface's udev node. */ + intf_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "usb", + "usb_interface"); + if (intf_dev) { + str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); + cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; + } + + break; + + case BUS_BLUETOOTH: + /* Manufacturer and Product strings */ + cur_dev->manufacturer_string = wcsdup(L""); + cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); + + break; + + default: + /* Unknown device type - this should never happen, as we + * check for USB and Bluetooth devices above */ + break; + } + } + + next: + free(serial_number_utf8); + free(product_name_utf8); + udev_device_unref(raw_dev); + /* hid_dev, usb_dev and intf_dev don't need to be (and can't be) + unref()d. It will cause a double-free() error. I'm not + sure why. */ + } + /* Free the enumerator and udev objects. */ + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return root; +} + +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) +{ + struct hid_device_info *d = devs; + while (d) { + struct hid_device_info *next = d->next; + free(d->path); + free(d->serial_number); + free(d->manufacturer_string); + free(d->product_string); + free(d); + d = next; + } +} + +hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + struct hid_device_info *devs, *cur_dev; + const char *path_to_open = NULL; + hid_device *handle = NULL; + + devs = hid_enumerate(vendor_id, product_id); + cur_dev = devs; + while (cur_dev) { + if (cur_dev->vendor_id == vendor_id && + cur_dev->product_id == product_id) { + if (serial_number) { + if (wcscmp(serial_number, cur_dev->serial_number) == 0) { + path_to_open = cur_dev->path; + break; + } + } + else { + path_to_open = cur_dev->path; + break; + } + } + cur_dev = cur_dev->next; + } + + if (path_to_open) { + /* Open the device */ + handle = hid_open_path(path_to_open); + } + + hid_free_enumeration(devs); + + return handle; +} + +hid_device * HID_API_EXPORT hid_open_path(const char *path) +{ + hid_device *dev = NULL; + + hid_init(); + + dev = new_hid_device(); + + /* OPEN HERE */ + dev->device_handle = open(path, O_RDWR); + + /* If we have a good handle, return it. */ + if (dev->device_handle > 0) { + + /* Get the report descriptor */ + int res, desc_size = 0; + struct hidraw_report_descriptor rpt_desc; + + memset(&rpt_desc, 0x0, sizeof(rpt_desc)); + + /* Get Report Descriptor Size */ + res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); + if (res < 0) + perror("HIDIOCGRDESCSIZE"); + + + /* Get Report Descriptor */ + rpt_desc.size = desc_size; + res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc); + if (res < 0) { + perror("HIDIOCGRDESC"); + } else { + /* Determine if this device uses numbered reports. */ + dev->uses_numbered_reports = + uses_numbered_reports(rpt_desc.value, + rpt_desc.size); + } + + return dev; + } + else { + /* Unable to open any devices. */ + free(dev); + return NULL; + } +} + + +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + int bytes_written; + + bytes_written = write(dev->device_handle, data, length); + + return bytes_written; +} + + +int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int bytes_read; + + if (milliseconds >= 0) { + /* Milliseconds is either 0 (non-blocking) or > 0 (contains + a valid timeout). In both cases we want to call poll() + and wait for data to arrive. Don't rely on non-blocking + operation (O_NONBLOCK) since some kernels don't seem to + properly report device disconnection through read() when + in non-blocking mode. */ + int ret; + struct pollfd fds; + + fds.fd = dev->device_handle; + fds.events = POLLIN; + fds.revents = 0; + ret = poll(&fds, 1, milliseconds); + if (ret == -1 || ret == 0) { + /* Error or timeout */ + return ret; + } + else { + /* Check for errors on the file descriptor. This will + indicate a device disconnection. */ + if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) + return -1; + } + } + + bytes_read = read(dev->device_handle, data, length); + if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS)) + bytes_read = 0; + + if (bytes_read >= 0 && + kernel_version != 0 && + kernel_version < KERNEL_VERSION(2,6,34) && + dev->uses_numbered_reports) { + /* Work around a kernel bug. Chop off the first byte. */ + memmove(data, data+1, bytes_read); + bytes_read--; + } + + return bytes_read; +} + +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); +} + +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) +{ + /* Do all non-blocking in userspace using poll(), since it looks + like there's a bug in the kernel in some versions where + read() will not return -1 on disconnection of the USB device */ + + dev->blocking = !nonblock; + return 0; /* Success */ +} + + +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + int res; + + res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); + if (res < 0) + perror("ioctl (SFEATURE)"); + + return res; +} + +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + int res; + + res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); + if (res < 0) + perror("ioctl (GFEATURE)"); + + + return res; +} + + +void HID_API_EXPORT hid_close(hid_device *dev) +{ + if (!dev) + return; + close(dev->device_handle); + free(dev); +} + + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen); +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + return -1; +} + + +HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) +{ + return NULL; +} + + +#endif + diff --git a/colorchord2/hidapi.conf b/colorchord2/hidapi.conf new file mode 100644 index 0000000..f4155e3 --- /dev/null +++ b/colorchord2/hidapi.conf @@ -0,0 +1,30 @@ +#What display output driver should be used? +outdrivers = DisplayPie, OutputLinear, DisplayHIDAPI +leds = 107 +light_siding = 2.2 +satamp = 6.000 +is_loop=1 +led_floor = .1 +note_attach_amp_iir2 = .0500 +note_attach_amp_iir2 = .1500 +note_attach_freq_iir = 0.3000 +steady_bright = 0 +pie_min=.15 +pie_max=.25 +lightx=300 +lighty=1 + +ledoutamp = 1 + +sourcename = alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor + + +bank1_size = 40 +bank1_id = 8 +bank2_size = 27 +bank2_id = 2 +bank3_size = 40 +bank3_id = 4 +bank4_size = 0 +bank4_id = 0 +ledisrgby = 1 diff --git a/colorchord2/hidapi.h b/colorchord2/hidapi.h new file mode 100644 index 0000000..43b8e7a --- /dev/null +++ b/colorchord2/hidapi.h @@ -0,0 +1,405 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +/* Copy of LICENSE-orig.txt (compatible with MIT/x11 license) + + HIDAPI - Multi-Platform library for + communication with HID devices. + + Copyright 2009, Alan Ott, Signal 11 Software. + All Rights Reserved. + + This software may be used by anyone for any reason so + long as the copyright notice in the source files + remains intact. +*/ + + +/** @file + * @defgroup API hidapi API + */ + +#ifndef HIDAPI_H__ +#define HIDAPI_H__ + +#include + +#ifdef _WIN32 + #define HID_API_EXPORT __declspec(dllexport) + #define HID_API_CALL +#else + #define HID_API_EXPORT /**< API export macro */ + #define HID_API_CALL /**< API call macro */ +#endif + +#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ + +#ifdef __cplusplus +extern "C" { +#endif + struct hid_device_; + typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ + + /** hidapi info structure */ + struct hid_device_info { + /** Platform-specific device path */ + char *path; + /** Device Vendor ID */ + unsigned short vendor_id; + /** Device Product ID */ + unsigned short product_id; + /** Serial Number */ + wchar_t *serial_number; + /** Device Release Number in binary-coded decimal, + also known as Device Version Number */ + unsigned short release_number; + /** Manufacturer String */ + wchar_t *manufacturer_string; + /** Product string */ + wchar_t *product_string; + /** Usage Page for this Device/Interface + (Windows/Mac only). */ + unsigned short usage_page; + /** Usage for this Device/Interface + (Windows/Mac only).*/ + unsigned short usage; + /** The USB interface which this logical device + represents. Valid on both Linux implementations + in all cases, and valid on the Windows implementation + only if the device contains more than one interface. */ + int interface_number; + + /** Pointer to the next device */ + struct hid_device_info *next; + }; + + + /** @brief Initialize the HIDAPI library. + + This function initializes the HIDAPI library. Calling it is not + strictly necessary, as it will be called automatically by + hid_enumerate() and any of the hid_open_*() functions if it is + needed. This function should be called at the beginning of + execution however, if there is a chance of HIDAPI handles + being opened by different threads simultaneously. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_init(void); + + /** @brief Finalize the HIDAPI library. + + This function frees all of the static data associated with + HIDAPI. It should be called at the end of execution to avoid + memory leaks. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_exit(void); + + /** @brief Enumerate the HID Devices. + + This function returns a linked list of all the HID devices + attached to the system which match vendor_id and product_id. + If @p vendor_id is set to 0 then any vendor matches. + If @p product_id is set to 0 then any product matches. + If @p vendor_id and @p product_id are both set to 0, then + all HID devices will be returned. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the types of device + to open. + @param product_id The Product ID (PID) of the types of + device to open. + + @returns + This function returns a pointer to a linked list of type + struct #hid_device, containing information about the HID devices + attached to the system, or NULL in the case of failure. Free + this linked list by calling hid_free_enumeration(). + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); + + /** @brief Free an enumeration Linked List + + This function frees a linked list created by hid_enumerate(). + + @ingroup API + @param devs Pointer to a list of struct_device returned from + hid_enumerate(). + */ + void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); + + /** @brief Open a HID device using a Vendor ID (VID), Product ID + (PID) and optionally a serial number. + + If @p serial_number is NULL, the first device with the + specified VID and PID is opened. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the device to open. + @param product_id The Product ID (PID) of the device to open. + @param serial_number The Serial Number of the device to open + (Optionally NULL). + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); + + /** @brief Open a HID device by its path name. + + The path name be determined by calling hid_enumerate(), or a + platform-specific path name can be used (eg: /dev/hidraw0 on + Linux). + + @ingroup API + @param path The path name of the device to open + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); + + /** @brief Write an Output report to a HID device. + + The first byte of @p data[] must contain the Report ID. For + devices which only support a single report, this must be set + to 0x0. The remaining bytes contain the report data. Since + the Report ID is mandatory, calls to hid_write() will always + contain one more byte than the report contains. For example, + if a hid report is 16 bytes long, 17 bytes must be passed to + hid_write(), the Report ID (or 0x0, for devices with a + single report), followed by the report data (16 bytes). In + this example, the length passed in would be 17. + + hid_write() will send the data on the first OUT endpoint, if + one exists. If it does not, it will send the data through + the Control Endpoint (Endpoint 0). + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Read an Input report from a HID device with timeout. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + @param milliseconds timeout in milliseconds or -1 for blocking wait. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read within + the timeout period, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); + + /** @brief Read an Input report from a HID device. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + + @returns + This function returns the actual number of bytes read and + -1 on error. If no packet was available to be read and + the handle is in non-blocking mode, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); + + /** @brief Set the device handle to be non-blocking. + + In non-blocking mode calls to hid_read() will return + immediately with a value of 0 if there is no data to be + read. In blocking mode, hid_read() will wait (block) until + there is data to read before returning. + + Nonblocking can be turned on and off at any time. + + @ingroup API + @param device A device handle returned from hid_open(). + @param nonblock enable or not the nonblocking reads + - 1 to enable nonblocking + - 0 to disable nonblocking. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); + + /** @brief Send a Feature report to the device. + + Feature reports are sent over the Control endpoint as a + Set_Report transfer. The first byte of @p data[] must + contain the Report ID. For devices which only support a + single report, this must be set to 0x0. The remaining bytes + contain the report data. Since the Report ID is mandatory, + calls to hid_send_feature_report() will always contain one + more byte than the report contains. For example, if a hid + report is 16 bytes long, 17 bytes must be passed to + hid_send_feature_report(): the Report ID (or 0x0, for + devices which do not use numbered reports), followed by the + report data (16 bytes). In this example, the length passed + in would be 17. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send, including + the report number. + + @returns + This function returns the actual number of bytes written and + -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); + + /** @brief Get a feature report from a HID device. + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + + @ingroup API + @param device A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); + + /** @brief Close a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + */ + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); + + /** @brief Get The Manufacturer String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Product String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get The Serial Number String from a HID device. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); + + /** @brief Get a string from a HID device, based on its string index. + + @ingroup API + @param device A device handle returned from hid_open(). + @param string_index The index of the string to get. + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); + + /** @brief Get a string describing the last error which occurred. + + @ingroup API + @param device A device handle returned from hid_open(). + + @returns + This function returns a string containing the last error + which occurred or NULL if none has occurred. + */ + HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/colorchord2/main.c b/colorchord2/main.c index 981df57..0a902de 100644 --- a/colorchord2/main.c +++ b/colorchord2/main.c @@ -20,7 +20,8 @@ struct SoundDriver * sd; -#ifdef WIN32 +#if defined(WIN32) || defined(USE_WINDOWS) +#include #include #define ESCAPE_KEY 0x1B @@ -41,8 +42,8 @@ double Now = 0; int lastfps; short screenx, screeny; -struct DriverInstances * outdriver[MAX_OUT_DRIVERS]; +struct DriverInstances * outdriver[MAX_OUT_DRIVERS]; int headless = 0; REGISTER_PARAM( headless, PAINT ); int set_screenx = 640; REGISTER_PARAM( set_screenx, PAINT ); @@ -160,18 +161,19 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun *samplesp = samplesr; } - int main(int argc, char ** argv) { int i; - +#ifdef TCC + ManuallyRegisterDevices(); +#endif + printf( "Output Drivers:\n" ); for( i = 0; i < MAX_OUT_DRIVERS; i++ ) { if( ODList[i].Name ) printf( "\t%s\n", ODList[i].Name ); } - -#ifdef WIN32 +#if defined(WIN32) || defined(USE_WINDOWS) WSADATA wsaData; WSAStartup(0x202, &wsaData); diff --git a/colorchord2/netlight.conf b/colorchord2/netlight.conf index c426aad..edc1ce1 100644 --- a/colorchord2/netlight.conf +++ b/colorchord2/netlight.conf @@ -12,7 +12,8 @@ steady_bright = 0 #dft_q = 20.0000 #dft_speedup = 1000.0000 -sourcename = alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1.monitor +sourcename = alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor +# alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1.monitor #alsa_output.pci-0000_00_1f.3.analog-stereo.monitor skipfirst = 1 firstval = 0 diff --git a/colorchord2/os_generic.c b/colorchord2/os_generic.c index effe5eb..da281e3 100644 --- a/colorchord2/os_generic.c +++ b/colorchord2/os_generic.c @@ -2,7 +2,6 @@ #include "os_generic.h" - #ifdef USE_WINDOWS #include @@ -49,15 +48,16 @@ double OGGetFileTime( const char * file ) } -og_thread_t OGCreateThread( void * (function)( void * ), void * parameter ) +og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter ) { - return (og_thread_t)CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)function, parameter, 0, 0 ); + return (og_thread_t)CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)routine, parameter, 0, 0 ); } void * OGJoinThread( og_thread_t ot ) { WaitForSingleObject( ot, INFINITE ); CloseHandle( ot ); + return 0; } void OGCancelThread( og_thread_t ot ) @@ -93,28 +93,23 @@ og_sema_t OGCreateSema() return (og_sema_t)sem; } - - -typedef LONG NTSTATUS; - -typedef NTSTATUS (NTAPI *_NtQuerySemaphore)( - HANDLE SemaphoreHandle, - DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */ - PVOID SemaphoreInformation, /* but this is to much to dump here */ - ULONG SemaphoreInformationLength, - PULONG ReturnLength OPTIONAL -); - - -typedef struct _SEMAPHORE_BASIC_INFORMATION { - ULONG CurrentCount; - ULONG MaximumCount; -} SEMAPHORE_BASIC_INFORMATION; - - int OGGetSema( og_sema_t os ) { + typedef LONG NTSTATUS; HANDLE sem = (HANDLE)os; + typedef NTSTATUS (NTAPI *_NtQuerySemaphore)( + HANDLE SemaphoreHandle, + DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */ + PVOID SemaphoreInformation, /* but this is to much to dump here */ + ULONG SemaphoreInformationLength, + PULONG ReturnLength OPTIONAL + ); + + typedef struct _SEMAPHORE_BASIC_INFORMATION { + ULONG CurrentCount; + ULONG MaximumCount; + } SEMAPHORE_BASIC_INFORMATION; + static _NtQuerySemaphore NtQuerySemaphore; SEMAPHORE_BASIC_INFORMATION BasicInfo; @@ -158,9 +153,8 @@ void OGDeleteSema( og_sema_t os ) #else -#ifndef _GNU_SOURCE #define _GNU_SOURCE -#endif + #include #include diff --git a/colorchord2/os_generic.h b/colorchord2/os_generic.h index c7de7db..163f2db 100644 --- a/colorchord2/os_generic.h +++ b/colorchord2/os_generic.h @@ -1,9 +1,8 @@ //Copyright 2015 <>< Charles Lohr under the NewBSD or MIT/x11 License. - #ifndef _OS_GENERIC_H #define _OS_GENERIC_H -#ifdef WIN32 +#if defined( WIN32 ) || defined (WINDOWS) || defined( _WIN32) #define USE_WINDOWS #endif @@ -12,12 +11,7 @@ extern "C" { #endif -#define EXECUTE_AT_BOOT( x, y ) \ - \ - void fn##x() __attribute__((constructor)); \ - void fn##x() \ - { y; } \ - + //Things that shouldn't be macro'd double OGGetAbsoluteTime(); void OGSleep( int is ); @@ -55,7 +49,7 @@ void OGDeleteSema( og_sema_t os ); #endif -//Date Stamp: 2014-06-12 +//Date Stamp: 2012-02-15 /* NOTE: Portions (namely the top section) are part of headers from other diff --git a/colorchord2/outdrivers.h b/colorchord2/outdrivers.h index 60f56ce..44db767 100644 --- a/colorchord2/outdrivers.h +++ b/colorchord2/outdrivers.h @@ -41,6 +41,6 @@ struct DriverInstances * SetupOutDriver( ); void RegOutDriver( const char * ron, struct DriverInstances * (*Init)( ) ); #define REGISTER_OUT_DRIVER( name ) \ - EXECUTE_AT_BOOT( r##name, RegOutDriver( #name, name ) ); + void __attribute__((constructor)) REGISTER##name() { RegOutDriver( #name, name ); } #endif diff --git a/colorchord2/parameters.h b/colorchord2/parameters.h index f23bacd..db1eecf 100644 --- a/colorchord2/parameters.h +++ b/colorchord2/parameters.h @@ -58,8 +58,7 @@ void SetParametersFromString( const char * string ); void AddCallback( const char * name, ParamCallbackT t, void * v ); #define REGISTER_PARAM( parameter_name, type ) \ - void Register##parameter_name() __attribute__((constructor)); \ - void Register##parameter_name() { RegisterValue( #parameter_name, type, ¶meter_name, sizeof( parameter_name ) ); } + void __attribute__((constructor)) REGISTER##parameter_name() { RegisterValue( #parameter_name, type, ¶meter_name, sizeof( parameter_name ) ); } #endif diff --git a/colorchord2/shmtest.conf b/colorchord2/shmtest.conf new file mode 100644 index 0000000..a6dc6ed --- /dev/null +++ b/colorchord2/shmtest.conf @@ -0,0 +1,50 @@ +cpu_autolimit = 1 + +#General GUI properties. +title = PA Test +set_screenx = 720 +set_screeny = 480 + +sample_channel = -1 +sourcename = alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2.monitor +#alsa_output.pci-0000_00_1f.3.analog-stereo.monitor +#default +# alsa_output.pci-0000_00_1b.0.analog-stereo.monitor +#alsa_output.pci-0000_00_1f.3.analog-stereo.monitor << New laptop +#use pactl list | grep pci- | grep monitor + + +#How many bins a note can jump from frame to frame to be considered a slide. +#this is used to prevent notes from popping in and out a lot. +note_combine_distance = 0.5000 +note_jumpability = 1.8000 +note_minimum_new_distribution_value = 0.0200 +note_out_chop = 0.05000 + +#compress_coefficient = 4.0 +#compress_exponent = .5 + + +#======================================================================= +#Outputs + + +#DisplayArray +outdrivers = OutputCells, DisplaySHM + +shm_lights = /cclights +shm_dft = /ccdft +shm_notes = /ccnotes + +lightx = 20 +lighty = 4 +fromsides = 1 +leds = 120 +qtyamp = 120 + +satamp = 2.800 +amppow = 2.510 +distpow = 1.500 + + + diff --git a/colorchord2/sound.c b/colorchord2/sound.c index df7ff1c..9f03707 100644 --- a/colorchord2/sound.c +++ b/colorchord2/sound.c @@ -55,7 +55,6 @@ struct SoundDriver * InitSound( const char * driver_name, SoundCBType cb ) { int i; struct SoundDriver * ret = 0; - if( driver_name == 0 || strlen( driver_name ) == 0 ) { //Search for a driver. @@ -74,6 +73,7 @@ struct SoundDriver * InitSound( const char * driver_name, SoundCBType cb ) } else { + printf( "Initializing sound. Recommended driver: %s\n", driver_name ); for( i = 0; i < MAX_SOUND_DRIVERS; i++ ) { if( SoundDrivers[i] == 0 ) diff --git a/colorchord2/sound.h b/colorchord2/sound.h index 0bfe9b9..38a7f19 100644 --- a/colorchord2/sound.h +++ b/colorchord2/sound.h @@ -34,5 +34,8 @@ void CloseSound( struct SoundDriver * soundobject ); //Called by various sound drivers. Notice priority must be greater than 0. Priority of 0 or less will not register. void RegSound( int priority, const char * name, SoundInitFn * fn ); +#define REGISTER_SOUND( sounddriver, priority, name, function ) \ + void __attribute__((constructor)) REGISTER##sounddriver() { RegSound( priority, name, function ); } + #endif diff --git a/colorchord2/sound_alsa.c b/colorchord2/sound_alsa.c index 64dc720..1161c1e 100644 --- a/colorchord2/sound_alsa.c +++ b/colorchord2/sound_alsa.c @@ -337,5 +337,5 @@ void * InitSoundAlsa( SoundCBType cb ) return InitASound(r); } -EXECUTE_AT_BOOT( AlsaSoundReg, RegSound( 10, "ALSA", InitSoundAlsa ) ); +REGISTER_SOUND( AlsaSound, 10, "ALSA", InitSoundAlsa ); diff --git a/colorchord2/sound_null.c b/colorchord2/sound_null.c index 47d5415..d7f8d16 100644 --- a/colorchord2/sound_null.c +++ b/colorchord2/sound_null.c @@ -41,6 +41,5 @@ void * InitSoundNull( SoundCBType cb ) } - -EXECUTE_AT_BOOT( NullSoundReg, RegSound( 1, "NULL", InitSoundNull ) ); +REGISTER_SOUND( NullSound, 1, "NULL", InitSoundNull ); diff --git a/colorchord2/sound_pulse.c b/colorchord2/sound_pulse.c index 2cecc35..4664c2e 100644 --- a/colorchord2/sound_pulse.c +++ b/colorchord2/sound_pulse.c @@ -374,6 +374,6 @@ fail: -EXECUTE_AT_BOOT( PulseSoundReg, RegSound( 11, "PULSE", InitSoundPulse ) ); +REGISTER_SOUND( PulseSound, 11, "PULSE", InitSoundPulse ); diff --git a/colorchord2/sound_win.c b/colorchord2/sound_win.c index 684e61c..559b87f 100644 --- a/colorchord2/sound_win.c +++ b/colorchord2/sound_win.c @@ -4,9 +4,9 @@ #include "parameters.h" #include "sound.h" #include "os_generic.h" -#include #include #include +#include #if defined(WIN32) #pragma comment(lib,"winmm.lib") @@ -106,7 +106,8 @@ static struct SoundDriverWin * InitWinSound( struct SoundDriverWin * r ) { int i; WAVEFORMATEX wfmt; - + memset( &wfmt, 0, sizeof(wfmt) ); + printf ("WFMT Size (debugging temp for TCC): %d\n", sizeof(wfmt) ); if( GetParameterI( "play", 0 ) ) { fprintf( stderr, "Error: This Windows Sound Driver does not support playback.\n" ); @@ -136,7 +137,7 @@ static struct SoundDriverWin * InitWinSound( struct SoundDriverWin * r ) int p = waveInOpen(&r->hMyWave, dwdevice, &wfmt,(DWORD)(void*)(&HANDLEMIC) , 0, CALLBACK_FUNCTION); - printf( "WIO: %d\n", p ); //On real windows, returns 11 + printf( "WIO: %d\n", p ); for ( i=0;ihMyWave); - printf( "WIS: %d\n", p ); //On real windows returns 5. + printf( "WIS: %d\n", p ); return r; } @@ -159,7 +160,7 @@ static struct SoundDriverWin * InitWinSound( struct SoundDriverWin * r ) void * InitSoundWin( SoundCBType cb ) { - struct SoundDriverWin * r = malloc( sizeof( struct SoundDriverWin ) ); + struct SoundDriverWin * r = (struct SoundDriverWin *)malloc( sizeof( struct SoundDriverWin ) ); r->CloseFn = CloseSoundWin; r->SoundStateFn = SoundStateWin; @@ -177,5 +178,5 @@ void * InitSoundWin( SoundCBType cb ) return InitWinSound(r); } -EXECUTE_AT_BOOT( WinSoundReg, RegSound( 10, "WIN", InitSoundWin ) ); +REGISTER_SOUND( SoundWin, 10, "WIN", InitSoundWin ); diff --git a/colorchord2/util.c b/colorchord2/util.c index d1e2d4e..9d1c8c4 100644 --- a/colorchord2/util.c +++ b/colorchord2/util.c @@ -2,8 +2,8 @@ //This file may be used in whole or part in any way for any purpose by anyone //without restriction. -#include "util.h" #include +#include "util.h" #include //Take the absolute distance between two points on a torus. diff --git a/colorchord2/windows/32/WS2_32.Lib b/colorchord2/windows/32/WS2_32.Lib new file mode 100644 index 0000000..750a539 Binary files /dev/null and b/colorchord2/windows/32/WS2_32.Lib differ diff --git a/colorchord2/windows/32/WinMM.Lib b/colorchord2/windows/32/WinMM.Lib new file mode 100644 index 0000000..7459425 Binary files /dev/null and b/colorchord2/windows/32/WinMM.Lib differ diff --git a/colorchord2/windows/64/WS2_32.Lib b/colorchord2/windows/64/WS2_32.Lib new file mode 100644 index 0000000..1ff5934 Binary files /dev/null and b/colorchord2/windows/64/WS2_32.Lib differ diff --git a/colorchord2/windows/64/WinMM.Lib b/colorchord2/windows/64/WinMM.Lib new file mode 100644 index 0000000..0c66d27 Binary files /dev/null and b/colorchord2/windows/64/WinMM.Lib differ diff --git a/colorchord2/windows/compile.bat b/colorchord2/windows/compile.bat new file mode 100644 index 0000000..32f1031 --- /dev/null +++ b/colorchord2/windows/compile.bat @@ -0,0 +1,8 @@ +@echo off +echo Unzip https://download.savannah.gnu.org/releases/tinycc/tcc-0.9.26-win64-bin.zip to C:\tcc +set CFLAGS=-v -DHIDAPI -DWINDOWS -DWIN32 -DTCC -DRUNTIME_SYMNUM -Os -Itccinc -DINCLUDING_EMBEDDED -I.. -I. -I../../embeddedcommon -rdynamic -g +set LDFLAGS=-lkernel32 -lgdi32 -luser32 -lsetupapi -ldbghelp -ltcc1 -lwinmm -lws2_32 +set SOURCES=..\chash.c ..\color.c ..\configs.c ..\decompose.c ..\dft.c ..\DisplayNetwork.c ..\DisplayArray.c ..\DisplayHIDAPI.c ..\DisplayOUTDriver.c ..\DisplayPie.c ..\DrawFunctions.c ..\filter.c ..\hidapi.c ..\hook.c ..\main.c ..\os_generic.c ..\outdrivers.c ..\OutputCells.c ..\OutputLinear.c ..\OutputProminent.c ..\OutputVoronoi.c ..\parameters.c ..\sound.c ..\sound_win.c ..\sound_null.c ..\util.c ..\WinDriver.c ..\notefinder.c ..\..\embeddedcommon\DFT32.c tcc_stubs.c symbol_enumerator.c +set ARCH_SPECIFIC=-L32 +@echo on +C:\tcc\tcc %CFLAGS% %ARCH_SPECIFIC% %SOURCES% %LDFLAGS% -o ..\colorchord.exe \ No newline at end of file diff --git a/colorchord2/windows/math.h b/colorchord2/windows/math.h new file mode 100644 index 0000000..cd5ee3d --- /dev/null +++ b/colorchord2/windows/math.h @@ -0,0 +1,926 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ +#ifndef _MATH_H_ +#define _MATH_H_ + +#if __GNUC__ >= 3 +#pragma GCC system_header +#endif + +#include <_mingw.h> + +struct exception; + +#pragma pack(push,_CRT_PACKING) + +#define _DOMAIN 1 +#define _SING 2 +#define _OVERFLOW 3 +#define _UNDERFLOW 4 +#define _TLOSS 5 +#define _PLOSS 6 + +#ifndef __STRICT_ANSI__ +#ifndef NO_OLDNAMES +#define DOMAIN _DOMAIN +#define SING _SING +#define OVERFLOW _OVERFLOW +#define UNDERFLOW _UNDERFLOW +#define TLOSS _TLOSS +#define PLOSS _PLOSS +#endif +#endif + +#ifndef __STRICT_ANSI__ +#define M_E 2.71828182845904523536 +#define M_LOG2E 1.44269504088896340736 +#define M_LOG10E 0.434294481903251827651 +#define M_LN2 0.693147180559945309417 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.785398163397448309616 +#define M_1_PI 0.318309886183790671538 +#define M_2_PI 0.636619772367581343076 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.707106781186547524401 +#endif + +#ifndef __STRICT_ANSI__ +/* See also float.h */ +#ifndef __MINGW_FPCLASS_DEFINED +#define __MINGW_FPCLASS_DEFINED 1 +#define _FPCLASS_SNAN 0x0001 /* Signaling "Not a Number" */ +#define _FPCLASS_QNAN 0x0002 /* Quiet "Not a Number" */ +#define _FPCLASS_NINF 0x0004 /* Negative Infinity */ +#define _FPCLASS_NN 0x0008 /* Negative Normal */ +#define _FPCLASS_ND 0x0010 /* Negative Denormal */ +#define _FPCLASS_NZ 0x0020 /* Negative Zero */ +#define _FPCLASS_PZ 0x0040 /* Positive Zero */ +#define _FPCLASS_PD 0x0080 /* Positive Denormal */ +#define _FPCLASS_PN 0x0100 /* Positive Normal */ +#define _FPCLASS_PINF 0x0200 /* Positive Infinity */ +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _EXCEPTION_DEFINED +#define _EXCEPTION_DEFINED + struct _exception { + int type; + char *name; + double arg1; + double arg2; + double retval; + }; +#endif + +#ifndef _COMPLEX_DEFINED +#define _COMPLEX_DEFINED + struct _complex { + double x,y; + }; +#endif + +#define EDOM 33 +#define ERANGE 34 + +#ifndef _HUGE +#ifdef _MSVCRT_ + extern double *_HUGE; +#else + extern double *_imp___HUGE; +#define _HUGE (*_imp___HUGE) +#endif +#endif + +#define HUGE_VAL _HUGE + +#ifndef _CRT_ABS_DEFINED +#define _CRT_ABS_DEFINED + int __cdecl abs(int _X); + long __cdecl labs(long _X); +#endif + double __cdecl acos(double _X); + double __cdecl asin(double _X); + double __cdecl atan(double _X); + double __cdecl atan2(double _Y,double _X); +#ifndef _SIGN_DEFINED +#define _SIGN_DEFINED + _CRTIMP double __cdecl _copysign (double _Number,double _Sign); + _CRTIMP double __cdecl _chgsign (double _X); +#endif + double __cdecl cos(double _X); + double __cdecl cosh(double _X); + double __cdecl exp(double _X); + double __cdecl expm1(double _X); + double __cdecl fabs(double _X); + double __cdecl fmod(double _X,double _Y); + double __cdecl log(double _X); + double __cdecl log10(double _X); + double __cdecl pow(double _X,double _Y); + double __cdecl sin(double _X); + double __cdecl sinh(double _X); + double __cdecl tan(double _X); + double __cdecl tanh(double _X); + double __cdecl sqrt(double _X); +#ifndef _CRT_ATOF_DEFINED +#define _CRT_ATOF_DEFINED + double __cdecl atof(const char *_String); + double __cdecl _atof_l(const char *_String,_locale_t _Locale); +#endif + + _CRTIMP double __cdecl _cabs(struct _complex _ComplexA); + double __cdecl ceil(double _X); + double __cdecl floor(double _X); + double __cdecl frexp(double _X,int *_Y); + double __cdecl _hypot(double _X,double _Y); + _CRTIMP double __cdecl _j0(double _X); + _CRTIMP double __cdecl _j1(double _X); + _CRTIMP double __cdecl _jn(int _X,double _Y); + double __cdecl ldexp(double _X,int _Y); +#ifndef _CRT_MATHERR_DEFINED +#define _CRT_MATHERR_DEFINED + int __cdecl _matherr(struct _exception *_Except); +#endif + double __cdecl modf(double _X,double *_Y); + _CRTIMP double __cdecl _y0(double _X); + _CRTIMP double __cdecl _y1(double _X); + _CRTIMP double __cdecl _yn(int _X,double _Y); + +#if(defined(_X86_) && !defined(__x86_64)) + _CRTIMP int __cdecl _set_SSE2_enable(int _Flag); + /* from libmingwex */ + float __cdecl _hypotf(float _X,float _Y); +#endif + + float frexpf(float _X,int *_Y); + float __cdecl ldexpf(float _X,int _Y); + long double __cdecl ldexpl(long double _X,int _Y); + float __cdecl acosf(float _X); + float __cdecl asinf(float _X); + float __cdecl atanf(float _X); + float __cdecl atan2f(float _X,float _Y); + float __cdecl cosf(float _X); + float __cdecl sinf(float _X); + float __cdecl tanf(float _X); + float __cdecl coshf(float _X); + float __cdecl sinhf(float _X); + float __cdecl tanhf(float _X); + float __cdecl expf(float _X); + float __cdecl expm1f(float _X); + float __cdecl logf(float _X); + float __cdecl log10f(float _X); + float __cdecl modff(float _X,float *_Y); + float __cdecl powf(float _X,float _Y); + float __cdecl sqrtf(float _X); + float __cdecl ceilf(float _X); + float __cdecl floorf(float _X); + float __cdecl fmodf(float _X,float _Y); + float __cdecl _hypotf(float _X,float _Y); + float __cdecl fabsf(float _X); +#if !defined(__ia64__) + /* from libmingwex */ + float __cdecl _copysignf (float _Number,float _Sign); + float __cdecl _chgsignf (float _X); + float __cdecl _logbf(float _X); + float __cdecl _nextafterf(float _X,float _Y); + int __cdecl _finitef(float _X); + int __cdecl _isnanf(float _X); + int __cdecl _fpclassf(float _X); +#endif + +#ifndef __cplusplus + __CRT_INLINE long double __cdecl fabsl (long double x) + { + long double res; + __asm__ ("fabs;" : "=t" (res) : "0" (x)); + return res; + } +#define _hypotl(x,y) ((long double)_hypot((double)(x),(double)(y))) +#define _matherrl _matherr + __CRT_INLINE long double _chgsignl(long double _Number) { return _chgsign((double)(_Number)); } + __CRT_INLINE long double _copysignl(long double _Number,long double _Sign) { return _copysign((double)(_Number),(double)(_Sign)); } + __CRT_INLINE float frexpf(float _X,int *_Y) { return ((float)frexp((double)_X,_Y)); } + +#if !defined (__ia64__) + __CRT_INLINE float __cdecl fabsf (float x) + { + return fabs(x); + } + + __CRT_INLINE float __cdecl ldexpf (float x, int expn) { return (float) ldexp (x, expn); } +#endif +#else + // cplusplus + __CRT_INLINE long double __cdecl fabsl (long double x) + { + long double res; + __asm__ ("fabs;" : "=t" (res) : "0" (x)); + return res; + } + __CRT_INLINE long double modfl(long double _X,long double *_Y) { + double _Di,_Df = modf((double)_X,&_Di); + *_Y = (long double)_Di; + return (_Df); + } + __CRT_INLINE long double _chgsignl(long double _Number) { return _chgsign(static_cast(_Number)); } + __CRT_INLINE long double _copysignl(long double _Number,long double _Sign) { return _copysign(static_cast(_Number),static_cast(_Sign)); } + __CRT_INLINE float frexpf(float _X,int *_Y) { return ((float)frexp((double)_X,_Y)); } +#ifndef __ia64__ + __CRT_INLINE float __cdecl fabsf (float x) + { + float res; + __asm__ ("fabs;" : "=t" (res) : "0" (x)); + return res; + } + __CRT_INLINE float __cdecl ldexpf (float x, int expn) { return (float) ldexp (x, expn); } +#ifndef __x86_64 + __CRT_INLINE float acosf(float _X) { return ((float)acos((double)_X)); } + __CRT_INLINE float asinf(float _X) { return ((float)asin((double)_X)); } + __CRT_INLINE float atanf(float _X) { return ((float)atan((double)_X)); } + __CRT_INLINE float atan2f(float _X,float _Y) { return ((float)atan2((double)_X,(double)_Y)); } + __CRT_INLINE float ceilf(float _X) { return ((float)ceil((double)_X)); } + __CRT_INLINE float cosf(float _X) { return ((float)cos((double)_X)); } + __CRT_INLINE float coshf(float _X) { return ((float)cosh((double)_X)); } + __CRT_INLINE float expf(float _X) { return ((float)exp((double)_X)); } + __CRT_INLINE float floorf(float _X) { return ((float)floor((double)_X)); } + __CRT_INLINE float fmodf(float _X,float _Y) { return ((float)fmod((double)_X,(double)_Y)); } + __CRT_INLINE float logf(float _X) { return ((float)log((double)_X)); } + __CRT_INLINE float log10f(float _X) { return ((float)log10((double)_X)); } + __CRT_INLINE float modff(float _X,float *_Y) { + double _Di,_Df = modf((double)_X,&_Di); + *_Y = (float)_Di; + return ((float)_Df); + } + __CRT_INLINE float powf(float _X,float _Y) { return ((float)pow((double)_X,(double)_Y)); } + __CRT_INLINE float sinf(float _X) { return ((float)sin((double)_X)); } + __CRT_INLINE float sinhf(float _X) { return ((float)sinh((double)_X)); } + __CRT_INLINE float sqrtf(float _X) { return ((float)sqrt((double)_X)); } + __CRT_INLINE float tanf(float _X) { return ((float)tan((double)_X)); } + __CRT_INLINE float tanhf(float _X) { return ((float)tanh((double)_X)); } +#endif +#endif +#endif + +#ifndef NO_OLDNAMES +#define matherr _matherr + +#define HUGE _HUGE + /* double __cdecl cabs(struct _complex _X); */ + double __cdecl hypot(double _X,double _Y); + _CRTIMP double __cdecl j0(double _X); + _CRTIMP double __cdecl j1(double _X); + _CRTIMP double __cdecl jn(int _X,double _Y); + _CRTIMP double __cdecl y0(double _X); + _CRTIMP double __cdecl y1(double _X); + _CRTIMP double __cdecl yn(int _X,double _Y); +#endif + +#ifndef __NO_ISOCEXT +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \ + || !defined __STRICT_ANSI__ || defined __GLIBCPP__ + +#define NAN (0.0F/0.0F) +#define HUGE_VALF (1.0F/0.0F) +#define HUGE_VALL (1.0L/0.0L) +#define INFINITY (1.0F/0.0F) + + +#define FP_NAN 0x0100 +#define FP_NORMAL 0x0400 +#define FP_INFINITE (FP_NAN | FP_NORMAL) +#define FP_ZERO 0x4000 +#define FP_SUBNORMAL (FP_NORMAL | FP_ZERO) + /* 0x0200 is signbit mask */ + + + /* + We can't __CRT_INLINE float or double, because we want to ensure truncation + to semantic type before classification. + (A normal long double value might become subnormal when + converted to double, and zero when converted to float.) + */ + + extern int __cdecl __fpclassifyf (float); + extern int __cdecl __fpclassify (double); + extern int __cdecl __fpclassifyl (long double); + +/* Implemented at tcc/tcc_libm.h */ +#define fpclassify(x) (sizeof (x) == sizeof (float) ? __fpclassifyf (x) \ + : sizeof (x) == sizeof (double) ? __fpclassify (x) \ + : __fpclassifyl (x)) + + /* 7.12.3.2 */ +#define isfinite(x) ((fpclassify(x) & FP_NAN) == 0) + + /* 7.12.3.3 */ +#define isinf(x) (fpclassify(x) == FP_INFINITE) + + /* 7.12.3.4 */ + /* We don't need to worry about trucation here: + A NaN stays a NaN. */ +#define isnan(x) (fpclassify(x) == FP_NAN) + + /* 7.12.3.5 */ +#define isnormal(x) (fpclassify(x) == FP_NORMAL) + + /* 7.12.3.6 The signbit macro */ + + extern int __cdecl __signbitf (float); + extern int __cdecl __signbit (double); + extern int __cdecl __signbitl (long double); + +/* Implemented at tcc/tcc_libm.h */ +#define signbit(x) (sizeof (x) == sizeof (float) ? __signbitf (x) \ + : sizeof (x) == sizeof (double) ? __signbit (x) \ + : __signbitl (x)) + + extern double __cdecl exp2(double); + extern float __cdecl exp2f(float); + extern long double __cdecl exp2l(long double); + +#define FP_ILOGB0 ((int)0x80000000) +#define FP_ILOGBNAN ((int)0x80000000) + extern int __cdecl ilogb (double); + extern int __cdecl ilogbf (float); + extern int __cdecl ilogbl (long double); + + extern double __cdecl log1p(double); + extern float __cdecl log1pf(float); + extern long double __cdecl log1pl(long double); + + extern double __cdecl log2 (double); + extern float __cdecl log2f (float); + extern long double __cdecl log2l (long double); + + extern double __cdecl logb (double); + extern float __cdecl logbf (float); + extern long double __cdecl logbl (long double); + + __CRT_INLINE double __cdecl logb (double x) + { + double res; + __asm__ ("fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; + } + + __CRT_INLINE float __cdecl logbf (float x) + { + float res; + __asm__ ("fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; + } + + __CRT_INLINE long double __cdecl logbl (long double x) + { + long double res; + __asm__ ("fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; + } + + extern long double __cdecl modfl (long double, long double*); + + /* 7.12.6.13 */ + extern double __cdecl scalbn (double, int); + extern float __cdecl scalbnf (float, int); + extern long double __cdecl scalbnl (long double, int); + + extern double __cdecl scalbln (double, long); + extern float __cdecl scalblnf (float, long); + extern long double __cdecl scalblnl (long double, long); + + /* 7.12.7.1 */ + /* Implementations adapted from Cephes versions */ + extern double __cdecl cbrt (double); + extern float __cdecl cbrtf (float); + extern long double __cdecl cbrtl (long double); + + __CRT_INLINE float __cdecl hypotf (float x, float y) + { return (float) hypot (x, y);} + extern long double __cdecl hypotl (long double, long double); + + extern long double __cdecl powl (long double, long double); + extern long double __cdecl expl(long double); + extern long double __cdecl expm1l(long double); + extern long double __cdecl coshl(long double); + extern long double __cdecl fabsl (long double); + extern long double __cdecl acosl(long double); + extern long double __cdecl asinl(long double); + extern long double __cdecl atanl(long double); + extern long double __cdecl atan2l(long double,long double); + extern long double __cdecl sinhl(long double); + extern long double __cdecl tanhl(long double); + + /* 7.12.8.1 The erf functions */ + extern double __cdecl erf (double); + extern float __cdecl erff (float); + /* TODO + extern long double __cdecl erfl (long double); + */ + + /* 7.12.8.2 The erfc functions */ + extern double __cdecl erfc (double); + extern float __cdecl erfcf (float); + /* TODO + extern long double __cdecl erfcl (long double); + */ + + /* 7.12.8.3 The lgamma functions */ + extern double __cdecl lgamma (double); + extern float __cdecl lgammaf (float); + extern long double __cdecl lgammal (long double); + + /* 7.12.8.4 The tgamma functions */ + extern double __cdecl tgamma (double); + extern float __cdecl tgammaf (float); + extern long double __cdecl tgammal (long double); + + extern long double __cdecl ceill (long double); + extern long double __cdecl floorl (long double); + extern long double __cdecl frexpl(long double,int *); + extern long double __cdecl log10l(long double); + extern long double __cdecl logl(long double); + extern long double __cdecl cosl(long double); + extern long double __cdecl sinl(long double); + extern long double __cdecl tanl(long double); + extern long double sqrtl(long double); + + /* 7.12.9.3 */ + extern double __cdecl nearbyint ( double); + extern float __cdecl nearbyintf (float); + extern long double __cdecl nearbyintl (long double); + + /* 7.12.9.4 */ + /* round, using fpu control word settings */ + __CRT_INLINE double __cdecl rint (double x) + { + double retval; + __asm__ ( + "fldl %1\n" + "frndint \n" + "fstl %0\n" : "=m" (retval) : "m" (x)); + return retval; + } + + __CRT_INLINE float __cdecl rintf (float x) + { + float retval; + __asm__ ( + "flds %1\n" + "frndint \n" + "fsts %0\n" : "=m" (retval) : "m" (x)); + return retval; + } + + __CRT_INLINE long double __cdecl rintl (long double x) + { + long double retval; + __asm__ ( + "fldt %1\n" + "frndint \n" + "fstt %0\n" : "=m" (retval) : "m" (x)); + return retval; + } + + /* 7.12.9.5 */ + __CRT_INLINE long __cdecl lrint (double x) + { + long retval; + __asm__ __volatile__ \ + ("fldl %1\n" \ + "fistpl %0" : "=m" (retval) : "m" (x)); \ + return retval; + } + + __CRT_INLINE long __cdecl lrintf (float x) + { + long retval; + __asm__ __volatile__ \ + ("flds %1\n" \ + "fistpl %0" : "=m" (retval) : "m" (x)); \ + return retval; + } + + __CRT_INLINE long __cdecl lrintl (long double x) + { + long retval; + __asm__ __volatile__ \ + ("fldt %1\n" \ + "fistpl %0" : "=m" (retval) : "m" (x)); \ + return retval; + } + + __CRT_INLINE long long __cdecl llrint (double x) + { + long long retval; + __asm__ __volatile__ \ + ("fldl %1\n" \ + "fistpll %0" : "=m" (retval) : "m" (x)); \ + return retval; + } + + __CRT_INLINE long long __cdecl llrintf (float x) + { + long long retval; + __asm__ __volatile__ \ + ("flds %1\n" \ + "fistpll %0" : "=m" (retval) : "m" (x)); \ + return retval; + } + + __CRT_INLINE long long __cdecl llrintl (long double x) + { + long long retval; + __asm__ __volatile__ \ + ("fldt %1\n" \ + "fistpll %0" : "=m" (retval) : "m" (x)); \ + return retval; + } + + #define FE_TONEAREST 0x0000 + #define FE_DOWNWARD 0x0400 + #define FE_UPWARD 0x0800 + #define FE_TOWARDZERO 0x0c00 + + __CRT_INLINE double trunc (double _x) + { + double retval; + unsigned short saved_cw; + unsigned short tmp_cw; + __asm__ ("fnstcw %0;" : "=m" (saved_cw)); /* save FPU control word */ + tmp_cw = (saved_cw & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) + | FE_TOWARDZERO; + __asm__ ("fldcw %0;" : : "m" (tmp_cw)); + __asm__ ("fldl %1;" + "frndint;" + "fstl %0;" : "=m" (retval) : "m" (_x)); /* round towards zero */ + __asm__ ("fldcw %0;" : : "m" (saved_cw) ); /* restore saved control word */ + return retval; + } + + /* 7.12.9.6 */ + /* round away from zero, regardless of fpu control word settings */ + extern double __cdecl round (double); + extern float __cdecl roundf (float); + extern long double __cdecl roundl (long double); + + /* 7.12.9.7 */ + extern long __cdecl lround (double); + extern long __cdecl lroundf (float); + extern long __cdecl lroundl (long double); + + extern long long __cdecl llround (double); + extern long long __cdecl llroundf (float); + extern long long __cdecl llroundl (long double); + + /* 7.12.9.8 */ + /* round towards zero, regardless of fpu control word settings */ + extern double __cdecl trunc (double); + extern float __cdecl truncf (float); + extern long double __cdecl truncl (long double); + + extern long double __cdecl fmodl (long double, long double); + + /* 7.12.10.2 */ + extern double __cdecl remainder (double, double); + extern float __cdecl remainderf (float, float); + extern long double __cdecl remainderl (long double, long double); + + /* 7.12.10.3 */ + extern double __cdecl remquo(double, double, int *); + extern float __cdecl remquof(float, float, int *); + extern long double __cdecl remquol(long double, long double, int *); + + /* 7.12.11.1 */ + extern double __cdecl copysign (double, double); /* in libmoldname.a */ + extern float __cdecl copysignf (float, float); + extern long double __cdecl copysignl (long double, long double); + + /* 7.12.11.2 Return a NaN */ + extern double __cdecl nan(const char *tagp); + extern float __cdecl nanf(const char *tagp); + extern long double __cdecl nanl(const char *tagp); + +#ifndef __STRICT_ANSI__ +#define _nan() nan("") +#define _nanf() nanf("") +#define _nanl() nanl("") +#endif + + /* 7.12.11.3 */ + extern double __cdecl nextafter (double, double); /* in libmoldname.a */ + extern float __cdecl nextafterf (float, float); + extern long double __cdecl nextafterl (long double, long double); + + /* 7.12.11.4 The nexttoward functions: TODO */ + + /* 7.12.12.1 */ + /* x > y ? (x - y) : 0.0 */ + extern double __cdecl fdim (double x, double y); + extern float __cdecl fdimf (float x, float y); + extern long double __cdecl fdiml (long double x, long double y); + + /* fmax and fmin. + NaN arguments are treated as missing data: if one argument is a NaN + and the other numeric, then these functions choose the numeric + value. */ + + /* 7.12.12.2 */ + extern double __cdecl fmax (double, double); + extern float __cdecl fmaxf (float, float); + extern long double __cdecl fmaxl (long double, long double); + + /* 7.12.12.3 */ + extern double __cdecl fmin (double, double); + extern float __cdecl fminf (float, float); + extern long double __cdecl fminl (long double, long double); + + /* 7.12.13.1 */ + /* return x * y + z as a ternary op */ + extern double __cdecl fma (double, double, double); + extern float __cdecl fmaf (float, float, float); + extern long double __cdecl fmal (long double, long double, long double); + + +#if 0 // gr: duplicate, see below + /* 7.12.14 */ + /* + * With these functions, comparisons involving quiet NaNs set the FP + * condition code to "unordered". The IEEE floating-point spec + * dictates that the result of floating-point comparisons should be + * false whenever a NaN is involved, with the exception of the != op, + * which always returns true: yes, (NaN != NaN) is true). + */ + +#if __GNUC__ >= 3 + +#define isgreater(x, y) __builtin_isgreater(x, y) +#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) +#define isless(x, y) __builtin_isless(x, y) +#define islessequal(x, y) __builtin_islessequal(x, y) +#define islessgreater(x, y) __builtin_islessgreater(x, y) +#define isunordered(x, y) __builtin_isunordered(x, y) + +#else + /* helper */ + __CRT_INLINE int __cdecl + __fp_unordered_compare (long double x, long double y){ + unsigned short retval; + __asm__ ("fucom %%st(1);" + "fnstsw;": "=a" (retval) : "t" (x), "u" (y)); + return retval; + } + +#define isgreater(x, y) ((__fp_unordered_compare(x, y) \ + & 0x4500) == 0) +#define isless(x, y) ((__fp_unordered_compare (y, x) \ + & 0x4500) == 0) +#define isgreaterequal(x, y) ((__fp_unordered_compare (x, y) \ + & FP_INFINITE) == 0) +#define islessequal(x, y) ((__fp_unordered_compare(y, x) \ + & FP_INFINITE) == 0) +#define islessgreater(x, y) ((__fp_unordered_compare(x, y) \ + & FP_SUBNORMAL) == 0) +#define isunordered(x, y) ((__fp_unordered_compare(x, y) \ + & 0x4500) == 0x4500) + +#endif +#endif //0 + + +#endif /* __STDC_VERSION__ >= 199901L */ +#endif /* __NO_ISOCEXT */ + +#ifdef __cplusplus +} +extern "C++" { + template inline _Ty _Pow_int(_Ty _X,int _Y) { + unsigned int _N; + if(_Y >= 0) _N = (unsigned int)_Y; + else _N = (unsigned int)(-_Y); + for(_Ty _Z = _Ty(1);;_X *= _X) { + if((_N & 1)!=0) _Z *= _X; + if((_N >>= 1)==0) return (_Y < 0 ? _Ty(1) / _Z : _Z); + } + } +} +#endif + +#pragma pack(pop) + +/* 7.12.14 */ +/* + * With these functions, comparisons involving quiet NaNs set the FP + * condition code to "unordered". The IEEE floating-point spec + * dictates that the result of floating-point comparisons should be + * false whenever a NaN is involved, with the exception of the != op, + * which always returns true: yes, (NaN != NaN) is true). + */ + +/* Mini libm (inline __fpclassify*, __signbit* and variants) */ + +/* TCC uses 8 bytes for double and long double, so effectively the l variants + * are never used. For now, they just run the normal (double) variant. + */ + +/* + * most of the code in this file is taken from MUSL rs-1.0 (MIT license) + * - musl-libc: http://git.musl-libc.org/cgit/musl/tree/src/math?h=rs-1.0 + * - License: http://git.musl-libc.org/cgit/musl/tree/COPYRIGHT?h=rs-1.0 + */ + +/******************************************************************************* + Start of code based on MUSL +*******************************************************************************/ +/* +musl as a whole is licensed under the following standard MIT license: + +---------------------------------------------------------------------- +Copyright © 2005-2014 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +---------------------------------------------------------------------- +*/ + +/* fpclassify */ + +__CRT_INLINE int __cdecl __fpclassify (double x) { + union {double f; uint64_t i;} u = {x}; + int e = u.i>>52 & 0x7ff; + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; + if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE; + return FP_NORMAL; +} + +__CRT_INLINE int __cdecl __fpclassifyf (float x) { + union {float f; uint32_t i;} u = {x}; + int e = u.i>>23 & 0xff; + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; + if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE; + return FP_NORMAL; +} + +__CRT_INLINE int __cdecl __fpclassifyl (long double x) { + return __fpclassify(x); +} + + +/* signbit */ + +__CRT_INLINE int __cdecl __signbit (double x) { + union {double d; uint64_t i;} y = { x }; + return y.i>>63; +} + +__CRT_INLINE int __cdecl __signbitf (float x) { + union {float f; uint32_t i; } y = { x }; + return y.i>>31; +} + +__CRT_INLINE int __cdecl __signbitl (long double x) { + return __signbit(x); +} + + +/* fmin*, fmax* */ + +#define TCCFP_FMIN_EVAL (isnan(x) ? y : \ + isnan(y) ? x : \ + (signbit(x) != signbit(y)) ? (signbit(x) ? x : y) : \ + x < y ? x : y) + +__CRT_INLINE double __cdecl fmin (double x, double y) { + return TCCFP_FMIN_EVAL; +} + +__CRT_INLINE float __cdecl fminf (float x, float y) { + return TCCFP_FMIN_EVAL; +} + +__CRT_INLINE long double __cdecl fminl (long double x, long double y) { + return TCCFP_FMIN_EVAL; +} + +#define TCCFP_FMAX_EVAL (isnan(x) ? y : \ + isnan(y) ? x : \ + (signbit(x) != signbit(y)) ? (signbit(x) ? y : x) : \ + x < y ? y : x) + +__CRT_INLINE double __cdecl fmax (double x, double y) { + return TCCFP_FMAX_EVAL; +} + +__CRT_INLINE float __cdecl fmaxf (float x, float y) { + return TCCFP_FMAX_EVAL; +} + +__CRT_INLINE long double __cdecl fmaxl (long double x, long double y) { + return TCCFP_FMAX_EVAL; +} + + +/* *round* */ + +#define TCCFP_FORCE_EVAL(x) do { \ +if (sizeof(x) == sizeof(float)) { \ + volatile float __x; \ + __x = (x); \ +} else if (sizeof(x) == sizeof(double)) { \ + volatile double __x; \ + __x = (x); \ +} else { \ + volatile long double __x; \ + __x = (x); \ +} \ +} while(0) + +__CRT_INLINE double __cdecl round (double x) { + union {double f; uint64_t i;} u = {x}; + int e = u.i >> 52 & 0x7ff; + double y; + + if (e >= 0x3ff+52) + return x; + if (u.i >> 63) + x = -x; + if (e < 0x3ff-1) { + /* raise inexact if x!=0 */ + TCCFP_FORCE_EVAL(x + 0x1p52); + return 0*u.f; + } + y = (double)(x + 0x1p52) - 0x1p52 - x; + if (y > 0.5) + y = y + x - 1; + else if (y <= -0.5) + y = y + x + 1; + else + y = y + x; + if (u.i >> 63) + y = -y; + return y; +} + +__CRT_INLINE long __cdecl lround (double x) { + return round(x); +} + +__CRT_INLINE long long __cdecl llround (double x) { + return round(x); +} + +__CRT_INLINE float __cdecl roundf (float x) { + return round(x); +} + +__CRT_INLINE long __cdecl lroundf (float x) { + return round(x); +} + +__CRT_INLINE long long __cdecl llroundf (float x) { + return round(x); +} + +__CRT_INLINE long double __cdecl roundl (long double x) { + return round(x); +} + +__CRT_INLINE long __cdecl lroundl (long double x) { + return round(x); +} + +__CRT_INLINE long long __cdecl llroundl (long double x) { + return round(x); +} + + + +#endif /* End _MATH_H_ */ + diff --git a/colorchord2/windows/mmsystem.h b/colorchord2/windows/mmsystem.h new file mode 100644 index 0000000..3eb06a4 --- /dev/null +++ b/colorchord2/windows/mmsystem.h @@ -0,0 +1,1950 @@ + +#ifndef _MMSYSTEM_H +#define _MMSYSTEM_H +#if __GNUC__ >=3 +#pragma GCC system_header +#endif +#pragma pack(push,1) +#ifdef __cplusplus +extern "C" { +#endif + +#if defined( TCC ) || defined (TinyCC) || defined(TINYCC) +#define _STRUCT_NAME(x) x +typedef UINT* LPUINT; +#endif + +#define WINMMAPI DECLSPEC_IMPORT +#define _loadds +#define _huge +#define MAXPNAMELEN 32 +#define MAXERRORLENGTH 256 +#define MAX_JOYSTICKOEMVXDNAME 260 +#define _MMRESULT_ +#define TIME_MS 1 +#define TIME_SAMPLES 2 +#define TIME_BYTES 4 +#define TIME_SMPTE 8 +#define TIME_MIDI 16 +#define TIME_TICKS 32 +#define MAKEFOURCC(c0,c1,c2,c3) ((DWORD)(BYTE)(c0)|((DWORD)(BYTE)(c1)<<8)|((DWORD)(BYTE)(c2)<<16)|((DWORD)(BYTE)(c3)<<24)) +#ifndef mmioFOURCC +#define mmioFOURCC(c0,c1,c2,c3) MAKEFOURCC(c0,c1,c2,c3) +#endif +#define MM_JOY1MOVE 0x3A0 +#define MM_JOY2MOVE 0x3A1 +#define MM_JOY1ZMOVE 0x3A2 +#define MM_JOY2ZMOVE 0x3A3 +#define MM_JOY1BUTTONDOWN 0x3B5 +#define MM_JOY2BUTTONDOWN 0x3B6 +#define MM_JOY1BUTTONUP 0x3B7 +#define MM_JOY2BUTTONUP 0x3B8 +#define MM_MCINOTIFY 0x3B9 +#define MM_WOM_OPEN 0x3BB +#define MM_WOM_CLOSE 0x3BC +#define MM_WOM_DONE 0x3BD +#define MM_WIM_OPEN 0x3BE +#define MM_WIM_CLOSE 0x3BF +#define MM_WIM_DATA 0x3C0 +#define MM_MIM_OPEN 0x3C1 +#define MM_MIM_CLOSE 0x3C2 +#define MM_MIM_DATA 0x3C3 +#define MM_MIM_LONGDATA 0x3C4 +#define MM_MIM_ERROR 0x3C5 +#define MM_MIM_LONGERROR 0x3C6 +#define MM_MOM_OPEN 0x3C7 +#define MM_MOM_CLOSE 0x3C8 +#define MM_MOM_DONE 0x3C9 +#define MM_DRVM_OPEN 0x3D0 +#define MM_DRVM_CLOSE 0x3D1 +#define MM_DRVM_DATA 0x3D2 +#define MM_DRVM_ERROR 0x3D3 +#define MM_STREAM_OPEN 0x3D4 +#define MM_STREAM_CLOSE 0x3D5 +#define MM_STREAM_DONE 0x3D6 +#define MM_STREAM_ERROR 0x3D7 +#define MM_MOM_POSITIONCB 0x3CA +#define MM_MCISIGNAL 0x3CB +#define MM_MIM_MOREDATA 0x3CC +#define MM_MIXM_LINE_CHANGE 0x3D0 +#define MM_MIXM_CONTROL_CHANGE 0x3D1 +#define MMSYSERR_BASE 0 +#define WAVERR_BASE 32 +#define MIDIERR_BASE 64 +#define TIMERR_BASE 96 +#define JOYERR_BASE 160 +#define MCIERR_BASE 256 +#define MIXERR_BASE 1024 +#define MCI_STRING_OFFSET 512 +#define MCI_VD_OFFSET 1024 +#define MCI_CD_OFFSET 1088 +#define MCI_WAVE_OFFSET 1152 +#define MCI_SEQ_OFFSET 1216 +#define MMSYSERR_NOERROR 0 +#define MMSYSERR_ERROR (MMSYSERR_BASE+1) +#define MMSYSERR_BADDEVICEID (MMSYSERR_BASE+2) +#define MMSYSERR_NOTENABLED (MMSYSERR_BASE+3) +#define MMSYSERR_ALLOCATED (MMSYSERR_BASE+4) +#define MMSYSERR_INVALHANDLE (MMSYSERR_BASE+5) +#define MMSYSERR_NODRIVER (MMSYSERR_BASE+6) +#define MMSYSERR_NOMEM (MMSYSERR_BASE+7) +#define MMSYSERR_NOTSUPPORTED (MMSYSERR_BASE+8) +#define MMSYSERR_BADERRNUM (MMSYSERR_BASE+9) +#define MMSYSERR_INVALFLAG (MMSYSERR_BASE+10) +#define MMSYSERR_INVALPARAM (MMSYSERR_BASE+11) +#define MMSYSERR_HANDLEBUSY (MMSYSERR_BASE+12) +#define MMSYSERR_INVALIDALIAS (MMSYSERR_BASE+13) +#define MMSYSERR_BADDB (MMSYSERR_BASE+14) +#define MMSYSERR_KEYNOTFOUND (MMSYSERR_BASE+15) +#define MMSYSERR_READERROR (MMSYSERR_BASE+16) +#define MMSYSERR_WRITEERROR (MMSYSERR_BASE+17) +#define MMSYSERR_DELETEERROR (MMSYSERR_BASE+18) +#define MMSYSERR_VALNOTFOUND (MMSYSERR_BASE+19) +#define MMSYSERR_NODRIVERCB (MMSYSERR_BASE+20) +#define MMSYSERR_LASTERROR (MMSYSERR_BASE+20) +#define DRV_LOAD 1 +#define DRV_ENABLE 2 +#define DRV_OPEN 3 +#define DRV_CLOSE 4 +#define DRV_DISABLE 5 +#define DRV_FREE 6 +#define DRV_CONFIGURE 7 +#define DRV_QUERYCONFIGURE 8 +#define DRV_INSTALL 9 +#define DRV_REMOVE 10 +#define DRV_EXITSESSION 11 +#define DRV_POWER 15 +#define DRV_RESERVED 0x800 +#define DRV_USER 0x4000 +#define DRVCNF_CANCEL 0 +#define DRVCNF_OK 1 +#define DRVCNF_RESTART 2 +#define DRV_CANCEL DRVCNF_CANCEL +#define DRV_OK DRVCNF_OK +#define DRV_RESTART DRVCNF_RESTART +#define DRV_MCI_FIRST DRV_RESERVED +#define DRV_MCI_LAST (DRV_RESERVED+0xFFF) +#define CALLBACK_TYPEMASK 0x70000 +#define CALLBACK_NULL 0 +#define CALLBACK_WINDOW 0x10000 +#define CALLBACK_TASK 0x20000 +#define CALLBACK_FUNCTION 0x30000 +#define CALLBACK_THREAD CALLBACK_TASK +#define CALLBACK_EVENT 0x50000 +#define SND_SYNC 0 +#define SND_ASYNC 1 +#define SND_NODEFAULT 2 +#define SND_MEMORY 4 +#define SND_LOOP 8 +#define SND_NOSTOP 16 +#define SND_NOWAIT 0x2000 +#define SND_ALIAS 0x10000 +#define SND_ALIAS_ID 0x110000 +#define SND_FILENAME 0x20000 +#define SND_RESOURCE 0x40004 +#define SND_PURGE 0x40 +#define SND_APPLICATION 0x80 +#define SND_ALIAS_START 0 +#define sndAlias(c0,c1) (SND_ALIAS_START+(DWORD)(BYTE)(c0)|((DWORD)(BYTE)(c1)<<8)) +#define SND_ALIAS_SYSTEMASTERISK sndAlias('S','*') +#define SND_ALIAS_SYSTEMQUESTION sndAlias('S','?') +#define SND_ALIAS_SYSTEMHAND sndAlias('S','H') +#define SND_ALIAS_SYSTEMEXIT sndAlias('S','E') +#define SND_ALIAS_SYSTEMSTART sndAlias('S','S') +#define SND_ALIAS_SYSTEMWELCOME sndAlias('S','W') +#define SND_ALIAS_SYSTEMEXCLAMATION sndAlias('S','!') +#define SND_ALIAS_SYSTEMDEFAULT sndAlias('S','D') +#define WAVERR_BADFORMAT (WAVERR_BASE + 0) +#define WAVERR_STILLPLAYING (WAVERR_BASE + 1) +#define WAVERR_UNPREPARED (WAVERR_BASE + 2) +#define WAVERR_SYNC (WAVERR_BASE + 3) +#define WAVERR_LASTERROR (WAVERR_BASE + 3) +#define WOM_OPEN MM_WOM_OPEN +#define WOM_CLOSE MM_WOM_CLOSE +#define WOM_DONE MM_WOM_DONE +#define WIM_OPEN MM_WIM_OPEN +#define WIM_CLOSE MM_WIM_CLOSE +#define WIM_DATA MM_WIM_DATA +#define WAVE_MAPPER ((UINT)-1) +#define WAVE_FORMAT_QUERY 1 +#define WAVE_ALLOWSYNC 2 +#define WAVE_MAPPED 4 +#define WAVE_FORMAT_DIRECT 8 +#define WAVE_FORMAT_DIRECT_QUERY (WAVE_FORMAT_QUERY|WAVE_FORMAT_DIRECT) +#define WHDR_DONE 1 +#define WHDR_PREPARED 2 +#define WHDR_BEGINLOOP 4 +#define WHDR_ENDLOOP 8 +#define WHDR_INQUEUE 16 +#define WAVECAPS_PITCH 1 +#define WAVECAPS_PLAYBACKRATE 2 +#define WAVECAPS_VOLUME 4 +#define WAVECAPS_LRVOLUME 8 +#define WAVECAPS_SYNC 16 +#define WAVECAPS_SAMPLEACCURATE 32 +#define WAVECAPS_DIRECTSOUND 64 +#define WAVE_INVALIDFORMAT 0 +#define WAVE_FORMAT_1M08 1 +#define WAVE_FORMAT_1S08 2 +#define WAVE_FORMAT_1M16 4 +#define WAVE_FORMAT_1S16 8 +#define WAVE_FORMAT_2M08 16 +#define WAVE_FORMAT_2S08 32 +#define WAVE_FORMAT_2M16 64 +#define WAVE_FORMAT_2S16 128 +#define WAVE_FORMAT_4M08 256 +#define WAVE_FORMAT_4S08 512 +#define WAVE_FORMAT_4M16 1024 +#define WAVE_FORMAT_4S16 2048 +#define WAVE_FORMAT_PCM 1 +#define WAVE_FORMAT_EXTENSIBLE 0xFFFE +#define MIDIERR_UNPREPARED MIDIERR_BASE +#define MIDIERR_STILLPLAYING (MIDIERR_BASE+1) +#define MIDIERR_NOMAP (MIDIERR_BASE+2) +#define MIDIERR_NOTREADY (MIDIERR_BASE+3) +#define MIDIERR_NODEVICE (MIDIERR_BASE+4) +#define MIDIERR_INVALIDSETUP (MIDIERR_BASE+5) +#define MIDIERR_BADOPENMODE (MIDIERR_BASE+6) +#define MIDIERR_DONT_CONTINUE (MIDIERR_BASE+7) +#define MIDIERR_LASTERROR (MIDIERR_BASE+7) +#define MIDIPATCHSIZE 128 +#define MIM_OPEN MM_MIM_OPEN +#define MIM_CLOSE MM_MIM_CLOSE +#define MIM_DATA MM_MIM_DATA +#define MIM_LONGDATA MM_MIM_LONGDATA +#define MIM_ERROR MM_MIM_ERROR +#define MIM_LONGERROR MM_MIM_LONGERROR +#define MOM_OPEN MM_MOM_OPEN +#define MOM_CLOSE MM_MOM_CLOSE +#define MOM_DONE MM_MOM_DONE +#define MIM_MOREDATA MM_MIM_MOREDATA +#define MOM_POSITIONCB MM_MOM_POSITIONCB +#define MIDIMAPPER ((UINT)-1) +#define MIDI_MAPPER ((UINT)-1) +#define MIDI_IO_STATUS 32 +#define MIDI_CACHE_ALL 1 +#define MIDI_CACHE_BESTFIT 2 +#define MIDI_CACHE_QUERY 3 +#define MIDI_UNCACHE 4 +#define MOD_MIDIPORT 1 +#define MOD_SYNTH 2 +#define MOD_SQSYNTH 3 +#define MOD_FMSYNTH 4 +#define MOD_MAPPER 5 +#define MIDICAPS_VOLUME 1 +#define MIDICAPS_LRVOLUME 2 +#define MIDICAPS_CACHE 4 +#define MIDICAPS_STREAM 8 +#define MHDR_DONE 1 +#define MHDR_PREPARED 2 +#define MHDR_INQUEUE 4 +#define MHDR_ISSTRM 8 +#define MEVT_F_SHORT 0 +#define MEVT_F_LONG 0x80000000 +#define MEVT_F_CALLBACK 0x40000000 +#define MEVT_EVENTTYPE(x) ((BYTE)(((x)>>24)&0xFF)) +#define MEVT_EVENTPARM(x) ((DWORD)((x)&0xFFFFFFL)) +#define MEVT_SHORTMSG 0 +#define MEVT_TEMPO 1 +#define MEVT_NOP 2 +#define MEVT_LONGMSG ((BYTE)0x80) +#define MEVT_COMMENT ((BYTE)0x82) +#define MEVT_VERSION ((BYTE)0x84) +#define MIDISTRM_ERROR (-2) +#define MIDIPROP_SET 0x80000000 +#define MIDIPROP_GET 0x40000000 +#define MIDIPROP_TIMEDIV 1 +#define MIDIPROP_TEMPO 2 +#define AUX_MAPPER ((UINT)-1) +#define AUXCAPS_CDAUDIO 1 +#define AUXCAPS_AUXIN 2 +#define AUXCAPS_VOLUME 1 +#define AUXCAPS_LRVOLUME 2 +#define MIXER_SHORT_NAME_CHARS 16 +#define MIXER_LONG_NAME_CHARS 64 +#define MIXERR_INVALLINE MIXERR_BASE +#define MIXERR_INVALCONTROL (MIXERR_BASE+1) +#define MIXERR_INVALVALUE (MIXERR_BASE+2) +#define MIXERR_LASTERROR (MIXERR_BASE+2) +#define MIXER_OBJECTF_HANDLE 0x80000000 +#define MIXER_OBJECTF_MIXER 0 +#define MIXER_OBJECTF_HMIXER (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIXER) +#define MIXER_OBJECTF_WAVEOUT 0x10000000 +#define MIXER_OBJECTF_HWAVEOUT (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_WAVEOUT) +#define MIXER_OBJECTF_WAVEIN 0x20000000 +#define MIXER_OBJECTF_HWAVEIN (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_WAVEIN) +#define MIXER_OBJECTF_MIDIOUT 0x30000000 +#define MIXER_OBJECTF_HMIDIOUT (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIDIOUT) +#define MIXER_OBJECTF_MIDIIN 0x40000000 +#define MIXER_OBJECTF_HMIDIIN (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIDIIN) +#define MIXER_OBJECTF_AUX 0x50000000 +#define MIXERLINE_LINEF_ACTIVE 1 +#define MIXERLINE_LINEF_DISCONNECTED 0x8000 +#define MIXERLINE_LINEF_SOURCE 0x80000000 +#define MIXERLINE_COMPONENTTYPE_DST_FIRST 0 +#define MIXERLINE_COMPONENTTYPE_DST_UNDEFINED MIXERLINE_COMPONENTTYPE_DST_FIRST +#define MIXERLINE_COMPONENTTYPE_DST_DIGITAL (MIXERLINE_COMPONENTTYPE_DST_FIRST+1) +#define MIXERLINE_COMPONENTTYPE_DST_LINE (MIXERLINE_COMPONENTTYPE_DST_FIRST+2) +#define MIXERLINE_COMPONENTTYPE_DST_MONITOR (MIXERLINE_COMPONENTTYPE_DST_FIRST+3) +#define MIXERLINE_COMPONENTTYPE_DST_SPEAKERS (MIXERLINE_COMPONENTTYPE_DST_FIRST+4) +#define MIXERLINE_COMPONENTTYPE_DST_HEADPHONES (MIXERLINE_COMPONENTTYPE_DST_FIRST+5) +#define MIXERLINE_COMPONENTTYPE_DST_TELEPHONE (MIXERLINE_COMPONENTTYPE_DST_FIRST+6) +#define MIXERLINE_COMPONENTTYPE_DST_WAVEIN (MIXERLINE_COMPONENTTYPE_DST_FIRST+7) +#define MIXERLINE_COMPONENTTYPE_DST_VOICEIN (MIXERLINE_COMPONENTTYPE_DST_FIRST+8) +#define MIXERLINE_COMPONENTTYPE_DST_LAST (MIXERLINE_COMPONENTTYPE_DST_FIRST+8) +#define MIXERLINE_COMPONENTTYPE_SRC_FIRST 0x1000 +#define MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED MIXERLINE_COMPONENTTYPE_SRC_FIRST +#define MIXERLINE_COMPONENTTYPE_SRC_DIGITAL (MIXERLINE_COMPONENTTYPE_SRC_FIRST+1) +#define MIXERLINE_COMPONENTTYPE_SRC_LINE (MIXERLINE_COMPONENTTYPE_SRC_FIRST+2) +#define MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE (MIXERLINE_COMPONENTTYPE_SRC_FIRST+3) +#define MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER (MIXERLINE_COMPONENTTYPE_SRC_FIRST+4) +#define MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC (MIXERLINE_COMPONENTTYPE_SRC_FIRST+5) +#define MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE (MIXERLINE_COMPONENTTYPE_SRC_FIRST+6) +#define MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER (MIXERLINE_COMPONENTTYPE_SRC_FIRST+7) +#define MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT (MIXERLINE_COMPONENTTYPE_SRC_FIRST+8) +#define MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY (MIXERLINE_COMPONENTTYPE_SRC_FIRST+9) +#define MIXERLINE_COMPONENTTYPE_SRC_ANALOG (MIXERLINE_COMPONENTTYPE_SRC_FIRST+10) +#define MIXERLINE_COMPONENTTYPE_SRC_LAST (MIXERLINE_COMPONENTTYPE_SRC_FIRST+10) +#define MIXERLINE_TARGETTYPE_UNDEFINED 0 +#define MIXERLINE_TARGETTYPE_WAVEOUT 1 +#define MIXERLINE_TARGETTYPE_WAVEIN 2 +#define MIXERLINE_TARGETTYPE_MIDIOUT 3 +#define MIXERLINE_TARGETTYPE_MIDIIN 4 +#define MIXERLINE_TARGETTYPE_AUX 5 +#define MIXER_GETLINEINFOF_DESTINATION 0 +#define MIXER_GETLINEINFOF_SOURCE 1 +#define MIXER_GETLINEINFOF_LINEID 2 +#define MIXER_GETLINEINFOF_COMPONENTTYPE 3 +#define MIXER_GETLINEINFOF_TARGETTYPE 4 +#define MIXER_GETLINEINFOF_QUERYMASK 15 +#define MIXERCONTROL_CONTROLF_UNIFORM 1 +#define MIXERCONTROL_CONTROLF_MULTIPLE 2 +#define MIXERCONTROL_CONTROLF_DISABLED 0x80000000 +#define MIXERCONTROL_CT_CLASS_MASK 0xF0000000 +#define MIXERCONTROL_CT_CLASS_CUSTOM 0 +#define MIXERCONTROL_CT_CLASS_METER 0x10000000 +#define MIXERCONTROL_CT_CLASS_SWITCH 0x20000000 +#define MIXERCONTROL_CT_CLASS_NUMBER 0x30000000 +#define MIXERCONTROL_CT_CLASS_SLIDER 0x40000000 +#define MIXERCONTROL_CT_CLASS_FADER 0x50000000 +#define MIXERCONTROL_CT_CLASS_TIME 0x60000000 +#define MIXERCONTROL_CT_CLASS_LIST 0x70000000 +#define MIXERCONTROL_CT_SUBCLASS_MASK 0xF000000 +#define MIXERCONTROL_CT_SC_SWITCH_BOOLEAN 0 +#define MIXERCONTROL_CT_SC_SWITCH_BUTTON 0x1000000 +#define MIXERCONTROL_CT_SC_METER_POLLED 0 +#define MIXERCONTROL_CT_SC_TIME_MICROSECS 0 +#define MIXERCONTROL_CT_SC_TIME_MILLISECS 0x1000000 +#define MIXERCONTROL_CT_SC_LIST_SINGLE 0 +#define MIXERCONTROL_CT_SC_LIST_MULTIPLE 0x1000000 +#define MIXERCONTROL_CT_UNITS_MASK 0xFF0000 +#define MIXERCONTROL_CT_UNITS_CUSTOM 0 +#define MIXERCONTROL_CT_UNITS_BOOLEAN 0x10000 +#define MIXERCONTROL_CT_UNITS_SIGNED 0x20000 +#define MIXERCONTROL_CT_UNITS_UNSIGNED 0x30000 +#define MIXERCONTROL_CT_UNITS_DECIBELS 0x40000 +#define MIXERCONTROL_CT_UNITS_PERCENT 0x50000 +#define MIXERCONTROL_CONTROLTYPE_CUSTOM (MIXERCONTROL_CT_CLASS_CUSTOM|MIXERCONTROL_CT_UNITS_CUSTOM) +#define MIXERCONTROL_CONTROLTYPE_BOOLEANMETER (MIXERCONTROL_CT_CLASS_METER|MIXERCONTROL_CT_SC_METER_POLLED|MIXERCONTROL_CT_UNITS_BOOLEAN) +#define MIXERCONTROL_CONTROLTYPE_SIGNEDMETER (MIXERCONTROL_CT_CLASS_METER|MIXERCONTROL_CT_SC_METER_POLLED|MIXERCONTROL_CT_UNITS_SIGNED) +#define MIXERCONTROL_CONTROLTYPE_PEAKMETER (MIXERCONTROL_CONTROLTYPE_SIGNEDMETER+1) +#define MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER (MIXERCONTROL_CT_CLASS_METER|MIXERCONTROL_CT_SC_METER_POLLED|MIXERCONTROL_CT_UNITS_UNSIGNED) +#define MIXERCONTROL_CONTROLTYPE_BOOLEAN (MIXERCONTROL_CT_CLASS_SWITCH|MIXERCONTROL_CT_SC_SWITCH_BOOLEAN|MIXERCONTROL_CT_UNITS_BOOLEAN) +#define MIXERCONTROL_CONTROLTYPE_ONOFF (MIXERCONTROL_CONTROLTYPE_BOOLEAN+1) +#define MIXERCONTROL_CONTROLTYPE_MUTE (MIXERCONTROL_CONTROLTYPE_BOOLEAN+2) +#define MIXERCONTROL_CONTROLTYPE_MONO (MIXERCONTROL_CONTROLTYPE_BOOLEAN+3) +#define MIXERCONTROL_CONTROLTYPE_LOUDNESS (MIXERCONTROL_CONTROLTYPE_BOOLEAN+4) +#define MIXERCONTROL_CONTROLTYPE_STEREOENH (MIXERCONTROL_CONTROLTYPE_BOOLEAN+5) +#define MIXERCONTROL_CONTROLTYPE_BUTTON (MIXERCONTROL_CT_CLASS_SWITCH|MIXERCONTROL_CT_SC_SWITCH_BUTTON|MIXERCONTROL_CT_UNITS_BOOLEAN) +#define MIXERCONTROL_CONTROLTYPE_DECIBELS (MIXERCONTROL_CT_CLASS_NUMBER|MIXERCONTROL_CT_UNITS_DECIBELS) +#define MIXERCONTROL_CONTROLTYPE_SIGNED (MIXERCONTROL_CT_CLASS_NUMBER|MIXERCONTROL_CT_UNITS_SIGNED) +#define MIXERCONTROL_CONTROLTYPE_UNSIGNED (MIXERCONTROL_CT_CLASS_NUMBER|MIXERCONTROL_CT_UNITS_UNSIGNED) +#define MIXERCONTROL_CONTROLTYPE_PERCENT (MIXERCONTROL_CT_CLASS_NUMBER|MIXERCONTROL_CT_UNITS_PERCENT) +#define MIXERCONTROL_CONTROLTYPE_SLIDER (MIXERCONTROL_CT_CLASS_SLIDER|MIXERCONTROL_CT_UNITS_SIGNED) +#define MIXERCONTROL_CONTROLTYPE_PAN (MIXERCONTROL_CONTROLTYPE_SLIDER+1) +#define MIXERCONTROL_CONTROLTYPE_QSOUNDPAN (MIXERCONTROL_CONTROLTYPE_SLIDER+2) +#define MIXERCONTROL_CONTROLTYPE_FADER (MIXERCONTROL_CT_CLASS_FADER|MIXERCONTROL_CT_UNITS_UNSIGNED) +#define MIXERCONTROL_CONTROLTYPE_VOLUME (MIXERCONTROL_CONTROLTYPE_FADER+1) +#define MIXERCONTROL_CONTROLTYPE_BASS (MIXERCONTROL_CONTROLTYPE_FADER+2) +#define MIXERCONTROL_CONTROLTYPE_TREBLE (MIXERCONTROL_CONTROLTYPE_FADER+3) +#define MIXERCONTROL_CONTROLTYPE_EQUALIZER (MIXERCONTROL_CONTROLTYPE_FADER+4) +#define MIXERCONTROL_CONTROLTYPE_SINGLESELECT (MIXERCONTROL_CT_CLASS_LIST|MIXERCONTROL_CT_SC_LIST_SINGLE|MIXERCONTROL_CT_UNITS_BOOLEAN) +#define MIXERCONTROL_CONTROLTYPE_MUX (MIXERCONTROL_CONTROLTYPE_SINGLESELECT+1) +#define MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT (MIXERCONTROL_CT_CLASS_LIST|MIXERCONTROL_CT_SC_LIST_MULTIPLE|MIXERCONTROL_CT_UNITS_BOOLEAN) +#define MIXERCONTROL_CONTROLTYPE_MIXER (MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT+1) +#define MIXERCONTROL_CONTROLTYPE_MICROTIME (MIXERCONTROL_CT_CLASS_TIME|MIXERCONTROL_CT_SC_TIME_MICROSECS|MIXERCONTROL_CT_UNITS_UNSIGNED) +#define MIXERCONTROL_CONTROLTYPE_MILLITIME (MIXERCONTROL_CT_CLASS_TIME|MIXERCONTROL_CT_SC_TIME_MILLISECS|MIXERCONTROL_CT_UNITS_UNSIGNED) +#define MIXER_GETLINECONTROLSF_ALL 0 +#define MIXER_GETLINECONTROLSF_ONEBYID 1 +#define MIXER_GETLINECONTROLSF_ONEBYTYPE 2 +#define MIXER_GETLINECONTROLSF_QUERYMASK 15 +#define MIXER_GETCONTROLDETAILSF_VALUE 0 +#define MIXER_GETCONTROLDETAILSF_LISTTEXT 1 +#define MIXER_GETCONTROLDETAILSF_QUERYMASK 15 +#define MIXER_SETCONTROLDETAILSF_VALUE 0 +#define MIXER_SETCONTROLDETAILSF_CUSTOM 1 +#define MIXER_SETCONTROLDETAILSF_QUERYMASK 15 +#define TIMERR_NOERROR 0 +#define TIMERR_NOCANDO (TIMERR_BASE+1) +#define TIMERR_STRUCT (TIMERR_BASE+33) +#define TIME_ONESHOT 0 +#define TIME_PERIODIC 1 +#define TIME_CALLBACK_FUNCTION 0 +#define TIME_CALLBACK_EVENT_SET 16 +#define TIME_CALLBACK_EVENT_PULSE 32 +#if (WINVER >= 0x0501) +#define TIME_KILL_SYNCHRONOUS 0x0100 +#endif +#define JOYERR_NOERROR (0) +#define JOYERR_PARMS (JOYERR_BASE+5) +#define JOYERR_NOCANDO (JOYERR_BASE+6) +#define JOYERR_UNPLUGGED (JOYERR_BASE+7) +#define JOY_BUTTON1 1 +#define JOY_BUTTON2 2 +#define JOY_BUTTON3 4 +#define JOY_BUTTON4 8 +#define JOY_BUTTON1CHG 256 +#define JOY_BUTTON2CHG 512 +#define JOY_BUTTON3CHG 1024 +#define JOY_BUTTON4CHG 2048 +#define JOY_BUTTON5 257 +#define JOY_BUTTON6 513 +#define JOY_BUTTON7 1025 +#define JOY_BUTTON8 2049 +#define JOY_BUTTON9 256 +#define JOY_BUTTON10 512 +#define JOY_BUTTON11 1024 +#define JOY_BUTTON12 2048 +#define JOY_BUTTON13 4096 +#define JOY_BUTTON14 8192 +#define JOY_BUTTON15 16384 +#define JOY_BUTTON16 32768 +#define JOY_BUTTON17 65536 +#define JOY_BUTTON18 0x20000 +#define JOY_BUTTON19 0x40000 +#define JOY_BUTTON20 0x80000 +#define JOY_BUTTON21 0x100000 +#define JOY_BUTTON22 0x200000 +#define JOY_BUTTON23 0x400000 +#define JOY_BUTTON24 0x800000 +#define JOY_BUTTON25 0x1000000 +#define JOY_BUTTON26 0x2000000 +#define JOY_BUTTON27 0x4000000 +#define JOY_BUTTON28 0x8000000 +#define JOY_BUTTON29 0x10000000 +#define JOY_BUTTON30 0x20000000 +#define JOY_BUTTON31 0x40000000 +#define JOY_BUTTON32 0x80000000 +#define JOY_POVCENTERED ((WORD)-1) +#define JOY_POVFORWARD 0 +#define JOY_POVRIGHT 9000 +#define JOY_POVBACKWARD 18000 +#define JOY_POVLEFT 27000 +#define JOY_RETURNX 1 +#define JOY_RETURNY 2 +#define JOY_RETURNZ 4l +#define JOY_RETURNR 8 +#define JOY_RETURNU 16 +#define JOY_RETURNV 32 +#define JOY_RETURNPOV 64 +#define JOY_RETURNBUTTONS 128 +#define JOY_RETURNRAWDATA 256 +#define JOY_RETURNPOVCTS 512 +#define JOY_RETURNCENTERED 1024 +#define JOY_USEDEADZONE 2048 +#define JOY_RETURNALL (JOY_RETURNX|JOY_RETURNY|JOY_RETURNZ|JOY_RETURNR|JOY_RETURNU|JOY_RETURNV|JOY_RETURNPOV|JOY_RETURNBUTTONS) +#define JOY_CAL_READALWAYS 0x10000 +#define JOY_CAL_READXYONLY 0x20000 +#define JOY_CAL_READ3 0x40000 +#define JOY_CAL_READ4 0x80000 +#define JOY_CAL_READXONLY 0x100000 +#define JOY_CAL_READYONLY 0x200000 +#define JOY_CAL_READ5 0x400000 +#define JOY_CAL_READ6 0x800000 +#define JOY_CAL_READZONLY 0x1000000 +#define JOY_CAL_READRONLY 0x2000000 +#define JOY_CAL_READUONLY 0x4000000 +#define JOY_CAL_READVONLY 0x8000000 +#define JOYSTICKID1 0 +#define JOYSTICKID2 1 +#define JOYCAPS_HASZ 1 +#define JOYCAPS_HASR 2 +#define JOYCAPS_HASU 4 +#define JOYCAPS_HASV 8 +#define JOYCAPS_HASPOV 16 +#define JOYCAPS_POV4DIR 32 +#define JOYCAPS_POVCTS 64 +#define MMIOERR_BASE 256 +#define MMIOERR_FILENOTFOUND (MMIOERR_BASE+1) +#define MMIOERR_OUTOFMEMORY (MMIOERR_BASE+2) +#define MMIOERR_CANNOTOPEN (MMIOERR_BASE+3) +#define MMIOERR_CANNOTCLOSE (MMIOERR_BASE+4) +#define MMIOERR_CANNOTREAD (MMIOERR_BASE+5) +#define MMIOERR_CANNOTWRITE (MMIOERR_BASE+6) +#define MMIOERR_CANNOTSEEK (MMIOERR_BASE+7) +#define MMIOERR_CANNOTEXPAND (MMIOERR_BASE+8) +#define MMIOERR_CHUNKNOTFOUND (MMIOERR_BASE+9) +#define MMIOERR_UNBUFFERED (MMIOERR_BASE+10) +#define MMIOERR_PATHNOTFOUND (MMIOERR_BASE+11) +#define MMIOERR_ACCESSDENIED (MMIOERR_BASE+12) +#define MMIOERR_SHARINGVIOLATION (MMIOERR_BASE+13) +#define MMIOERR_NETWORKERROR (MMIOERR_BASE+14) +#define MMIOERR_TOOMANYOPENFILES (MMIOERR_BASE+15) +#define MMIOERR_INVALIDFILE (MMIOERR_BASE+16) +#define CFSEPCHAR '+' +#define MMIO_RWMODE 3 +#define MMIO_SHAREMODE 0x70 +#define MMIO_CREATE 0x1000 +#define MMIO_PARSE 256 +#define MMIO_DELETE 512 +#define MMIO_EXIST 0x4000 +#define MMIO_ALLOCBUF 0x10000 +#define MMIO_GETTEMP 0x20000 +#define MMIO_DIRTY 0x10000000 +#define MMIO_READ 0 +#define MMIO_WRITE 1 +#define MMIO_READWRITE 2 +#define MMIO_COMPAT 0 +#define MMIO_EXCLUSIVE 16 +#define MMIO_DENYWRITE 32 +#define MMIO_DENYREAD 0x30 +#define MMIO_DENYNONE 64 +#define MMIO_FHOPEN 16 +#define MMIO_EMPTYBUF 16 +#define MMIO_TOUPPER 16 +#define MMIO_INSTALLPROC 0x10000 +#define MMIO_GLOBALPROC 0x10000000 +#define MMIO_REMOVEPROC 0x20000 +#define MMIO_UNICODEPROC 0x1000000 +#define MMIO_FINDPROC 0x40000 +#define MMIO_FINDCHUNK 16 +#define MMIO_FINDRIFF 32 +#define MMIO_FINDLIST 64 +#define MMIO_CREATERIFF 32 +#define MMIO_CREATELIST 64 +#define MMIOM_READ MMIO_READ +#define MMIOM_WRITE MMIO_WRITE +#define MMIOM_SEEK 2 +#define MMIOM_OPEN 3 +#define MMIOM_CLOSE 4 +#define MMIOM_WRITEFLUSH 5 +#define MMIOM_RENAME 6 +#define MMIOM_USER 0x8000 +#define FOURCC_RIFF mmioFOURCC('R', 'I', 'F', 'F') +#define FOURCC_LIST mmioFOURCC('L', 'I', 'S', 'T') +#define FOURCC_DOS mmioFOURCC('D', 'O', 'S', ' ') +#define FOURCC_MEM mmioFOURCC('M', 'E', 'M', ' ') +#define MMIO_DEFAULTBUFFER 8192 +#define MCIERR_INVALID_DEVICE_ID (MCIERR_BASE+1) +#define MCIERR_UNRECOGNIZED_KEYWORD (MCIERR_BASE+3) +#define MCIERR_UNRECOGNIZED_COMMAND (MCIERR_BASE+5) +#define MCIERR_HARDWARE (MCIERR_BASE+6) +#define MCIERR_INVALID_DEVICE_NAME (MCIERR_BASE+7) +#define MCIERR_OUT_OF_MEMORY (MCIERR_BASE+8) +#define MCIERR_DEVICE_OPEN (MCIERR_BASE+9) +#define MCIERR_CANNOT_LOAD_DRIVER (MCIERR_BASE+10) +#define MCIERR_MISSING_COMMAND_STRING (MCIERR_BASE+11) +#define MCIERR_PARAM_OVERFLOW (MCIERR_BASE+12) +#define MCIERR_MISSING_STRING_ARGUMENT (MCIERR_BASE+13) +#define MCIERR_BAD_INTEGER (MCIERR_BASE+14) +#define MCIERR_PARSER_INTERNAL (MCIERR_BASE+15) +#define MCIERR_DRIVER_INTERNAL (MCIERR_BASE+16) +#define MCIERR_MISSING_PARAMETER (MCIERR_BASE+17) +#define MCIERR_UNSUPPORTED_FUNCTION (MCIERR_BASE+18) +#define MCIERR_FILE_NOT_FOUND (MCIERR_BASE+19) +#define MCIERR_DEVICE_NOT_READY (MCIERR_BASE+20) +#define MCIERR_INTERNAL (MCIERR_BASE+21) +#define MCIERR_DRIVER (MCIERR_BASE+22) +#define MCIERR_CANNOT_USE_ALL (MCIERR_BASE+23) +#define MCIERR_MULTIPLE (MCIERR_BASE+24) +#define MCIERR_EXTENSION_NOT_FOUND (MCIERR_BASE+25) +#define MCIERR_OUTOFRANGE (MCIERR_BASE+26) +#define MCIERR_FLAGS_NOT_COMPATIBLE (MCIERR_BASE+28) +#define MCIERR_FILE_NOT_SAVED (MCIERR_BASE+30) +#define MCIERR_DEVICE_TYPE_REQUIRED (MCIERR_BASE+31) +#define MCIERR_DEVICE_LOCKED (MCIERR_BASE+32) +#define MCIERR_DUPLICATE_ALIAS (MCIERR_BASE+33) +#define MCIERR_BAD_CONSTANT (MCIERR_BASE+34) +#define MCIERR_MUST_USE_SHAREABLE (MCIERR_BASE+35) +#define MCIERR_MISSING_DEVICE_NAME (MCIERR_BASE+36) +#define MCIERR_BAD_TIME_FORMAT (MCIERR_BASE+37) +#define MCIERR_NO_CLOSING_QUOTE (MCIERR_BASE+38) +#define MCIERR_DUPLICATE_FLAGS (MCIERR_BASE+39) +#define MCIERR_INVALID_FILE (MCIERR_BASE+40) +#define MCIERR_NULL_PARAMETER_BLOCK (MCIERR_BASE+41) +#define MCIERR_UNNAMED_RESOURCE (MCIERR_BASE+42) +#define MCIERR_NEW_REQUIRES_ALIAS (MCIERR_BASE+43) +#define MCIERR_NOTIFY_ON_AUTO_OPEN (MCIERR_BASE+44) +#define MCIERR_NO_ELEMENT_ALLOWED (MCIERR_BASE+45) +#define MCIERR_NONAPPLICABLE_FUNCTION (MCIERR_BASE+46) +#define MCIERR_ILLEGAL_FOR_AUTO_OPEN (MCIERR_BASE+47) +#define MCIERR_FILENAME_REQUIRED (MCIERR_BASE+48) +#define MCIERR_EXTRA_CHARACTERS (MCIERR_BASE+49) +#define MCIERR_DEVICE_NOT_INSTALLED (MCIERR_BASE+50) +#define MCIERR_GET_CD (MCIERR_BASE+51) +#define MCIERR_SET_CD (MCIERR_BASE+52) +#define MCIERR_SET_DRIVE (MCIERR_BASE+53) +#define MCIERR_DEVICE_LENGTH (MCIERR_BASE+54) +#define MCIERR_DEVICE_ORD_LENGTH (MCIERR_BASE+55) +#define MCIERR_NO_INTEGER (MCIERR_BASE+56) +#define MCIERR_WAVE_OUTPUTSINUSE (MCIERR_BASE+64) +#define MCIERR_WAVE_SETOUTPUTINUSE (MCIERR_BASE+65) +#define MCIERR_WAVE_INPUTSINUSE (MCIERR_BASE+66) +#define MCIERR_WAVE_SETINPUTINUSE (MCIERR_BASE+67) +#define MCIERR_WAVE_OUTPUTUNSPECIFIED (MCIERR_BASE+68) +#define MCIERR_WAVE_INPUTUNSPECIFIED (MCIERR_BASE+69) +#define MCIERR_WAVE_OUTPUTSUNSUITABLE (MCIERR_BASE+70) +#define MCIERR_WAVE_SETOUTPUTUNSUITABLE (MCIERR_BASE+71) +#define MCIERR_WAVE_INPUTSUNSUITABLE (MCIERR_BASE+72) +#define MCIERR_WAVE_SETINPUTUNSUITABLE (MCIERR_BASE+73) +#define MCIERR_SEQ_DIV_INCOMPATIBLE (MCIERR_BASE+80) +#define MCIERR_SEQ_PORT_INUSE (MCIERR_BASE+81) +#define MCIERR_SEQ_PORT_NONEXISTENT (MCIERR_BASE+82) +#define MCIERR_SEQ_PORT_MAPNODEVICE (MCIERR_BASE+83) +#define MCIERR_SEQ_PORT_MISCERROR (MCIERR_BASE+84) +#define MCIERR_SEQ_TIMER (MCIERR_BASE+85) +#define MCIERR_SEQ_PORTUNSPECIFIED (MCIERR_BASE+86) +#define MCIERR_SEQ_NOMIDIPRESENT (MCIERR_BASE+87) +#define MCIERR_NO_WINDOW (MCIERR_BASE+90) +#define MCIERR_CREATEWINDOW (MCIERR_BASE+91) +#define MCIERR_FILE_READ (MCIERR_BASE+92) +#define MCIERR_FILE_WRITE (MCIERR_BASE+93) +#define MCIERR_NO_IDENTITY (MCIERR_BASE+94) +#define MCIERR_CUSTOM_DRIVER_BASE (MCIERR_BASE+256) +#define MCI_FIRST DRV_MCI_FIRST +#define MCI_OPEN 0x803 +#define MCI_CLOSE 0x804 +#define MCI_ESCAPE 0x805 +#define MCI_PLAY 0x806 +#define MCI_SEEK 0x807 +#define MCI_STOP 0x808 +#define MCI_PAUSE 0x809 +#define MCI_INFO 0x80A +#define MCI_GETDEVCAPS 0x80B +#define MCI_SPIN 0x80C +#define MCI_SET 0x80D +#define MCI_STEP 0x80E +#define MCI_RECORD 0x80F +#define MCI_SYSINFO 0x810 +#define MCI_BREAK 0x811 +#define MCI_SAVE 0x813 +#define MCI_STATUS 0x814 +#define MCI_CUE 0x830 +#define MCI_REALIZE 0x840 +#define MCI_WINDOW 0x841 +#define MCI_PUT 0x842 +#define MCI_WHERE 0x843 +#define MCI_FREEZE 0x844 +#define MCI_UNFREEZE 0x845 +#define MCI_LOAD 0x850 +#define MCI_CUT 0x851 +#define MCI_COPY 0x852 +#define MCI_PASTE 0x853 +#define MCI_UPDATE 0x854 +#define MCI_RESUME 0x855 +#define MCI_DELETE 0x856 +#define MCI_USER_MESSAGES (DRV_MCI_FIRST+0x400) +#define MCI_LAST 0xFFF +#define MCI_ALL_DEVICE_ID ((MCIDEVICEID)-1) +#define MCI_DEVTYPE_VCR 513 +#define MCI_DEVTYPE_VIDEODISC 514 +#define MCI_DEVTYPE_OVERLAY 515 +#define MCI_DEVTYPE_CD_AUDIO 516 +#define MCI_DEVTYPE_DAT 517 +#define MCI_DEVTYPE_SCANNER 518 +#define MCI_DEVTYPE_ANIMATION 519 +#define MCI_DEVTYPE_DIGITAL_VIDEO 520 +#define MCI_DEVTYPE_OTHER 521 +#define MCI_DEVTYPE_WAVEFORM_AUDIO 522 +#define MCI_DEVTYPE_SEQUENCER 523 +#define MCI_DEVTYPE_FIRST MCI_DEVTYPE_VCR +#define MCI_DEVTYPE_LAST MCI_DEVTYPE_SEQUENCER +#define MCI_DEVTYPE_FIRST_USER 0x1000 +#define MCI_MODE_NOT_READY (MCI_STRING_OFFSET+12) +#define MCI_MODE_STOP (MCI_STRING_OFFSET+13) +#define MCI_MODE_PLAY (MCI_STRING_OFFSET+14) +#define MCI_MODE_RECORD (MCI_STRING_OFFSET+15) +#define MCI_MODE_SEEK (MCI_STRING_OFFSET+16) +#define MCI_MODE_PAUSE (MCI_STRING_OFFSET+17) +#define MCI_MODE_OPEN (MCI_STRING_OFFSET+18) +#define MCI_FORMAT_MILLISECONDS 0 +#define MCI_FORMAT_HMS 1 +#define MCI_FORMAT_MSF 2 +#define MCI_FORMAT_FRAMES 3 +#define MCI_FORMAT_SMPTE_24 4 +#define MCI_FORMAT_SMPTE_25 5 +#define MCI_FORMAT_SMPTE_30 6 +#define MCI_FORMAT_SMPTE_30DROP 7 +#define MCI_FORMAT_BYTES 8 +#define MCI_FORMAT_SAMPLES 9 +#define MCI_FORMAT_TMSF 10 +#define MCI_MSF_MINUTE(t) ((BYTE)(t)) +#define MCI_MSF_SECOND(t) ((BYTE)(((WORD)(t))>>8)) +#define MCI_MSF_FRAME(t) ((BYTE)((t)>>16)) +#define MCI_MAKE_MSF(m,s,f) ((DWORD)(((BYTE)(m)|((WORD)(s)<<8))|(((DWORD)(BYTE)(f))<<16))) +#define MCI_TMSF_TRACK(t) ((BYTE)(t)) +#define MCI_TMSF_MINUTE(t) ((BYTE)(((WORD)(t))>>8)) +#define MCI_TMSF_SECOND(t) ((BYTE)((t)>>16)) +#define MCI_TMSF_FRAME(t) ((BYTE)((t)>>24)) +#define MCI_MAKE_TMSF(t,m,s,f) ((DWORD)(((BYTE)(t)|((WORD)(m)<<8))|(((DWORD)(BYTE)(s)|((WORD)(f)<<8))<<16))) +#define MCI_HMS_HOUR(t) ((BYTE)(t)) +#define MCI_HMS_MINUTE(t) ((BYTE)(((WORD)(t))>>8)) +#define MCI_HMS_SECOND(t) ((BYTE)((t)>>16)) +#define MCI_MAKE_HMS(h,m,s) ((DWORD)(((BYTE)(h)|((WORD)(m)<<8))|(((DWORD)(BYTE)(s))<<16))) +#define MCI_NOTIFY_SUCCESSFUL 1 +#define MCI_NOTIFY_SUPERSEDED 2 +#define MCI_NOTIFY_ABORTED 4 +#define MCI_NOTIFY_FAILURE 8 +#define MCI_NOTIFY 1 +#define MCI_WAIT 2 +#define MCI_FROM 4 +#define MCI_TO 8 +#define MCI_TRACK 16 +#define MCI_OPEN_SHAREABLE 256 +#define MCI_OPEN_ELEMENT 512 +#define MCI_OPEN_ALIAS 1024 +#define MCI_OPEN_ELEMENT_ID 2048 +#define MCI_OPEN_TYPE_ID 0x1000 +#define MCI_OPEN_TYPE 0x2000 +#define MCI_SEEK_TO_START 256 +#define MCI_SEEK_TO_END 512 +#define MCI_STATUS_ITEM 256 +#define MCI_STATUS_START 512 +#define MCI_STATUS_LENGTH 1 +#define MCI_STATUS_POSITION 2 +#define MCI_STATUS_NUMBER_OF_TRACKS 3 +#define MCI_STATUS_MODE 4 +#define MCI_STATUS_MEDIA_PRESENT 5 +#define MCI_STATUS_TIME_FORMAT 6 +#define MCI_STATUS_READY 7 +#define MCI_STATUS_CURRENT_TRACK 8 +#define MCI_INFO_PRODUCT 256 +#define MCI_INFO_FILE 512 +#define MCI_INFO_MEDIA_UPC 1024 +#define MCI_INFO_MEDIA_IDENTITY 2048 +#define MCI_INFO_NAME 0x1000 +#define MCI_INFO_COPYRIGHT 0x2000 +#define MCI_GETDEVCAPS_ITEM 256 +#define MCI_GETDEVCAPS_CAN_RECORD 1 +#define MCI_GETDEVCAPS_HAS_AUDIO 2 +#define MCI_GETDEVCAPS_HAS_VIDEO 3 +#define MCI_GETDEVCAPS_DEVICE_TYPE 4 +#define MCI_GETDEVCAPS_USES_FILES 5 +#define MCI_GETDEVCAPS_COMPOUND_DEVICE 6 +#define MCI_GETDEVCAPS_CAN_EJECT 7 +#define MCI_GETDEVCAPS_CAN_PLAY 8 +#define MCI_GETDEVCAPS_CAN_SAVE 9 +#define MCI_SYSINFO_QUANTITY 256 +#define MCI_SYSINFO_OPEN 512 +#define MCI_SYSINFO_NAME 1024 +#define MCI_SYSINFO_INSTALLNAME 2048 +#define MCI_SET_DOOR_OPEN 256 +#define MCI_SET_DOOR_CLOSED 512 +#define MCI_SET_TIME_FORMAT 1024 +#define MCI_SET_AUDIO 2048 +#define MCI_SET_VIDEO 0x1000 +#define MCI_SET_ON 0x2000 +#define MCI_SET_OFF 0x4000 +#define MCI_SET_AUDIO_ALL 0 +#define MCI_SET_AUDIO_LEFT 1 +#define MCI_SET_AUDIO_RIGHT 2 +#define MCI_BREAK_KEY 256 +#define MCI_BREAK_HWND 512 +#define MCI_BREAK_OFF 1024 +#define MCI_RECORD_INSERT 256 +#define MCI_RECORD_OVERWRITE 512 +#define MCI_SAVE_FILE 256 +#define MCI_LOAD_FILE 256 +#define MCI_VD_MODE_PARK (MCI_VD_OFFSET+1) +#define MCI_VD_MEDIA_CLV (MCI_VD_OFFSET+2) +#define MCI_VD_MEDIA_CAV (MCI_VD_OFFSET+3) +#define MCI_VD_MEDIA_OTHER (MCI_VD_OFFSET+4) +#define MCI_VD_FORMAT_TRACK 0x4001 +#define MCI_VD_PLAY_REVERSE 0x10000 +#define MCI_VD_PLAY_FAST 0x20000 +#define MCI_VD_PLAY_SPEED 0x40000 +#define MCI_VD_PLAY_SCAN 0x80000 +#define MCI_VD_PLAY_SLOW 0x100000 +#define MCI_VD_SEEK_REVERSE 0x10000 +#define MCI_VD_STATUS_SPEED 0x4002 +#define MCI_VD_STATUS_FORWARD 0x4003 +#define MCI_VD_STATUS_MEDIA_TYPE 0x4004 +#define MCI_VD_STATUS_SIDE 0x4005 +#define MCI_VD_STATUS_DISC_SIZE 0x4006 +#define MCI_VD_GETDEVCAPS_CLV 0x10000 +#define MCI_VD_GETDEVCAPS_CAV 0x20000 +#define MCI_VD_SPIN_UP 0x10000 +#define MCI_VD_SPIN_DOWN 0x20000 +#define MCI_VD_GETDEVCAPS_CAN_REVERSE 0x4002 +#define MCI_VD_GETDEVCAPS_FAST_RATE 0x4003 +#define MCI_VD_GETDEVCAPS_SLOW_RATE 0x4004 +#define MCI_VD_GETDEVCAPS_NORMAL_RATE 0x4005 +#define MCI_VD_STEP_FRAMES 0x10000 +#define MCI_VD_STEP_REVERSE 0x20000 +#define MCI_VD_ESCAPE_STRING 256 +#define MCI_CDA_STATUS_TYPE_TRACK 0x4001 +#define MCI_CDA_TRACK_AUDIO MCI_CD_OFFSET +#define MCI_CDA_TRACK_OTHER (MCI_CD_OFFSET+1) +#define MCI_WAVE_PCM MCI_WAVE_OFFSET +#define MCI_WAVE_MAPPER (MCI_WAVE_OFFSET+1) +#define MCI_WAVE_OPEN_BUFFER 0x10000 +#define MCI_WAVE_SET_FORMATTAG 0x10000 +#define MCI_WAVE_SET_CHANNELS 0x20000 +#define MCI_WAVE_SET_SAMPLESPERSEC 0x40000 +#define MCI_WAVE_SET_AVGBYTESPERSEC 0x80000 +#define MCI_WAVE_SET_BLOCKALIGN 0x100000 +#define MCI_WAVE_SET_BITSPERSAMPLE 0x200000 +#define MCI_WAVE_INPUT 0x400000 +#define MCI_WAVE_OUTPUT 0x800000 +#define MCI_WAVE_STATUS_FORMATTAG 0x4001 +#define MCI_WAVE_STATUS_CHANNELS 0x4002 +#define MCI_WAVE_STATUS_SAMPLESPERSEC 0x4003 +#define MCI_WAVE_STATUS_AVGBYTESPERSEC 0x4004 +#define MCI_WAVE_STATUS_BLOCKALIGN 0x4005 +#define MCI_WAVE_STATUS_BITSPERSAMPLE 0x4006 +#define MCI_WAVE_STATUS_LEVEL 0x4007 +#define MCI_WAVE_SET_ANYINPUT 0x4000000 +#define MCI_WAVE_SET_ANYOUTPUT 0x8000000 +#define MCI_WAVE_GETDEVCAPS_INPUTS 0x4001 +#define MCI_WAVE_GETDEVCAPS_OUTPUTS 0x4002 +#define MCI_SEQ_DIV_PPQN MCI_SEQ_OFFSET +#define MCI_SEQ_DIV_SMPTE_24 (MCI_SEQ_OFFSET+1) +#define MCI_SEQ_DIV_SMPTE_25 (MCI_SEQ_OFFSET+2) +#define MCI_SEQ_DIV_SMPTE_30DROP (MCI_SEQ_OFFSET+3) +#define MCI_SEQ_DIV_SMPTE_30 (MCI_SEQ_OFFSET+4) +#define MCI_SEQ_FORMAT_SONGPTR 0x4001 +#define MCI_SEQ_FILE 0x4002 +#define MCI_SEQ_MIDI 0x4003 +#define MCI_SEQ_SMPTE 0x4004 +#define MCI_SEQ_NONE 65533 +#define MCI_SEQ_MAPPER 65535 +#define MCI_SEQ_STATUS_TEMPO 0x4002 +#define MCI_SEQ_STATUS_PORT 0x4003 +#define MCI_SEQ_STATUS_SLAVE 0x4007 +#define MCI_SEQ_STATUS_MASTER 0x4008 +#define MCI_SEQ_STATUS_OFFSET 0x4009 +#define MCI_SEQ_STATUS_DIVTYPE 0x400A +#define MCI_SEQ_STATUS_NAME 0x400B +#define MCI_SEQ_STATUS_COPYRIGHT 0x400C +#define MCI_SEQ_SET_TEMPO 0x10000 +#define MCI_SEQ_SET_PORT 0x20000 +#define MCI_SEQ_SET_SLAVE 0x40000 +#define MCI_SEQ_SET_MASTER 0x80000 +#define MCI_SEQ_SET_OFFSET 0x1000000 +#define MCI_ANIM_OPEN_WS 0x10000 +#define MCI_ANIM_OPEN_PARENT 0x20000 +#define MCI_ANIM_OPEN_NOSTATIC 0x40000 +#define MCI_ANIM_PLAY_SPEED 0x10000 +#define MCI_ANIM_PLAY_REVERSE 0x20000 +#define MCI_ANIM_PLAY_FAST 0x40000 +#define MCI_ANIM_PLAY_SLOW 0x80000 +#define MCI_ANIM_PLAY_SCAN 0x100000 +#define MCI_ANIM_STEP_REVERSE 0x10000 +#define MCI_ANIM_STEP_FRAMES 0x20000 +#define MCI_ANIM_STATUS_SPEED 0x4001 +#define MCI_ANIM_STATUS_FORWARD 0x4002 +#define MCI_ANIM_STATUS_HWND 0x4003 +#define MCI_ANIM_STATUS_HPAL 0x4004 +#define MCI_ANIM_STATUS_STRETCH 0x4005 +#define MCI_ANIM_INFO_TEXT 0x10000 +#define MCI_ANIM_GETDEVCAPS_CAN_REVERSE 0x4001 +#define MCI_ANIM_GETDEVCAPS_FAST_RATE 0x4002 +#define MCI_ANIM_GETDEVCAPS_SLOW_RATE 0x4003 +#define MCI_ANIM_GETDEVCAPS_NORMAL_RATE 0x4004 +#define MCI_ANIM_GETDEVCAPS_PALETTES 0x4006 +#define MCI_ANIM_GETDEVCAPS_CAN_STRETCH 0x4007 +#define MCI_ANIM_GETDEVCAPS_MAX_WINDOWS 0x4008 +#define MCI_ANIM_REALIZE_NORM 0x10000 +#define MCI_ANIM_REALIZE_BKGD 0x20000 +#define MCI_ANIM_WINDOW_HWND 0x10000 +#define MCI_ANIM_WINDOW_STATE 0x40000 +#define MCI_ANIM_WINDOW_TEXT 0x80000 +#define MCI_ANIM_WINDOW_ENABLE_STRETCH 0x100000 +#define MCI_ANIM_WINDOW_DISABLE_STRETCH 0x200000 +#define MCI_ANIM_WINDOW_DEFAULT 0xL +#define MCI_ANIM_RECT 0x10000 +#define MCI_ANIM_PUT_SOURCE 0x20000 +#define MCI_ANIM_PUT_DESTINATION 0x40000 +#define MCI_ANIM_WHERE_SOURCE 0x20000 +#define MCI_ANIM_WHERE_DESTINATION 0x40000 +#define MCI_ANIM_UPDATE_HDC 0x20000 +#define MCI_OVLY_OPEN_WS 0x10000 +#define MCI_OVLY_OPEN_PARENT 0x20000 +#define MCI_OVLY_STATUS_HWND 0x4001 +#define MCI_OVLY_STATUS_STRETCH 0x4002 +#define MCI_OVLY_INFO_TEXT 0x10000 +#define MCI_OVLY_GETDEVCAPS_CAN_STRETCH 0x4001 +#define MCI_OVLY_GETDEVCAPS_CAN_FREEZE 0x4002 +#define MCI_OVLY_GETDEVCAPS_MAX_WINDOWS 0x4003 +#define MCI_OVLY_WINDOW_HWND 0x10000 +#define MCI_OVLY_WINDOW_STATE 0x40000 +#define MCI_OVLY_WINDOW_TEXT 0x80000 +#define MCI_OVLY_WINDOW_ENABLE_STRETCH 0x100000 +#define MCI_OVLY_WINDOW_DISABLE_STRETCH 0x200000 +#define MCI_OVLY_WINDOW_DEFAULT 0xL +#define MCI_OVLY_RECT 0x10000 +#define MCI_OVLY_PUT_SOURCE 0x20000 +#define MCI_OVLY_PUT_DESTINATION 0x40000 +#define MCI_OVLY_PUT_FRAME 0x80000 +#define MCI_OVLY_PUT_VIDEO 0x100000 +#define MCI_OVLY_WHERE_SOURCE 0x20000 +#define MCI_OVLY_WHERE_DESTINATION 0x40000 +#define MCI_OVLY_WHERE_FRAME 0x80000 +#define MCI_OVLY_WHERE_VIDEO 0x100000 +#define NEWTRANSPARENT 3 +#define QUERYROPSUPPORT 40 +#define SELECTDIB 41 +#define DIBINDEX(n) MAKELONG((n),0x10FF) +#define SC_SCREENSAVE 0xF140 +#define CAPS1 94 +#define C1_TRANSPARENT 1 +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +typedef DWORD MCIERROR; +typedef UINT MCIDEVICEID; +typedef UINT(CALLBACK *YIELDPROC)(MCIDEVICEID,DWORD); +typedef UINT MMVERSION; +typedef UINT MMRESULT; +typedef struct mmtime_tag { + UINT wType; + union { + DWORD ms; + DWORD sample; + DWORD cb; + DWORD ticks; + struct { + BYTE hour; + BYTE min; + BYTE sec; + BYTE frame; + BYTE fps; + BYTE dummy; + BYTE pad[2]; + } smpte; + struct { + DWORD songptrpos; + } midi; + } u; +} MMTIME,*PMMTIME,*LPMMTIME; +DECLARE_HANDLE(HDRVR); +typedef struct tagDRVCONFIGINFO { + DWORD dwDCISize; + LPCWSTR lpszDCISectionName; + LPCWSTR lpszDCIAliasName; +} DRVCONFIGINFO,*PDRVCONFIGINFO,*LPDRVCONFIGINFO; +typedef struct DRVCONFIGINFOEX { + DWORD dwDCISize; + LPCWSTR lpszDCISectionName; + LPCWSTR lpszDCIAliasName; + DWORD dnDevNode; +} DRVCONFIGINFOEX,*PDRVCONFIGINFOEX,*LPDRVCONFIGINFOEX; +typedef LRESULT(CALLBACK* DRIVERPROC)(DWORD,HDRVR,UINT,LPARAM,LPARAM); +typedef void (CALLBACK DRVCALLBACK)(HDRVR,UINT,DWORD,DWORD,DWORD); +typedef DRVCALLBACK *LPDRVCALLBACK; +typedef DRVCALLBACK *PDRVCALLBACK; +DECLARE_HANDLE(HWAVE); +DECLARE_HANDLE(HWAVEIN); +DECLARE_HANDLE(HWAVEOUT); +typedef HWAVEIN *LPHWAVEIN; +typedef HWAVEOUT *LPHWAVEOUT; +typedef DRVCALLBACK WAVECALLBACK; +typedef WAVECALLBACK *LPWAVECALLBACK; +typedef struct wavehdr_tag { + LPSTR lpData; + DWORD dwBufferLength; + DWORD dwBytesRecorded; + DWORD dwUser; + DWORD dwFlags; + DWORD dwLoops; + struct wavehdr_tag *lpNext; + DWORD reserved; +} WAVEHDR,*PWAVEHDR,*LPWAVEHDR; +typedef struct tagWAVEOUTCAPSA { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + CHAR szPname[MAXPNAMELEN]; + DWORD dwFormats; + WORD wChannels; + WORD wReserved1; + DWORD dwSupport; +} WAVEOUTCAPSA,*PWAVEOUTCAPSA,*LPWAVEOUTCAPSA; +typedef struct tagWAVEOUTCAPSW { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + WCHAR szPname[MAXPNAMELEN]; + DWORD dwFormats; + WORD wChannels; + WORD wReserved1; + DWORD dwSupport; +} WAVEOUTCAPSW,*PWAVEOUTCAPSW,*LPWAVEOUTCAPSW; +typedef struct tagWAVEINCAPSA { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + CHAR szPname[MAXPNAMELEN]; + DWORD dwFormats; + WORD wChannels; + WORD wReserved1; +} WAVEINCAPSA,*PWAVEINCAPSA,*LPWAVEINCAPSA; +typedef struct tagWAVEINCAPSW { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + WCHAR szPname[MAXPNAMELEN]; + DWORD dwFormats; + WORD wChannels; + WORD wReserved1; +} WAVEINCAPSW,*PWAVEINCAPSW,*LPWAVEINCAPSW; +typedef struct waveformat_tag { + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; +} WAVEFORMAT,*PWAVEFORMAT,*LPWAVEFORMAT; +typedef struct pcmwaveformat_tag { + WAVEFORMAT wf; + WORD wBitsPerSample; +} PCMWAVEFORMAT, *PPCMWAVEFORMAT,*LPPCMWAVEFORMAT; +#ifndef _LPCWAVEFORMATEX_DEFINED +#define _LPCWAVEFORMATEX_DEFINED +#define _WAVEFORMATEX_ +typedef struct tWAVEFORMATEX { + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wBitsPerSample; + WORD cbSize; +} WAVEFORMATEX,*PWAVEFORMATEX,*LPWAVEFORMATEX; +typedef const WAVEFORMATEX *LPCWAVEFORMATEX; +#endif +DECLARE_HANDLE(HMIDI); +DECLARE_HANDLE(HMIDIIN); +DECLARE_HANDLE(HMIDIOUT); +DECLARE_HANDLE(HMIDISTRM); +typedef HMIDI *LPHMIDI; +typedef HMIDIIN *LPHMIDIIN; +typedef HMIDIOUT *LPHMIDIOUT; +typedef HMIDISTRM *LPHMIDISTRM; +typedef DRVCALLBACK MIDICALLBACK; +typedef MIDICALLBACK *LPMIDICALLBACK; +typedef WORD PATCHARRAY[MIDIPATCHSIZE]; +typedef WORD *LPPATCHARRAY; +typedef WORD KEYARRAY[MIDIPATCHSIZE]; +typedef WORD *LPKEYARRAY; +typedef struct tagMIDIOUTCAPSA { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + CHAR szPname[MAXPNAMELEN]; + WORD wTechnology; + WORD wVoices; + WORD wNotes; + WORD wChannelMask; + DWORD dwSupport; +} MIDIOUTCAPSA,*PMIDIOUTCAPSA,*LPMIDIOUTCAPSA; +typedef struct tagMIDIOUTCAPSW { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + WCHAR szPname[MAXPNAMELEN]; + WORD wTechnology; + WORD wVoices; + WORD wNotes; + WORD wChannelMask; + DWORD dwSupport; +} MIDIOUTCAPSW,*PMIDIOUTCAPSW,*LPMIDIOUTCAPSW; +typedef struct tagMIDIINCAPSA { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + CHAR szPname[MAXPNAMELEN]; + DWORD dwSupport; +} MIDIINCAPSA,*PMIDIINCAPSA,*LPMIDIINCAPSA; +typedef struct tagMIDIINCAPSW { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + WCHAR szPname[MAXPNAMELEN]; + DWORD dwSupport; +} MIDIINCAPSW,*PMIDIINCAPSW,*NPMIDIINCAPSW,*LPMIDIINCAPSW; +typedef struct midihdr_tag { + LPSTR lpData; + DWORD dwBufferLength; + DWORD dwBytesRecorded; + DWORD dwUser; + DWORD dwFlags; + struct midihdr_tag *lpNext; + DWORD reserved; + DWORD dwOffset; + DWORD dwReserved[8]; +} MIDIHDR,*PMIDIHDR,*LPMIDIHDR; +typedef struct midievent_tag { + DWORD dwDeltaTime; + DWORD dwStreamID; + DWORD dwEvent; + DWORD dwParms[1]; +} MIDIEVENT; +typedef struct midistrmbuffver_tag { + DWORD dwVersion; + DWORD dwMid; + DWORD dwOEMVersion; +} MIDISTRMBUFFVER; +typedef struct midiproptimediv_tag { + DWORD cbStruct; + DWORD dwTimeDiv; +} MIDIPROPTIMEDIV,*LPMIDIPROPTIMEDIV; +typedef struct midiproptempo_tag { + DWORD cbStruct; + DWORD dwTempo; +} MIDIPROPTEMPO,*LPMIDIPROPTEMPO; +typedef struct tagAUXCAPSA { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + CHAR szPname[MAXPNAMELEN]; + WORD wTechnology; + WORD wReserved1; + DWORD dwSupport; +} AUXCAPSA,*PAUXCAPSA,*LPAUXCAPSA; +typedef struct tagAUXCAPSW { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + WCHAR szPname[MAXPNAMELEN]; + WORD wTechnology; + WORD wReserved1; + DWORD dwSupport; +} AUXCAPSW,*PAUXCAPSW,*LPAUXCAPSW; +DECLARE_HANDLE(HMIXEROBJ); +typedef HMIXEROBJ *LPHMIXEROBJ; +DECLARE_HANDLE(HMIXER); +typedef HMIXER *LPHMIXER; +typedef struct tagMIXERCAPSA { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + CHAR szPname[MAXPNAMELEN]; + DWORD fdwSupport; + DWORD cDestinations; +} MIXERCAPSA,*PMIXERCAPSA,*LPMIXERCAPSA; +typedef struct tagMIXERCAPSW { + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + WCHAR szPname[MAXPNAMELEN]; + DWORD fdwSupport; + DWORD cDestinations; +} MIXERCAPSW,*PMIXERCAPSW,*LPMIXERCAPSW; +typedef struct tagMIXERLINEA { + DWORD cbStruct; + DWORD dwDestination; + DWORD dwSource; + DWORD dwLineID; + DWORD fdwLine; + DWORD dwUser; + DWORD dwComponentType; + DWORD cChannels; + DWORD cConnections; + DWORD cControls; + CHAR szShortName[MIXER_SHORT_NAME_CHARS]; + CHAR szName[MIXER_LONG_NAME_CHARS]; + struct { + DWORD dwType; + DWORD dwDeviceID; + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + CHAR szPname[MAXPNAMELEN]; + } Target; +} MIXERLINEA,*PMIXERLINEA,*LPMIXERLINEA; +typedef struct tagMIXERLINEW { + DWORD cbStruct; + DWORD dwDestination; + DWORD dwSource; + DWORD dwLineID; + DWORD fdwLine; + DWORD dwUser; + DWORD dwComponentType; + DWORD cChannels; + DWORD cConnections; + DWORD cControls; + WCHAR szShortName[MIXER_SHORT_NAME_CHARS]; + WCHAR szName[MIXER_LONG_NAME_CHARS]; + struct { + DWORD dwType; + DWORD dwDeviceID; + WORD wMid; + WORD wPid; + MMVERSION vDriverVersion; + WCHAR szPname[MAXPNAMELEN]; + } Target; +} MIXERLINEW,*PMIXERLINEW,*LPMIXERLINEW; +typedef struct tagMIXERCONTROLA { + DWORD cbStruct; + DWORD dwControlID; + DWORD dwControlType; + DWORD fdwControl; + DWORD cMultipleItems; + CHAR szShortName[MIXER_SHORT_NAME_CHARS]; + CHAR szName[MIXER_LONG_NAME_CHARS]; + union { + _ANONYMOUS_STRUCT struct { + LONG lMinimum; + LONG lMaximum; + }_STRUCT_NAME(s); + _ANONYMOUS_STRUCT struct { + DWORD dwMinimum; + DWORD dwMaximum; + }_STRUCT_NAME(s1); + DWORD dwReserved[6]; + } Bounds; + union { + DWORD cSteps; + DWORD cbCustomData; + DWORD dwReserved[6]; + } Metrics; +} MIXERCONTROLA,*PMIXERCONTROLA,*LPMIXERCONTROLA; +typedef struct tagMIXERCONTROLW { + DWORD cbStruct; + DWORD dwControlID; + DWORD dwControlType; + DWORD fdwControl; + DWORD cMultipleItems; + WCHAR szShortName[MIXER_SHORT_NAME_CHARS]; + WCHAR szName[MIXER_LONG_NAME_CHARS]; + union { + _ANONYMOUS_STRUCT struct { + LONG lMinimum; + LONG lMaximum; + }_STRUCT_NAME(s); + _ANONYMOUS_STRUCT struct { + DWORD dwMinimum; + DWORD dwMaximum; + }_STRUCT_NAME(s1); + DWORD dwReserved[6]; + } Bounds; + union { + DWORD cSteps; + DWORD cbCustomData; + DWORD dwReserved[6]; + } Metrics; +} MIXERCONTROLW,*PMIXERCONTROLW,*LPMIXERCONTROLW; +typedef struct tagMIXERLINECONTROLSA { + DWORD cbStruct; + DWORD dwLineID; + _ANONYMOUS_UNION union { + DWORD dwControlID; + DWORD dwControlType; + } DUMMYUNIONNAME; + DWORD cControls; + DWORD cbmxctrl; + LPMIXERCONTROLA pamxctrl; +} MIXERLINECONTROLSA,*PMIXERLINECONTROLSA,*LPMIXERLINECONTROLSA; +typedef struct tagMIXERLINECONTROLSW { + DWORD cbStruct; + DWORD dwLineID; + _ANONYMOUS_UNION union { + DWORD dwControlID; + DWORD dwControlType; + } DUMMYUNIONNAME; + DWORD cControls; + DWORD cbmxctrl; + LPMIXERCONTROLW pamxctrl; +} MIXERLINECONTROLSW,*PMIXERLINECONTROLSW,*LPMIXERLINECONTROLSW; +typedef struct tMIXERCONTROLDETAILS { + DWORD cbStruct; + DWORD dwControlID; + DWORD cChannels; + _ANONYMOUS_UNION union { + HWND hwndOwner; + DWORD cMultipleItems; + } DUMMYUNIONNAME; + DWORD cbDetails; + PVOID paDetails; +} MIXERCONTROLDETAILS,*PMIXERCONTROLDETAILS,*LPMIXERCONTROLDETAILS; +typedef struct tagMIXERCONTROLDETAILS_LISTTEXTA { + DWORD dwParam1; + DWORD dwParam2; + CHAR szName[MIXER_LONG_NAME_CHARS]; +} MIXERCONTROLDETAILS_LISTTEXTA,*PMIXERCONTROLDETAILS_LISTTEXTA,*LPMIXERCONTROLDETAILS_LISTTEXTA; +typedef struct tagMIXERCONTROLDETAILS_LISTTEXTW { + DWORD dwParam1; + DWORD dwParam2; + WCHAR szName[MIXER_LONG_NAME_CHARS]; +} MIXERCONTROLDETAILS_LISTTEXTW,*PMIXERCONTROLDETAILS_LISTTEXTW,*LPMIXERCONTROLDETAILS_LISTTEXTW; +typedef struct tMIXERCONTROLDETAILS_BOOLEAN { + LONG fValue; +} MIXERCONTROLDETAILS_BOOLEAN,*PMIXERCONTROLDETAILS_BOOLEAN,*LPMIXERCONTROLDETAILS_BOOLEAN; +typedef struct tMIXERCONTROLDETAILS_SIGNED { + LONG lValue; +} MIXERCONTROLDETAILS_SIGNED,*PMIXERCONTROLDETAILS_SIGNED,*LPMIXERCONTROLDETAILS_SIGNED; +typedef struct tMIXERCONTROLDETAILS_UNSIGNED { + DWORD dwValue; +} MIXERCONTROLDETAILS_UNSIGNED,*PMIXERCONTROLDETAILS_UNSIGNED,*LPMIXERCONTROLDETAILS_UNSIGNED; +typedef void(CALLBACK TIMECALLBACK)(UINT,UINT,DWORD,DWORD,DWORD); +typedef TIMECALLBACK *LPTIMECALLBACK; +typedef struct timecaps_tag { + UINT wPeriodMin; + UINT wPeriodMax; +} TIMECAPS,*PTIMECAPS,*LPTIMECAPS; +typedef struct tagJOYCAPSA { + WORD wMid; + WORD wPid; + CHAR szPname[MAXPNAMELEN]; + UINT wXmin; + UINT wXmax; + UINT wYmin; + UINT wYmax; + UINT wZmin; + UINT wZmax; + UINT wNumButtons; + UINT wPeriodMin; + UINT wPeriodMax; + UINT wRmin; + UINT wRmax; + UINT wUmin; + UINT wUmax; + UINT wVmin; + UINT wVmax; + UINT wCaps; + UINT wMaxAxes; + UINT wNumAxes; + UINT wMaxButtons; + CHAR szRegKey[MAXPNAMELEN]; + CHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME]; +} JOYCAPSA,*PJOYCAPSA,*LPJOYCAPSA; +typedef struct tagJOYCAPSW { + WORD wMid; + WORD wPid; + WCHAR szPname[MAXPNAMELEN]; + UINT wXmin; + UINT wXmax; + UINT wYmin; + UINT wYmax; + UINT wZmin; + UINT wZmax; + UINT wNumButtons; + UINT wPeriodMin; + UINT wPeriodMax; + UINT wRmin; + UINT wRmax; + UINT wUmin; + UINT wUmax; + UINT wVmin; + UINT wVmax; + UINT wCaps; + UINT wMaxAxes; + UINT wNumAxes; + UINT wMaxButtons; + WCHAR szRegKey[MAXPNAMELEN]; + WCHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME]; +} JOYCAPSW,*PJOYCAPSW,*LPJOYCAPSW; +typedef struct joyinfo_tag { + UINT wXpos; + UINT wYpos; + UINT wZpos; + UINT wButtons; +} JOYINFO,*PJOYINFO,*LPJOYINFO; +typedef struct joyinfoex_tag { + DWORD dwSize; + DWORD dwFlags; + DWORD dwXpos; + DWORD dwYpos; + DWORD dwZpos; + DWORD dwRpos; + DWORD dwUpos; + DWORD dwVpos; + DWORD dwButtons; + DWORD dwButtonNumber; + DWORD dwPOV; + DWORD dwReserved1; + DWORD dwReserved2; +} JOYINFOEX,*PJOYINFOEX,*LPJOYINFOEX; +typedef DWORD FOURCC; +typedef char *HPSTR; +DECLARE_HANDLE(HMMIO); +typedef LRESULT (CALLBACK MMIOPROC)(LPSTR,UINT,LPARAM,LPARAM); +typedef MMIOPROC *LPMMIOPROC; +typedef struct _MMIOINFO { + DWORD dwFlags; + FOURCC fccIOProc; + LPMMIOPROC pIOProc; + UINT wErrorRet; + HTASK htask; + LONG cchBuffer; + HPSTR pchBuffer; + HPSTR pchNext; + HPSTR pchEndRead; + HPSTR pchEndWrite; + LONG lBufOffset; + LONG lDiskOffset; + DWORD adwInfo[3]; + DWORD dwReserved1; + DWORD dwReserved2; + HMMIO hmmio; +} MMIOINFO,*PMMIOINFO,*LPMMIOINFO; +typedef const MMIOINFO *LPCMMIOINFO; +typedef struct _MMCKINFO { + FOURCC ckid; + DWORD cksize; + FOURCC fccType; + DWORD dwDataOffset; + DWORD dwFlags; +} MMCKINFO,*PMMCKINFO,*LPMMCKINFO; +typedef const MMCKINFO *LPCMMCKINFO; +typedef struct tagMCI_GENERIC_PARMS { + DWORD dwCallback; +} MCI_GENERIC_PARMS,*PMCI_GENERIC_PARMS,*LPMCI_GENERIC_PARMS; +typedef struct tagMCI_OPEN_PARMSA { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCSTR lpstrDeviceType; + LPCSTR lpstrElementName; + LPCSTR lpstrAlias; +} MCI_OPEN_PARMSA,*PMCI_OPEN_PARMSA,*LPMCI_OPEN_PARMSA; +typedef struct tagMCI_OPEN_PARMSW { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCWSTR lpstrDeviceType; + LPCWSTR lpstrElementName; + LPCWSTR lpstrAlias; +} MCI_OPEN_PARMSW,*PMCI_OPEN_PARMSW,*LPMCI_OPEN_PARMSW; +typedef struct tagMCI_PLAY_PARMS { + DWORD dwCallback; + DWORD dwFrom; + DWORD dwTo; +} MCI_PLAY_PARMS,*PMCI_PLAY_PARMS,*LPMCI_PLAY_PARMS; +typedef struct tagMCI_SEEK_PARMS { + DWORD dwCallback; + DWORD dwTo; +} MCI_SEEK_PARMS, *PMCI_SEEK_PARMS,*LPMCI_SEEK_PARMS; +typedef struct tagMCI_STATUS_PARMS { + DWORD dwCallback; + DWORD dwReturn; + DWORD dwItem; + DWORD dwTrack; +} MCI_STATUS_PARMS,*PMCI_STATUS_PARMS,*LPMCI_STATUS_PARMS; +typedef struct tagMCI_INFO_PARMSA { + DWORD dwCallback; + LPSTR lpstrReturn; + DWORD dwRetSize; +} MCI_INFO_PARMSA,*LPMCI_INFO_PARMSA; +typedef struct tagMCI_INFO_PARMSW { + DWORD dwCallback; + LPWSTR lpstrReturn; + DWORD dwRetSize; +} MCI_INFO_PARMSW,*LPMCI_INFO_PARMSW; +typedef struct tagMCI_GETDEVCAPS_PARMS { + DWORD dwCallback; + DWORD dwReturn; + DWORD dwItem; +} MCI_GETDEVCAPS_PARMS,*PMCI_GETDEVCAPS_PARMS,*LPMCI_GETDEVCAPS_PARMS; +typedef struct tagMCI_SYSINFO_PARMSA { + DWORD dwCallback; + LPSTR lpstrReturn; + DWORD dwRetSize; + DWORD dwNumber; + UINT wDeviceType; +} MCI_SYSINFO_PARMSA,*PMCI_SYSINFO_PARMSA,*LPMCI_SYSINFO_PARMSA; +typedef struct tagMCI_SYSINFO_PARMSW { + DWORD dwCallback; + LPWSTR lpstrReturn; + DWORD dwRetSize; + DWORD dwNumber; + UINT wDeviceType; +} MCI_SYSINFO_PARMSW,*PMCI_SYSINFO_PARMSW,*LPMCI_SYSINFO_PARMSW; +typedef struct tagMCI_SET_PARMS { + DWORD dwCallback; + DWORD dwTimeFormat; + DWORD dwAudio; +} MCI_SET_PARMS,*PMCI_SET_PARMS,*LPMCI_SET_PARMS; +typedef struct tagMCI_BREAK_PARMS { + DWORD dwCallback; + int nVirtKey; + HWND hwndBreak; +} MCI_BREAK_PARMS,*PMCI_BREAK_PARMS,*LPMCI_BREAK_PARMS; +typedef struct tagMCI_SAVE_PARMSA { + DWORD dwCallback; + LPCSTR lpfilename; +} MCI_SAVE_PARMSA,*PMCI_SAVE_PARMSA,*LPMCI_SAVE_PARMSA; +typedef struct tagMCI_SAVE_PARMSW { + DWORD dwCallback; + LPCWSTR lpfilename; +} MCI_SAVE_PARMSW,*PMCI_SAVE_PARMSW,*LPMCI_SAVE_PARMSW; +typedef struct tagMCI_LOAD_PARMSA { + DWORD dwCallback; + LPCSTR lpfilename; +} MCI_LOAD_PARMSA,*PMCI_LOAD_PARMSA,*LPMCI_LOAD_PARMSA; +typedef struct tagMCI_LOAD_PARMSW { + DWORD dwCallback; + LPCWSTR lpfilename; +} MCI_LOAD_PARMSW,*PMCI_LOAD_PARMSW,*LPMCI_LOAD_PARMSW; +typedef struct tagMCI_RECORD_PARMS { + DWORD dwCallback; + DWORD dwFrom; + DWORD dwTo; +} MCI_RECORD_PARMS,*LPMCI_RECORD_PARMS; +typedef struct tagMCI_VD_PLAY_PARMS { + DWORD dwCallback; + DWORD dwFrom; + DWORD dwTo; + DWORD dwSpeed; +} MCI_VD_PLAY_PARMS,*PMCI_VD_PLAY_PARMS,*LPMCI_VD_PLAY_PARMS; +typedef struct tagMCI_VD_STEP_PARMS { + DWORD dwCallback; + DWORD dwFrames; +} MCI_VD_STEP_PARMS,*PMCI_VD_STEP_PARMS,*LPMCI_VD_STEP_PARMS; +typedef struct tagMCI_VD_ESCAPE_PARMSA { + DWORD dwCallback; + LPCSTR lpstrCommand; +} MCI_VD_ESCAPE_PARMSA,*PMCI_VD_ESCAPE_PARMSA,*LPMCI_VD_ESCAPE_PARMSA; +typedef struct tagMCI_VD_ESCAPE_PARMSW { + DWORD dwCallback; + LPCWSTR lpstrCommand; +} MCI_VD_ESCAPE_PARMSW,*PMCI_VD_ESCAPE_PARMSW,*LPMCI_VD_ESCAPE_PARMSW; +typedef struct tagMCI_WAVE_OPEN_PARMSA { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCSTR lpstrDeviceType; + LPCSTR lpstrElementName; + LPCSTR lpstrAlias; + DWORD dwBufferSeconds; +} MCI_WAVE_OPEN_PARMSA,*PMCI_WAVE_OPEN_PARMSA,*LPMCI_WAVE_OPEN_PARMSA; +typedef struct tagMCI_WAVE_OPEN_PARMSW { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCWSTR lpstrDeviceType; + LPCWSTR lpstrElementName; + LPCWSTR lpstrAlias; + DWORD dwBufferSeconds; +} MCI_WAVE_OPEN_PARMSW,*PMCI_WAVE_OPEN_PARMSW,*LPMCI_WAVE_OPEN_PARMSW; +typedef struct tagMCI_WAVE_DELETE_PARMS { + DWORD dwCallback; + DWORD dwFrom; + DWORD dwTo; +} MCI_WAVE_DELETE_PARMS, *PMCI_WAVE_DELETE_PARMS,*LPMCI_WAVE_DELETE_PARMS; +typedef struct tagMCI_WAVE_SET_PARMS { + DWORD dwCallback; + DWORD dwTimeFormat; + DWORD dwAudio; + UINT wInput; + UINT wOutput; + WORD wFormatTag; + WORD wReserved2; + WORD nChannels; + WORD wReserved3; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wReserved4; + WORD wBitsPerSample; + WORD wReserved5; +} MCI_WAVE_SET_PARMS,*PMCI_WAVE_SET_PARMS,*LPMCI_WAVE_SET_PARMS; + +LRESULT WINAPI CloseDriver(HDRVR,LONG,LONG); +HDRVR WINAPI OpenDriver(LPCWSTR,LPCWSTR,LONG); +LRESULT WINAPI SendDriverMessage(HDRVR,UINT,LONG,LONG); +HMODULE WINAPI DrvGetModuleHandle(HDRVR); +HMODULE WINAPI GetDriverModuleHandle(HDRVR); +LRESULT WINAPI DefDriverProc(DWORD,HDRVR,UINT,LPARAM,LPARAM); +UINT WINAPI mmsystemGetVersion(void); +#define OutputDebugStr OutputDebugString +BOOL WINAPI sndPlaySoundA(LPCSTR,UINT); +BOOL WINAPI sndPlaySoundW(LPCWSTR,UINT); +BOOL WINAPI PlaySoundA(LPCSTR,HMODULE,DWORD); +BOOL WINAPI PlaySoundW(LPCWSTR,HMODULE,DWORD); +UINT WINAPI waveOutGetNumDevs(void); +MMRESULT WINAPI waveOutGetDevCapsA(UINT,LPWAVEOUTCAPSA,UINT); +MMRESULT WINAPI waveOutGetDevCapsW(UINT,LPWAVEOUTCAPSW,UINT); +MMRESULT WINAPI waveOutGetVolume(HWAVEOUT,PDWORD); +MMRESULT WINAPI waveOutSetVolume(HWAVEOUT,DWORD); +MMRESULT WINAPI waveOutGetErrorTextA(MMRESULT,LPSTR,UINT); +MMRESULT WINAPI waveOutGetErrorTextW(MMRESULT,LPWSTR,UINT); +MMRESULT WINAPI waveOutOpen(LPHWAVEOUT,UINT,LPCWAVEFORMATEX,DWORD,DWORD,DWORD); +MMRESULT WINAPI waveOutClose(HWAVEOUT); +MMRESULT WINAPI waveOutPrepareHeader(HWAVEOUT,LPWAVEHDR,UINT); +MMRESULT WINAPI waveOutUnprepareHeader(HWAVEOUT,LPWAVEHDR,UINT); +MMRESULT WINAPI waveOutWrite(HWAVEOUT,LPWAVEHDR,UINT); +MMRESULT WINAPI waveOutPause(HWAVEOUT); +MMRESULT WINAPI waveOutRestart(HWAVEOUT); +MMRESULT WINAPI waveOutReset(HWAVEOUT); +MMRESULT WINAPI waveOutBreakLoop(HWAVEOUT); +MMRESULT WINAPI waveOutGetPosition(HWAVEOUT,LPMMTIME,UINT); +MMRESULT WINAPI waveOutGetPitch(HWAVEOUT,PDWORD); +MMRESULT WINAPI waveOutSetPitch(HWAVEOUT,DWORD); +MMRESULT WINAPI waveOutGetPlaybackRate(HWAVEOUT,PDWORD); +MMRESULT WINAPI waveOutSetPlaybackRate(HWAVEOUT,DWORD); +MMRESULT WINAPI waveOutGetID(HWAVEOUT,LPUINT); +MMRESULT WINAPI waveOutMessage(HWAVEOUT,UINT,DWORD,DWORD); +UINT WINAPI waveInGetNumDevs(void); +MMRESULT WINAPI waveInGetDevCapsA(UINT,LPWAVEINCAPSA,UINT); +MMRESULT WINAPI waveInGetDevCapsW(UINT,LPWAVEINCAPSW,UINT); +MMRESULT WINAPI waveInGetErrorTextA(MMRESULT,LPSTR,UINT); +MMRESULT WINAPI waveInGetErrorTextW(MMRESULT,LPWSTR,UINT); +MMRESULT WINAPI waveInOpen(LPHWAVEIN,UINT,LPCWAVEFORMATEX,DWORD*,DWORD*,DWORD); +//MMRESULT WINAPI waveInOpen(LPHWAVEIN,UINT,LPCWAVEFORMATEX,DWORD,DWORD,DWORD); +MMRESULT WINAPI waveInClose(HWAVEIN); +MMRESULT WINAPI waveInPrepareHeader(HWAVEIN,LPWAVEHDR,UINT); +MMRESULT WINAPI waveInUnprepareHeader(HWAVEIN,LPWAVEHDR,UINT); +MMRESULT WINAPI waveInAddBuffer(HWAVEIN,LPWAVEHDR,UINT); +MMRESULT WINAPI waveInStart(HWAVEIN); +MMRESULT WINAPI waveInStop(HWAVEIN); +MMRESULT WINAPI waveInReset(HWAVEIN); +MMRESULT WINAPI waveInGetPosition(HWAVEIN,LPMMTIME,UINT); +MMRESULT WINAPI waveInGetID(HWAVEIN,LPUINT); +MMRESULT WINAPI waveInMessage(HWAVEIN,UINT,DWORD,DWORD); +UINT WINAPI midiOutGetNumDevs(void); +MMRESULT WINAPI midiStreamOpen(LPHMIDISTRM,LPUINT,DWORD,DWORD,DWORD,DWORD); +MMRESULT WINAPI midiStreamClose(HMIDISTRM); +MMRESULT WINAPI midiStreamProperty(HMIDISTRM,LPBYTE,DWORD); +MMRESULT WINAPI midiStreamPosition(HMIDISTRM,LPMMTIME,UINT); +MMRESULT WINAPI midiStreamOut(HMIDISTRM,LPMIDIHDR,UINT); +MMRESULT WINAPI midiStreamPause(HMIDISTRM); +MMRESULT WINAPI midiStreamRestart(HMIDISTRM); +MMRESULT WINAPI midiStreamStop(HMIDISTRM); +MMRESULT WINAPI midiConnect(HMIDI,HMIDIOUT,PVOID); +MMRESULT WINAPI midiDisconnect(HMIDI,HMIDIOUT,PVOID); +MMRESULT WINAPI midiOutGetDevCapsA(UINT,LPMIDIOUTCAPSA,UINT); +MMRESULT WINAPI midiOutGetDevCapsW(UINT,LPMIDIOUTCAPSW,UINT); +MMRESULT WINAPI midiOutGetVolume(HMIDIOUT,PDWORD); +MMRESULT WINAPI midiOutSetVolume(HMIDIOUT,DWORD); +MMRESULT WINAPI midiOutGetErrorTextA(MMRESULT,LPSTR,UINT); +MMRESULT WINAPI midiOutGetErrorTextW(MMRESULT,LPWSTR,UINT); +MMRESULT WINAPI midiOutOpen(LPHMIDIOUT,UINT,DWORD,DWORD,DWORD); +MMRESULT WINAPI midiOutClose(HMIDIOUT); +MMRESULT WINAPI midiOutPrepareHeader(HMIDIOUT,LPMIDIHDR,UINT); +MMRESULT WINAPI midiOutUnprepareHeader(HMIDIOUT,LPMIDIHDR,UINT); +MMRESULT WINAPI midiOutShortMsg(HMIDIOUT,DWORD); +MMRESULT WINAPI midiOutLongMsg(HMIDIOUT,LPMIDIHDR,UINT); +MMRESULT WINAPI midiOutReset(HMIDIOUT); +MMRESULT WINAPI midiOutCachePatches(HMIDIOUT,UINT,LPWORD,UINT); +MMRESULT WINAPI midiOutCacheDrumPatches(HMIDIOUT,UINT,LPWORD,UINT); +MMRESULT WINAPI midiOutGetID(HMIDIOUT,LPUINT); +MMRESULT WINAPI midiOutMessage(HMIDIOUT,UINT,DWORD,DWORD); +UINT WINAPI midiInGetNumDevs(void); +MMRESULT WINAPI midiInGetDevCapsA(UINT,LPMIDIINCAPSA,UINT); +MMRESULT WINAPI midiInGetDevCapsW(UINT,LPMIDIINCAPSW,UINT); +MMRESULT WINAPI midiInGetErrorTextA(MMRESULT,LPSTR,UINT); +MMRESULT WINAPI midiInGetErrorTextW(MMRESULT,LPWSTR,UINT); +MMRESULT WINAPI midiInOpen(LPHMIDIIN,UINT,DWORD,DWORD,DWORD); +MMRESULT WINAPI midiInClose(HMIDIIN); +MMRESULT WINAPI midiInPrepareHeader(HMIDIIN,LPMIDIHDR,UINT); +MMRESULT WINAPI midiInUnprepareHeader(HMIDIIN,LPMIDIHDR,UINT); +MMRESULT WINAPI midiInAddBuffer(HMIDIIN,LPMIDIHDR,UINT); +MMRESULT WINAPI midiInStart(HMIDIIN); +MMRESULT WINAPI midiInStop(HMIDIIN); +MMRESULT WINAPI midiInReset(HMIDIIN); +MMRESULT WINAPI midiInGetID(HMIDIIN,LPUINT); +MMRESULT WINAPI midiInMessage(HMIDIIN,UINT,DWORD,DWORD); +UINT WINAPI auxGetNumDevs(void); +MMRESULT WINAPI auxGetDevCapsA(UINT,LPAUXCAPSA,UINT); +MMRESULT WINAPI auxGetDevCapsW(UINT,LPAUXCAPSW,UINT); +MMRESULT WINAPI auxSetVolume(UINT,DWORD); +MMRESULT WINAPI auxGetVolume(UINT,PDWORD); +MMRESULT WINAPI auxOutMessage(UINT,UINT,DWORD,DWORD); +UINT WINAPI mixerGetNumDevs(void); +MMRESULT WINAPI mixerGetDevCapsA(UINT,LPMIXERCAPSA,UINT); +MMRESULT WINAPI mixerGetDevCapsW(UINT,LPMIXERCAPSW,UINT); +MMRESULT WINAPI mixerOpen(LPHMIXER,UINT,DWORD,DWORD,DWORD); +MMRESULT WINAPI mixerClose(HMIXER); +DWORD WINAPI mixerMessage(HMIXER,UINT,DWORD,DWORD); +MMRESULT WINAPI mixerGetLineInfoA(HMIXEROBJ,LPMIXERLINEA,DWORD); +MMRESULT WINAPI mixerGetLineInfoW(HMIXEROBJ,LPMIXERLINEW,DWORD); +MMRESULT WINAPI mixerGetID(HMIXEROBJ,PUINT,DWORD); +MMRESULT WINAPI mixerGetLineControlsA(HMIXEROBJ,LPMIXERLINECONTROLSA,DWORD); +MMRESULT WINAPI mixerGetLineControlsW(HMIXEROBJ,LPMIXERLINECONTROLSW,DWORD); +MMRESULT WINAPI mixerGetControlDetailsA(HMIXEROBJ,LPMIXERCONTROLDETAILS,DWORD); +MMRESULT WINAPI mixerGetControlDetailsW(HMIXEROBJ,LPMIXERCONTROLDETAILS,DWORD); +MMRESULT WINAPI mixerSetControlDetails(HMIXEROBJ,LPMIXERCONTROLDETAILS,DWORD); +MMRESULT WINAPI timeGetSystemTime(LPMMTIME,UINT); +DWORD WINAPI timeGetTime(void); +MMRESULT WINAPI timeSetEvent(UINT,UINT,LPTIMECALLBACK,DWORD,UINT); +MMRESULT WINAPI timeKillEvent(UINT); +MMRESULT WINAPI timeGetDevCaps(LPTIMECAPS,UINT); +MMRESULT WINAPI timeBeginPeriod(UINT); +MMRESULT WINAPI timeEndPeriod(UINT); +UINT WINAPI joyGetNumDevs(void); +MMRESULT WINAPI joyGetDevCapsA(UINT,LPJOYCAPSA,UINT); +MMRESULT WINAPI joyGetDevCapsW(UINT,LPJOYCAPSW,UINT); +MMRESULT WINAPI joyGetPos(UINT,LPJOYINFO); +MMRESULT WINAPI joyGetPosEx(UINT,LPJOYINFOEX); +MMRESULT WINAPI joyGetThreshold(UINT,LPUINT); +MMRESULT WINAPI joyReleaseCapture(UINT); +MMRESULT WINAPI joySetCapture(HWND,UINT,UINT,BOOL); +MMRESULT WINAPI joySetThreshold(UINT,UINT); +FOURCC WINAPI mmioStringToFOURCCA(LPCSTR,UINT); +FOURCC WINAPI mmioStringToFOURCCW(LPCWSTR,UINT); +LPMMIOPROC WINAPI mmioInstallIOProcA(FOURCC,LPMMIOPROC,DWORD); +LPMMIOPROC WINAPI mmioInstallIOProcW(FOURCC,LPMMIOPROC,DWORD); +HMMIO WINAPI mmioOpenA(LPSTR,LPMMIOINFO,DWORD); +HMMIO WINAPI mmioOpenW(LPWSTR,LPMMIOINFO,DWORD); +MMRESULT WINAPI mmioRenameA(LPCSTR,LPCSTR,LPCMMIOINFO,DWORD); +MMRESULT WINAPI mmioRenameW(LPCWSTR,LPCWSTR,LPCMMIOINFO,DWORD); +MMRESULT WINAPI mmioClose(HMMIO,UINT); +LONG WINAPI mmioRead(HMMIO,HPSTR,LONG); +LONG WINAPI mmioWrite(HMMIO,LPCSTR,LONG); +LONG WINAPI mmioSeek(HMMIO,LONG,int); +MMRESULT WINAPI mmioGetInfo(HMMIO,LPMMIOINFO,UINT); +MMRESULT WINAPI mmioSetInfo(HMMIO,LPCMMIOINFO,UINT); +MMRESULT WINAPI mmioSetBuffer(HMMIO,LPSTR,LONG,UINT); +MMRESULT WINAPI mmioFlush(HMMIO,UINT); +MMRESULT WINAPI mmioAdvance(HMMIO,LPMMIOINFO,UINT); +LRESULT WINAPI mmioSendMessage(HMMIO,UINT,LPARAM,LPARAM); +MMRESULT WINAPI mmioDescend(HMMIO,LPMMCKINFO,const MMCKINFO*,UINT); +MMRESULT WINAPI mmioAscend(HMMIO,LPMMCKINFO,UINT); +MMRESULT WINAPI mmioCreateChunk(HMMIO,LPMMCKINFO,UINT); +MCIERROR WINAPI mciSendCommandA(MCIDEVICEID,UINT,DWORD,DWORD); +MCIERROR WINAPI mciSendCommandW(MCIDEVICEID,UINT,DWORD,DWORD); +MCIERROR WINAPI mciSendStringA(LPCSTR,LPSTR,UINT,HWND); +MCIERROR WINAPI mciSendStringW(LPCWSTR,LPWSTR,UINT,HWND); +MCIDEVICEID WINAPI mciGetDeviceIDA(LPCSTR); +MCIDEVICEID WINAPI mciGetDeviceIDW(LPCWSTR); +MCIDEVICEID WINAPI mciGetDeviceIDFromElementIDA(DWORD,LPCSTR); +MCIDEVICEID WINAPI mciGetDeviceIDFromElementIDW(DWORD,LPCWSTR); +BOOL WINAPI mciGetErrorStringA(MCIERROR,LPSTR,UINT); +BOOL WINAPI mciGetErrorStringW(MCIERROR,LPWSTR,UINT); +BOOL WINAPI mciSetYieldProc(MCIDEVICEID,YIELDPROC,DWORD); +HTASK WINAPI mciGetCreatorTask(MCIDEVICEID); +YIELDPROC WINAPI mciGetYieldProc(MCIDEVICEID,PDWORD); + +typedef struct tagMCI_SEQ_SET_PARMS { + DWORD dwCallback; + DWORD dwTimeFormat; + DWORD dwAudio; + DWORD dwTempo; + DWORD dwPort; + DWORD dwSlave; + DWORD dwMaster; + DWORD dwOffset; +} MCI_SEQ_SET_PARMS,*PMCI_SEQ_SET_PARMS,*LPMCI_SEQ_SET_PARMS; +typedef struct tagMCI_ANIM_OPEN_PARMSA { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCSTR lpstrDeviceType; + LPCSTR lpstrElementName; + LPCSTR lpstrAlias; + DWORD dwStyle; + HWND hWndParent; +} MCI_ANIM_OPEN_PARMSA,*PMCI_ANIM_OPEN_PARMSA,*LPMCI_ANIM_OPEN_PARMSA; +typedef struct tagMCI_ANIM_OPEN_PARMSW { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCWSTR lpstrDeviceType; + LPCWSTR lpstrElementName; + LPCWSTR lpstrAlias; + DWORD dwStyle; + HWND hWndParent; +} MCI_ANIM_OPEN_PARMSW,*PMCI_ANIM_OPEN_PARMSW,*LPMCI_ANIM_OPEN_PARMSW; +typedef struct tagMCI_ANIM_PLAY_PARMS { + DWORD dwCallback; + DWORD dwFrom; + DWORD dwTo; + DWORD dwSpeed; +} MCI_ANIM_PLAY_PARMS,*PMCI_ANIM_PLAY_PARMS,*LPMCI_ANIM_PLAY_PARMS; +typedef struct tagMCI_ANIM_STEP_PARMS { + DWORD dwCallback; + DWORD dwFrames; +} MCI_ANIM_STEP_PARMS,*PMCI_ANIM_STEP_PARMS,*LPMCI_ANIM_STEP_PARMS; +typedef struct tagMCI_ANIM_WINDOW_PARMSA { + DWORD dwCallback; + HWND hWnd; + UINT nCmdShow; + LPCSTR lpstrText; +} MCI_ANIM_WINDOW_PARMSA,*PMCI_ANIM_WINDOW_PARMSA,*LPMCI_ANIM_WINDOW_PARMSA; +typedef struct tagMCI_ANIM_WINDOW_PARMSW { + DWORD dwCallback; + HWND hWnd; + UINT nCmdShow; + LPCWSTR lpstrText; +} MCI_ANIM_WINDOW_PARMSW,*PMCI_ANIM_WINDOW_PARMSW,*LPMCI_ANIM_WINDOW_PARMSW; +typedef struct tagMCI_ANIM_RECT_PARMS { + DWORD dwCallback; +#ifdef MCI_USE_OFFEXT + POINT ptOffset; + POINT ptExtent; +#else + RECT rc; +#endif +} MCI_ANIM_RECT_PARMS,*PMCI_ANIM_RECT_PARMS,*LPMCI_ANIM_RECT_PARMS; +typedef struct tagMCI_ANIM_UPDATE_PARMS { + DWORD dwCallback; + RECT rc; + HDC hDC; +} MCI_ANIM_UPDATE_PARMS,*PMCI_ANIM_UPDATE_PARMS,*LPMCI_ANIM_UPDATE_PARMS; +typedef struct tagMCI_OVLY_OPEN_PARMSA { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCSTR lpstrDeviceType; + LPCSTR lpstrElementName; + LPCSTR lpstrAlias; + DWORD dwStyle; + HWND hWndParent; +} MCI_OVLY_OPEN_PARMSA,*PMCI_OVLY_OPEN_PARMSA,*LPMCI_OVLY_OPEN_PARMSA; +typedef struct tagMCI_OVLY_OPEN_PARMSW { + DWORD dwCallback; + MCIDEVICEID wDeviceID; + LPCWSTR lpstrDeviceType; + LPCWSTR lpstrElementName; + LPCWSTR lpstrAlias; + DWORD dwStyle; + HWND hWndParent; +} MCI_OVLY_OPEN_PARMSW,*PMCI_OVLY_OPEN_PARMSW,*LPMCI_OVLY_OPEN_PARMSW; +typedef struct tagMCI_OVLY_WINDOW_PARMSA { + DWORD dwCallback; + HWND hWnd; + UINT nCmdShow; + LPCSTR lpstrText; +} MCI_OVLY_WINDOW_PARMSA,*PMCI_OVLY_WINDOW_PARMSA,*LPMCI_OVLY_WINDOW_PARMSA; +typedef struct tagMCI_OVLY_WINDOW_PARMSW { + DWORD dwCallback; + HWND hWnd; + UINT nCmdShow; + LPCWSTR lpstrText; +} MCI_OVLY_WINDOW_PARMSW,*PMCI_OVLY_WINDOW_PARMSW,*LPMCI_OVLY_WINDOW_PARMSW; +typedef struct tagMCI_OVLY_RECT_PARMS { + DWORD dwCallback; +#ifdef MCI_USE_OFFEXT + POINT ptOffset; + POINT ptExtent; +#else + RECT rc; +#endif +} MCI_OVLY_RECT_PARMS,*PMCI_OVLY_RECT_PARMS,*LPMCI_OVLY_RECT_PARMS; +typedef struct tagMCI_OVLY_SAVE_PARMSA { + DWORD dwCallback; + LPCSTR lpfilename; + RECT rc; +} MCI_OVLY_SAVE_PARMSA,*PMCI_OVLY_SAVE_PARMSA,*LPMCI_OVLY_SAVE_PARMSA; +typedef struct tagMCI_OVLY_SAVE_PARMSW { + DWORD dwCallback; + LPCWSTR lpfilename; + RECT rc; +} MCI_OVLY_SAVE_PARMSW,*PMCI_OVLY_SAVE_PARMSW,*LPMCI_OVLY_SAVE_PARMSW; +typedef struct tagMCI_OVLY_LOAD_PARMSA { + DWORD dwCallback; + LPCSTR lpfilename; + RECT rc; +} MCI_OVLY_LOAD_PARMSA,*PMCI_OVLY_LOAD_PARMSA,*LPMCI_OVLY_LOAD_PARMSA; +typedef struct tagMCI_OVLY_LOAD_PARMSW { + DWORD dwCallback; + LPCWSTR lpfilename; + RECT rc; +} MCI_OVLY_LOAD_PARMSW,*PMCI_OVLY_LOAD_PARMSW,*LPMCI_OVLY_LOAD_PARMSW; + +#ifdef UNICODE +typedef WAVEOUTCAPSW WAVEOUTCAPS,*PWAVEOUTCAPS,*LPWAVEOUTCAPS; +typedef WAVEINCAPSW WAVEINCAPS,*PWAVEINCAPS,*LPWAVEINCAPS; +typedef MIDIOUTCAPSW MIDIOUTCAPS,*PMIDIOUTCAPS,*LPMIDIOUTCAPS; +typedef MIDIINCAPSW MIDIINCAPS,*PMIDIINCAPS,*LPMIDIINCAPS; +typedef AUXCAPSW AUXCAPS,*PAUXCAPS,*LPAUXCAPS; +typedef MIXERCAPSW MIXERCAPS,*PMIXERCAPS,*LPMIXERCAPS; +typedef MIXERLINEW MIXERLINE,*PMIXERLINE,*LPMIXERLINE; +typedef MIXERCONTROLW MIXERCONTROL,*PMIXERCONTROL,*LPMIXERCONTROL; +typedef MIXERLINECONTROLSW MIXERLINECONTROLS,*PMIXERLINECONTROLS,*LPMIXERLINECONTROLS; +typedef MIXERCONTROLDETAILS_LISTTEXTW MIXERCONTROLDETAILS_LISTTEXT,*PMIXERCONTROLDETAILS_LISTTEXT,*LPMIXERCONTROLDETAILS_LISTTEXT; +typedef JOYCAPSW JOYCAPS,*PJOYCAPS,*LPJOYCAPS; +typedef MCI_OPEN_PARMSW MCI_OPEN_PARMS,*PMCI_OPEN_PARMS,*LPMCI_OPEN_PARMS; +typedef MCI_INFO_PARMSW MCI_INFO_PARMS,*LPMCI_INFO_PARMS; +typedef MCI_SYSINFO_PARMSW MCI_SYSINFO_PARMS,*PMCI_SYSINFO_PARMS,*LPMCI_SYSINFO_PARMS; +typedef MCI_SAVE_PARMSW MCI_SAVE_PARMS,*PMCI_SAVE_PARMS,*LPMCI_SAVE_PARMS; +typedef MCI_LOAD_PARMSW MCI_LOAD_PARMS,*PMCI_LOAD_PARMS,*LPMCI_LOAD_PARMS; +typedef MCI_VD_ESCAPE_PARMSW MCI_VD_ESCAPE_PARMS,*PMCI_VD_ESCAPE_PARMS,*LPMCI_VD_ESCAPE_PARMS; +typedef MCI_WAVE_OPEN_PARMSW MCI_WAVE_OPEN_PARMS,*PMCI_WAVE_OPEN_PARMS,*LPMCI_WAVE_OPEN_PARMS; +typedef MCI_ANIM_OPEN_PARMSW MCI_ANIM_OPEN_PARMS,*PMCI_ANIM_OPEN_PARMS,*LPMCI_ANIM_OPEN_PARMS; +typedef MCI_ANIM_WINDOW_PARMSW MCI_ANIM_WINDOW_PARMS,*PMCI_ANIM_WINDOW_PARMS,*LPMCI_ANIM_WINDOW_PARMS; +typedef MCI_OVLY_OPEN_PARMSW MCI_OVLY_OPEN_PARMS,*PMCI_OVLY_OPEN_PARMS,*LPMCI_OVLY_OPEN_PARMS; +typedef MCI_OVLY_WINDOW_PARMSW MCI_OVLY_WINDOW_PARMS,*PMCI_OVLY_WINDOW_PARMS,*LPMCI_OVLY_WINDOW_PARMS; +typedef MCI_OVLY_SAVE_PARMSW MCI_OVLY_SAVE_PARMS,*PMCI_OVLY_SAVE_PARMS,*LPMCI_OVLY_SAVE_PARMS; +#define sndPlaySound sndPlaySoundW +#define PlaySound PlaySoundW +#define waveOutGetDevCaps waveOutGetDevCapsW +#define waveOutGetErrorText waveOutGetErrorTextW +#define waveInGetDevCaps waveInGetDevCapsW +#define waveInGetErrorText waveInGetErrorTextW +#define midiOutGetDevCaps midiOutGetDevCapsW +#define midiOutGetErrorText midiOutGetErrorTextW +#define midiInGetDevCaps midiInGetDevCapsW +#define midiInGetErrorText midiInGetErrorTextW +#define auxGetDevCaps auxGetDevCapsW +#define mixerGetDevCaps mixerGetDevCapsW +#define mixerGetLineInfo mixerGetLineInfoW +#define mixerGetLineControls mixerGetLineControlsW +#define mixerGetControlDetails mixerGetControlDetailsW +#define joyGetDevCaps joyGetDevCapsW +#define mmioInstallIOProc mmioInstallIOProcW +#define mmioStringToFOURCC mmioStringToFOURCCW +#define mmioOpen mmioOpenW +#define mmioRename mmioRenameW +#define mciSendCommand mciSendCommandW +#define mciSendString mciSendStringW +#define mciGetDeviceID mciGetDeviceIDW +#define mciGetDeviceIDFromElementID mciGetDeviceIDFromElementIDW +#define mciGetErrorString mciGetErrorStringW +#else +typedef WAVEOUTCAPSA WAVEOUTCAPS,*PWAVEOUTCAPS,*LPWAVEOUTCAPS; +typedef WAVEINCAPSA WAVEINCAPS,*PWAVEINCAPS,*LPWAVEINCAPS; +typedef MIDIOUTCAPSA MIDIOUTCAPS,*PMIDIOUTCAPS,*LPMIDIOUTCAPS; +typedef MIDIINCAPSA MIDIINCAPS,*PMIDIINCAPS,*LPMIDIINCAPS; +typedef AUXCAPSA AUXCAPS,*PAUXCAPS,*LPAUXCAPS; +typedef MIXERCAPSA MIXERCAPS,*PMIXERCAPS,*LPMIXERCAPS; +typedef MIXERLINEA MIXERLINE,*PMIXERLINE,*LPMIXERLINE; +typedef MIXERCONTROLA MIXERCONTROL,*PMIXERCONTROL,*LPMIXERCONTROL; +typedef MIXERLINECONTROLSA MIXERLINECONTROLS,*PMIXERLINECONTROLS,*LPMIXERLINECONTROLS; +typedef MIXERCONTROLDETAILS_LISTTEXTA MIXERCONTROLDETAILS_LISTTEXT,*PMIXERCONTROLDETAILS_LISTTEXT,*LPMIXERCONTROLDETAILS_LISTTEXT; +typedef JOYCAPSA JOYCAPS,*PJOYCAPS,*LPJOYCAPS; +typedef MCI_OPEN_PARMSA MCI_OPEN_PARMS,*PMCI_OPEN_PARMS,*LPMCI_OPEN_PARMS; +typedef MCI_INFO_PARMSA MCI_INFO_PARMS,*LPMCI_INFO_PARMS; +typedef MCI_SYSINFO_PARMSA MCI_SYSINFO_PARMS,*PMCI_SYSINFO_PARMS,*LPMCI_SYSINFO_PARMS; +typedef MCI_SAVE_PARMSA MCI_SAVE_PARMS,*PMCI_SAVE_PARMS,*LPMCI_SAVE_PARMS; +typedef MCI_LOAD_PARMSA MCI_LOAD_PARMS,*PMCI_LOAD_PARMS,*LPMCI_LOAD_PARMS; +typedef MCI_VD_ESCAPE_PARMSA MCI_VD_ESCAPE_PARMS,*PMCI_VD_ESCAPE_PARMS,*LPMCI_VD_ESCAPE_PARMS; +typedef MCI_WAVE_OPEN_PARMSA MCI_WAVE_OPEN_PARMS,*PMCI_WAVE_OPEN_PARMS,*LPMCI_WAVE_OPEN_PARMS; +typedef MCI_ANIM_OPEN_PARMSA MCI_ANIM_OPEN_PARMS,*PMCI_ANIM_OPEN_PARMS,*LPMCI_ANIM_OPEN_PARMS; +typedef MCI_ANIM_WINDOW_PARMSA MCI_ANIM_WINDOW_PARMS,*PMCI_ANIM_WINDOW_PARMS,*LPMCI_ANIM_WINDOW_PARMS; +typedef MCI_OVLY_OPEN_PARMSA MCI_OVLY_OPEN_PARMS,*PMCI_OVLY_OPEN_PARMS,*LPMCI_OVLY_OPEN_PARMS; +typedef MCI_OVLY_WINDOW_PARMSA MCI_OVLY_WINDOW_PARMS,*PMCI_OVLY_WINDOW_PARMS,*LPMCI_OVLY_WINDOW_PARMS; +typedef MCI_OVLY_SAVE_PARMSA MCI_OVLY_SAVE_PARMS,*PMCI_OVLY_SAVE_PARMS,*LPMCI_OVLY_SAVE_PARMS; +#define sndPlaySound sndPlaySoundA +#define PlaySound PlaySoundA +#define waveOutGetDevCaps waveOutGetDevCapsA +#define waveOutGetErrorText waveOutGetErrorTextA +#define waveInGetDevCaps waveInGetDevCapsA +#define waveInGetErrorText waveInGetErrorTextA +#define midiOutGetDevCaps midiOutGetDevCapsA +#define midiOutGetErrorText midiOutGetErrorTextA +#define midiInGetDevCaps midiInGetDevCapsA +#define midiInGetErrorText midiInGetErrorTextA +#define auxGetDevCaps auxGetDevCapsA +#define mixerGetDevCaps mixerGetDevCapsA +#define mixerGetLineInfo mixerGetLineInfoA +#define mixerGetLineControls mixerGetLineControlsA +#define mixerGetControlDetails mixerGetControlDetailsA +#define joyGetDevCaps joyGetDevCapsA +#define mmioInstallIOProc mmioInstallIOProcA +#define mmioStringToFOURCC mmioStringToFOURCCA +#define mmioOpen mmioOpenA +#define mmioRename mmioRenameA +#define mciSendCommand mciSendCommandA +#define mciSendString mciSendStringA +#define mciGetDeviceID mciGetDeviceIDA +#define mciGetDeviceIDFromElementID mciGetDeviceIDFromElementIDA +#define mciGetErrorString mciGetErrorStringA +#endif +#ifdef __cplusplus +} +#endif +#pragma pack(pop) +#endif diff --git a/colorchord2/windows/symbol_enumerator.c b/colorchord2/windows/symbol_enumerator.c new file mode 100644 index 0000000..fcb3727 --- /dev/null +++ b/colorchord2/windows/symbol_enumerator.c @@ -0,0 +1,245 @@ +#include +#include "symbol_enumerator.h" + +#if defined( WIN32 ) || defined( WINDOWS ) || defined( USE_WINDOWS ) || defined( _WIN32 ) + +#include + +typedef struct _SYMBOL_INFO { + ULONG SizeOfStruct; + ULONG TypeIndex; + ULONG64 Reserved[2]; + ULONG Index; + ULONG Size; + ULONG64 ModBase; + ULONG Flags; + ULONG64 Value; + ULONG64 Address; + ULONG Register; + ULONG Scope; + ULONG Tag; + ULONG NameLen; + ULONG MaxNameLen; + TCHAR Name[1]; +} SYMBOL_INFO, *PSYMBOL_INFO; +typedef struct _IMAGEHLP_STACK_FRAME { + ULONG64 InstructionOffset; + ULONG64 ReturnOffset; + ULONG64 FrameOffset; + ULONG64 StackOffset; + ULONG64 BackingStoreOffset; + ULONG64 FuncTableEntry; + ULONG64 Params[4]; + ULONG64 Reserved[5]; + BOOL Virtual; + ULONG Reserved2; +} IMAGEHLP_STACK_FRAME, *PIMAGEHLP_STACK_FRAME; + + +typedef BOOL (*PSYM_ENUMERATESYMBOLS_CALLBACK)( + PSYMBOL_INFO pSymInfo, + ULONG SymbolSize, + PVOID UserContext + ); + +BOOL WINAPI SymEnumSymbols( + HANDLE hProcess, + ULONG64 BaseOfDll, + PCTSTR Mask, + PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + const PVOID UserContext +); + +BOOL WINAPI SymInitialize( + HANDLE hProcess, + PCTSTR UserSearchPath, + BOOL fInvadeProcess +); + +BOOL WINAPI SymCleanup( + HANDLE hProcess +); + +BOOL CALLBACK __cdecl mycb( + PSYMBOL_INFO pSymInfo, + ULONG SymbolSize, + PVOID UserContext + ){ + SymEnumeratorCallback cb = (SymEnumeratorCallback)UserContext; + return !cb( "", &pSymInfo->Name[0], (void*)pSymInfo->Address, (long) pSymInfo->Size ); + } + +int EnumerateSymbols( SymEnumeratorCallback cb ) +{ + HANDLE proc = GetCurrentProcess(); + if( !SymInitialize( proc, 0, 1 ) ) return -1; + if( !SymEnumSymbols( proc, 0, "*!*", &mycb, (void*)cb ) ) + { + SymCleanup(proc); + return -2; + } + SymCleanup(proc); + return 0; +} + +#else + + +#include +#include +#include +#include +#include + +#ifndef __GNUC__ +#define __int128_t long long long +#endif + +#include +#include + +#define UINTS_PER_WORD (__WORDSIZE / (CHAR_BIT * sizeof (unsigned int))) + + + struct dl_phdr_info { + ElfW(Addr) dlpi_addr; /* Base address of object */ + const char *dlpi_name; /* (Null-terminated) name of + object */ + const ElfW(Phdr) *dlpi_phdr; /* Pointer to array of + ELF program headers + for this object */ + ElfW(Half) dlpi_phnum; /* # of items in dlpi_phdr */ + }; + + + +void dl_iterate_phdr( void*, void*); + + +static ElfW(Word) gnu_hashtab_symbol_count(const unsigned int *const table) +{ + const unsigned int *const bucket = table + 4 + table[2] * (unsigned int)(UINTS_PER_WORD); + unsigned int b = table[0]; + unsigned int max = 0U; + + while (b-->0U) + if (bucket[b] > max) + max = bucket[b]; + + return (ElfW(Word))max; +} + +static static void *dynamic_pointer(const ElfW(Addr) addr, + const ElfW(Addr) base, const ElfW(Phdr) *const header, const ElfW(Half) headers) +{ + if (addr) { + ElfW(Half) h; + + for (h = 0; h < headers; h++) + if (header[h].p_type == PT_LOAD) + if (addr >= base + header[h].p_vaddr && + addr < base + header[h].p_vaddr + header[h].p_memsz) + return (void *)addr; + } + + return NULL; +} + +//Mostly based off of http://stackoverflow.com/questions/29903049/get-names-and-addresses-of-exported-functions-from-in-linux +static int callback(struct dl_phdr_info *info, + size_t size, void *data) +{ + SymEnumeratorCallback cb = (SymEnumeratorCallback)data; + const ElfW(Addr) base = info->dlpi_addr; + const ElfW(Phdr) *const header = info->dlpi_phdr; + const ElfW(Half) headers = info->dlpi_phnum; + const char *libpath, *libname; + ElfW(Half) h; + + if (info->dlpi_name && info->dlpi_name[0]) + libpath = info->dlpi_name; + else + libpath = ""; + + libname = strrchr(libpath, '/'); + + if (libname && libname[0] == '/' && libname[1]) + libname++; + else + libname = libpath; + + for (h = 0; h < headers; h++) + { + if (header[h].p_type == PT_DYNAMIC) + { + const ElfW(Dyn) *entry = (const ElfW(Dyn) *)(base + header[h].p_vaddr); + const ElfW(Word) *hashtab; + const ElfW(Sym) *symtab = NULL; + const char *strtab = NULL; + ElfW(Word) symbol_count = 0; + + for (; entry->d_tag != DT_NULL; entry++) + { + switch (entry->d_tag) + { + case DT_HASH: + hashtab = dynamic_pointer(entry->d_un.d_ptr, base, header, headers); + if (hashtab) + symbol_count = hashtab[1]; + break; + case DT_GNU_HASH: + hashtab = dynamic_pointer(entry->d_un.d_ptr, base, header, headers); + if (hashtab) + { + ElfW(Word) count = gnu_hashtab_symbol_count(hashtab); + if (count > symbol_count) + symbol_count = count; + } + break; + case DT_STRTAB: + strtab = dynamic_pointer(entry->d_un.d_ptr, base, header, headers); + break; + case DT_SYMTAB: + symtab = dynamic_pointer(entry->d_un.d_ptr, base, header, headers); + break; + } + } + + if (symtab && strtab && symbol_count > 0) { + ElfW(Word) s; + + for (s = 0; s < symbol_count; s++) { + const char *name; + void *const ptr = dynamic_pointer(base + symtab[s].st_value, base, header, headers); + int result; + + if (!ptr) + continue; + + if (symtab[s].st_name) + name = strtab + symtab[s].st_name; + else + name = ""; + + result = cb( libpath, name, ptr, symtab[s].st_size ); + if( result ) return result; //Bail early. + } + } + } + } + return 0; +} + + + + + +int EnumerateSymbols( SymEnumeratorCallback cb ) +{ + dl_iterate_phdr( callback, cb ); +} + + + + +#endif diff --git a/colorchord2/windows/symbol_enumerator.h b/colorchord2/windows/symbol_enumerator.h new file mode 100644 index 0000000..87e033b --- /dev/null +++ b/colorchord2/windows/symbol_enumerator.h @@ -0,0 +1,12 @@ +#ifndef _SYMBOL_ENUMERATOR_H +#define _SYMBOL_ENUMERATOR_H + +//Enumerates all symbols in the currently loaded excutable. +//Don't forget to compile with -rdynamic! + +//Return 0 to continue search. 1 to stop. +typedef int (*SymEnumeratorCallback)( const char * path, const char * name, void * location, long size ); + +int EnumerateSymbols( SymEnumeratorCallback cb ); + +#endif diff --git a/colorchord2/windows/tcc_stubs.c b/colorchord2/windows/tcc_stubs.c new file mode 100644 index 0000000..c6dfc76 --- /dev/null +++ b/colorchord2/windows/tcc_stubs.c @@ -0,0 +1,80 @@ + +#include <_mingw.h> + +#define REMATH(x) double __cdecl x( double f ); float x##f(float v) { return x(v); } + +int SymnumCheck( const char * path, const char * name, void * location, long size ) +{ + if( strncmp( name, "REGISTER", 8 ) == 0 ) + { + typedef void (*sf)(); + sf fn = (sf)location; + fn(); + } + return 0; +} + + + +void ManuallyRegisterDevices() +{ + EnumerateSymbols( SymnumCheck ); +} + +REMATH( acos ); +REMATH( cos ); +REMATH( sin ); +REMATH( sqrt ); +REMATH( asin ); +REMATH( exp ); +REMATH( fmod ); +REMATH( pow ); + +double __cdecl strtod (const char* str, char** endptr); +float strtof( const char* str, char** endptr) +{ + return strtod( str, endptr ); +} + +double __cdecl atan2(double a, double b); +float atan2f(float a, float b) +{ + return atan2( a, b ); +} + +//From http://stackoverflow.com/questions/40159892/using-asprintf-on-windows +int __cdecl vsprintf_s( + char *buffer, + size_t numberOfElements, + const char *format, + va_list argptr +); + +int asprintf(char **strp, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = vasprintf(strp, fmt, ap); + va_end(ap); + return r; +} + +int vasprintf(char **strp, const char *fmt, va_list ap) { + // _vscprintf tells you how big the buffer needs to be + int len = _vscprintf(fmt, ap); + if (len == -1) { + return -1; + } + size_t size = (size_t)len + 1; + char *str = (char*)malloc(size); + if (!str) { + return -1; + } + // _vsprintf_s is the "secure" version of vsprintf + int r = vsprintf_s(str, len + 1, fmt, ap); + if (r == -1) { + free(str); + return -1; + } + *strp = str; + return r; +} \ No newline at end of file diff --git a/colorchord2/windows/winsock2.h b/colorchord2/windows/winsock2.h new file mode 100644 index 0000000..d318eb6 --- /dev/null +++ b/colorchord2/windows/winsock2.h @@ -0,0 +1,1303 @@ +/* + + Definitions for winsock 2 + + Contributed by the WINE project. + + Portions Copyright (c) 1980, 1983, 1988, 1993 + The Regents of the University of California. All rights reserved. + + Portions Copyright (c) 1993 by Digital Equipment Corporation. + */ + +#if !(defined _WINSOCK2_H || defined _WINSOCK_H) +#define _WINSOCK2_H +#define _WINSOCK_H /* to prevent later inclusion of winsock.h */ +#if __GNUC__ >= 3 +#pragma GCC system_header +#endif + +#define _GNU_H_WINDOWS32_SOCKETS + +#include + +#ifndef WINSOCK_API_LINKAGE +#ifdef __W32API_USE_DLLIMPORT__ +#define WINSOCK_API_LINKAGE DECLSPEC_IMPORT +#else +#define WINSOCK_API_LINKAGE +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif +/* Names common to Winsock1.1 and Winsock2 */ +#if !defined ( _BSDTYPES_DEFINED ) +/* also defined in gmon.h and in cygwin's sys/types */ +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +#define _BSDTYPES_DEFINED +#endif /* ! def _BSDTYPES_DEFINED */ +typedef u_int SOCKET; +#ifndef FD_SETSIZE +#define FD_SETSIZE 64 +#endif + +/* shutdown() how types */ +#define SD_RECEIVE 0x00 +#define SD_SEND 0x01 +#define SD_BOTH 0x02 + +#ifndef _SYS_TYPES_FD_SET +/* fd_set may be defined by the newlib + * if __USE_W32_SOCKETS not defined. + */ +#ifdef fd_set +#undef fd_set +#endif +typedef struct fd_set { + u_int fd_count; + SOCKET fd_array[FD_SETSIZE]; +} fd_set; +int PASCAL __WSAFDIsSet(SOCKET,fd_set*); +#ifndef FD_CLR +#define FD_CLR(fd,set) do { u_int __i;\ +for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) {\ + if (((fd_set *)(set))->fd_array[__i] == (fd)) {\ + while (__i < ((fd_set *)(set))->fd_count-1) {\ + ((fd_set*)(set))->fd_array[__i] = ((fd_set*)(set))->fd_array[__i+1];\ + __i++;\ + }\ + ((fd_set*)(set))->fd_count--;\ + break;\ + }\ +}\ +} while (0) +#endif +#ifndef FD_SET +/* this differs from the define in winsock.h and in cygwin sys/types.h */ +#define FD_SET(fd, set) do { u_int __i;\ +for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) {\ + if (((fd_set *)(set))->fd_array[__i] == (fd)) {\ + break;\ + }\ +}\ +if (__i == ((fd_set *)(set))->fd_count) {\ + if (((fd_set *)(set))->fd_count < FD_SETSIZE) {\ + ((fd_set *)(set))->fd_array[__i] = (fd);\ + ((fd_set *)(set))->fd_count++;\ + }\ +}\ +} while(0) +#endif +#ifndef FD_ZERO +#define FD_ZERO(set) (((fd_set *)(set))->fd_count=0) +#endif +#ifndef FD_ISSET +#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set *)(set)) +#endif +#elif !defined (USE_SYS_TYPES_FD_SET) +#warning "fd_set and associated macros have been defined in sys/types. \ + This may cause runtime problems with W32 sockets" +#endif /* ndef _SYS_TYPES_FD_SET */ +#if !(defined (__INSIDE_CYGWIN__) || (__INSIDE_MSYS__)) +#ifndef _TIMEVAL_DEFINED /* also in sys/time.h */ +#define _TIMEVAL_DEFINED +struct timeval { + long tv_sec; + long tv_usec; +}; +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec != (uvp)->tv_sec) ? \ + ((tvp)->tv_sec cmp (uvp)->tv_sec) : \ + ((tvp)->tv_usec cmp (uvp)->tv_usec)) +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#endif /* _TIMEVAL_DEFINED */ +struct hostent { + char *h_name; + char **h_aliases; + short h_addrtype; + short h_length; + char **h_addr_list; +#define h_addr h_addr_list[0] +}; +struct linger { + u_short l_onoff; + u_short l_linger; +}; +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ +#define IOCPARM_MASK 0x7f +#define IOC_VOID 0x20000000 +#define IOC_OUT 0x40000000 +#define IOC_IN 0x80000000 +#define IOC_INOUT (IOC_IN|IOC_OUT) + +#if ! (defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__)) +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#define FIONBIO _IOW('f', 126, u_long) +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ + +#define FIONREAD _IOR('f', 127, u_long) +#define FIOASYNC _IOW('f', 125, u_long) +#define SIOCSHIWAT _IOW('s', 0, u_long) +#define SIOCGHIWAT _IOR('s', 1, u_long) +#define SIOCSLOWAT _IOW('s', 2, u_long) +#define SIOCGLOWAT _IOR('s', 3, u_long) +#define SIOCATMARK _IOR('s', 7, u_long) + +#if ! (defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__)) +struct netent { + char * n_name; + char **n_aliases; + short n_addrtype; + u_long n_net; +}; +struct servent { + char *s_name; + char **s_aliases; + short s_port; + char *s_proto; +}; +struct protoent { + char *p_name; + char **p_aliases; + short p_proto; +}; +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_IGMP 2 +#define IPPROTO_GGP 3 +#define IPPROTO_TCP 6 +#define IPPROTO_PUP 12 +#define IPPROTO_UDP 17 +#define IPPROTO_IDP 22 +#define IPPROTO_ND 77 +#define IPPROTO_RAW 255 +#define IPPROTO_MAX 256 +/* IPv6 options */ +#define IPPROTO_HOPOPTS 0 /* IPv6 Hop-by-Hop options */ +#define IPPROTO_IPV6 41 /* IPv6 header */ +#define IPPROTO_ROUTING 43 /* IPv6 Routing header */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IPPROTO_ESP 50 /* encapsulating security payload */ +#define IPPROTO_AH 51 /* authentication header */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header */ +#define IPPROTO_DSTOPTS 60 /* IPv6 Destination options */ +#define IPPORT_ECHO 7 +#define IPPORT_DISCARD 9 +#define IPPORT_SYSTAT 11 +#define IPPORT_DAYTIME 13 +#define IPPORT_NETSTAT 15 +#define IPPORT_FTP 21 +#define IPPORT_TELNET 23 +#define IPPORT_SMTP 25 +#define IPPORT_TIMESERVER 37 +#define IPPORT_NAMESERVER 42 +#define IPPORT_WHOIS 43 +#define IPPORT_MTP 57 +#define IPPORT_TFTP 69 +#define IPPORT_RJE 77 +#define IPPORT_FINGER 79 +#define IPPORT_TTYLINK 87 +#define IPPORT_SUPDUP 95 +#define IPPORT_EXECSERVER 512 +#define IPPORT_LOGINSERVER 513 +#define IPPORT_CMDSERVER 514 +#define IPPORT_EFSSERVER 520 +#define IPPORT_BIFFUDP 512 +#define IPPORT_WHOSERVER 513 +#define IPPORT_ROUTESERVER 520 +#define IPPORT_RESERVED 1024 +#define IMPLINK_IP 155 +#define IMPLINK_LOWEXPER 156 +#define IMPLINK_HIGHEXPER 158 +struct in_addr { + union { + struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; + struct { u_short s_w1,s_w2; } S_un_w; + u_long S_addr; + } S_un; +#define s_addr S_un.S_addr +#define s_host S_un.S_un_b.s_b2 +#define s_net S_un.S_un_b.s_b1 +#define s_imp S_un.S_un_w.s_w2 +#define s_impno S_un.S_un_b.s_b4 +#define s_lh S_un.S_un_b.s_b3 +}; +#define IN_CLASSA(i) (((long)(i)&0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_MAX 128 +#define IN_CLASSB(i) (((long)(i)&0xc0000000)==0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_MAX 65536 +#define IN_CLASSC(i) (((long)(i)&0xe0000000)==0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST 0xff +#define INADDR_ANY (u_long)0 +#define INADDR_LOOPBACK 0x7f000001 +#define INADDR_BROADCAST (u_long)0xffffffff +#define INADDR_NONE 0xffffffff +struct sockaddr_in { + short sin_family; + u_short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; +#define WSADESCRIPTION_LEN 256 +#define WSASYS_STATUS_LEN 128 +typedef struct WSAData { + WORD wVersion; + WORD wHighVersion; + char szDescription[WSADESCRIPTION_LEN+1]; + char szSystemStatus[WSASYS_STATUS_LEN+1]; + unsigned short iMaxSockets; + unsigned short iMaxUdpDg; + char * lpVendorInfo; +} WSADATA; +typedef WSADATA *LPWSADATA; + +#if ! (defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__)) +#define IP_OPTIONS 1 +#define SO_DEBUG 1 +#define SO_ACCEPTCONN 2 +#define SO_REUSEADDR 4 +#define SO_KEEPALIVE 8 +#define SO_DONTROUTE 16 +#define SO_BROADCAST 32 +#define SO_USELOOPBACK 64 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_DONTLINGER (u_int)(~SO_LINGER) +#define SO_EXCLUSIVEADDRUSE ((u_int)(~SO_REUSEADDR)) +#define SO_SNDBUF 0x1001 +#define SO_RCVBUF 0x1002 +#define SO_SNDLOWAT 0x1003 +#define SO_RCVLOWAT 0x1004 +#define SO_SNDTIMEO 0x1005 +#define SO_RCVTIMEO 0x1006 +#define SO_ERROR 0x1007 +#define SO_TYPE 0x1008 +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ + +#define INVALID_SOCKET (SOCKET)(~0) +#define SOCKET_ERROR (-1) +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 +#define SOCK_RDM 4 +#define SOCK_SEQPACKET 5 +#define TCP_NODELAY 0x0001 +#define AF_UNSPEC 0 +#define AF_UNIX 1 +#define AF_INET 2 +#define AF_IMPLINK 3 +#define AF_PUP 4 +#define AF_CHAOS 5 +#define AF_IPX 6 +#define AF_NS 6 +#define AF_ISO 7 +#define AF_OSI AF_ISO +#define AF_ECMA 8 +#define AF_DATAKIT 9 +#define AF_CCITT 10 +#define AF_SNA 11 +#define AF_DECnet 12 +#define AF_DLI 13 +#define AF_LAT 14 +#define AF_HYLINK 15 +#define AF_APPLETALK 16 +#define AF_NETBIOS 17 +#define AF_VOICEVIEW 18 +#define AF_FIREFOX 19 +#define AF_UNKNOWN1 20 +#define AF_BAN 21 +#define AF_ATM 22 +#define AF_INET6 23 +#define AF_CLUSTER 24 +#define AF_12844 25 +#define AF_IRDA 26 +#define AF_NETDES 28 +#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__)) +#define AF_MAX 29 +struct sockaddr { + u_short sa_family; + char sa_data[14]; +}; + +/* Portable IPv6/IPv4 version of sockaddr. Based on RFC 2553. + Pad to force 8 byte alignment and maximum size of 128 bytes. */ + +/* + * Desired design of maximum size and alignment + */ +#define _SS_MAXSIZE 128 +#define _SS_ALIGNSIZE (sizeof (__int64)) +/* + * Definitions used for sockaddr_storage structure paddings design. + */ +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short)) +#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) \ + + _SS_PAD1SIZE \ + + _SS_ALIGNSIZE)) +struct sockaddr_storage { + short ss_family; + char __ss_pad1[_SS_PAD1SIZE]; /* pad to 8 */ + __int64 __ss_align; /* force alignment */ + char __ss_pad2[_SS_PAD2SIZE]; /* pad to 128 */ +}; +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ + +struct sockproto { + u_short sp_family; + u_short sp_protocol; +}; +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_INET AF_INET +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_IPX AF_IPX +#define PF_ISO AF_ISO +#define PF_OSI AF_OSI +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK +#define PF_VOICEVIEW AF_VOICEVIEW +#define PF_FIREFOX AF_FIREFOX +#define PF_UNKNOWN1 AF_UNKNOWN1 +#define PF_BAN AF_BAN +#define PF_ATM AF_ATM +#define PF_INET6 AF_INET6 +#define PF_MAX AF_MAX +#define SOL_SOCKET 0xffff +#if ! (defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__)) +#define SOMAXCONN 0x7fffffff /* (5) in WinSock1.1 */ +#define MSG_OOB 1 +#define MSG_PEEK 2 +#define MSG_DONTROUTE 4 +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ +#define MSG_MAXIOVLEN 16 +#define MSG_PARTIAL 0x8000 +#define MAXGETHOSTSTRUCT 1024 + +#define FD_READ_BIT 0 +#define FD_READ (1 << FD_READ_BIT) +#define FD_WRITE_BIT 1 +#define FD_WRITE (1 << FD_WRITE_BIT) +#define FD_OOB_BIT 2 +#define FD_OOB (1 << FD_OOB_BIT) +#define FD_ACCEPT_BIT 3 +#define FD_ACCEPT (1 << FD_ACCEPT_BIT) +#define FD_CONNECT_BIT 4 +#define FD_CONNECT (1 << FD_CONNECT_BIT) +#define FD_CLOSE_BIT 5 +#define FD_CLOSE (1 << FD_CLOSE_BIT) +/* winsock1.1 defines stop at FD_CLOSE (32) */ +#define FD_QOS_BIT 6 +#define FD_QOS (1 << FD_QOS_BIT) +#define FD_GROUP_QOS_BIT 7 +#define FD_GROUP_QOS (1 << FD_GROUP_QOS_BIT) +#define FD_ROUTING_INTERFACE_CHANGE_BIT 8 +#define FD_ROUTING_INTERFACE_CHANGE (1 << FD_ROUTING_INTERFACE_CHANGE_BIT) +#define FD_ADDRESS_LIST_CHANGE_BIT 9 +#define FD_ADDRESS_LIST_CHANGE (1 << FD_ADDRESS_LIST_CHANGE_BIT) +#define FD_MAX_EVENTS 10 +#define FD_ALL_EVENTS ((1 << FD_MAX_EVENTS) - 1) + +#ifndef WSABASEERR +#define WSABASEERR 10000 +#define WSAEINTR (WSABASEERR+4) +#define WSAEBADF (WSABASEERR+9) +#define WSAEACCES (WSABASEERR+13) +#define WSAEFAULT (WSABASEERR+14) +#define WSAEINVAL (WSABASEERR+22) +#define WSAEMFILE (WSABASEERR+24) +#define WSAEWOULDBLOCK (WSABASEERR+35) +#define WSAEINPROGRESS (WSABASEERR+36) /* deprecated on WinSock2 */ +#define WSAEALREADY (WSABASEERR+37) +#define WSAENOTSOCK (WSABASEERR+38) +#define WSAEDESTADDRREQ (WSABASEERR+39) +#define WSAEMSGSIZE (WSABASEERR+40) +#define WSAEPROTOTYPE (WSABASEERR+41) +#define WSAENOPROTOOPT (WSABASEERR+42) +#define WSAEPROTONOSUPPORT (WSABASEERR+43) +#define WSAESOCKTNOSUPPORT (WSABASEERR+44) +#define WSAEOPNOTSUPP (WSABASEERR+45) +#define WSAEPFNOSUPPORT (WSABASEERR+46) +#define WSAEAFNOSUPPORT (WSABASEERR+47) +#define WSAEADDRINUSE (WSABASEERR+48) +#define WSAEADDRNOTAVAIL (WSABASEERR+49) +#define WSAENETDOWN (WSABASEERR+50) +#define WSAENETUNREACH (WSABASEERR+51) +#define WSAENETRESET (WSABASEERR+52) +#define WSAECONNABORTED (WSABASEERR+53) +#define WSAECONNRESET (WSABASEERR+54) +#define WSAENOBUFS (WSABASEERR+55) +#define WSAEISCONN (WSABASEERR+56) +#define WSAENOTCONN (WSABASEERR+57) +#define WSAESHUTDOWN (WSABASEERR+58) +#define WSAETOOMANYREFS (WSABASEERR+59) +#define WSAETIMEDOUT (WSABASEERR+60) +#define WSAECONNREFUSED (WSABASEERR+61) +#define WSAELOOP (WSABASEERR+62) +#define WSAENAMETOOLONG (WSABASEERR+63) +#define WSAEHOSTDOWN (WSABASEERR+64) +#define WSAEHOSTUNREACH (WSABASEERR+65) +#define WSAENOTEMPTY (WSABASEERR+66) +#define WSAEPROCLIM (WSABASEERR+67) +#define WSAEUSERS (WSABASEERR+68) +#define WSAEDQUOT (WSABASEERR+69) +#define WSAESTALE (WSABASEERR+70) +#define WSAEREMOTE (WSABASEERR+71) +#define WSAEDISCON (WSABASEERR+101) +#define WSASYSNOTREADY (WSABASEERR+91) +#define WSAVERNOTSUPPORTED (WSABASEERR+92) +#define WSANOTINITIALISED (WSABASEERR+93) +#define WSAHOST_NOT_FOUND (WSABASEERR+1001) +#define WSATRY_AGAIN (WSABASEERR+1002) +#define WSANO_RECOVERY (WSABASEERR+1003) +#define WSANO_DATA (WSABASEERR+1004) + +/* WinSock2 specific error codes */ +#define WSAENOMORE (WSABASEERR+102) +#define WSAECANCELLED (WSABASEERR+103) +#define WSAEINVALIDPROCTABLE (WSABASEERR+104) +#define WSAEINVALIDPROVIDER (WSABASEERR+105) +#define WSAEPROVIDERFAILEDINIT (WSABASEERR+106) +#define WSASYSCALLFAILURE (WSABASEERR+107) +#define WSASERVICE_NOT_FOUND (WSABASEERR+108) +#define WSATYPE_NOT_FOUND (WSABASEERR+109) +#define WSA_E_NO_MORE (WSABASEERR+110) +#define WSA_E_CANCELLED (WSABASEERR+111) +#define WSAEREFUSED (WSABASEERR+112) + +/* WS QualityofService errors */ +#define WSA_QOS_RECEIVERS (WSABASEERR + 1005) +#define WSA_QOS_SENDERS (WSABASEERR + 1006) +#define WSA_QOS_NO_SENDERS (WSABASEERR + 1007) +#define WSA_QOS_NO_RECEIVERS (WSABASEERR + 1008) +#define WSA_QOS_REQUEST_CONFIRMED (WSABASEERR + 1009) +#define WSA_QOS_ADMISSION_FAILURE (WSABASEERR + 1010) +#define WSA_QOS_POLICY_FAILURE (WSABASEERR + 1011) +#define WSA_QOS_BAD_STYLE (WSABASEERR + 1012) +#define WSA_QOS_BAD_OBJECT (WSABASEERR + 1013) +#define WSA_QOS_TRAFFIC_CTRL_ERROR (WSABASEERR + 1014) +#define WSA_QOS_GENERIC_ERROR (WSABASEERR + 1015) +#define WSA_QOS_ESERVICETYPE (WSABASEERR + 1016) +#define WSA_QOS_EFLOWSPEC (WSABASEERR + 1017) +#define WSA_QOS_EPROVSPECBUF (WSABASEERR + 1018) +#define WSA_QOS_EFILTERSTYLE (WSABASEERR + 1019) +#define WSA_QOS_EFILTERTYPE (WSABASEERR + 1020) +#define WSA_QOS_EFILTERCOUNT (WSABASEERR + 1021) +#define WSA_QOS_EOBJLENGTH (WSABASEERR + 1022) +#define WSA_QOS_EFLOWCOUNT (WSABASEERR + 1023) +#define WSA_QOS_EUNKOWNPSOBJ (WSABASEERR + 1024) +#define WSA_QOS_EPOLICYOBJ (WSABASEERR + 1025) +#define WSA_QOS_EFLOWDESC (WSABASEERR + 1026) +#define WSA_QOS_EPSFLOWSPEC (WSABASEERR + 1027) +#define WSA_QOS_EPSFILTERSPEC (WSABASEERR + 1028) +#define WSA_QOS_ESDMODEOBJ (WSABASEERR + 1029) +#define WSA_QOS_ESHAPERATEOBJ (WSABASEERR + 1030) +#define WSA_QOS_RESERVED_PETYPE (WSABASEERR + 1031) + +#endif /* !WSABASEERR */ + +#define WSANO_ADDRESS WSANO_DATA +#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__)) +#define h_errno WSAGetLastError() +#define HOST_NOT_FOUND WSAHOST_NOT_FOUND +#define TRY_AGAIN WSATRY_AGAIN +#define NO_RECOVERY WSANO_RECOVERY +#define NO_DATA WSANO_DATA +#define NO_ADDRESS WSANO_ADDRESS +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ +WINSOCK_API_LINKAGE SOCKET PASCAL accept(SOCKET,struct sockaddr*,int*); +WINSOCK_API_LINKAGE int PASCAL bind(SOCKET,const struct sockaddr*,int); +WINSOCK_API_LINKAGE int PASCAL closesocket(SOCKET); +WINSOCK_API_LINKAGE int PASCAL connect(SOCKET,const struct sockaddr*,int); +WINSOCK_API_LINKAGE int PASCAL ioctlsocket(SOCKET,long,u_long *); +WINSOCK_API_LINKAGE int PASCAL getpeername(SOCKET,struct sockaddr*,int*); +WINSOCK_API_LINKAGE int PASCAL getsockname(SOCKET,struct sockaddr*,int*); +WINSOCK_API_LINKAGE int PASCAL getsockopt(SOCKET,int,int,char*,int*); +WINSOCK_API_LINKAGE unsigned long PASCAL inet_addr(const char*); +WINSOCK_API_LINKAGE DECLARE_STDCALL_P(char *) inet_ntoa(struct in_addr); +WINSOCK_API_LINKAGE int PASCAL listen(SOCKET,int); +WINSOCK_API_LINKAGE int PASCAL recv(SOCKET,char*,int,int); +WINSOCK_API_LINKAGE int PASCAL recvfrom(SOCKET,char*,int,int,struct sockaddr*,int*); +WINSOCK_API_LINKAGE int PASCAL send(SOCKET,const char*,int,int); +WINSOCK_API_LINKAGE int PASCAL sendto(SOCKET,const char*,int,int,const struct sockaddr*,int); +WINSOCK_API_LINKAGE int PASCAL setsockopt(SOCKET,int,int,const char*,int); +WINSOCK_API_LINKAGE int PASCAL shutdown(SOCKET,int); +WINSOCK_API_LINKAGE SOCKET PASCAL socket(int,int,int); +WINSOCK_API_LINKAGE DECLARE_STDCALL_P(struct hostent *) gethostbyaddr(const char*,int,int); +WINSOCK_API_LINKAGE DECLARE_STDCALL_P(struct hostent *) gethostbyname(const char*); +WINSOCK_API_LINKAGE DECLARE_STDCALL_P(struct servent *) getservbyport(int,const char*); +WINSOCK_API_LINKAGE DECLARE_STDCALL_P(struct servent *) getservbyname(const char*,const char*); +WINSOCK_API_LINKAGE DECLARE_STDCALL_P(struct protoent *) getprotobynumber(int); +WINSOCK_API_LINKAGE DECLARE_STDCALL_P(struct protoent *) getprotobyname(const char*); +typedef SOCKET (PASCAL * LPFN_ACCEPT)(SOCKET, struct sockaddr*,int *); +typedef int (PASCAL * LPFN_BIND)(SOCKET, const struct sockaddr*,int); +typedef int (PASCAL * LPFN_CLOSESOCKET)(SOCKET); +typedef int (PASCAL * LPFN_CONNECT)(SOCKET, const struct sockaddr*,int); +typedef int (PASCAL * LPFN_IOCTLSOCKET)(SOCKET, long, u_long*); +typedef int (PASCAL * LPFN_GETPEERNAME)(SOCKET, struct sockaddr*, int*); +typedef int(PASCAL * LPFN_GETSOCKNAME)(SOCKET, struct sockaddr*, int*); +typedef int(PASCAL * LPFN_GETSOCKOPT)(SOCKET, int, int, char*, int*); +typedef u_long(PASCAL * LPFN_HTONL)(u_long); +typedef u_short(PASCAL * LPFN_HTONS)(u_short); +typedef unsigned long(PASCAL * LPFN_INET_ADDR)(const char*); +typedef char*(PASCAL * LPFN_INET_NTOA)(struct in_addr); +typedef int(PASCAL * LPFN_LISTEN)(SOCKET, int); +typedef u_long(PASCAL * LPFN_NTOHL)(u_long); +typedef u_short(PASCAL * LPFN_NTOHS)(u_short); +typedef int(PASCAL * LPFN_RECV)(SOCKET, char*, int, int); +typedef int(PASCAL * LPFN_RECVFROM)(SOCKET, char*, int, int, struct sockaddr*, int*); +typedef int(PASCAL * LPFN_SELECT)(int, fd_set*, fd_set*, fd_set*, const struct timeval*); +typedef int(PASCAL * LPFN_SEND)(SOCKET, const char*, int, int); +typedef int(PASCAL * LPFN_SENDTO)(SOCKET, const char*, int, int, const struct sockaddr*, int); +typedef int(PASCAL * LPFN_SETSOCKOPT)(SOCKET, int, int, const char*, int); +typedef int(PASCAL * LPFN_SHUTDOWN)(SOCKET, int); +typedef SOCKET(PASCAL * LPFN_SOCKET)(int, int, int); +typedef struct hostent*(PASCAL * LPFN_GETHOSTBYADDR)( const char*, int, int); +typedef struct hostent*(PASCAL * LPFN_GETHOSTBYNAME)( const char*); +typedef int(PASCAL * LPFN_GETHOSTNAME)(char*, int); +typedef struct servent*(PASCAL * LPFN_GETSERVBYPORT)(int, const char*); +typedef struct servent*(PASCAL * LPFN_GETSERVBYNAME)(const char*, const char*); +typedef struct protoent*(PASCAL * LPFN_GETPROTOBYNUMBER)(int); +typedef struct protoent*(PASCAL * LPFN_GETPROTOBYNAME)(const char*); + +WINSOCK_API_LINKAGE int PASCAL WSAStartup(WORD,LPWSADATA); +WINSOCK_API_LINKAGE int PASCAL WSACleanup(void); +WINSOCK_API_LINKAGE void PASCAL WSASetLastError(int); +WINSOCK_API_LINKAGE int PASCAL WSAGetLastError(void); +WINSOCK_API_LINKAGE typedef int(PASCAL * LPFN_WSASTARTUP)(WORD, LPWSADATA); +typedef int(PASCAL * LPFN_WSACLEANUP)(void); +typedef void(PASCAL * LPFN_WSASETLASTERROR)(int); +typedef int(PASCAL * LPFN_WSAGETLASTERROR)(void); +/* + * Pseudo-blocking functions are deprecated in WinSock2 + * spec. Use threads instead. + */ +WINSOCK_API_LINKAGE BOOL PASCAL WSAIsBlocking(void); +WINSOCK_API_LINKAGE int PASCAL WSAUnhookBlockingHook(void); +WINSOCK_API_LINKAGE FARPROC PASCAL WSASetBlockingHook(FARPROC); +WINSOCK_API_LINKAGE int PASCAL WSACancelBlockingCall(void); +typedef BOOL(PASCAL * LPFN_WSAISBLOCKING)(void); +typedef int(PASCAL * LPFN_WSAUNHOOKBLOCKINGHOOK)(void); +typedef FARPROC (PASCAL * LPFN_WSASETBLOCKINGHOOK)(FARPROC); +typedef int(PASCAL * LPFN_WSACANCELBLOCKINGCALL)(void); + +WINSOCK_API_LINKAGE HANDLE PASCAL WSAAsyncGetServByName(HWND,u_int,const char*,const char*,char*,int); +WINSOCK_API_LINKAGE HANDLE PASCAL WSAAsyncGetServByPort(HWND,u_int,int,const char*,char*,int); +WINSOCK_API_LINKAGE HANDLE PASCAL WSAAsyncGetProtoByName(HWND,u_int,const char*,char*,int); +WINSOCK_API_LINKAGE HANDLE PASCAL WSAAsyncGetProtoByNumber(HWND,u_int,int,char*,int); +WINSOCK_API_LINKAGE HANDLE PASCAL WSAAsyncGetHostByName(HWND,u_int,const char*,char*,int); +WINSOCK_API_LINKAGE HANDLE PASCAL WSAAsyncGetHostByAddr(HWND,u_int,const char*,int,int,char*,int); +WINSOCK_API_LINKAGE int PASCAL WSACancelAsyncRequest(HANDLE); +WINSOCK_API_LINKAGE int PASCAL WSAAsyncSelect(SOCKET,HWND,u_int,long); +typedef HANDLE(PASCAL * LPFN_WSAASYNCGETSERVBYNAME)(HWND, u_int, const char *, const char *, char *, int); +typedef HANDLE(PASCAL * LPFN_WSAASYNCGETSERVBYPORT)(HWND, u_int, int, const char *, char *, int); +typedef HANDLE(PASCAL * LPFN_WSAASYNCGETPROTOBYNAME)(HWND, u_int, const char*, char*, int); +typedef HANDLE(PASCAL * LPFN_WSAASYNCGETPROTOBYNUMBER)(HWND, u_int, int, char*, int); +typedef HANDLE(PASCAL * LPFN_WSAASYNCGETHOSTBYADDR)(HWND, u_int, const char*, int, int, char*, int); +typedef int(PASCAL * LPFN_WSACANCELASYNCREQUEST)(HANDLE); +typedef int(PASCAL * LPFN_WSAASYNCSELECT)(SOCKET, HWND, u_int, long); +#if ! (defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__)) +WINSOCK_API_LINKAGE u_long PASCAL htonl(u_long); +WINSOCK_API_LINKAGE u_long PASCAL ntohl(u_long); +WINSOCK_API_LINKAGE u_short PASCAL htons(u_short); +WINSOCK_API_LINKAGE u_short PASCAL ntohs(u_short); +WINSOCK_API_LINKAGE int PASCAL select(int nfds,fd_set*,fd_set*,fd_set*,const struct timeval*); +#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */ + +int PASCAL gethostname(char*,int); + +#define WSAMAKEASYNCREPLY(b,e) MAKELONG(b,e) +#define WSAMAKESELECTREPLY(e,error) MAKELONG(e,error) +#define WSAGETASYNCBUFLEN(l) LOWORD(l) +#define WSAGETASYNCERROR(l) HIWORD(l) +#define WSAGETSELECTEVENT(l) LOWORD(l) +#define WSAGETSELECTERROR(l) HIWORD(l) + +typedef struct sockaddr SOCKADDR; +typedef struct sockaddr *PSOCKADDR; +typedef struct sockaddr *LPSOCKADDR; +typedef struct sockaddr_storage SOCKADDR_STORAGE, *PSOCKADDR_STORAGE; +typedef struct sockaddr_in SOCKADDR_IN; +typedef struct sockaddr_in *PSOCKADDR_IN; +typedef struct sockaddr_in *LPSOCKADDR_IN; +typedef struct linger LINGER; +typedef struct linger *PLINGER; +typedef struct linger *LPLINGER; +typedef struct in_addr IN_ADDR; +typedef struct in_addr *PIN_ADDR; +typedef struct in_addr *LPIN_ADDR; +typedef struct fd_set FD_SET; +typedef struct fd_set *PFD_SET; +typedef struct fd_set *LPFD_SET; +typedef struct hostent HOSTENT; +typedef struct hostent *PHOSTENT; +typedef struct hostent *LPHOSTENT; +typedef struct servent SERVENT; +typedef struct servent *PSERVENT; +typedef struct servent *LPSERVENT; +typedef struct protoent PROTOENT; +typedef struct protoent *PPROTOENT; +typedef struct protoent *LPPROTOENT; +typedef struct timeval TIMEVAL; +typedef struct timeval *PTIMEVAL; +typedef struct timeval *LPTIMEVAL; + +/* winsock2 additions */ +#define ADDR_ANY INADDR_ANY + +#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_CLASSD_NET 0xf0000000 +#define IN_CLASSD_NSHIFT 28 +#define IN_CLASSD_HOST 0x0fffffff +#define IN_MULTICAST(i) IN_CLASSD(i) + +#define FROM_PROTOCOL_INFO (-1) + +#define SO_DONTLINGER (u_int)(~SO_LINGER) +#define SO_GROUP_ID 0x2001 +#define SO_GROUP_PRIORITY 0x2002 +#define SO_MAX_MSG_SIZE 0x2003 +#define SO_PROTOCOL_INFOA 0x2004 +#define SO_PROTOCOL_INFOW 0x2005 +#ifdef UNICODE +#define SO_PROTOCOL_INFO SO_PROTOCOL_INFOW +#else +#define SO_PROTOCOL_INFO SO_PROTOCOL_INFOA +#endif +#define PVD_CONFIG 0x3001 + +#define MSG_INTERRUPT 0x10 +#define MSG_MAXIOVLEN 16 + +#define WSAAPI WINAPI +#define WSAEVENT HANDLE +#define LPWSAEVENT LPHANDLE +#define WSAOVERLAPPED OVERLAPPED +typedef struct _OVERLAPPED *LPWSAOVERLAPPED; + +#define WSA_IO_PENDING (ERROR_IO_PENDING) +#define WSA_IO_INCOMPLETE (ERROR_IO_INCOMPLETE) +#define WSA_INVALID_HANDLE (ERROR_INVALID_HANDLE) +#define WSA_INVALID_PARAMETER (ERROR_INVALID_PARAMETER) +#define WSA_NOT_ENOUGH_MEMORY (ERROR_NOT_ENOUGH_MEMORY) +#define WSA_OPERATION_ABORTED (ERROR_OPERATION_ABORTED) + +#define WSA_INVALID_EVENT ((WSAEVENT)NULL) +#define WSA_MAXIMUM_WAIT_EVENTS (MAXIMUM_WAIT_OBJECTS) +#define WSA_WAIT_FAILED ((DWORD)-1L) +#define WSA_WAIT_EVENT_0 (WAIT_OBJECT_0) +#define WSA_WAIT_IO_COMPLETION (WAIT_IO_COMPLETION) +#define WSA_WAIT_TIMEOUT (WAIT_TIMEOUT) +#define WSA_INFINITE (INFINITE) + +typedef struct _WSABUF { + unsigned long len; + char *buf; +} WSABUF, *LPWSABUF; + +typedef enum +{ + BestEffortService, + ControlledLoadService, + PredictiveService, + GuaranteedDelayService, + GuaranteedService +} GUARANTEE; + +/* TODO: FLOWSPEC and related definitions belong in qos.h */ + +/* + Windows Sockets 2 Application Programming Interface, + revision 2.2.2 (1997) uses the type uint32 for SERVICETYPE + and the elements of _flowspec, but the type uint32 is not defined + or used anywhere else in the w32api. For now, just use + unsigned int, which is 32 bits on _WIN32 and _WIN64. +*/ + +typedef unsigned int SERVICETYPE; +typedef struct _flowspec +{ + unsigned int TokenRate; + unsigned int TokenBucketSize; + unsigned int PeakBandwidth; + unsigned int Latency; + unsigned int DelayVariation; + SERVICETYPE ServiceType; + unsigned int MaxSduSize; + unsigned int MinimumPolicedSize; + } FLOWSPEC, *PFLOWSPEC, *LPFLOWSPEC; + +typedef struct _QualityOfService +{ + FLOWSPEC SendingFlowspec; + FLOWSPEC ReceivingFlowspec; + WSABUF ProviderSpecific; +} QOS, *LPQOS; + +#define CF_ACCEPT 0x0000 +#define CF_REJECT 0x0001 +#define CF_DEFER 0x0002 +#define SD_RECEIVE 0x00 +#define SD_SEND 0x01 +#define SD_BOTH 0x02 +typedef unsigned int GROUP; + +#define SG_UNCONSTRAINED_GROUP 0x01 +#define SG_CONSTRAINED_GROUP 0x02 +typedef struct _WSANETWORKEVENTS { + long lNetworkEvents; + int iErrorCode[FD_MAX_EVENTS]; +} WSANETWORKEVENTS, *LPWSANETWORKEVENTS; + +#define MAX_PROTOCOL_CHAIN 7 + +#define BASE_PROTOCOL 1 +#define LAYERED_PROTOCOL 0 + +typedef enum _WSAESETSERVICEOP +{ + RNRSERVICE_REGISTER=0, + RNRSERVICE_DEREGISTER, + RNRSERVICE_DELETE +} WSAESETSERVICEOP, *PWSAESETSERVICEOP, *LPWSAESETSERVICEOP; + +typedef struct _AFPROTOCOLS { + INT iAddressFamily; + INT iProtocol; +} AFPROTOCOLS, *PAFPROTOCOLS, *LPAFPROTOCOLS; + +typedef enum _WSAEcomparator +{ + COMP_EQUAL = 0, + COMP_NOTLESS +} WSAECOMPARATOR, *PWSAECOMPARATOR, *LPWSAECOMPARATOR; + +typedef struct _WSAVersion +{ + DWORD dwVersion; + WSAECOMPARATOR ecHow; +} WSAVERSION, *PWSAVERSION, *LPWSAVERSION; + +#ifndef __CSADDR_T_DEFINED /* also in nspapi.h */ +#define __CSADDR_T_DEFINED +typedef struct _SOCKET_ADDRESS { + LPSOCKADDR lpSockaddr; + INT iSockaddrLength; +} SOCKET_ADDRESS,*PSOCKET_ADDRESS,*LPSOCKET_ADDRESS; +typedef struct _CSADDR_INFO { + SOCKET_ADDRESS LocalAddr; + SOCKET_ADDRESS RemoteAddr; + INT iSocketType; + INT iProtocol; +} CSADDR_INFO,*PCSADDR_INFO,*LPCSADDR_INFO; +#endif + +typedef struct _SOCKET_ADDRESS_LIST { + INT iAddressCount; + SOCKET_ADDRESS Address[1]; +} SOCKET_ADDRESS_LIST, * LPSOCKET_ADDRESS_LIST; + +#ifndef __BLOB_T_DEFINED /* also in wtypes.h and nspapi.h */ +#define __BLOB_T_DEFINED +typedef struct _BLOB { + ULONG cbSize; + BYTE *pBlobData; +} BLOB,*PBLOB,*LPBLOB; +#endif + +typedef struct _WSAQuerySetA +{ + DWORD dwSize; + LPSTR lpszServiceInstanceName; + LPGUID lpServiceClassId; + LPWSAVERSION lpVersion; + LPSTR lpszComment; + DWORD dwNameSpace; + LPGUID lpNSProviderId; + LPSTR lpszContext; + DWORD dwNumberOfProtocols; + LPAFPROTOCOLS lpafpProtocols; + LPSTR lpszQueryString; + DWORD dwNumberOfCsAddrs; + LPCSADDR_INFO lpcsaBuffer; + DWORD dwOutputFlags; + LPBLOB lpBlob; +} WSAQUERYSETA, *PWSAQUERYSETA, *LPWSAQUERYSETA; + +typedef struct _WSAQuerySetW +{ + DWORD dwSize; + LPWSTR lpszServiceInstanceName; + LPGUID lpServiceClassId; + LPWSAVERSION lpVersion; + LPWSTR lpszComment; + DWORD dwNameSpace; + LPGUID lpNSProviderId; + LPWSTR lpszContext; + DWORD dwNumberOfProtocols; + LPAFPROTOCOLS lpafpProtocols; + LPWSTR lpszQueryString; + DWORD dwNumberOfCsAddrs; + LPCSADDR_INFO lpcsaBuffer; + DWORD dwOutputFlags; + LPBLOB lpBlob; +} WSAQUERYSETW, *PWSAQUERYSETW, *LPWSAQUERYSETW; + +#ifdef UNICODE +typedef WSAQUERYSETW WSAQUERYSET; +typedef PWSAQUERYSETW PWSAQUERYSET; +typedef LPWSAQUERYSETW LPWSAQUERYSET; +#else +typedef WSAQUERYSETA WSAQUERYSET; +typedef PWSAQUERYSETA PWSAQUERYSET; +typedef LPWSAQUERYSETA LPWSAQUERYSET; +#endif + +#define LUP_DEEP 0x0001 +#define LUP_CONTAINERS 0x0002 +#define LUP_NOCONTAINERS 0x0004 +#define LUP_NEAREST 0x0008 +#define LUP_RETURN_NAME 0x0010 +#define LUP_RETURN_TYPE 0x0020 +#define LUP_RETURN_VERSION 0x0040 +#define LUP_RETURN_COMMENT 0x0080 +#define LUP_RETURN_ADDR 0x0100 +#define LUP_RETURN_BLOB 0x0200 +#define LUP_RETURN_ALIASES 0x0400 +#define LUP_RETURN_QUERY_STRING 0x0800 +#define LUP_RETURN_ALL 0x0FF0 +#define LUP_RES_SERVICE 0x8000 +#define LUP_FLUSHCACHE 0x1000 +#define LUP_FLUSHPREVIOUS 0x2000 + +typedef struct _WSANSClassInfoA +{ + LPSTR lpszName; + DWORD dwNameSpace; + DWORD dwValueType; + DWORD dwValueSize; + LPVOID lpValue; +} WSANSCLASSINFOA, *PWSANSCLASSINFOA, *LPWSANSCLASSINFOA; + +typedef struct _WSANSClassInfoW +{ + LPWSTR lpszName; + DWORD dwNameSpace; + DWORD dwValueType; + DWORD dwValueSize; + LPVOID lpValue; +} WSANSCLASSINFOW, *PWSANSCLASSINFOW, *LPWSANSCLASSINFOW; + +#ifdef UNICODE +typedef WSANSCLASSINFOW WSANSCLASSINFO; +typedef PWSANSCLASSINFOW PWSANSCLASSINFO; +typedef LPWSANSCLASSINFOW LPWSANSCLASSINFO; +#else +typedef WSANSCLASSINFOA WSANSCLASSINFO; +typedef PWSANSCLASSINFOA PWSANSCLASSINFO; +typedef LPWSANSCLASSINFOA LPWSANSCLASSINFO; +#endif + +typedef struct _WSAServiceClassInfoA +{ + LPGUID lpServiceClassId; + LPSTR lpszServiceClassName; + DWORD dwCount; + LPWSANSCLASSINFOA lpClassInfos; +} WSASERVICECLASSINFOA, *PWSASERVICECLASSINFOA, *LPWSASERVICECLASSINFOA; + +typedef struct _WSAServiceClassInfoW +{ + LPGUID lpServiceClassId; + LPWSTR lpszServiceClassName; + DWORD dwCount; + LPWSANSCLASSINFOW lpClassInfos; +} WSASERVICECLASSINFOW, *PWSASERVICECLASSINFOW, *LPWSASERVICECLASSINFOW; + +#ifdef UNICODE +typedef WSASERVICECLASSINFOW WSASERVICECLASSINFO; +typedef PWSASERVICECLASSINFOW PWSASERVICECLASSINFO; +typedef LPWSASERVICECLASSINFOW LPWSASERVICECLASSINFO; +#else +typedef WSASERVICECLASSINFOA WSASERVICECLASSINFO; +typedef PWSASERVICECLASSINFOA PWSASERVICECLASSINFO; +typedef LPWSASERVICECLASSINFOA LPWSASERVICECLASSINFO; +#endif + +typedef struct _WSANAMESPACE_INFOA { + GUID NSProviderId; + DWORD dwNameSpace; + BOOL fActive; + DWORD dwVersion; + LPSTR lpszIdentifier; +} WSANAMESPACE_INFOA, *PWSANAMESPACE_INFOA, *LPWSANAMESPACE_INFOA; + +typedef struct _WSANAMESPACE_INFOW { + GUID NSProviderId; + DWORD dwNameSpace; + BOOL fActive; + DWORD dwVersion; + LPWSTR lpszIdentifier; +} WSANAMESPACE_INFOW, *PWSANAMESPACE_INFOW, *LPWSANAMESPACE_INFOW; + +#ifdef UNICODE +typedef WSANAMESPACE_INFOW WSANAMESPACE_INFO; +typedef PWSANAMESPACE_INFOW PWSANAMESPACE_INFO; +typedef LPWSANAMESPACE_INFOW LPWSANAMESPACE_INFO; +#else +typedef WSANAMESPACE_INFOA WSANAMESPACE_INFO; +typedef PWSANAMESPACE_INFOA PWSANAMESPACE_INFO; +typedef LPWSANAMESPACE_INFOA LPWSANAMESPACE_INFO; +#endif + +typedef struct _WSAPROTOCOLCHAIN { + int ChainLen; + DWORD ChainEntries[MAX_PROTOCOL_CHAIN]; +} WSAPROTOCOLCHAIN, *LPWSAPROTOCOLCHAIN; + +#define WSAPROTOCOL_LEN 255 + +typedef struct _WSAPROTOCOL_INFOA { + DWORD dwServiceFlags1; + DWORD dwServiceFlags2; + DWORD dwServiceFlags3; + DWORD dwServiceFlags4; + DWORD dwProviderFlags; + GUID ProviderId; + DWORD dwCatalogEntryId; + WSAPROTOCOLCHAIN ProtocolChain; + int iVersion; + int iAddressFamily; + int iMaxSockAddr; + int iMinSockAddr; + int iSocketType; + int iProtocol; + int iProtocolMaxOffset; + int iNetworkByteOrder; + int iSecurityScheme; + DWORD dwMessageSize; + DWORD dwProviderReserved; + CHAR szProtocol[WSAPROTOCOL_LEN+1]; +} WSAPROTOCOL_INFOA, *LPWSAPROTOCOL_INFOA; + +typedef struct _WSAPROTOCOL_INFOW { + DWORD dwServiceFlags1; + DWORD dwServiceFlags2; + DWORD dwServiceFlags3; + DWORD dwServiceFlags4; + DWORD dwProviderFlags; + GUID ProviderId; + DWORD dwCatalogEntryId; + WSAPROTOCOLCHAIN ProtocolChain; + int iVersion; + int iAddressFamily; + int iMaxSockAddr; + int iMinSockAddr; + int iSocketType; + int iProtocol; + int iProtocolMaxOffset; + int iNetworkByteOrder; + int iSecurityScheme; + DWORD dwMessageSize; + DWORD dwProviderReserved; + WCHAR szProtocol[WSAPROTOCOL_LEN+1]; +} WSAPROTOCOL_INFOW, * LPWSAPROTOCOL_INFOW; + +typedef int (CALLBACK *LPCONDITIONPROC)(LPWSABUF, LPWSABUF, LPQOS, LPQOS, LPWSABUF, LPWSABUF, GROUP *, DWORD); +typedef void (WINAPI *LPWSAOVERLAPPED_COMPLETION_ROUTINE)(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); + + +#ifdef UNICODE +typedef WSAPROTOCOL_INFOW WSAPROTOCOL_INFO; +typedef LPWSAPROTOCOL_INFOW LPWSAPROTOCOL_INFO; +#else +typedef WSAPROTOCOL_INFOA WSAPROTOCOL_INFO; +typedef LPWSAPROTOCOL_INFOA LPWSAPROTOCOL_INFO; +#endif + +/* Needed for XP & .NET Server function WSANSPIoctl. */ +typedef enum _WSACOMPLETIONTYPE { + NSP_NOTIFY_IMMEDIATELY = 0, + NSP_NOTIFY_HWND, + NSP_NOTIFY_EVENT, + NSP_NOTIFY_PORT, + NSP_NOTIFY_APC +} WSACOMPLETIONTYPE, * PWSACOMPLETIONTYPE, * LPWSACOMPLETIONTYPE; +typedef struct _WSACOMPLETION { + WSACOMPLETIONTYPE Type; + union { + struct { + HWND hWnd; + UINT uMsg; + WPARAM context; + } WindowMessage; + struct { + LPWSAOVERLAPPED lpOverlapped; + } Event; + struct { + LPWSAOVERLAPPED lpOverlapped; + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpfnCompletionProc; + } Apc; + struct { + LPWSAOVERLAPPED lpOverlapped; + HANDLE hPort; + ULONG_PTR Key; + } Port; + } Parameters; +} WSACOMPLETION, *PWSACOMPLETION, *LPWSACOMPLETION; + +#define PFL_MULTIPLE_PROTO_ENTRIES 0x00000001 +#define PFL_RECOMMENDED_PROTO_ENTRY 0x00000002 +#define PFL_HIDDEN 0x00000004 +#define PFL_MATCHES_PROTOCOL_ZERO 0x00000008 +#define XP1_CONNECTIONLESS 0x00000001 +#define XP1_GUARANTEED_DELIVERY 0x00000002 +#define XP1_GUARANTEED_ORDER 0x00000004 +#define XP1_MESSAGE_ORIENTED 0x00000008 +#define XP1_PSEUDO_STREAM 0x00000010 +#define XP1_GRACEFUL_CLOSE 0x00000020 +#define XP1_EXPEDITED_DATA 0x00000040 +#define XP1_CONNECT_DATA 0x00000080 +#define XP1_DISCONNECT_DATA 0x00000100 +#define XP1_SUPPORT_BROADCAST 0x00000200 +#define XP1_SUPPORT_MULTIPOINT 0x00000400 +#define XP1_MULTIPOINT_CONTROL_PLANE 0x00000800 +#define XP1_MULTIPOINT_DATA_PLANE 0x00001000 +#define XP1_QOS_SUPPORTED 0x00002000 +#define XP1_INTERRUPT 0x00004000 +#define XP1_UNI_SEND 0x00008000 +#define XP1_UNI_RECV 0x00010000 +#define XP1_IFS_HANDLES 0x00020000 +#define XP1_PARTIAL_MESSAGE 0x00040000 + +#define BIGENDIAN 0x0000 +#define LITTLEENDIAN 0x0001 + +#define SECURITY_PROTOCOL_NONE 0x0000 +#define JL_SENDER_ONLY 0x01 +#define JL_RECEIVER_ONLY 0x02 +#define JL_BOTH 0x04 +#define WSA_FLAG_OVERLAPPED 0x01 +#define WSA_FLAG_MULTIPOINT_C_ROOT 0x02 +#define WSA_FLAG_MULTIPOINT_C_LEAF 0x04 +#define WSA_FLAG_MULTIPOINT_D_ROOT 0x08 +#define WSA_FLAG_MULTIPOINT_D_LEAF 0x10 +#define IOC_UNIX 0x00000000 +#define IOC_WS2 0x08000000 +#define IOC_PROTOCOL 0x10000000 +#define IOC_VENDOR 0x18000000 + +#define _WSAIO(x,y) (IOC_VOID|(x)|(y)) +#define _WSAIOR(x,y) (IOC_OUT|(x)|(y)) +#define _WSAIOW(x,y) (IOC_IN|(x)|(y)) +#define _WSAIORW(x,y) (IOC_INOUT|(x)|(y)) + +#define SIO_ASSOCIATE_HANDLE _WSAIOW(IOC_WS2,1) +#define SIO_ENABLE_CIRCULAR_QUEUEING _WSAIO(IOC_WS2,2) +#define SIO_FIND_ROUTE _WSAIOR(IOC_WS2,3) +#define SIO_FLUSH _WSAIO(IOC_WS2,4) +#define SIO_GET_BROADCAST_ADDRESS _WSAIOR(IOC_WS2,5) +#define SIO_GET_EXTENSION_FUNCTION_POINTER _WSAIORW(IOC_WS2,6) +#define SIO_GET_QOS _WSAIORW(IOC_WS2,7) +#define SIO_GET_GROUP_QOS _WSAIORW(IOC_WS2,8) +#define SIO_MULTIPOINT_LOOPBACK _WSAIOW(IOC_WS2,9) +#define SIO_MULTICAST_SCOPE _WSAIOW(IOC_WS2,10) +#define SIO_SET_QOS _WSAIOW(IOC_WS2,11) +#define SIO_SET_GROUP_QOS _WSAIOW(IOC_WS2,12) +#define SIO_TRANSLATE_HANDLE _WSAIORW(IOC_WS2,13) +#define SIO_ROUTING_INTERFACE_QUERY _WSAIORW(IOC_WS2,20) +#define SIO_ROUTING_INTERFACE_CHANGE _WSAIOW(IOC_WS2,21) +#define SIO_ADDRESS_LIST_QUERY _WSAIOR(IOC_WS2,22) +#define SIO_ADDRESS_LIST_CHANGE _WSAIO(IOC_WS2,23) +#define SIO_QUERY_TARGET_PNP_HANDLE _WSAIOR(IOC_WS2,24) +#define SIO_NSP_NOTIFY_CHANGE _WSAIOW(IOC_WS2,25) + +#define TH_NETDEV 0x00000001 +#define TH_TAPI 0x00000002 + +WINSOCK_API_LINKAGE SOCKET WINAPI WSAAccept(SOCKET, struct sockaddr *, LPINT, LPCONDITIONPROC, DWORD); +WINSOCK_API_LINKAGE INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); +WINSOCK_API_LINKAGE INT WINAPI WSAAddressToStringW(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOW, LPWSTR, LPDWORD); +WINSOCK_API_LINKAGE BOOL WINAPI WSACloseEvent(WSAEVENT); +WINSOCK_API_LINKAGE int WINAPI WSAConnect(SOCKET, const struct sockaddr *, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS); +WINSOCK_API_LINKAGE WSAEVENT WINAPI WSACreateEvent(void); +WINSOCK_API_LINKAGE int WINAPI WSADuplicateSocketA(SOCKET, DWORD, LPWSAPROTOCOL_INFOA); +WINSOCK_API_LINKAGE int WINAPI WSADuplicateSocketW(SOCKET, DWORD, LPWSAPROTOCOL_INFOW); +WINSOCK_API_LINKAGE INT WINAPI WSAEnumNameSpaceProvidersA(LPDWORD, LPWSANAMESPACE_INFOA); +WINSOCK_API_LINKAGE INT WINAPI WSAEnumNameSpaceProvidersW(LPDWORD, LPWSANAMESPACE_INFOW); +WINSOCK_API_LINKAGE int WINAPI WSAEnumNetworkEvents(SOCKET, WSAEVENT, LPWSANETWORKEVENTS); +WINSOCK_API_LINKAGE int WINAPI WSAEnumProtocolsA(LPINT, LPWSAPROTOCOL_INFOA, LPDWORD); +WINSOCK_API_LINKAGE int WINAPI WSAEnumProtocolsW(LPINT, LPWSAPROTOCOL_INFOW, LPDWORD); +WINSOCK_API_LINKAGE int WINAPI WSAEventSelect(SOCKET, WSAEVENT, long); +WINSOCK_API_LINKAGE BOOL WINAPI WSAGetOverlappedResult(SOCKET, LPWSAOVERLAPPED, LPDWORD, BOOL, LPDWORD); +WINSOCK_API_LINKAGE BOOL WINAPI WSAGetQOSByName(SOCKET, LPWSABUF, LPQOS); +WINSOCK_API_LINKAGE INT WINAPI WSAGetServiceClassInfoA(LPGUID, LPGUID, LPDWORD, LPWSASERVICECLASSINFOA); +WINSOCK_API_LINKAGE INT WINAPI WSAGetServiceClassInfoW(LPGUID, LPGUID, LPDWORD, LPWSASERVICECLASSINFOW); +WINSOCK_API_LINKAGE INT WINAPI WSAGetServiceClassNameByClassIdA(LPGUID, LPSTR, LPDWORD); +WINSOCK_API_LINKAGE INT WINAPI WSAGetServiceClassNameByClassIdW(LPGUID, LPWSTR, LPDWORD); +WINSOCK_API_LINKAGE int WINAPI WSAHtonl(SOCKET, unsigned long, unsigned long *); +WINSOCK_API_LINKAGE int WINAPI WSAHtons(SOCKET, unsigned short, unsigned short *); +WINSOCK_API_LINKAGE INT WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA); +WINSOCK_API_LINKAGE INT WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW); +WINSOCK_API_LINKAGE int WINAPI WSAIoctl(SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +WINSOCK_API_LINKAGE SOCKET WINAPI WSAJoinLeaf(SOCKET, const struct sockaddr *, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS, DWORD); +WINSOCK_API_LINKAGE INT WINAPI WSALookupServiceBeginA(LPWSAQUERYSETA, DWORD, LPHANDLE); +WINSOCK_API_LINKAGE INT WINAPI WSALookupServiceBeginW(LPWSAQUERYSETW lpqsRestrictions, DWORD, LPHANDLE); +WINSOCK_API_LINKAGE INT WINAPI WSALookupServiceNextA(HANDLE, DWORD, LPDWORD, LPWSAQUERYSETA); +WINSOCK_API_LINKAGE INT WINAPI WSALookupServiceNextW(HANDLE, DWORD, LPDWORD, LPWSAQUERYSETW); +WINSOCK_API_LINKAGE INT WINAPI WSALookupServiceEnd(HANDLE); +WINSOCK_API_LINKAGE int WINAPI WSANSPIoctl(HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPWSACOMPLETION); /* XP or .NET Server */ +WINSOCK_API_LINKAGE int WINAPI WSANtohl(SOCKET, unsigned long, unsigned long *); +WINSOCK_API_LINKAGE int WINAPI WSANtohs(SOCKET, unsigned short, unsigned short *); +WINSOCK_API_LINKAGE int WINAPI WSARecv(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +WINSOCK_API_LINKAGE int WINAPI WSARecvDisconnect(SOCKET, LPWSABUF); +WINSOCK_API_LINKAGE int WINAPI WSARecvFrom(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, struct sockaddr *, LPINT, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +WINSOCK_API_LINKAGE INT WINAPI WSARemoveServiceClass(LPGUID); +WINSOCK_API_LINKAGE BOOL WINAPI WSAResetEvent(WSAEVENT); +WINSOCK_API_LINKAGE int WINAPI WSASend(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +WINSOCK_API_LINKAGE int WINAPI WSASendDisconnect(SOCKET, LPWSABUF); +WINSOCK_API_LINKAGE int WINAPI WSASendTo(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, const struct sockaddr *, int, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +WINSOCK_API_LINKAGE BOOL WINAPI WSASetEvent(WSAEVENT); +WINSOCK_API_LINKAGE INT WSAAPI WSASetServiceA(LPWSAQUERYSETA, WSAESETSERVICEOP, DWORD); +WINSOCK_API_LINKAGE INT WINAPI WSASetServiceW(LPWSAQUERYSETW, WSAESETSERVICEOP, DWORD); +WINSOCK_API_LINKAGE SOCKET WINAPI WSASocketA(int, int, int, LPWSAPROTOCOL_INFOA, GROUP, DWORD); +WINSOCK_API_LINKAGE SOCKET WINAPI WSASocketW(int, int, int, LPWSAPROTOCOL_INFOW, GROUP, DWORD); +WINSOCK_API_LINKAGE INT WINAPI WSAStringToAddressA(LPSTR, INT, LPWSAPROTOCOL_INFOA, LPSOCKADDR, LPINT); +WINSOCK_API_LINKAGE INT WINAPI WSAStringToAddressW(LPWSTR, INT, LPWSAPROTOCOL_INFOW, LPSOCKADDR, LPINT); +WINSOCK_API_LINKAGE DWORD WINAPI WSAWaitForMultipleEvents(DWORD, const WSAEVENT *, BOOL, DWORD, BOOL); + +typedef SOCKET (WINAPI *LPFN_WSAACCEPT)(SOCKET, struct sockaddr *, LPINT, LPCONDITIONPROC, DWORD); +typedef INT (WINAPI *LPFN_WSAADDRESSTOSTRINGA)(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); +typedef INT (WINAPI *LPFN_WSAADDRESSTOSTRINGW)(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOW, LPWSTR, LPDWORD); +typedef BOOL (WINAPI *LPFN_WSACLOSEEVENT)(WSAEVENT); +typedef int (WINAPI *LPFN_WSACONNECT)(SOCKET, const struct sockaddr *, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS); +typedef WSAEVENT (WINAPI *LPFN_WSACREATEEVENT)(void); +typedef int (WINAPI *LPFN_WSADUPLICATESOCKETA)(SOCKET, DWORD, LPWSAPROTOCOL_INFOA); +typedef int (WINAPI *LPFN_WSADUPLICATESOCKETW)(SOCKET, DWORD, LPWSAPROTOCOL_INFOW); +typedef INT (WINAPI *LPFN_WSAENUMNAMESPACEPROVIDERSA)(LPDWORD, LPWSANAMESPACE_INFOA); +typedef INT (WINAPI *LPFN_WSAENUMNAMESPACEPROVIDERSW)(LPDWORD, LPWSANAMESPACE_INFOW); +typedef int (WINAPI *LPFN_WSAENUMNETWORKEVENTS)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS); +typedef int (WINAPI *LPFN_WSAENUMPROTOCOLSA)(LPINT, LPWSAPROTOCOL_INFOA, LPDWORD); +typedef int (WINAPI *LPFN_WSAENUMPROTOCOLSW)(LPINT, LPWSAPROTOCOL_INFOW, LPDWORD); +typedef int (WINAPI *LPFN_WSAEVENTSELECT)(SOCKET, WSAEVENT, long); +typedef BOOL (WINAPI *LPFN_WSAGETOVERLAPPEDRESULT)(SOCKET, LPWSAOVERLAPPED, LPDWORD, BOOL, LPDWORD); +typedef BOOL (WINAPI *LPFN_WSAGETQOSBYNAME)(SOCKET, LPWSABUF, LPQOS); +typedef INT (WINAPI *LPFN_WSAGETSERVICECLASSINFOA)(LPGUID, LPGUID, LPDWORD, LPWSASERVICECLASSINFOA); +typedef INT (WINAPI *LPFN_WSAGETSERVICECLASSINFOW)(LPGUID, LPGUID, LPDWORD, LPWSASERVICECLASSINFOW); +typedef INT (WINAPI *LPFN_WSAGETSERVICECLASSNAMEBYCLASSIDA)(LPGUID, LPSTR, LPDWORD); +typedef INT (WINAPI *LPFN_WSAGETSERVICECLASSNAMEBYCLASSIDW)(LPGUID, LPWSTR, LPDWORD); +typedef int (WINAPI *LPFN_WSAHTONL)(SOCKET, unsigned long, unsigned long *); +typedef int (WINAPI *LPFN_WSAHTONS)(SOCKET, unsigned short, unsigned short *); +typedef INT (WINAPI *LPFN_WSAINSTALLSERVICECLASSA)(LPWSASERVICECLASSINFOA); +typedef INT (WINAPI *LPFN_WSAINSTALLSERVICECLASSW)(LPWSASERVICECLASSINFOW); +typedef int (WINAPI *LPFN_WSAIOCTL)(SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +typedef SOCKET (WINAPI *LPFN_WSAJOINLEAF)(SOCKET, const struct sockaddr *, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS, DWORD); +typedef INT (WINAPI *LPFN_WSALOOKUPSERVICEBEGINA)(LPWSAQUERYSETA, DWORD, LPHANDLE); +typedef INT (WINAPI *LPFN_WSALOOKUPSERVICEBEGINW)(LPWSAQUERYSETW, DWORD, LPHANDLE); +typedef INT (WINAPI *LPFN_WSALOOKUPSERVICENEXTA)(HANDLE, DWORD, LPDWORD, LPWSAQUERYSETA); +typedef INT (WINAPI *LPFN_WSALOOKUPSERVICENEXTW)(HANDLE, DWORD, LPDWORD, LPWSAQUERYSETW); +typedef INT (WINAPI *LPFN_WSALOOKUPSERVICEEND)(HANDLE); +typedef int (WINAPI *LPFN_WSANSPIoctl)(HANDLE, DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPWSACOMPLETION); +typedef int (WINAPI *LPFN_WSANTOHL)(SOCKET, unsigned long, unsigned long *); +typedef int (WINAPI *LPFN_WSANTOHS)(SOCKET, unsigned short, unsigned short *); +typedef int (WINAPI *LPFN_WSARECV)(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +typedef int (WINAPI *LPFN_WSARECVDISCONNECT)(SOCKET, LPWSABUF); +typedef int (WINAPI *LPFN_WSARECVFROM)(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, struct sockaddr *, LPINT, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +typedef INT (WINAPI *LPFN_WSAREMOVESERVICECLASS)(LPGUID); +typedef BOOL (WINAPI *LPFN_WSARESETEVENT)(WSAEVENT); +typedef int (WINAPI *LPFN_WSASEND)(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +typedef int (WINAPI *LPFN_WSASENDDISCONNECT)(SOCKET, LPWSABUF); +typedef int (WINAPI *LPFN_WSASENDTO)(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, const struct sockaddr *, int, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); +typedef BOOL (WINAPI *LPFN_WSASETEVENT)(WSAEVENT); +typedef INT (WINAPI *LPFN_WSASETSERVICEA)(LPWSAQUERYSETA, WSAESETSERVICEOP, DWORD); +typedef INT (WINAPI *LPFN_WSASETSERVICEW)(LPWSAQUERYSETW, WSAESETSERVICEOP, DWORD); +typedef SOCKET (WINAPI *LPFN_WSASOCKETA)(int, int, int, LPWSAPROTOCOL_INFOA, GROUP, DWORD); +typedef SOCKET (WINAPI *LPFN_WSASOCKETW)(int, int, int, LPWSAPROTOCOL_INFOW, GROUP, DWORD); +typedef INT (WINAPI *LPFN_WSASTRINGTOADDRESSA)(LPSTR, INT, LPWSAPROTOCOL_INFOA, LPSOCKADDR, LPINT); +typedef INT (WINAPI *LPFN_WSASTRINGTOADDRESSW)(LPWSTR, INT, LPWSAPROTOCOL_INFOW, LPSOCKADDR, LPINT); +typedef DWORD (WINAPI *LPFN_WSAWAITFORMULTIPLEEVENTS)(DWORD, const WSAEVENT *, BOOL, DWORD, BOOL); + +#ifdef UNICODE +#define LPFN_WSAADDRESSTOSTRING LPFN_WSAADDRESSTOSTRINGW +#define LPFN_WSADUPLICATESOCKET LPFN_WSADUPLICATESOCKETW +#define LPFN_WSAENUMNAMESPACEPROVIDERS LPFN_WSAENUMNAMESPACEPROVIDERSW +#define LPFN_WSAENUMPROTOCOLS LPFN_WSAENUMPROTOCOLSW +#define LPFN_WSAGETSERVICECLASSINFO LPFN_WSAGETSERVICECLASSINFOW +#define LPFN_WSAGETSERVICECLASSNAMEBYCLASSID LPFN_WSAGETSERVICECLASSNAMEBYCLASSIDW +#define LPFN_WSAINSTALLSERVICECLASS LPFN_WSAINSTALLSERVICECLASSW +#define LPFN_WSALOOKUPSERVICEBEGIN LPFN_WSALOOKUPSERVICEBEGINW +#define LPFN_WSALOOKUPSERVICENEXT LPFN_WSALOOKUPSERVICENEXTW +#define LPFN_WSASETSERVICE LPFN_WSASETSERVICEW +#define LPFN_WSASOCKET LPFN_WSASOCKETW +#define LPFN_WSASTRINGTOADDRESS LPFN_WSASTRINGTOADDRESSW +#define WSAAddressToString WSAAddressToStringW +#define WSADuplicateSocket WSADuplicateSocketW +#define WSAEnumNameSpaceProviders WSAEnumNameSpaceProvidersW +#define WSAEnumProtocols WSAEnumProtocolsW +#define WSAGetServiceClassInfo WSAGetServiceClassInfoW +#define WSAGetServiceClassNameByClassId WSAGetServiceClassNameByClassIdW +#define WSASetService WSASetServiceW +#define WSASocket WSASocketW +#define WSAStringToAddress WSAStringToAddressW +#define WSALookupServiceBegin WSALookupServiceBeginW +#define WSALookupServiceNext WSALookupServiceNextW +#define WSAInstallServiceClass WSAInstallServiceClassW +#else +#define LPFN_WSAADDRESSTOSTRING LPFN_WSAADDRESSTOSTRINGA +#define LPFN_WSADUPLICATESOCKET LPFN_WSADUPLICATESOCKETW +#define LPFN_WSAENUMNAMESPACEPROVIDERS LPFN_WSAENUMNAMESPACEPROVIDERSA +#define LPFN_WSAENUMPROTOCOLS LPFN_WSAENUMPROTOCOLSA +#define LPFN_WSAGETSERVICECLASSINFO LPFN_WSAGETSERVICECLASSINFOA +#define LPFN_WSAGETSERVICECLASSNAMEBYCLASSID LPFN_WSAGETSERVICECLASSNAMEBYCLASSIDA +#define LPFN_WSAINSTALLSERVICECLASS LPFN_WSAINSTALLSERVICECLASSA +#define LPFN_WSALOOKUPSERVICEBEGIN LPFN_WSALOOKUPSERVICEBEGINA +#define LPFN_WSALOOKUPSERVICENEXT LPFN_WSALOOKUPSERVICENEXTA +#define LPFN_WSASETSERVICE LPFN_WSASETSERVICEA +#define LPFN_WSASOCKET LPFN_WSASOCKETA +#define LPFN_WSASTRINGTOADDRESS LPFN_WSASTRINGTOADDRESSA +#define WSAAddressToString WSAAddressToStringA +#define WSADuplicateSocket WSADuplicateSocketA +#define WSAEnumNameSpaceProviders WSAEnumNameSpaceProvidersA +#define WSAEnumProtocols WSAEnumProtocolsA +#define WSAGetServiceClassInfo WSAGetServiceClassInfoA +#define WSAGetServiceClassNameByClassId WSAGetServiceClassNameByClassIdA +#define WSAInstallServiceClass WSAInstallServiceClassA +#define WSALookupServiceBegin WSALookupServiceBeginA +#define WSALookupServiceNext WSALookupServiceNextA +#define WSASocket WSASocketA +#define WSAStringToAddress WSAStringToAddressA +#define WSASetService WSASetServiceA +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/embedded8266/ccconfig.h b/embedded8266/ccconfig.h index b3a09e5..02b9c33 100644 --- a/embedded8266/ccconfig.h +++ b/embedded8266/ccconfig.h @@ -12,52 +12,56 @@ #define memcpy ets_memcpy #define memset ets_memset -extern uint8_t gDFTIIR; //=6 -#define DFTIIR gDFTIIR - -extern uint8_t gFUZZ_IIR_BITS; //=1 -#define FUZZ_IIR_BITS gFUZZ_IIR_BITS - +#define ROOT_NOTE_OFFSET CCS.gROOT_NOTE_OFFSET +#define DFTIIR CCS.gDFTIIR +#define FUZZ_IIR_BITS CCS.gFUZZ_IIR_BITS #define MAXNOTES 12 //MAXNOTES cannot be changed dynamically. - -extern uint8_t gFILTER_BLUR_PASSES; //=2 -#define FILTER_BLUR_PASSES gFILTER_BLUR_PASSES - -extern uint8_t gSEMIBITSPERBIN; //=3 -#define SEMIBITSPERBIN gSEMIBITSPERBIN - -extern uint8_t gMAX_JUMP_DISTANCE; //=4 -#define MAX_JUMP_DISTANCE gMAX_JUMP_DISTANCE - -extern uint8_t gMAX_COMBINE_DISTANCE; //=7 -#define MAX_COMBINE_DISTANCE gMAX_COMBINE_DISTANCE - -extern uint8_t gAMP_1_IIR_BITS; //=4 -#define AMP_1_IIR_BITS gAMP_1_IIR_BITS - -extern uint8_t gAMP_2_IIR_BITS; //=2 -#define AMP_2_IIR_BITS gAMP_2_IIR_BITS - -extern uint8_t gMIN_AMP_FOR_NOTE; //=80 -#define MIN_AMP_FOR_NOTE gMIN_AMP_FOR_NOTE - -extern uint8_t gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR; //=64 -#define MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR - -extern uint8_t gNOTE_FINAL_AMP; //=12 -#define NOTE_FINAL_AMP gNOTE_FINAL_AMP - -extern uint8_t gNERF_NOTE_PORP; //=15 -#define NERF_NOTE_PORP gNERF_NOTE_PORP - -extern uint8_t gUSE_NUM_LIN_LEDS; // = NUM_LIN_LEDS -#define USE_NUM_LIN_LEDS gUSE_NUM_LIN_LEDS +#define FILTER_BLUR_PASSES CCS.gFILTER_BLUR_PASSES +#define SEMIBITSPERBIN CCS.gSEMIBITSPERBIN +#define MAX_JUMP_DISTANCE CCS.gMAX_JUMP_DISTANCE +#define MAX_COMBINE_DISTANCE CCS.gMAX_COMBINE_DISTANCE +#define AMP_1_IIR_BITS CCS.gAMP_1_IIR_BITS +#define AMP_2_IIR_BITS CCS.gAMP_2_IIR_BITS +#define MIN_AMP_FOR_NOTE CCS.gMIN_AMP_FOR_NOTE +#define MINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR CCS.gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR +#define NOTE_FINAL_AMP CCS.gNOTE_FINAL_AMP +#define NERF_NOTE_PORP CCS.gNERF_NOTE_PORP +#define USE_NUM_LIN_LEDS CCS.gUSE_NUM_LIN_LEDS +#define COLORCHORD_OUTPUT_DRIVER CCS.gCOLORCHORD_OUTPUT_DRIVER +#define COLORCHORD_ACTIVE CCS.gCOLORCHORD_ACTIVE +#define INITIAL_AMP CCS.gINITIAL_AMP //We are not enabling these for the ESP8266 port. #define LIN_WRAPAROUND 0 #define SORT_NOTES 0 +struct CCSettings +{ + uint8_t gSETTINGS_KEY; + uint8_t gROOT_NOTE_OFFSET; //Set to define what the root note is. 0 = A. + uint8_t gDFTIIR; //=6 + uint8_t gFUZZ_IIR_BITS; //=1 + uint8_t gFILTER_BLUR_PASSES; //=2 + uint8_t gSEMIBITSPERBIN; //=3 + uint8_t gMAX_JUMP_DISTANCE; //=4 + uint8_t gMAX_COMBINE_DISTANCE; //=7 + uint8_t gAMP_1_IIR_BITS; //=4 + uint8_t gAMP_2_IIR_BITS; //=2 + uint8_t gMIN_AMP_FOR_NOTE; //=80 + uint8_t gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR; //=64 + uint8_t gNOTE_FINAL_AMP; //=12 + uint8_t gNERF_NOTE_PORP; //=15 + uint8_t gUSE_NUM_LIN_LEDS; // = NUM_LIN_LEDS + uint8_t gCOLORCHORD_ACTIVE; + uint8_t gCOLORCHORD_OUTPUT_DRIVER; + uint8_t gINITIAL_AMP; +}; + +extern struct CCSettings CCS; + + + #endif diff --git a/embedded8266/esp82xx b/embedded8266/esp82xx index 113e0d1..248dcac 160000 --- a/embedded8266/esp82xx +++ b/embedded8266/esp82xx @@ -1 +1 @@ -Subproject commit 113e0d1a182cd138510f748abf2854c0e84cfa23 +Subproject commit 248dcac4022bf1e3d3574f2f49626c99d794dd06 diff --git a/embedded8266/image.elf-0x00000.bin b/embedded8266/image.elf-0x00000.bin new file mode 100644 index 0000000..6d69844 Binary files /dev/null and b/embedded8266/image.elf-0x00000.bin differ diff --git a/embedded8266/image.elf-0x40000.bin b/embedded8266/image.elf-0x40000.bin new file mode 100644 index 0000000..13b21fd Binary files /dev/null and b/embedded8266/image.elf-0x40000.bin differ diff --git a/embedded8266/user.cfg b/embedded8266/user.cfg index 5945534..923a30e 100644 --- a/embedded8266/user.cfg +++ b/embedded8266/user.cfg @@ -12,12 +12,17 @@ PAGE_OFFSET = 65536 # 1048576 #SDK_DEFAULT = $(HOME)/esp8266/esp-open-sdk ESP_GCC_VERS = 4.8.5 -SDK = $(HOME)/esp8266/esp_iot_sdk_v1.5.2 +#SDK = $(HOME)/esp8266/esp_iot_sdk_v1.5.2 PAGE_SCRIPTS = main.js -FWBURNFLAGS = -b 1000000 +FWBURNFLAGS = -b 2000000 OPTS += -DICACHE_FLASH +OPTS += -DDISABLE_CHARRX #Saves about 48 bytes. +OPTS += -DQUIET_REFLASH #Saves about 128 bytes. +OPTS += -DWS2812_FOUR_SAMPLE #Saves about 224 bytes. +#OPTS += -DWS2812_THREE_SAMPLE + #OPTS += -DVERIFY_FLASH_WRITE #OPTS += -DDEBUG #OPTS += -DFREQ=12500 diff --git a/embedded8266/user/custom_commands.c b/embedded8266/user/custom_commands.c index 3afe2ef..3a04c75 100644 --- a/embedded8266/user/custom_commands.c +++ b/embedded8266/user/custom_commands.c @@ -11,51 +11,51 @@ extern volatile uint8_t sounddata[]; extern volatile uint16_t soundhead; -#define CONFIGURABLES 17 //(plus1) +#define CONFIGURABLES 18 //(plus1) -extern uint8_t RootNoteOffset; //Set to define what the root note is. 0 = A. -uint8_t gDFTIIR = 6; -uint8_t gFUZZ_IIR_BITS = 1; -uint8_t gFILTER_BLUR_PASSES = 2; -uint8_t gSEMIBITSPERBIN = 3; -uint8_t gMAX_JUMP_DISTANCE = 4; -uint8_t gMAX_COMBINE_DISTANCE = 7; -uint8_t gAMP_1_IIR_BITS = 4; -uint8_t gAMP_2_IIR_BITS = 2; -uint8_t gMIN_AMP_FOR_NOTE = 80; -uint8_t gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR = 64; -uint8_t gNOTE_FINAL_AMP = 12; -uint8_t gNERF_NOTE_PORP = 15; -uint8_t gUSE_NUM_LIN_LEDS = NUM_LIN_LEDS; -uint8_t gCOLORCHORD_ACTIVE = 1; -uint8_t gCOLORCHORD_OUTPUT_DRIVER = 0; struct SaveLoad { uint8_t configs[CONFIGURABLES]; + uint8_t SaveLoadKey; //Must be 0xaa to be valid. } settings; -uint8_t gConfigDefaults[CONFIGURABLES] = { 0, 6, 1, 2, 3, 4, 7, 4, 2, 80, 64, 12, 15, NUM_LIN_LEDS, 1, 0, 0 }; +struct CCSettings CCS; -uint8_t * gConfigurables[CONFIGURABLES] = { &RootNoteOffset, &gDFTIIR, &gFUZZ_IIR_BITS, &gFILTER_BLUR_PASSES, - &gSEMIBITSPERBIN, &gMAX_JUMP_DISTANCE, &gMAX_COMBINE_DISTANCE, &gAMP_1_IIR_BITS, - &gAMP_2_IIR_BITS, &gMIN_AMP_FOR_NOTE, &gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR, &gNOTE_FINAL_AMP, - &gNERF_NOTE_PORP, &gUSE_NUM_LIN_LEDS, &gCOLORCHORD_ACTIVE, &gCOLORCHORD_OUTPUT_DRIVER, 0 }; +uint8_t gConfigDefaults[CONFIGURABLES] = { 0, 6, 1, 2, 3, 4, 7, 4, 2, 80, 64, 12, 15, NUM_LIN_LEDS, 1, 0, 16, 0 }; + +uint8_t * gConfigurables[CONFIGURABLES] = { &CCS.gROOT_NOTE_OFFSET, &CCS.gDFTIIR, &CCS.gFUZZ_IIR_BITS, &CCS.gFILTER_BLUR_PASSES, + &CCS.gSEMIBITSPERBIN, &CCS.gMAX_JUMP_DISTANCE, &CCS.gMAX_COMBINE_DISTANCE, &CCS.gAMP_1_IIR_BITS, + &CCS.gAMP_2_IIR_BITS, &CCS.gMIN_AMP_FOR_NOTE, &CCS.gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR, &CCS.gNOTE_FINAL_AMP, + &CCS.gNERF_NOTE_PORP, &CCS.gUSE_NUM_LIN_LEDS, &CCS.gCOLORCHORD_ACTIVE, &CCS.gCOLORCHORD_OUTPUT_DRIVER, &CCS.gINITIAL_AMP, 0 }; char * gConfigurableNames[CONFIGURABLES] = { "gROOT_NOTE_OFFSET", "gDFTIIR", "gFUZZ_IIR_BITS", "gFILTER_BLUR_PASSES", "gSEMIBITSPERBIN", "gMAX_JUMP_DISTANCE", "gMAX_COMBINE_DISTANCE", "gAMP_1_IIR_BITS", "gAMP_2_IIR_BITS", "gMIN_AMP_FOR_NOTE", "gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR", "gNOTE_FINAL_AMP", - "gNERF_NOTE_PORP", "gUSE_NUM_LIN_LEDS", "gCOLORCHORD_ACTIVE", "gCOLORCHORD_OUTPUT_DRIVER", 0 }; + "gNERF_NOTE_PORP", "gUSE_NUM_LIN_LEDS", "gCOLORCHORD_ACTIVE", "gCOLORCHORD_OUTPUT_DRIVER", "gINITIAL_AMP", 0 }; void ICACHE_FLASH_ATTR CustomStart( ) { int i; spi_flash_read( 0x3D000, (uint32*)&settings, sizeof( settings ) ); - for( i = 0; i < CONFIGURABLES; i++ ) + if( settings.SaveLoadKey == 0xaa ) { - if( gConfigurables[i] ) + for( i = 0; i < CONFIGURABLES; i++ ) { - *gConfigurables[i] = settings.configs[i]; + if( gConfigurables[i] ) + { + *gConfigurables[i] = settings.configs[i]; + } + } + } + else + { + for( i = 0; i < CONFIGURABLES; i++ ) + { + if( gConfigurables[i] ) + { + *gConfigurables[i] = gConfigDefaults[i]; + } } } } @@ -105,8 +105,8 @@ int ICACHE_FLASH_ATTR CustomCommand(char * buffer, int retsize, char *pusrdata, case 'l': case 'L': //LEDs { int i, it = 0; - buffend += ets_sprintf( buffend, "CL\t%d\t", gUSE_NUM_LIN_LEDS ); - uint16_t toledsvals = gUSE_NUM_LIN_LEDS*3; + buffend += ets_sprintf( buffend, "CL\t%d\t", USE_NUM_LIN_LEDS ); + uint16_t toledsvals = USE_NUM_LIN_LEDS*3; if( toledsvals > 600 ) toledsvals = 600; for( i = 0; i < toledsvals; i++ ) { @@ -198,6 +198,7 @@ int ICACHE_FLASH_ATTR CustomCommand(char * buffer, int retsize, char *pusrdata, if( gConfigurables[i] ) settings.configs[i] = *gConfigurables[i]; } + settings.SaveLoadKey = 0xAA; EnterCritical(); ets_intr_lock(); diff --git a/embedded8266/user/user_main.c b/embedded8266/user/user_main.c index 3b858e7..a047897 100644 --- a/embedded8266/user/user_main.c +++ b/embedded8266/user/user_main.c @@ -15,9 +15,9 @@ #include "ccconfig.h" #include #include +#include #include "ets_sys.h" #include "gpio.h" - //#define PROFILE #define PORT 7777 @@ -28,6 +28,7 @@ #define procTaskPrio 0 #define procTaskQueueLen 1 +struct CCSettings CCS; static volatile os_timer_t some_timer; static struct espconn *pUdpServer; @@ -37,27 +38,26 @@ void ExitCritical(); extern volatile uint8_t sounddata[HPABUFFSIZE]; extern volatile uint16_t soundhead; uint16_t soundtail; -extern uint8_t gCOLORCHORD_ACTIVE; -static uint8_t hpa_running = 0; +static uint8_t hpa_running = 0; +static uint8_t hpa_is_paused_for_wifi; void ICACHE_FLASH_ATTR CustomStart( ); void ICACHE_FLASH_ATTR user_rf_pre_init() { } -extern uint8_t gCOLORCHORD_OUTPUT_DRIVER; //Call this once we've stacked together one full colorchord frame. static void NewFrame() { - if( !gCOLORCHORD_ACTIVE ) return; + if( !COLORCHORD_ACTIVE ) return; //uint8_t led_outs[NUM_LIN_LEDS*3]; int i; HandleFrameInfo(); - switch( gCOLORCHORD_OUTPUT_DRIVER ) + switch( COLORCHORD_OUTPUT_DRIVER ) { case 0: UpdateLinearLEDs(); @@ -72,56 +72,22 @@ static void NewFrame() } os_event_t procTaskQueue[procTaskQueueLen]; -static uint8_t printed_ip = 0; uint32_t samp_iir = 0; int wf = 0; //Tasks that happen all the time. -static void ICACHE_FLASH_ATTR HandleIPStuff() -{ - //Idle Event. - struct station_config wcfg; - char stret[256]; - char *stt = &stret[0]; - struct ip_info ipi; - - int stat = wifi_station_get_connect_status(); - - //printf( "STAT: %d %d\n", stat, wifi_get_opmode() ); - - if( stat == STATION_WRONG_PASSWORD || stat == STATION_NO_AP_FOUND || stat == STATION_CONNECT_FAIL ) - { - wifi_set_opmode_current( 2 ); - stt += ets_sprintf( stt, "Connection failed: %d\n", stat ); - uart0_sendStr(stret); - } - - if( stat == STATION_GOT_IP && !printed_ip ) - { - wifi_station_get_config( &wcfg ); - wifi_get_ip_info(0, &ipi); - stt += ets_sprintf( stt, "STAT: %d\n", stat ); - stt += ets_sprintf( stt, "IP: %d.%d.%d.%d\n", (ipi.ip.addr>>0)&0xff,(ipi.ip.addr>>8)&0xff,(ipi.ip.addr>>16)&0xff,(ipi.ip.addr>>24)&0xff ); - stt += ets_sprintf( stt, "NM: %d.%d.%d.%d\n", (ipi.netmask.addr>>0)&0xff,(ipi.netmask.addr>>8)&0xff,(ipi.netmask.addr>>16)&0xff,(ipi.netmask.addr>>24)&0xff ); - stt += ets_sprintf( stt, "GW: %d.%d.%d.%d\n", (ipi.gw.addr>>0)&0xff,(ipi.gw.addr>>8)&0xff,(ipi.gw.addr>>16)&0xff,(ipi.gw.addr>>24)&0xff ); - stt += ets_sprintf( stt, "WCFG: /%s/%s/\n", wcfg.ssid, wcfg.password ); - uart0_sendStr(stret); - printed_ip = 1; - } -} - static void procTask(os_event_t *events) { system_os_post(procTaskPrio, 0, 0 ); - if( gCOLORCHORD_ACTIVE && !hpa_running ) + if( COLORCHORD_ACTIVE && !hpa_running ) { ExitCritical(); hpa_running = 1; } - if( !gCOLORCHORD_ACTIVE && hpa_running ) + if( !COLORCHORD_ACTIVE && hpa_running ) { EnterCritical(); hpa_running = 0; @@ -133,9 +99,11 @@ static void procTask(os_event_t *events) #endif while( soundtail != soundhead ) { - int16_t samp = sounddata[soundtail]; + int32_t samp = sounddata[soundtail]; samp_iir = samp_iir - (samp_iir>>10) + samp; - PushSample32( (samp - (samp_iir>>10))*16 ); + samp = (samp - (samp_iir>>10))*16; + samp = (samp * CCS.gINITIAL_AMP) >> 4; + PushSample32( samp ); soundtail = (soundtail+1)&(HPABUFFSIZE-1); wf++; @@ -152,7 +120,6 @@ static void procTask(os_event_t *events) if( events->sig == 0 && events->par == 0 ) { CSTick( 0 ); - HandleIPStuff(); } } @@ -161,6 +128,13 @@ static void procTask(os_event_t *events) static void ICACHE_FLASH_ATTR myTimer(void *arg) { CSTick( 1 ); + + if( hpa_is_paused_for_wifi && printed_ip ) + { + StartHPATimer(); //Init the high speed ADC timer. + hpa_running = 1; + hpa_is_paused_for_wifi = 0; // only need to do once prevents unstable ADC + } // uart0_sendStr("."); // printf( "%d/%d\n",soundtail,soundhead ); // printf( "%d/%d\n",soundtail,soundhead ); @@ -238,11 +212,25 @@ void ICACHE_FLASH_ATTR user_init(void) InitColorChord(); //Init colorchord - StartHPATimer(); //Init the high speed ADC timer. - hpa_running = 1; + //Tricky: If we are in station mode, wait for that to get resolved before enabling the high speed timer. + if( wifi_get_opmode() == 1 ) + { + hpa_is_paused_for_wifi = 1; + } + else + { + StartHPATimer(); //Init the high speed ADC timer. + hpa_running = 1; + } ws2812_init(); + // Attempt to make ADC more stable + // https://github.com/esp8266/Arduino/issues/2070 + // see peripherals https://espressif.com/en/support/explore/faq + //wifi_set_sleep_type(NONE_SLEEP_T); // on its own stopped wifi working + //wifi_fpm_set_sleep_type(NONE_SLEEP_T); // with this seemed no difference + system_os_post(procTaskPrio, 0, 0 ); } diff --git a/embedded8266/user/ws2812_i2s.h b/embedded8266/user/ws2812_i2s.h index 85609d7..c0276e6 100644 --- a/embedded8266/user/ws2812_i2s.h +++ b/embedded8266/user/ws2812_i2s.h @@ -23,7 +23,8 @@ //4 takes up more RAM per LED than 3. //3 has slightly more restrictve timing requirements. //4 has more DMA load when running. -#define WS2812_THREE_SAMPLE + +//#define WS2812_THREE_SAMPLE //#define WS2812_FOUR_SAMPLE void ICACHE_FLASH_ATTR ws2812_init(); diff --git a/embedded8266/web/page.mpfs b/embedded8266/web/page.mpfs new file mode 100644 index 0000000..248e4c7 Binary files /dev/null and b/embedded8266/web/page.mpfs differ diff --git a/embedded8266/web/page/menuinterface.js b/embedded8266/web/page/menuinterface.js index 21cca02..ea3aea0 100644 --- a/embedded8266/web/page/menuinterface.js +++ b/embedded8266/web/page/menuinterface.js @@ -6,7 +6,7 @@ var output; var websocket; var commsup = 0; -var mpfs_start_at = 1048576; +var mpfs_start_at = 65536; //1048576; NOTE: If you select 1048576, it will override the 65536 sector, but has much more room. var flash_scratchpad_at = 524288; var flash_blocksize = 65536; var flash_sendsize = 256; @@ -44,10 +44,12 @@ function QueueOperation( command, callback ) workqueue.push( vp ); } - +did_init = false; function init() { - var GPIOlines = ''; + if( did_init ) return; + did_init = true; + GPIOlines = ''; for(var i=0; i<16; ++i) GPIOlines += ""+ i + "" @@ -56,10 +58,11 @@ function init() $('#MainMenu > tbody:first-child').before( "\ \ - \ + \
\
\ -
\n
" ); +
\n " + ); $('#MainMenu > tbody:last-child').after( "\ \ @@ -118,16 +121,19 @@ function init() $("#custom_command_response").val( "" ); //Preclude drag and drop on rest of document in event user misses firmware boxes. - var donothing = function(e) {e.stopPropagation();e.preventDefault();}; + donothing = function(e) {e.stopPropagation();e.preventDefault();}; $(document).on('drop', donothing ); $(document).on('dragover', donothing ); $(document).on('dragenter', donothing ); output = document.getElementById("output"); - Ticker(); KickWifiTicker(); GPIODataTickerStart(); + InitSystemTicker(); + + console.log( "Load complete.\n" ); + Ticker(); } window.addEventListener("load", init, false); @@ -141,6 +147,7 @@ function StartWebSocket() workqueue = []; lastitem = null; websocket = new WebSocket(wsUri); + websocket.binaryType = 'arraybuffer'; websocket.onopen = function(evt) { onOpen(evt) }; websocket.onclose = function(evt) { onClose(evt) }; websocket.onmessage = function(evt) { onMessage(evt) }; @@ -161,7 +168,8 @@ function onClose(evt) var msg = 0; var tickmessage = 0; var lasthz = 0; -var time_since_hz = 0; +var time_since_hz = 10; //Make it realize it was disconnected to begin with. + function Ticker() { setTimeout( Ticker, 1000 ); @@ -203,17 +211,24 @@ function onMessage(evt) } + var rawdat = new Uint8Array(evt.data) + var stringdata = String.fromCharCode.apply(null, rawdat); + if( lastitem ) { if( lastitem.callback ) { - lastitem.callback( lastitem, evt.data ); + lastitem.callback( lastitem, stringdata, rawdat ); lastitem = null; } } else { - output.innerHTML = "

Messages: " + msg + "

RSSI: " + evt.data.substr(2) + "

"; + if( stringdata.length > 2 ) + { + var wxresp = stringdata.substr(2).split("\t"); + output.innerHTML = "

Messages: " + msg + "

RSSI: " + wxresp[0] + " / IP: " + ((wxresp.length>1)?HexToIP( wxresp[1] ):"") + "

"; + } } @@ -278,27 +293,27 @@ function IssueCustomCommand() function MakeDragDrop( divname, callback ) { var obj = $("#" + divname); - obj.on('dragenter', function (e) + obj.on('dragenter', function (e) { e.stopPropagation(); e.preventDefault(); $(this).css('border', '2px solid #0B85A1'); }); - obj.on('dragover', function (e) + obj.on('dragover', function (e) { e.stopPropagation(); e.preventDefault(); }); - obj.on('dragend', function (e) + obj.on('dragend', function (e) { e.stopPropagation(); e.preventDefault(); $(this).css('border', '2px dotted #0B85A1'); }); - obj.on('drop', function (e) + obj.on('drop', function (e) { $(this).css('border', '2px dotted #0B85A1'); e.preventDefault(); @@ -318,9 +333,108 @@ function MakeDragDrop( divname, callback ) /////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///Below here are mostly just events... -var did_wifi_get_config = false; -var is_data_ticker_running = false; -var is_waiting_on_stations = false; +var sysset = null; +var snchanged = false; +var sdchanged = false; + +var lastpeerdata = ""; + +function CallbackForPeers(req,data) +{ + if( data == lastpeerdata ) return; + lastpeerdata = data; + var lines = data.split( "\n" ); + var searchcount = 0; + if( lines.length > 0 ) + { + var line1 = lines[0].split( "\t" ); + if( line1.length > 1 ) searchcount = Number( line1[1] ); + } + + var htm = ""; + for( var i = 1; i < lines.length; i++ ) + { + var elems = lines[i].split( "\t" ); + if( elems.length < 4 ) continue; + IP = HexToIP( elems[0] ); + + htm += ""; + } + htm += "
AddressServiceNameDescription
" + IP + "" + elems[1] + "" + elems[2] + "" + elems[3] + "
"; + if( searchcount == 0 ) + { + htm += ""; + } + + $("#peers").html( htm ); +} + +function SysTickBack(req,data) +{ + var params = data.split( "\t" ); + if( !snchanged ) + { + $("#SystemName").prop( "value", params[3] ); + $("#SystemName").removeClass( "unsaved-input"); + } + if( !sdchanged ) + { + $("#SystemDescription").prop( "value", params[4] ); + $("#SystemDescription").removeClass( "unsaved-input"); + } + $("#ServiceName").html( params[5] ); + $("#FreeHeap").html( params[6] ); + + QueueOperation( "BL", CallbackForPeers ); +} + +function SystemInfoTick() +{ + if( IsTabOpen('SystemStatus') ) + { + QueueOperation( "I", SysTickBack ); + setTimeout( SystemInfoTick, 500 ); + } + else + { + //Stop. + } +} + +function SystemChangesReset() +{ + snchanged = false; + sdchanged = false; +} + +function SystemUncommittedChanges() +{ + if( sdchanged || snchanged ) return true; + else return false; +} + +function InitSystemTicker() +{ + sysset = document.getElementById( "systemsettings" ); + SystemInfoTick(); + sysset.innerHTML = "\ +
System Name:
System Description:
Service Name:
Free Heap:
\ + \ + \ + \ + \ + \ +

Search for others:

\ +
"; + $("#SystemName").on("input propertychange paste",function(){snchanged = true; $("#SystemName").addClass( "unsaved-input"); }); + $("#SystemDescription").on("input propertychange paste",function(){sdchanged = true;$("#SystemDescription").addClass( "unsaved-input"); }); +} + + + +did_wifi_get_config = false; +is_data_ticker_running = false; +is_waiting_on_stations = false; function ScanForWifi() { @@ -378,7 +492,7 @@ function WifiDataTicker() QueueOperation( "WI", function(req,data) { var params = data.split( "\t" ); - + var opmode = Number( params[0].substr(2) ); document.wifisection.wifitype.value = opmode; document.wifisection.wificurname.value = params[1]; @@ -394,6 +508,7 @@ function WifiDataTicker() QueueOperation( "WR", function(req,data) { var lines = data.split( "\n" ); var innerhtml; + if( data[0] == '!' ) return; //If no APs, don't deal with list. if( lines.length < 3 ) { @@ -425,7 +540,7 @@ function WifiDataTicker() innerhtml += ""; document.getElementById("WifiStations").innerHTML = innerhtml; } ); - setTimeout( WifiDataTicker, 12000 ); + setTimeout( WifiDataTicker, 500 ); } else { @@ -435,7 +550,7 @@ function WifiDataTicker() function ChangeWifiConfig() { - + var st = "W"; st += document.wifisection.wifitype.value; st += "\t" + document.wifisection.wificurname.value; @@ -549,7 +664,7 @@ function SystemPushImageProgress( is_ok, comment, pushop ) pushop.ctx.file1md5 = faultylabs.MD5( pushop.paddata ).toLowerCase(); var reader = new FileReader(); - reader.onload = function(e) { + reader.onload = function(e) { $("#innersystemflashtext").html( "Pusing second half..." ); PushImageTo( e.target.result, flash_scratchpad_at + 0x40000, SystemPushImageProgress, pushop.ctx ); } @@ -567,7 +682,7 @@ function SystemPushImageProgress( is_ok, comment, pushop ) var stf = "FM" + flash_scratchpad_at + "\t0\t" + f1s + "\t" + f1m + "\t" + (flash_scratchpad_at+0x40000) + "\t" + 0x40000 + "\t" + f2s + "\t" + f2m + "\n"; var fun = function( fsrd, flashresponse ) { $("#innerflashtext").html( (flashresponse[0] == '!')?"Flashing failed.":"Flash success." ) }; - QueueOperation( stf, fun); + QueueOperation( stf, fun); } return false; @@ -578,7 +693,7 @@ function SystemPushImageProgress( is_ok, comment, pushop ) function WebPagePushImageFunction( ok, comment, pushop ) -{ +{ if( pushop.place == pushop.padlen ) { $("#innersystemflashtext").html("Push complete. Reload page."); @@ -589,7 +704,7 @@ function WebPagePushImageFunction( ok, comment, pushop ) } return true; -} +} function DragDropSystemFiles( file ) { @@ -607,7 +722,7 @@ function DragDropSystemFiles( file ) var reader = new FileReader(); - reader.onload = function(e) { + reader.onload = function(e) { PushImageTo( e.target.result, mpfs_start_at, WebPagePushImageFunction ); } @@ -620,18 +735,19 @@ function DragDropSystemFiles( file ) for( var i = 0; i < file.length; i++ ) { - if( file[i].name.substr( 0, 7 ) == "0x00000" ) file1 = file[i]; - if( file[i].name.substr( 0, 7 ) == "0x40000" ) file2 = file[i]; + console.log( "Found: " + file[i].name ); + if( file[i].name.substr( 0, 17 ) == "image.elf-0x00000" ) file1 = file[i]; + if( file[i].name.substr( 0, 17 ) == "image.elf-0x40000" ) file2 = file[i]; } if( !file1 ) { - $("#innersystemflashtext").html( "Could not find a 0x00000... file." ); return; + $("#innersystemflashtext").html( "Could not find a image.elf-0x00000... file." ); return; } if( !file2 ) { - $("#innersystemflashtext").html( "Could not find a 0x40000... file." ); return; + $("#innersystemflashtext").html( "Could not find a image.elf-0x40000... file." ); return; } if( file1.size > 65536 ) @@ -650,7 +766,7 @@ function DragDropSystemFiles( file ) var reader = new FileReader(); - reader.onload = function(e) { + reader.onload = function(e) { var ctx = new Object(); ctx.file1 = file1; ctx.file2 = file2; @@ -682,6 +798,15 @@ function tohex8( c ) } +function HexToIP( hexstr ) +{ + if( !hexstr ) return ""; + return parseInt( hexstr.substr( 6, 2 ), 16 ) + "." + + parseInt( hexstr.substr( 4, 2 ), 16 ) + "." + + parseInt( hexstr.substr( 2, 2 ), 16 ) + "." + + parseInt( hexstr.substr( 0, 2 ), 16 ); +} + function ContinueSystemFlash( fsrd, flashresponse, pushop ) { if( flashresponse[0] == '!' ) diff --git a/embeddedlinux/Makefile b/embeddedlinux/Makefile index 8ccdf93..961cce3 100644 --- a/embeddedlinux/Makefile +++ b/embeddedlinux/Makefile @@ -7,7 +7,7 @@ LDFLAGS:= -s -Wl,--relax -Wl,-Map=test.map -Wl,--gc-sections -ffunction-section embeddedcc : ../embeddedcommon/embeddednf.c ../embeddedcommon/DFT32.c embeddedcc.c ../embeddedcommon/embeddedout.c - gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) -m32 + gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) dummy_leds : dummy_leds.c gcc -o $@ $^ -lX11 -lpthread $(CFLAGS) $(LDFLAGS) diff --git a/embeddedlinux/embeddedcc.c b/embeddedlinux/embeddedcc.c index ee663eb..4ce7ea5 100644 --- a/embeddedlinux/embeddedcc.c +++ b/embeddedlinux/embeddedcc.c @@ -11,6 +11,7 @@ #include #include #include +#include // Added by [olel] for atoi #include "embeddedout.h" struct sockaddr_in servaddr; @@ -64,7 +65,7 @@ int main( int argc, char ** argv ) connect( sock, (struct sockaddr *)&servaddr, sizeof(servaddr) ); - Init(); + InitColorChord(); // Changed by [olel] cause this was changed in embeddednf while( ( ci = getchar() ) != EOF ) {