Files
llamaplayer/Src/Plugins/Input/in_mod/mikamp/src/rf_wrapper.c
2024-09-24 14:54:57 +02:00

242 lines
4.0 KiB
C

#include <windows.h>
#include <mmio.h>
#include <shlwapi.h>
#include "../../winamp/wa_ipc.h"
#include "../../winamp/in2.h"
extern In_Module mikmod;
//big mess here
typedef struct // quick _thiscall hack
{
char *(_fastcall *GetDescription)(void*,int);
int (_fastcall *Open)(void*,int,char *url, int *killswitch);
int (_fastcall *Read)(void*,int,void *buffer, int length, int *killswitch);
int (_fastcall *GetLength)(void*);
int (_fastcall *CanSeek)(void*);
int (_fastcall *Seek)(void*,int,int position, int *killswitch);
char *(_fastcall *GetHeader)(void*,int,char *name);
void (_fastcall *Release)(void*,int,int); // rough ~WReader() hack
} RF_vtbl;
#define RF_Open(x,a,b) (*x)->Open(x,0,a,b)
#define RF_Read(x,a,b,c) (*x)->Read(x,0,a,b,c)
#define RF_GetLength(x) (*x)->GetLength(x)
#define RF_Seek(x,a,b) (*x)->Seek(x,0,a,b)
#define RF_Release(x) (*x)->Release(x,0,0)
#define READ_VER 0x100
typedef struct
{
int version;
char *description;
RF_vtbl ** (_cdecl *create)();
int (_cdecl *ismine)(char *url);
} reader_source;
typedef int (_cdecl *RF_entry)(HINSTANCE hIns,reader_source** s);
static int initialized,got_dll;
static HINSTANCE hRF;
typedef struct
{
RF_vtbl ** r;
UINT size,pos;
} RFstruct;
static RF_vtbl** (_cdecl *rf_create)();
static int rf_init()
{
wchar_t fn[MAX_PATH] = {0};
RF_entry rf_entry;
reader_source * source;
if (initialized) return got_dll;
initialized=1;
PathCombineW(fn, (wchar_t*)SendMessage(mikmod.hMainWindow, WM_WA_IPC, 0, IPC_GETSHAREDDLLDIRECTORYW), L"read_file.dll");
hRF=LoadLibraryW(fn);
if (!hRF) return 0;
rf_entry = (RF_entry)GetProcAddress(hRF,"readerSource");
if (!rf_entry)
{
FreeLibrary(hRF);
return 0;
}
rf_entry(hRF,&source);
if (source->version!=READ_VER)
{
FreeLibrary(hRF);
return 0;
}
rf_create=source->create;
got_dll=1;
return 1;
}
static void rf_quit()
{
if (got_dll)
{
FreeLibrary(hRF);
got_dll=0;
}
initialized=0;
}
static void * _cdecl rfopen(const char * fn)
{
int ks;
RF_vtbl ** r;
RFstruct * rs;
if (!got_dll) return 0;
r=rf_create();
if (!r) return 0;
ks=0;
if (RF_Open(r,(char*)fn,&ks))
{
RF_Release(r);
return 0;
}
rs=malloc(sizeof(RFstruct));
if (!rs)
{
RF_Release(r);
return 0;
}
rs->r=r;
rs->pos=0;
rs->size=RF_GetLength(r);
return rs;
}
static size_t _cdecl rfread( void *buffer, size_t size, size_t count, void *stream )
{
RFstruct * rs;
int ks,rv;
UINT siz;
rs=stream;
ks=0;
siz=size*count;
if (siz>rs->size-rs->pos) siz=rs->size-rs->pos;//just to be sure
rv=RF_Read(rs->r,buffer,siz,&ks);
if (rv>0) rs->pos+=rv;
return rv;
}
static size_t _cdecl rfwrite( const void *buffer, size_t size, size_t count, void *stream ) {return -1;}
static int _cdecl rfgetc( void *stream )
{
RFstruct * rs;
int rv,ks;
rv=0;
ks=0;
rs=stream;
if (RF_Read(rs->r,&rv,1,&ks)>0) rs->pos++;
else rv=EOF;
return rv;
}
static int _cdecl rfputc( int c, void *stream )
{
// not implemented
return -1;
}
static int _cdecl rfseek( void *stream, long offset, int origin )
{
RFstruct * rs;
int ks;
UINT new_pos;
ks=0;
rs=stream;
switch(origin)
{
case SEEK_CUR:
new_pos=rs->pos+offset;
break;
case SEEK_END:
new_pos=rs->size+offset;
break;
case SEEK_SET:
new_pos=offset;
break;
default:
return -1;
}
if (new_pos>rs->size) new_pos=rs->size;
if (RF_Seek(rs->r,new_pos,&ks))
{
return -1;
}
rs->pos=new_pos;
return 0;
}
static long _cdecl rftell(void * stream)
{
RFstruct * rs=stream;
return rs->pos;
}
static int _cdecl rfeof(void * stream)
{
RFstruct * rs=stream;
return rs->pos==rs->size;
}
static int _cdecl rfclose(void * stream)
{
RFstruct * rs=stream;
RF_Release(rs->r);
free(rs);
return 0;
}
static const MMSTREAM_CALLBACK callback_rf =
{
rfread,
rfwrite,
rfgetc,
rfputc,
rfseek,
rftell,
rfeof,
rfclose
};
MMSTREAM *_mm_fopen_rf(const CHAR *fname)
{
void * handle;
if (!rf_init()) return 0;
handle = rfopen(fname);
if (!handle) return _mm_fopen(fname,"rb");
return _mmstream_createfp_callback(handle,0,&callback_rf);
}