Merge branch 'community' into patch-1
@ -16,6 +16,10 @@ Building of the Winamp desktop client is currently based around Visual Studio 20
|
|||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
|
#### libdiscid
|
||||||
|
|
||||||
|
We take libdiscid from https://github.com/metabrainz/libdiscid/tree/v0.6.2, copy it in /Src/external_dependencies/libdiscid-0.6.2/
|
||||||
|
|
||||||
#### libvpx
|
#### libvpx
|
||||||
|
|
||||||
We take libvpx from [https://github.com/ShiftMediaProject/libvpx](https://github.com/ShiftMediaProject/libvpx), modify it, and pack it to archive.
|
We take libvpx from [https://github.com/ShiftMediaProject/libvpx](https://github.com/ShiftMediaProject/libvpx), modify it, and pack it to archive.
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
#include "DlgBase.h"
|
|
||||||
|
|
||||||
void DlgBase::MakeComboEdit(UINT id, DWORD s)
|
|
||||||
{
|
|
||||||
HWND w = GetDlgItem(wnd, id);
|
|
||||||
RECT r;
|
|
||||||
GetChildRect(id, r);
|
|
||||||
DestroyWindow(w);
|
|
||||||
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", 0, WS_CHILD | s, r.left - 1, r.top - 1, r.right - r.left, r.bottom - r.top, wnd, (HMENU)id, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DlgBase::GetChildRect(UINT id, RECT& child)
|
|
||||||
{
|
|
||||||
RECT r_parent, r_child;
|
|
||||||
GetWindowRect(wnd, &r_parent);
|
|
||||||
GetWindowRect(GetDlgItem(wnd, id), &r_child);
|
|
||||||
int dx = r_parent.left;
|
|
||||||
int dy = r_parent.top;
|
|
||||||
if (!(GetWindowLong(wnd, GWL_STYLE)&WS_CHILD))
|
|
||||||
{
|
|
||||||
dy += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME);
|
|
||||||
dx += GetSystemMetrics(SM_CXDLGFRAME);
|
|
||||||
}
|
|
||||||
child.left = r_child.left - dx;
|
|
||||||
child.right = r_child.right - dx;
|
|
||||||
child.top = r_child.top - dy;
|
|
||||||
child.bottom = r_child.bottom - dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DlgBase::do_sizing(UINT wp, RECT * r)
|
|
||||||
{
|
|
||||||
UINT dx, dy;
|
|
||||||
dx = r->right - r->left;
|
|
||||||
dy = r->bottom - r->top;
|
|
||||||
if (dx < min_size_x_w)
|
|
||||||
{
|
|
||||||
switch (wp)
|
|
||||||
{
|
|
||||||
case WMSZ_BOTTOMLEFT:
|
|
||||||
case WMSZ_LEFT:
|
|
||||||
case WMSZ_TOPLEFT:
|
|
||||||
r->left = r->right - min_size_x_w;
|
|
||||||
break;
|
|
||||||
case WMSZ_BOTTOMRIGHT:
|
|
||||||
case WMSZ_RIGHT:
|
|
||||||
case WMSZ_TOPRIGHT:
|
|
||||||
r->right = r->left + min_size_x_w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dy < min_size_y_w)
|
|
||||||
{
|
|
||||||
switch (wp)
|
|
||||||
{
|
|
||||||
case WMSZ_BOTTOMLEFT:
|
|
||||||
case WMSZ_BOTTOM:
|
|
||||||
case WMSZ_BOTTOMRIGHT:
|
|
||||||
r->bottom = r->top + min_size_y_w;
|
|
||||||
break;
|
|
||||||
case WMSZ_TOPLEFT:
|
|
||||||
case WMSZ_TOP:
|
|
||||||
case WMSZ_TOPRIGHT:
|
|
||||||
r->top = r->bottom - min_size_y_w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
#include <windows.h>
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
static void SetWindowRect(HWND w, RECT * r)
|
|
||||||
{
|
|
||||||
SetWindowPos(w, 0, r->left, r->top, r->right - r->left, r->bottom - r->top, SWP_NOZORDER | SWP_NOCOPYBITS);
|
|
||||||
}
|
|
||||||
|
|
||||||
class DlgBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BOOL isDialogMessage(MSG * m)
|
|
||||||
{
|
|
||||||
return wnd ? IsDialogMessage(wnd, m) : 0;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
void endDialog(int x)
|
|
||||||
{
|
|
||||||
EndDialog(wnd, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _do_size_x(RECT * r, UINT id, UINT wx, UINT min_x)
|
|
||||||
{
|
|
||||||
RECT r1 = {r->left, r->top, wx - min_x + r->right, r->bottom};
|
|
||||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _do_size_xy(RECT * r, UINT id, UINT wx, UINT wy, UINT min_x, UINT min_y)
|
|
||||||
{
|
|
||||||
RECT r1 = {r->left, r->top, wx - min_x + r->right, wy - min_y + r->bottom};
|
|
||||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _do_align_x_size_y(RECT * r, UINT id, UINT wx, UINT wy, UINT min_x, UINT min_y)
|
|
||||||
{
|
|
||||||
RECT r1 = {wx - min_x + r->left, r->top, wx - min_x + r->right, wy - min_y + r->bottom};
|
|
||||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _do_align_x(RECT * r, UINT id, UINT wx, UINT min_x)
|
|
||||||
{
|
|
||||||
RECT r1 = {wx - min_x + r->left, r->top, wx - min_x + r->right, r->bottom};
|
|
||||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _do_align_xy(RECT * r, UINT id, UINT wx, UINT wy, UINT min_x, UINT min_y)
|
|
||||||
{
|
|
||||||
RECT r1 = {wx - min_x + r->left, wy - min_y + r->top, wx - min_x + r->right, wy - min_y + r->bottom};
|
|
||||||
SetWindowRect(GetDlgItem(wnd, id), &r1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define do_size_x(id,r) _do_size_x(r,id,sx,min_size_x)
|
|
||||||
#define do_size_xy(id,r) _do_size_xy(r,id,sx,sy,min_size_x,min_size_y)
|
|
||||||
#define do_align_x_size_y(id,r) _do_align_x_size_y(r,id,sx,sy,min_size_x,min_size_y)
|
|
||||||
#define do_align_xy(id,r) _do_align_xy(r,id,sx,sy,min_size_x,min_size_y)
|
|
||||||
#define do_align_x(id,r) _do_align_x(r,id,sx,min_size_x)
|
|
||||||
|
|
||||||
HWND wnd;
|
|
||||||
UINT min_size_x, min_size_y;
|
|
||||||
UINT min_size_x_w, min_size_y_w;
|
|
||||||
|
|
||||||
void do_sizing(UINT wp, RECT * r);
|
|
||||||
void MakeComboEdit(UINT id, DWORD s);
|
|
||||||
void GetChildRect(UINT id, RECT& child);
|
|
||||||
|
|
||||||
virtual BOOL DlgProc(UINT msg, WPARAM wp, LPARAM lp) { return 0;};
|
|
||||||
static BOOL CALLBACK TheDialogProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
|
|
||||||
{
|
|
||||||
DlgBase * p;
|
|
||||||
if (msg == WM_INITDIALOG)
|
|
||||||
{
|
|
||||||
p = (DlgBase*)lp;
|
|
||||||
SetWindowLong(wnd, DWL_USER, lp);
|
|
||||||
p->wnd = wnd;
|
|
||||||
RECT r;
|
|
||||||
GetClientRect(wnd, &r);
|
|
||||||
p->min_size_x = r.right;
|
|
||||||
p->min_size_y = r.bottom;
|
|
||||||
GetWindowRect(wnd, &r);
|
|
||||||
p->min_size_x_w = r.right - r.left;
|
|
||||||
p->min_size_y_w = r.bottom - r.top;
|
|
||||||
}
|
|
||||||
else p = (DlgBase*)GetWindowLong(wnd, DWL_USER);
|
|
||||||
BOOL rv = 0;
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
rv = p->DlgProc(msg, wp, lp);
|
|
||||||
if (msg == WM_DESTROY)
|
|
||||||
{
|
|
||||||
p->wnd = 0;
|
|
||||||
SetWindowLong(wnd, DWL_USER, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
HWND myCreateDialog(UINT id, HWND parent)
|
|
||||||
{
|
|
||||||
return CreateDialogParamT(hIns, (char*)id, parent, TheDialogProc, (long)this);
|
|
||||||
}
|
|
||||||
virtual void myProcessMessage(MSG * msg)
|
|
||||||
{
|
|
||||||
if (!IsDialogMessage(wnd, msg))
|
|
||||||
{
|
|
||||||
TranslateMessage(msg);
|
|
||||||
DispatchMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int myDialogBox(UINT id, HWND parent)
|
|
||||||
{
|
|
||||||
return DialogBoxParamT(hIns, (char*)id, parent, TheDialogProc, (long)this);
|
|
||||||
}
|
|
||||||
DlgBase() {
|
|
||||||
wnd = 0;
|
|
||||||
min_size_x = min_size_y = min_size_x_w = min_size_y_w = 0;
|
|
||||||
}
|
|
||||||
virtual ~DlgBase() {}
|
|
||||||
};
|
|
@ -1,65 +0,0 @@
|
|||||||
#include "main.h"
|
|
||||||
#include "decoder.h"
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
//returns handle!=0 if successful, 0 if error
|
|
||||||
//size will return the final nb of bytes written to the output, -1 if unknown
|
|
||||||
__declspec( dllexport ) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate) {
|
|
||||||
VorbisFile * f = VorbisFile::Create(fn,false);
|
|
||||||
if(f) {
|
|
||||||
if(!*bps) *bps=16; // FUCKO HAX
|
|
||||||
Decoder * d = new Decoder();
|
|
||||||
d->Init(f, *bps, *nch, false, false);
|
|
||||||
*nch = (int)d->nch;
|
|
||||||
*srate = (int)d->sr;
|
|
||||||
*bps = (int)d->bps;
|
|
||||||
*size = (int)(f->Length() * (double)((*nch) * (*srate) * (*bps/8)));
|
|
||||||
return (intptr_t)d;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec( dllexport ) intptr_t winampGetExtendedRead_openW_float(const wchar_t *fn, int *size, int *bps, int *nch, int *srate) {
|
|
||||||
VorbisFile * f = VorbisFile::Create(fn,false);
|
|
||||||
if(f) {
|
|
||||||
Decoder * d = new Decoder();
|
|
||||||
d->Init(f, *bps, *nch, true, false);
|
|
||||||
*nch = (int)d->nch;
|
|
||||||
*srate = (int)d->sr;
|
|
||||||
*bps = (int)d->bps;
|
|
||||||
*size = (int)(f->Length() * (double)((*nch) * (*srate) * (*bps/8)));
|
|
||||||
return (intptr_t)d;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//returns nb of bytes read. -1 if read error (like CD ejected). if (ret<len), EOF is assumed
|
|
||||||
__declspec( dllexport ) intptr_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch) {
|
|
||||||
Decoder * d = (Decoder *)handle;
|
|
||||||
size_t used = 0;
|
|
||||||
for(;;) {
|
|
||||||
used += (UINT)d->Read((UINT)(len - used),dest + used);
|
|
||||||
if(used >= len) break;
|
|
||||||
if(!d->DoFrame()) break;
|
|
||||||
if(*killswitch) break;
|
|
||||||
if (used)
|
|
||||||
return used;
|
|
||||||
}
|
|
||||||
return used;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return nonzero on success, zero on failure.
|
|
||||||
__declspec( dllexport ) int winampGetExtendedRead_setTime(intptr_t handle, int millisecs) {
|
|
||||||
Decoder * d = (Decoder *)handle;
|
|
||||||
d->Flush();
|
|
||||||
return !d->Seek(((double)millisecs) / 1000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec( dllexport ) void winampGetExtendedRead_close(intptr_t handle) {
|
|
||||||
Decoder * d = (Decoder *)handle;
|
|
||||||
d->Flush();
|
|
||||||
delete d->file;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,264 +0,0 @@
|
|||||||
#include "main.h"
|
|
||||||
#include "api__in_vorbis.h"
|
|
||||||
#include "resource.h"
|
|
||||||
#include <strsafe.h>
|
|
||||||
|
|
||||||
/*static UINT xiphframes_ids[12]={IDB_BITMAP1,IDB_BITMAP2,IDB_BITMAP3,IDB_BITMAP4,IDB_BITMAP5,IDB_BITMAP6,IDB_BITMAP7,IDB_BITMAP8,IDB_BITMAP9,IDB_BITMAP10,IDB_BITMAP11,IDB_BITMAP12};
|
|
||||||
static HBITMAP xiphframes[12];*/
|
|
||||||
|
|
||||||
static UINT xiphframes_ids[12]={IDB_PNG1,IDB_PNG2,IDB_PNG3,IDB_PNG4,IDB_PNG5,IDB_PNG6,IDB_PNG7,IDB_PNG8,IDB_PNG9,IDB_PNG10,IDB_PNG11,IDB_PNG12};
|
|
||||||
static ARGB32 *xiphframes[12] = {0};
|
|
||||||
static HBITMAP xiphframesBmp[12] = {0};
|
|
||||||
|
|
||||||
static void slap(HWND wnd,int v)
|
|
||||||
{
|
|
||||||
long hi=GetWindowLong(wnd,4);
|
|
||||||
if (v) hi+=v*1000;
|
|
||||||
else hi=0;
|
|
||||||
SetWindowLong(wnd,4,hi);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CfgInt cfg_rpm("rpm",0);
|
|
||||||
|
|
||||||
static int visible_rpm,visible_max_rpm;
|
|
||||||
static char show_rpm=0;
|
|
||||||
static DWORD last_visible_rpm;
|
|
||||||
|
|
||||||
ARGB32 * loadImg(const void * data, int len, int *w, int *h, bool ldata=false)
|
|
||||||
{
|
|
||||||
FOURCC imgload = svc_imageLoader::getServiceType();
|
|
||||||
int n = (int)mod.service->service_getNumServices(imgload);
|
|
||||||
for(int i=0; i<n; i++)
|
|
||||||
{
|
|
||||||
waServiceFactory *sf = mod.service->service_enumService(imgload,i);
|
|
||||||
if(sf)
|
|
||||||
{
|
|
||||||
svc_imageLoader * l = (svc_imageLoader*)sf->getInterface();
|
|
||||||
if(l)
|
|
||||||
{
|
|
||||||
if(l->testData(data,len))
|
|
||||||
{
|
|
||||||
ARGB32* ret;
|
|
||||||
if(ldata) ret = l->loadImageData(data,len,w,h);
|
|
||||||
else ret = l->loadImage(data,len,w,h);
|
|
||||||
sf->releaseInterface(l);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
sf->releaseInterface(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ARGB32 * loadRrc(int id, wchar_t * sec, int *w, int *h, bool data=false)
|
|
||||||
{
|
|
||||||
DWORD size=0;
|
|
||||||
HGLOBAL resourceHandle = WASABI_API_LOADRESFROMFILEW(sec, MAKEINTRESOURCEW(id), &size);
|
|
||||||
if(resourceHandle)
|
|
||||||
{
|
|
||||||
ARGB32* ret = loadImg(resourceHandle,size,w,h,data);
|
|
||||||
UnlockResource(resourceHandle);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LRESULT WINAPI XiphProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)
|
|
||||||
{
|
|
||||||
switch(msg)
|
|
||||||
{
|
|
||||||
case WM_CREATE:
|
|
||||||
SetWindowLong(wnd,8,last_visible_rpm=GetTickCount());
|
|
||||||
SetTimer(wnd,666,10,0);
|
|
||||||
visible_rpm=-1;
|
|
||||||
visible_max_rpm=-1;
|
|
||||||
show_rpm=0;
|
|
||||||
break;
|
|
||||||
case WM_TIMER:
|
|
||||||
if (wp==666)
|
|
||||||
{
|
|
||||||
long low=GetWindowLong(wnd,0);
|
|
||||||
long hi=GetWindowLong(wnd,4);
|
|
||||||
|
|
||||||
long org=low&~0xFFFF;
|
|
||||||
|
|
||||||
int rpm=MulDiv(abs(hi),1000*60,12*0x10000);
|
|
||||||
|
|
||||||
DWORD t=GetTickCount();
|
|
||||||
DWORD ot=(DWORD)SetWindowLong(wnd,8,t);
|
|
||||||
bool redraw=0;
|
|
||||||
|
|
||||||
if (rpm>25) show_rpm=1;
|
|
||||||
if (cfg_rpm<rpm) cfg_rpm=rpm;
|
|
||||||
|
|
||||||
if (show_rpm && (t&~0x3F)!=(ot&~0x3F))
|
|
||||||
{
|
|
||||||
wchar_t foo[128] = {0};
|
|
||||||
if (visible_rpm<rpm || (visible_rpm>rpm && (t-last_visible_rpm)>333))
|
|
||||||
{
|
|
||||||
last_visible_rpm=t;
|
|
||||||
visible_rpm=rpm;
|
|
||||||
StringCchPrintfW(foo,128,WASABI_API_LNGSTRINGW(IDS_GAME_SPEED),rpm);
|
|
||||||
SetDlgItemTextW(GetParent(wnd),IDC_RPM,foo);
|
|
||||||
}
|
|
||||||
if (visible_max_rpm!=cfg_rpm)
|
|
||||||
{
|
|
||||||
visible_max_rpm=cfg_rpm;
|
|
||||||
StringCchPrintfW(foo,128,WASABI_API_LNGSTRINGW(IDS_BEST_RPM),(int)cfg_rpm);
|
|
||||||
SetDlgItemTextW(GetParent(wnd),IDC_RPM2,foo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
low+=hi*(t-ot);
|
|
||||||
while(low<0) low+=12*0x10000;
|
|
||||||
while(low>=12*0x10000) low-=12*0x10000;
|
|
||||||
|
|
||||||
{
|
|
||||||
int z=hi>>6;
|
|
||||||
if (z) hi-=z;
|
|
||||||
else if (hi>0) hi--;
|
|
||||||
else if (hi<0) hi++;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWindowLong(wnd,0,low);
|
|
||||||
SetWindowLong(wnd,4,hi);
|
|
||||||
if (redraw || (low&~0xFFFF)!=org)
|
|
||||||
{
|
|
||||||
RedrawWindow(wnd,0,0,RDW_INVALIDATE);
|
|
||||||
}
|
|
||||||
KillTimer(wnd,666);
|
|
||||||
SetTimer(wnd,666,10,0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WM_LBUTTONDOWN:
|
|
||||||
slap(wnd,-1);
|
|
||||||
break;
|
|
||||||
case WM_RBUTTONDOWN:
|
|
||||||
slap(wnd,1);
|
|
||||||
break;
|
|
||||||
case WM_MBUTTONDOWN:
|
|
||||||
slap(wnd,0);
|
|
||||||
break;
|
|
||||||
case WM_PAINT:
|
|
||||||
{
|
|
||||||
int i=(GetWindowLong(wnd,0))>>16;
|
|
||||||
HDC dc = CreateCompatibleDC(0);
|
|
||||||
|
|
||||||
if (!xiphframesBmp[i])
|
|
||||||
{
|
|
||||||
int cur_w = 0, cur_h = 0;
|
|
||||||
xiphframes[i] = loadRrc(xiphframes_ids[i], L"PNG", &cur_w, &cur_h, true);
|
|
||||||
|
|
||||||
BITMAPINFO bmi = {0};
|
|
||||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
||||||
bmi.bmiHeader.biWidth = cur_w;
|
|
||||||
bmi.bmiHeader.biHeight = -cur_h;
|
|
||||||
bmi.bmiHeader.biPlanes = 1;
|
|
||||||
bmi.bmiHeader.biBitCount = 32;
|
|
||||||
bmi.bmiHeader.biCompression = BI_RGB;
|
|
||||||
void *bits = 0;
|
|
||||||
if(xiphframesBmp[i]) DeleteObject(xiphframesBmp[i]);
|
|
||||||
xiphframesBmp[i] = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
|
|
||||||
memcpy(bits, xiphframes[i], cur_w * cur_h * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xiphframesBmp[i])
|
|
||||||
{
|
|
||||||
HGDIOBJ foo = SelectObject(dc, xiphframesBmp[i]);
|
|
||||||
HDC wdc = GetDC(wnd);
|
|
||||||
RECT r = {0};
|
|
||||||
GetClientRect(wnd, &r);
|
|
||||||
FillRect(wdc, &r, GetSysColorBrush(COLOR_3DFACE));
|
|
||||||
|
|
||||||
BLENDFUNCTION blendFn = {0};
|
|
||||||
blendFn.BlendOp = AC_SRC_OVER;
|
|
||||||
blendFn.SourceConstantAlpha = 255;
|
|
||||||
blendFn.AlphaFormat = AC_SRC_ALPHA;
|
|
||||||
AlphaBlend(wdc, 2, 2, r.right - 2, r.bottom - 2, dc, 0, 0, 63, 63, blendFn);
|
|
||||||
|
|
||||||
ReleaseDC(wnd, wdc);
|
|
||||||
SelectObject(dc, foo);
|
|
||||||
}
|
|
||||||
DeleteDC(dc);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WM_DESTROY:
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ARRAYSIZE(xiphframes_ids); i++)
|
|
||||||
{
|
|
||||||
if(xiphframesBmp[i]) DeleteObject(xiphframesBmp[i]); xiphframesBmp[i] = 0;
|
|
||||||
if(xiphframes[i] && WASABI_API_MEMMGR) WASABI_API_MEMMGR->sysFree((void *)xiphframes[i]); xiphframes[i] = 0;
|
|
||||||
}
|
|
||||||
KillTimer(wnd,666);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return DefWindowProc(wnd,msg,wp,lp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CALLBACK AboutProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)
|
|
||||||
{
|
|
||||||
switch(msg)
|
|
||||||
{
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
{
|
|
||||||
wchar_t tmp[1024] = {0}, tmp2[1024] = {0}, *t1 = tmp, *t2 = tmp2, text[1024] = {0};
|
|
||||||
SetWindowTextW(wnd,WASABI_API_LNGSTRINGW_BUF(IDS_NULLSOFT_VORBIS_DECODER_OLD,text,1024));
|
|
||||||
StringCchPrintfW(tmp,1024,WASABI_API_LNGSTRINGW(IDS_ABOUT_TEXT),mod.description,__DATE__);
|
|
||||||
// due to quirks with the more common resource editors, is easier to just store the string
|
|
||||||
// internally only with \n and post-process to be \r\n (as here) so it will appear correctly
|
|
||||||
// on new lines as is wanted (silly multiline edit controls)
|
|
||||||
while(t1 && *t1 && (t2 - tmp2 < 1024))
|
|
||||||
{
|
|
||||||
if(*t1 == L'\n')
|
|
||||||
{
|
|
||||||
*t2 = L'\r';
|
|
||||||
t2 = CharNextW(t2);
|
|
||||||
}
|
|
||||||
*t2 = *t1;
|
|
||||||
t1 = CharNextW(t1);
|
|
||||||
t2 = CharNextW(t2);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetDlgItemTextW(wnd,IDC_ABOUT_TEXT,tmp2);
|
|
||||||
// fixes the incorrect selection of the text on dialog opening
|
|
||||||
PostMessage(GetDlgItem(wnd,IDC_ABOUT_TEXT),EM_SETSEL,-1,0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
case WM_COMMAND:
|
|
||||||
if (wp==IDOK || wp==IDCANCEL)
|
|
||||||
{
|
|
||||||
do_cfg(1);
|
|
||||||
EndDialog(wnd,0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void About(HWND hwndParent)
|
|
||||||
{
|
|
||||||
static char got_xiph;
|
|
||||||
if (!got_xiph)
|
|
||||||
{
|
|
||||||
WNDCLASS wc=
|
|
||||||
{
|
|
||||||
0,
|
|
||||||
XiphProc,
|
|
||||||
0,
|
|
||||||
12,
|
|
||||||
WASABI_API_LNG_HINST,
|
|
||||||
0,
|
|
||||||
LoadCursor(0,IDC_ARROW),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
L"XIPH_CLASS",
|
|
||||||
};
|
|
||||||
|
|
||||||
RegisterClassW(&wc);
|
|
||||||
got_xiph=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
WASABI_API_DIALOGBOXW(IDD_ABOUT,hwndParent,AboutProc);
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
#ifndef NULLSOFT_API_H
|
|
||||||
#define NULLSOFT_API_H
|
|
||||||
|
|
||||||
#include "../Agave/Config/api_config.h"
|
|
||||||
#include "../Agave/Language/api_language.h"
|
|
||||||
|
|
||||||
#include <api/application/api_application.h>
|
|
||||||
extern api_application *applicationApi;
|
|
||||||
#define WASABI_API_APP applicationApi
|
|
||||||
|
|
||||||
#include <api/service/svcs/svc_imgload.h>
|
|
||||||
|
|
||||||
#include <api/service/api_service.h>
|
|
||||||
|
|
||||||
#include <api/service/waServiceFactory.h>
|
|
||||||
|
|
||||||
#include <api/memmgr/api_memmgr.h>
|
|
||||||
extern api_memmgr *memmgrApi;
|
|
||||||
#define WASABI_API_MEMMGR memmgrApi
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,96 +0,0 @@
|
|||||||
#define STRICT
|
|
||||||
#include <windows.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "c_string.h"
|
|
||||||
#include "../nu/ns_wc.h"
|
|
||||||
|
|
||||||
extern BOOL is_nt;
|
|
||||||
|
|
||||||
template<class myChar>
|
|
||||||
void string_base<myChar>::makespace(UINT s)
|
|
||||||
{
|
|
||||||
if (size<s)
|
|
||||||
{
|
|
||||||
int oldSize = size;
|
|
||||||
do size<<=1; while(size<s);
|
|
||||||
myChar *newPtr = (myChar*)realloc(ptr,size*sizeof(myChar));
|
|
||||||
if (!newPtr)
|
|
||||||
{
|
|
||||||
newPtr = (myChar*)malloc(size*sizeof(myChar));
|
|
||||||
if (newPtr)
|
|
||||||
{
|
|
||||||
memcpy(newPtr, ptr, oldSize*sizeof(myChar));
|
|
||||||
free(ptr);
|
|
||||||
ptr = newPtr;
|
|
||||||
}
|
|
||||||
else return ;
|
|
||||||
}
|
|
||||||
else ptr = newPtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::s_GetWindowText(HWND w)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
int len=GetWindowTextLengthA(w)+1;
|
|
||||||
GetWindowTextA(w,StringTempA(*this,len),len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringW::s_GetWindowText(HWND w)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
int len=GetWindowTextLengthW(w)+1;
|
|
||||||
GetWindowTextW(w,StringTempW(*this,len),len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::SetStringW(const WCHAR * c)
|
|
||||||
{
|
|
||||||
UINT len=(lstrlenW(c)+1)*2;
|
|
||||||
WideCharToMultiByteSZ(CP_ACP,0,c,-1,StringTempA(*this,len),len,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringW::SetStringA(const char * c)
|
|
||||||
{
|
|
||||||
UINT len=(UINT)strlen(c)+1;
|
|
||||||
MultiByteToWideCharSZ(CP_ACP,0,c,-1,StringTempW(*this,len),len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::AddStringW(const WCHAR * c)
|
|
||||||
{
|
|
||||||
AddString(String(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringW::AddStringA(const char * c)
|
|
||||||
{
|
|
||||||
AddString(StringW(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::s_SetWindowText(HWND w)
|
|
||||||
{
|
|
||||||
SetWindowTextA(w,*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringW::s_SetWindowText(HWND w)
|
|
||||||
{
|
|
||||||
SetWindowTextW(w,*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StringPrintf::StringPrintf(const char * fmt,...)
|
|
||||||
{
|
|
||||||
va_list list;
|
|
||||||
va_start(list,fmt);
|
|
||||||
vsprintf(StringTempA(*this,1024),fmt,list);
|
|
||||||
va_end(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringPrintfW::StringPrintfW(const WCHAR * fmt,...)
|
|
||||||
{
|
|
||||||
va_list list;
|
|
||||||
va_start(list,fmt);
|
|
||||||
vswprintf(StringTempW(*this,1024),1024,fmt,list);
|
|
||||||
va_end(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(const StringW & z) {AddStringW(z);}
|
|
@ -1,156 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
template <class myChar>
|
|
||||||
class string_base
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
myChar * ptr;
|
|
||||||
UINT size,used;
|
|
||||||
void makespace(UINT s);
|
|
||||||
static UINT mylen(const myChar * p) {UINT r=0;while(p[r]) r++;return r;}
|
|
||||||
public:
|
|
||||||
void AddChar(myChar c)
|
|
||||||
{
|
|
||||||
makespace(used+2);
|
|
||||||
ptr[used++]=c;
|
|
||||||
ptr[used]=0;
|
|
||||||
}
|
|
||||||
string_base()
|
|
||||||
{
|
|
||||||
used=0;
|
|
||||||
size=128;
|
|
||||||
ptr=(myChar*)malloc(size*sizeof(myChar));
|
|
||||||
ptr[0]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~string_base() { if (ptr) free(ptr);}
|
|
||||||
|
|
||||||
operator const myChar*() const {return ptr;}
|
|
||||||
|
|
||||||
const myChar & operator*() const {return *ptr;}
|
|
||||||
|
|
||||||
UINT Length() const {return used;}
|
|
||||||
|
|
||||||
void AddString(const myChar * c)
|
|
||||||
{
|
|
||||||
UINT d=mylen(c);
|
|
||||||
makespace(used+d+1);
|
|
||||||
memcpy(ptr+used,c,sizeof(myChar)*d);
|
|
||||||
used+=d;
|
|
||||||
ptr[used]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reset() {Truncate(0);}
|
|
||||||
void Truncate(UINT x) {if (used>x) {used=x;ptr[x]=0;}}
|
|
||||||
|
|
||||||
void SetString(const myChar * s) {Reset();AddString(s);}
|
|
||||||
|
|
||||||
myChar * BufferStart(UINT n)
|
|
||||||
{
|
|
||||||
makespace(n+1);
|
|
||||||
memset(ptr,0,size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BufferDone() {used=mylen(ptr);}
|
|
||||||
|
|
||||||
void SetChar(UINT offset,myChar c)//hack for some ghey routines
|
|
||||||
{
|
|
||||||
if (!c) Truncate(offset);
|
|
||||||
else if (offset<used) ptr[offset]=c;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class myChar>
|
|
||||||
class StringTemp
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
string_base<myChar> * parent;
|
|
||||||
myChar * data;
|
|
||||||
public:
|
|
||||||
StringTemp(string_base<myChar> & s,UINT siz) {parent=&s;data=s.BufferStart(siz);}
|
|
||||||
~StringTemp() {parent->BufferDone();}
|
|
||||||
operator myChar* () {return data;}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define StringTempW StringTemp<WCHAR>
|
|
||||||
#define StringTempA StringTemp<char>
|
|
||||||
|
|
||||||
class StringW;
|
|
||||||
|
|
||||||
class String : public string_base<char>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
String() {}
|
|
||||||
String(HWND w) {s_GetWindowText(w);}
|
|
||||||
String(const char* z) {SetString(z);}
|
|
||||||
String(const WCHAR* z) {SetStringW(z);}
|
|
||||||
String(const String& z) {SetString(z);}
|
|
||||||
String(const StringW& z);
|
|
||||||
void AddStringW(const WCHAR * c);
|
|
||||||
void SetStringW(const WCHAR * c);
|
|
||||||
void s_GetWindowText(HWND w);
|
|
||||||
void s_SetWindowText(HWND w);
|
|
||||||
void operator=(const char * s) {SetString(s);}
|
|
||||||
void operator+=(const char * s) {AddString(s);}
|
|
||||||
void operator=(String & s) {SetString(s);}
|
|
||||||
void operator+=(String & s) {AddString(s);}
|
|
||||||
inline void s_GetDlgItemText(HWND w,UINT id) {s_GetWindowText(GetDlgItem(w,id));}
|
|
||||||
inline void s_SetDlgItemText(HWND w,UINT id) {s_SetWindowText(GetDlgItem(w,id));}
|
|
||||||
};
|
|
||||||
|
|
||||||
class StringW : public string_base<WCHAR>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringW() {}
|
|
||||||
StringW(HWND w) {s_GetWindowText(w);}
|
|
||||||
StringW(const WCHAR * z) {SetString(z);}
|
|
||||||
void AddStringA(const char * c);
|
|
||||||
void SetStringA(const char * c);
|
|
||||||
StringW(const char * z) {SetStringA(z);}
|
|
||||||
StringW(const StringW & z) {SetString(z);}
|
|
||||||
StringW(const String & z) {SetStringA(z);}
|
|
||||||
void s_GetWindowText(HWND w);
|
|
||||||
void s_SetWindowText(HWND w);
|
|
||||||
void operator=(const WCHAR * s) {SetString(s);}
|
|
||||||
void operator+=(const WCHAR * s) { if (s) AddString(s);}
|
|
||||||
void operator=(StringW & s) {SetString(s);}
|
|
||||||
void operator+=(StringW & s) {AddString(s);}
|
|
||||||
inline void s_GetDlgItemText(HWND w,UINT id) {s_GetWindowText(GetDlgItem(w,id));}
|
|
||||||
inline void s_SetDlgItemText(HWND w,UINT id) {s_SetWindowText(GetDlgItem(w,id));}
|
|
||||||
bool reg_read(const char *name);
|
|
||||||
void reg_write(const char *name);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class StringPrintf : public String
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringPrintf(const char * fmt,...);
|
|
||||||
};
|
|
||||||
|
|
||||||
class StringPrintfW : public StringW
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringPrintfW(const WCHAR * fmt,...);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class myChar>
|
|
||||||
class StringF2T : public string_base<myChar>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringF2T(const myChar * fn)
|
|
||||||
{
|
|
||||||
const myChar * ptr=fn,*dot=0,*src=fn;
|
|
||||||
while(ptr && *ptr)
|
|
||||||
{
|
|
||||||
if (*ptr=='\\' || *ptr=='/' || *ptr==':') src=ptr+1;
|
|
||||||
else if (*ptr=='.') dot=ptr;
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(src && *src && (!dot || src<dot)) AddChar(*(src++));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define StringF2T_A StringF2T<char>
|
|
||||||
#define StringF2T_W StringF2T<WCHAR>
|
|
@ -1,82 +0,0 @@
|
|||||||
#include <windows.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <ogg/ogg.h>
|
|
||||||
#include <vorbis/vorbisfile.h>
|
|
||||||
|
|
||||||
static size_t callback_fread(void *ptr, size_t size, size_t nmemb, HANDLE hFile)
|
|
||||||
{
|
|
||||||
DWORD bw = 0;
|
|
||||||
ReadFile(hFile,ptr,(DWORD)(size*nmemb),&bw,0);
|
|
||||||
return bw/size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t callback_write(void * ptr, size_t size, size_t nmemb, HANDLE hFile)
|
|
||||||
{
|
|
||||||
DWORD bw = 0;
|
|
||||||
WriteFile(hFile,ptr,(DWORD)(size*nmemb),&bw,0);
|
|
||||||
return bw/size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int callback_fseek(HANDLE hFile, __int64 offset, int whence)
|
|
||||||
{
|
|
||||||
__int64 temp = offset;
|
|
||||||
SetFilePointer(hFile,*(DWORD*)&temp,((long*)&temp+1),whence);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int callback_fclose(HANDLE f)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __int64 callback_ftell(HANDLE hFile)
|
|
||||||
{
|
|
||||||
__int64 ret=0;
|
|
||||||
*(DWORD*)&ret = SetFilePointer(hFile,0,((long*)&ret+1),FILE_CURRENT);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* callbacks[4]=
|
|
||||||
{
|
|
||||||
callback_fread,callback_fseek,callback_fclose,callback_ftell
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace ogg_helper
|
|
||||||
{
|
|
||||||
int num_get_tracks(HANDLE hFile/*track_indexer::callback * out,reader * r*/)
|
|
||||||
{
|
|
||||||
SetFilePointer(hFile,0,0,FILE_BEGIN);
|
|
||||||
OggVorbis_File l_vf;
|
|
||||||
memset(&l_vf,0,sizeof(l_vf));
|
|
||||||
if (ov_open_callbacks(hFile,&l_vf,0,0,*(ov_callbacks*)callbacks))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int rv = l_vf.links;
|
|
||||||
ov_clear(&l_vf);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int query_chained_stream_offset(HANDLE hFile,int idx,__int64 * out_beginning,__int64 * out_end)
|
|
||||||
{
|
|
||||||
SetFilePointer(hFile,0,0,FILE_BEGIN);
|
|
||||||
OggVorbis_File l_vf;
|
|
||||||
memset(&l_vf,0,sizeof(l_vf));
|
|
||||||
if (ov_open_callbacks(hFile,&l_vf,0,0,*(ov_callbacks*)callbacks))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int retval = 0;
|
|
||||||
if (idx>=0 && idx<l_vf.links)
|
|
||||||
{
|
|
||||||
retval = 1;
|
|
||||||
*out_beginning = l_vf.offsets[idx];
|
|
||||||
*out_end = l_vf.offsets[idx+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
ov_clear(&l_vf);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,335 +0,0 @@
|
|||||||
#include "main.h"
|
|
||||||
#include "api__in_vorbis.h"
|
|
||||||
#include "../nu/ns_wc.h"
|
|
||||||
#include <commctrl.h>
|
|
||||||
#include <shlobj.h>
|
|
||||||
#include "../winamp/wa_ipc.h"
|
|
||||||
#include "../nu/AutoChar.h"
|
|
||||||
#include <strsafe.h>
|
|
||||||
|
|
||||||
int mc6_dm_names_ids[]={IDS_LEAVE_AS_IS,IDS_REMAP_6_CHANNELS,IDS_DOWNMIX_TO_4_CHANNELS,IDS_DOWNMIX_TO_2_CHANNELS_DS,IDS_DOWNMIX_TO_2_CHANNELS_DS2,IDS_DOWNMIX_TO_MONO};
|
|
||||||
int mc6_map_names_id[]={IDS_CORRECT_FL_FC_FR_BL_BR_LFE,IDS_BROKEN_FL_FR_FC_BL_BR_LFE};
|
|
||||||
int32_t priority_tab[7]={THREAD_PRIORITY_IDLE,THREAD_PRIORITY_LOWEST,THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL,THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_HIGHEST,THREAD_PRIORITY_TIME_CRITICAL};
|
|
||||||
|
|
||||||
char* defaultDumpDir()
|
|
||||||
{
|
|
||||||
static char dumpdir[MAX_PATH] = {0};
|
|
||||||
if(FAILED(SHGetFolderPathA(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, dumpdir)))
|
|
||||||
{
|
|
||||||
if(FAILED(SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, dumpdir)))
|
|
||||||
{
|
|
||||||
lstrcpynA(dumpdir, "C:\\", MAX_PATH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dumpdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
CfgString
|
|
||||||
cfg_ssave_format("ssave_format","%filename%"),
|
|
||||||
cfg_dumpdir("dumpdir",defaultDumpDir());
|
|
||||||
|
|
||||||
CfgInt
|
|
||||||
cfg_http_bsize("http_bsize",0x10000),
|
|
||||||
cfg_fsave("fsave",0),
|
|
||||||
cfg_abr("abr",0),
|
|
||||||
cfg_proxy_mode("proxy_mode",2),
|
|
||||||
cfg_prebuf1("prebuf1",50),
|
|
||||||
cfg_prebuf2("prebuf2",75),
|
|
||||||
cfg_httpseek2("httpseek2",0),
|
|
||||||
cfg_fix0r("fix0r",1),
|
|
||||||
cfg_mc6_dm("mc6_dm",0),
|
|
||||||
cfg_mc6_map("_mc6_map",0),
|
|
||||||
cfg_remember_infosize("remember_infosize",1),
|
|
||||||
cfg_fullbuf("fullbuf",0),
|
|
||||||
cfg_cur_tab("cur_tab",0);
|
|
||||||
|
|
||||||
static int old_preamp;
|
|
||||||
CfgFont cfg_font("font");
|
|
||||||
static LOGFONT cfg_font_edit;
|
|
||||||
|
|
||||||
BOOL CALLBACK browseEnumProc(HWND hwnd, LPARAM lParam)
|
|
||||||
{
|
|
||||||
char cl[32] = {0};
|
|
||||||
GetClassNameA(hwnd, cl, ARRAYSIZE(cl));
|
|
||||||
if (!lstrcmpiA(cl, WC_TREEVIEWA))
|
|
||||||
{
|
|
||||||
PostMessage(hwnd, TVM_ENSUREVISIBLE, 0, (LPARAM)TreeView_GetSelection(hwnd));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CALLBACK browzaproc(HWND hwnd, UINT msg, LPARAM lp, LPARAM dat)
|
|
||||||
{
|
|
||||||
if (msg == BFFM_INITIALIZED)
|
|
||||||
{
|
|
||||||
SendMessageW(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)dat);
|
|
||||||
|
|
||||||
// this is not nice but it fixes the selection not working correctly on all OSes
|
|
||||||
EnumChildWindows(hwnd, browseEnumProc, 0);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void d_browza(HWND wnd,HWND bt,wchar_t* tx)
|
|
||||||
{
|
|
||||||
IMalloc* pMalloc=0;
|
|
||||||
|
|
||||||
SHGetMalloc(&pMalloc);
|
|
||||||
if (!pMalloc) return;
|
|
||||||
|
|
||||||
wchar_t dir[MAX_PATH] = {0};
|
|
||||||
GetWindowTextW(bt,dir,MAX_PATH);
|
|
||||||
BROWSEINFOW bi=
|
|
||||||
{
|
|
||||||
wnd,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
tx,
|
|
||||||
BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE,
|
|
||||||
browzaproc,
|
|
||||||
(LPARAM)dir,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
ITEMIDLIST* li=SHBrowseForFolderW(&bi);
|
|
||||||
if (li)
|
|
||||||
{
|
|
||||||
SHGetPathFromIDListW(li,dir);
|
|
||||||
SetWindowTextW(bt,dir);
|
|
||||||
pMalloc->Free(li);
|
|
||||||
}
|
|
||||||
|
|
||||||
pMalloc->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CALLBACK CfgProc1(HWND wnd,UINT msg,WPARAM wp,LPARAM lp)
|
|
||||||
{
|
|
||||||
switch(msg)
|
|
||||||
{
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
{
|
|
||||||
wchar_t temp[128] = {0}, cfg_dialog_name[128] = {0};
|
|
||||||
StringCchPrintfW(cfg_dialog_name,128,WASABI_API_LNGSTRINGW(IDS_TITLE_PREFERENCES),
|
|
||||||
WASABI_API_LNGSTRINGW_BUF(IDS_NULLSOFT_VORBIS_DECODER_OLD, temp, 128));
|
|
||||||
SetWindowTextW(wnd,cfg_dialog_name);
|
|
||||||
|
|
||||||
SendDlgItemMessage(wnd,IDC_FULLBUF,BM_SETCHECK,cfg_fullbuf,0);
|
|
||||||
|
|
||||||
UINT n;
|
|
||||||
HWND w=GetDlgItem(wnd,IDC_MC6_DM);
|
|
||||||
for(n=0;n<sizeof(mc6_dm_names_ids)/sizeof(mc6_dm_names_ids[0]);n++)
|
|
||||||
{
|
|
||||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(mc6_dm_names_ids[n]));
|
|
||||||
}
|
|
||||||
SendMessage(w,CB_SETCURSEL,cfg_mc6_dm,0);
|
|
||||||
|
|
||||||
w=GetDlgItem(wnd,IDC_MC6_MAP);
|
|
||||||
for(n=0;n<sizeof(mc6_map_names_id)/sizeof(mc6_map_names_id[0]);n++)
|
|
||||||
{
|
|
||||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(mc6_map_names_id[n]));
|
|
||||||
}
|
|
||||||
SendMessage(w,CB_SETCURSEL,cfg_mc6_map,0);
|
|
||||||
|
|
||||||
SendDlgItemMessage(wnd,IDC_AVG_BR,BM_SETCHECK,cfg_abr,0);
|
|
||||||
|
|
||||||
SetDlgItemInt(wnd,IDC_HTTP_BSIZE,cfg_http_bsize>>10,0);
|
|
||||||
if (cfg_fsave) SendDlgItemMessage(wnd,IDC_FSAVE,BM_SETCHECK,1,0);
|
|
||||||
if (cfg_fix0r) SendDlgItemMessage(wnd,IDC_FIX0R,BM_SETCHECK,1,0);
|
|
||||||
cfg_dumpdir.s_SetDlgItemText(wnd,IDC_STREAM_SAVE);
|
|
||||||
w=GetDlgItem(wnd,IDC_PROXY);
|
|
||||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(IDS_NEVER));
|
|
||||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(IDS_PORT_80_ONLY));
|
|
||||||
SendMessageW(w,CB_ADDSTRING,0,(LPARAM)WASABI_API_LNGSTRINGW(IDS_ALWAYS));
|
|
||||||
SendMessage(w,CB_SETCURSEL,cfg_proxy_mode,0);
|
|
||||||
|
|
||||||
w=GetDlgItem(wnd,IDC_SLIDER1);
|
|
||||||
SendMessage(w,TBM_SETRANGE,0,MAKELONG(1,100));
|
|
||||||
SendMessage(w,TBM_SETPOS,1,cfg_prebuf1);
|
|
||||||
w=GetDlgItem(wnd,IDC_SLIDER2);
|
|
||||||
SendMessage(w,TBM_SETRANGE,0,MAKELONG(1,100));
|
|
||||||
SendMessage(w,TBM_SETPOS,1,cfg_prebuf2);
|
|
||||||
|
|
||||||
cfg_ssave_format.s_SetDlgItemText(wnd,IDC_SSAVE_FMT);
|
|
||||||
SendMessage(wnd,WM_COMMAND,MAKEWPARAM(IDC_FSAVE,BN_CLICKED),(LPARAM)GetDlgItem(wnd,IDC_FSAVE));
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
|
||||||
switch(LOWORD(wp))
|
|
||||||
{
|
|
||||||
case IDC_STREAM_SAVE:
|
|
||||||
d_browza(wnd,(HWND)lp,WASABI_API_LNGSTRINGW(IDS_SELECT_OUTPUT_DIRECTORY));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_SSAVE_FMT_DEF:
|
|
||||||
SetDlgItemText(wnd,IDC_SSAVE_FMT,L"%filename%");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_FSAVE:
|
|
||||||
{
|
|
||||||
int checked = IsDlgButtonChecked(wnd,IDC_FSAVE);
|
|
||||||
EnableWindow(GetDlgItem(wnd,IDC_STREAM_SAVE),checked);
|
|
||||||
EnableWindow(GetDlgItem(wnd,IDC_SSAVE_FMT),checked);
|
|
||||||
EnableWindow(GetDlgItem(wnd,IDC_SSAVE_FMT_DEF),checked);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDOK:
|
|
||||||
case IDCANCEL:
|
|
||||||
{
|
|
||||||
if (LOWORD(wp) == IDOK)
|
|
||||||
{
|
|
||||||
cfg_fullbuf=(int)SendDlgItemMessage(wnd,IDC_FULLBUF,BM_GETCHECK,0,0);
|
|
||||||
|
|
||||||
cfg_mc6_dm=(int)SendDlgItemMessage(wnd,IDC_MC6_DM,CB_GETCURSEL,0,0);
|
|
||||||
cfg_mc6_map=(int)SendDlgItemMessage(wnd,IDC_MC6_MAP,CB_GETCURSEL,0,0);
|
|
||||||
|
|
||||||
cfg_abr=(int)SendDlgItemMessage(wnd,IDC_AVG_BR,BM_GETCHECK,0,0);
|
|
||||||
|
|
||||||
cfg_dumpdir.s_GetDlgItemText(wnd,IDC_STREAM_SAVE);
|
|
||||||
cfg_http_bsize=GetDlgItemInt(wnd,IDC_HTTP_BSIZE,0,0)<<10;
|
|
||||||
cfg_fsave=(int)SendDlgItemMessage(wnd,IDC_FSAVE,BM_GETCHECK,0,0);
|
|
||||||
cfg_fix0r=(int)SendDlgItemMessage(wnd,IDC_FIX0R,BM_GETCHECK,0,0);
|
|
||||||
cfg_proxy_mode=(int)SendDlgItemMessage(wnd,IDC_PROXY,CB_GETCURSEL,0,0);
|
|
||||||
cfg_prebuf1=(int)SendDlgItemMessage(wnd,IDC_SLIDER1,TBM_GETPOS,0,0);
|
|
||||||
cfg_prebuf2=(int)SendDlgItemMessage(wnd,IDC_SLIDER2,TBM_GETPOS,0,0);
|
|
||||||
cfg_ssave_format.s_GetDlgItemText(wnd,IDC_SSAVE_FMT);
|
|
||||||
}
|
|
||||||
do_cfg(1);
|
|
||||||
EndDialog(wnd,(LOWORD(wp) == IDOK));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int controls[] =
|
|
||||||
{
|
|
||||||
IDC_SLIDER1,
|
|
||||||
IDC_SLIDER2,
|
|
||||||
};
|
|
||||||
if (FALSE != WASABI_API_APP->DirectMouseWheel_ProcessDialogMessage(wnd, msg, wp, lp, controls, ARRAYSIZE(controls)))
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern HANDLE hThread;//hack
|
|
||||||
|
|
||||||
void Config(HWND p)
|
|
||||||
{
|
|
||||||
if (WASABI_API_DIALOGBOXPARAMW(IDD_CONFIG,p,CfgProc1,0))
|
|
||||||
{
|
|
||||||
if (hThread) PostMessage(mod.hMainWindow,WM_USER,0,243);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int CfgVar::read_int(const char *inifile, const char *section,const char * name,int def)
|
|
||||||
{
|
|
||||||
return GetPrivateProfileIntA(section, name, def, inifile);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfgVar::write_int(const char *inifile, const char *section, const char * name,int val)
|
|
||||||
{
|
|
||||||
char temp[32] = {0};
|
|
||||||
StringCchPrintfA(temp, 32, "%d", val);
|
|
||||||
WritePrivateProfileStringA(section, name, temp, inifile);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfgVar::write_struct(const char *inifile, const char *section, const char * name, void * ptr,UINT size)
|
|
||||||
{
|
|
||||||
WritePrivateProfileStructA("in_vorbis", name, ptr, size, INI_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CfgVar::read_struct(const char *inifile, const char *section, const char * name,void * ptr,UINT size)
|
|
||||||
{
|
|
||||||
return !!GetPrivateProfileStructA("in_vorbis", name, ptr, size, INI_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_cfg(int s)
|
|
||||||
{
|
|
||||||
#define CFG_VERSION 0x10204
|
|
||||||
|
|
||||||
if (!s)
|
|
||||||
{
|
|
||||||
if (CfgVar::read_int(INI_FILE, "in_vorbis", "version",0)==CFG_VERSION)
|
|
||||||
CfgVar::ReadConfig();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CfgVar::WriteConfig();
|
|
||||||
CfgVar::write_int(INI_FILE, "in_vorbis", "version",CFG_VERSION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CfgVar * CfgVar::list=0;
|
|
||||||
|
|
||||||
void CfgVar::ReadConfig()
|
|
||||||
{
|
|
||||||
CfgVar * p=list;
|
|
||||||
while(p)
|
|
||||||
{
|
|
||||||
p->Read(p->name);
|
|
||||||
p=p->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfgVar::WriteConfig()
|
|
||||||
{
|
|
||||||
CfgVar * p=list;
|
|
||||||
while(p)
|
|
||||||
{
|
|
||||||
p->Write(p->name);
|
|
||||||
p=p->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StringW::reg_read(const char * name)
|
|
||||||
{
|
|
||||||
char utf8_data[2048] = {0};
|
|
||||||
wchar_t utf16_data[2048] = {0};
|
|
||||||
GetPrivateProfileStringA("in_vorbis", name, "@default@", utf8_data, 2048, INI_FILE);
|
|
||||||
if (!strcmp("@default@", utf8_data))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
MultiByteToWideCharSZ(CP_UTF8, 0, utf8_data, -1, utf16_data, 2048);
|
|
||||||
SetString(utf16_data);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringW::reg_write(const char * name)
|
|
||||||
{
|
|
||||||
WritePrivateProfileStringA("in_vorbis", name, AutoChar((const WCHAR *)*this, CP_UTF8), INI_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfgString::Read(const char * name)
|
|
||||||
{
|
|
||||||
reg_read(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfgString::Write(const char * name)
|
|
||||||
{
|
|
||||||
StringW temp;
|
|
||||||
if (temp.reg_read(name))
|
|
||||||
{
|
|
||||||
if (wcscmp(temp,*this)) reg_write(name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (wcscmp(def,*this)) reg_write(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfgInt::Write(const char * name)
|
|
||||||
{
|
|
||||||
if (read_int(INI_FILE, "in_vorbis", name,def)!=value) write_int(INI_FILE, "in_vorbis",name,value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CfgInt::Read(const char * name)
|
|
||||||
{
|
|
||||||
value=read_int(INI_FILE, "in_vorbis", name,def);
|
|
||||||
}
|
|
@ -1,567 +0,0 @@
|
|||||||
|
|
||||||
/* Winamp 3 Player core api v0.1
|
|
||||||
** (c)2000 nullsoft jcf/ct/dk
|
|
||||||
** Notes:
|
|
||||||
** Keep in mind that this header file is subject to change prior to the
|
|
||||||
** release of Winamp 3. The ability to configure plug-ins has yet to be
|
|
||||||
** added and is the first and foremost concern of the engineering team.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __CORE_API_H
|
|
||||||
#define __CORE_API_H
|
|
||||||
/*
|
|
||||||
// Visual C 6 makes big unaligned dlls. the following will correct it
|
|
||||||
#ifndef _DEBUG
|
|
||||||
// release optimizations
|
|
||||||
// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers)
|
|
||||||
#pragma optimize("gsy",on)
|
|
||||||
#pragma comment(linker,"/RELEASE")
|
|
||||||
// set the 512-byte alignment
|
|
||||||
#pragma comment(linker,"/opt:nowin98")
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
// Use Assert in your code to catch errors that shouldn't happen, when compiled in release mode, they are #defined out
|
|
||||||
#ifndef ASSERT
|
|
||||||
#ifdef _DEBUG
|
|
||||||
#define ASSERT(x) if (!(x)) MessageBox(NULL,"ASSERT FAILED: " #x,"ASSERT FAILED in " __FILE__ ,MB_OK|MB_ICONSTOP);
|
|
||||||
#else
|
|
||||||
#define ASSERT(x)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* CLASS DESCRIPTIONS */
|
|
||||||
|
|
||||||
/* WReader
|
|
||||||
** File reader module class, ie. opens and reads files, streams
|
|
||||||
*/
|
|
||||||
class WReader;
|
|
||||||
|
|
||||||
/* WInputInfo
|
|
||||||
** Class that returns information (length, title, metadata) about a specified file
|
|
||||||
*/
|
|
||||||
class WInputInfo;
|
|
||||||
|
|
||||||
/* WInfo_callback
|
|
||||||
** Player's interface that provides Winamp 3 core functions to your WInputInfo classes
|
|
||||||
*/
|
|
||||||
class WInfo_callback;
|
|
||||||
|
|
||||||
/* WInputSource
|
|
||||||
** Input Source manager base class, ie. decodes mp3's, wavs
|
|
||||||
*/
|
|
||||||
class WInputSource;
|
|
||||||
|
|
||||||
/* WOutputFilter
|
|
||||||
** Abstract base class for any Output Filter plug-in, ie. changes pitch, converts format, outputs to speakers
|
|
||||||
*/
|
|
||||||
class WOutputFilter;
|
|
||||||
|
|
||||||
/* WPlayer_callback
|
|
||||||
** Player's interface that provides Winamp 3 core functions to your Input Sources and Output Filter plug-ins
|
|
||||||
** (Getting a reader for opening a file, sending stuff about what's going on to the Winamp 3 core)
|
|
||||||
*/
|
|
||||||
class WPlayer_callback;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WPlayer_callback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/* GetReader
|
|
||||||
** Allows your Input Source and Output Filter plugins to request a reader from Winamp,
|
|
||||||
** so you don't have to worry about opening files or streams
|
|
||||||
*/
|
|
||||||
virtual WReader *GetReader(char *url)=0;
|
|
||||||
|
|
||||||
|
|
||||||
/* The 3 following functions allows your Input Source and Output Filter plugins to send error/warning/status
|
|
||||||
** messages back to the Winamp 3 core
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Error
|
|
||||||
** playback should stop (soundcard driver error, etc)
|
|
||||||
*/
|
|
||||||
virtual void Error(char *reason)=0;
|
|
||||||
|
|
||||||
/* Warning
|
|
||||||
** warning (something recoverable, like file not found, etc)
|
|
||||||
*/
|
|
||||||
virtual void Warning(char *warning)=0;
|
|
||||||
|
|
||||||
/* Status
|
|
||||||
** status update (nothing really wrong)
|
|
||||||
*/
|
|
||||||
virtual void Status(char *status)=0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* TitleChange
|
|
||||||
** should be called if the current file titlename changes during the decoding
|
|
||||||
*/
|
|
||||||
virtual void TitleChange(char *new_title)=0;
|
|
||||||
|
|
||||||
/* InfoChange
|
|
||||||
** should be called if the infos about the current file changes during the decoding
|
|
||||||
*/
|
|
||||||
virtual void InfoChange(char *new_info_str, int new_length)=0;
|
|
||||||
|
|
||||||
/* UrlChange
|
|
||||||
** should be called if the current file associated URL changes during the decoding
|
|
||||||
*/
|
|
||||||
virtual void UrlChange(char *new_url)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WInfo_callback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/* GetReader
|
|
||||||
** Allows your WInfo classes to request a reader from Winamp
|
|
||||||
** so you don't have to worry about opening files or streams
|
|
||||||
*/
|
|
||||||
virtual WReader *GetReader(char *url)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WInputInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/* WInputInfo
|
|
||||||
** WInputInfo constructor
|
|
||||||
*/
|
|
||||||
WInputInfo(){ };
|
|
||||||
|
|
||||||
/* m_info
|
|
||||||
** Filled by Winamp. Pointer to WInputInfo callback function
|
|
||||||
*/
|
|
||||||
WInfo_callback *m_info;
|
|
||||||
|
|
||||||
/* Open
|
|
||||||
** Called by Winamp to request informations about a specified media (file, url, etc...)
|
|
||||||
** returns 0 if succesful, 1 if not
|
|
||||||
**
|
|
||||||
** You must open, get all information and close the specified file here and store
|
|
||||||
** the useful information into member elements for quick access by other functions
|
|
||||||
*/
|
|
||||||
virtual int Open(char *url) { return 1; }
|
|
||||||
|
|
||||||
/* GetTitle
|
|
||||||
** Called by Winamp to get the decoded title about the file opened
|
|
||||||
** i.e. id3 title name, etc...
|
|
||||||
*/
|
|
||||||
virtual void GetTitle(char *buf, int maxlen) { if (maxlen>0) buf[0]=0; };
|
|
||||||
|
|
||||||
/* GetInfoString
|
|
||||||
** Called by Winamp to get extra informations about the file opened
|
|
||||||
** i.e. "160kbps stereo 44Khz" for MP3 files,"4 channels" for MOD files,etc...
|
|
||||||
*/
|
|
||||||
virtual void GetInfoString(char *buf, int maxlen) { if (maxlen>0) buf[0]=0; };
|
|
||||||
|
|
||||||
/* GetLength
|
|
||||||
** Called by Winamp to retrieves media type length in milliseconds
|
|
||||||
** returns -1 if length is undefined/infinite
|
|
||||||
*/
|
|
||||||
virtual int GetLength(void) { return -1; };
|
|
||||||
|
|
||||||
/* GetMetaData
|
|
||||||
** Fetches metadata by attribute name (Artist, Album, Bitrate, etc...)
|
|
||||||
** attribute names are non case-sensitive.
|
|
||||||
** returns size of data
|
|
||||||
*/
|
|
||||||
virtual int GetMetaData(char *name, char *data, int data_len) { if (data&&data_len>0) *data=0; return 0; }
|
|
||||||
|
|
||||||
/* ~WInputInfo
|
|
||||||
** WInputInfo virtual destructor
|
|
||||||
*/
|
|
||||||
//virtual ~WInputInfo() { };
|
|
||||||
virtual void Release(int)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* WINAMP Output Filter NOTIFY MESSAGES
|
|
||||||
** Messages returned to notify Output Filter plug-ins of events
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
|
|
||||||
/* WOFNM_FILETITLECHANGE
|
|
||||||
** Sent when the song changes
|
|
||||||
** param1=new filename song
|
|
||||||
** param2=new title song
|
|
||||||
*/
|
|
||||||
WOFNM_FILETITLECHANGE=1024,
|
|
||||||
|
|
||||||
/* WOFNM_ENDOFDECODE
|
|
||||||
** Sent when decoding ends
|
|
||||||
*/
|
|
||||||
WOFNM_ENDOFDECODE,
|
|
||||||
|
|
||||||
} WOutputFilterNotifyMsg;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WOutputFilter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
/* WOutputFilter
|
|
||||||
** WOutputFilter constructor
|
|
||||||
*/
|
|
||||||
WOutputFilter() { m_next=NULL; };
|
|
||||||
|
|
||||||
public:
|
|
||||||
/* m_player
|
|
||||||
** Filled by Winamp. Pointer to Winamp 3 core player interface
|
|
||||||
*/
|
|
||||||
WPlayer_callback *m_player;
|
|
||||||
|
|
||||||
/* m_next
|
|
||||||
** Internally used by Winamp. Pointer to next activated Output Filter
|
|
||||||
*/
|
|
||||||
WOutputFilter *m_next;
|
|
||||||
|
|
||||||
/* ~WOutputFilter
|
|
||||||
** WOutputFilter destructor
|
|
||||||
*/
|
|
||||||
//virtual ~WOutputFilter() { };
|
|
||||||
virtual void Release(int)=0;
|
|
||||||
|
|
||||||
/* GetDescription
|
|
||||||
** Retrieves your plug-in's text description
|
|
||||||
*/
|
|
||||||
virtual char *GetDescription() { return "Unknown"; };
|
|
||||||
|
|
||||||
/* ProcessSamples
|
|
||||||
** Render data as it receives it
|
|
||||||
** sampledata: Data to process
|
|
||||||
** bytes: number of bytes to process
|
|
||||||
** bps: Bits per sample (8 or 16)
|
|
||||||
** nch: Number of channels (1 or 2)
|
|
||||||
** srate: Sample rate in Hz
|
|
||||||
** killswitch: Will be set to 1 by winamp if stop if requested. Poll the pointed value very often to
|
|
||||||
** make sure Winamp doesn't hang
|
|
||||||
**
|
|
||||||
** Returns the number of processed bytes or -1 if unable to open the device or an error occured.
|
|
||||||
**
|
|
||||||
** You have to open your device (ie. Directsound) the first time this function is called.
|
|
||||||
*/
|
|
||||||
virtual int ProcessSamples(char *sampledata, int bytes, int *bps, int *nch, int *srate, bool *killswitch) { return bytes; }
|
|
||||||
|
|
||||||
/* FlushSamples
|
|
||||||
** Flushes output buffers so that all is written
|
|
||||||
*/
|
|
||||||
virtual void FlushSamples(bool *killswitch) { };
|
|
||||||
|
|
||||||
/* Restart
|
|
||||||
** Called by Winamp after a seek
|
|
||||||
*/
|
|
||||||
virtual void Restart(void) { }
|
|
||||||
|
|
||||||
/* GetLatency
|
|
||||||
** Returns < 0 for a final output latency, > 0 for an additive
|
|
||||||
*/
|
|
||||||
virtual int GetLatency(void) { return 0; }
|
|
||||||
|
|
||||||
/* Pause
|
|
||||||
** Suspends output
|
|
||||||
*/
|
|
||||||
virtual void Pause(int pause) { }
|
|
||||||
|
|
||||||
/* ShutDown
|
|
||||||
** Completely stops output
|
|
||||||
**
|
|
||||||
** Close your device here (not in destructor)
|
|
||||||
*/
|
|
||||||
virtual void ShutDown(void) { }
|
|
||||||
|
|
||||||
/* SetVolume
|
|
||||||
** Sets the volume (0 to 255)
|
|
||||||
** return 1 if volume successfully modified
|
|
||||||
*/
|
|
||||||
virtual int SetVolume(int volume) { return 0; }
|
|
||||||
|
|
||||||
/* SetPan
|
|
||||||
** Sets Left-Right sound balance (-127 to 127)
|
|
||||||
** return 1 if pan successfully modified
|
|
||||||
*/
|
|
||||||
virtual int SetPan(int pan) { return 0; }
|
|
||||||
|
|
||||||
/* Notify
|
|
||||||
** Called by Winamp to notify what's going on
|
|
||||||
*/
|
|
||||||
virtual void Notify(WOutputFilterNotifyMsg msg, int data1, int data2) { }
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WInputSource
|
|
||||||
{
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/* WInputSource
|
|
||||||
** WInputSource constructor
|
|
||||||
*/
|
|
||||||
WInputSource(){ };
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
/* m_player
|
|
||||||
** Filled by Winamp. Pointer to Winamp 3 core interface
|
|
||||||
*/
|
|
||||||
WPlayer_callback *m_player;
|
|
||||||
|
|
||||||
/* GetDescription
|
|
||||||
** Retrieves your plug-in's text description
|
|
||||||
*/
|
|
||||||
virtual char *GetDescription() { return "Unknown"; };
|
|
||||||
|
|
||||||
/* UsesOutputFilters
|
|
||||||
** Returns whether or not the Output Filter pipeline can be used
|
|
||||||
*/
|
|
||||||
virtual int UsesOutputFilters(void) { return 1; }
|
|
||||||
|
|
||||||
/* Open
|
|
||||||
** Used to open and prepare input media type
|
|
||||||
*/
|
|
||||||
virtual int Open(char *url, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* GetSamples
|
|
||||||
** This function must fill bps, nch and srate.
|
|
||||||
** Here, you have to fill the sample_buffer with decoded data. Be sure to fill it with the specified
|
|
||||||
** size (bytes). Use an internal buffer, etc ...
|
|
||||||
**
|
|
||||||
** sample_buffer: buffer to put decoded data into
|
|
||||||
** bytes: size of the sample_buffer
|
|
||||||
** bps: Bits par sample (8 or 16)
|
|
||||||
** nch: Number of channels (1 or 2)
|
|
||||||
** srate: Sample rate in Hz
|
|
||||||
** killswitch: Will be set to 1 by winamp if stop if requested. Poll the pointed value very often to
|
|
||||||
** make sure Winamp doesn't hang
|
|
||||||
*/
|
|
||||||
virtual int GetSamples(char *sample_buffer, int bytes, int *bps, int *nch, int *srate, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* SetVolume
|
|
||||||
** Sets the volume (0 to 255)
|
|
||||||
** Return 1 if volume has been set
|
|
||||||
*/
|
|
||||||
virtual int SetVolume(int volume) { return 0; };
|
|
||||||
|
|
||||||
/* SetPan
|
|
||||||
** Sets Left-Right sound balance (-127 to 127)
|
|
||||||
** return 1 if pan successfully modified
|
|
||||||
*/
|
|
||||||
virtual int SetPan(int pan) { return 0; };
|
|
||||||
|
|
||||||
/* SetPosition
|
|
||||||
** Sets position in ms. returns 0 on success, 1 if seek impossible
|
|
||||||
*/
|
|
||||||
virtual int SetPosition(int)=0;
|
|
||||||
|
|
||||||
/* Pause
|
|
||||||
** Suspends input
|
|
||||||
*/
|
|
||||||
virtual void Pause(int pause) { };
|
|
||||||
|
|
||||||
/* GetPosition
|
|
||||||
** Retrieve position in milliseconds
|
|
||||||
*/
|
|
||||||
virtual int GetPosition(void) { return 0; }
|
|
||||||
|
|
||||||
/* GetTitle
|
|
||||||
** Called by Winamp to get the decoded title about the file opened
|
|
||||||
** i.e. stream name, id3 title name, etc...
|
|
||||||
*/
|
|
||||||
virtual void GetTitle(char *buf, int maxlen) { if(maxlen>0) buf[0]=0; };
|
|
||||||
|
|
||||||
/* GetInfoString
|
|
||||||
** Called by Winamp to get extra informations about the file openend
|
|
||||||
** i.e. "32kbps 44khz", etc...
|
|
||||||
*/
|
|
||||||
virtual void GetInfoString(char *buf, int maxlen) { if(maxlen>0) buf[0]=0; };
|
|
||||||
|
|
||||||
/* GetLength
|
|
||||||
** Called by Winamp to retrieves media type length in milliseconds
|
|
||||||
** returns -1 if length is undefined/infinite
|
|
||||||
*/
|
|
||||||
virtual int GetLength(void) { return -1; }
|
|
||||||
|
|
||||||
/* ~WInputSource
|
|
||||||
** ~WInputSource virtual destructor
|
|
||||||
*/
|
|
||||||
//virtual ~WInputSource() { };
|
|
||||||
virtual void Release(int)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WReader
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/* WReader
|
|
||||||
** WReader constructor
|
|
||||||
*/
|
|
||||||
WReader() { }
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/* m_player
|
|
||||||
** Filled by Winamp. Pointer to Winamp 3 core interface
|
|
||||||
*/
|
|
||||||
WPlayer_callback *m_player;
|
|
||||||
|
|
||||||
/* GetDescription
|
|
||||||
** Retrieves your plug-in's text description
|
|
||||||
*/
|
|
||||||
virtual char *GetDescription() { return "Unknown"; };
|
|
||||||
|
|
||||||
/* Open
|
|
||||||
** Used to open a file, return 0 on success
|
|
||||||
*/
|
|
||||||
virtual int Open(char *url, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* Read
|
|
||||||
** Returns number of BYTES read (if < length then eof or killswitch)
|
|
||||||
*/
|
|
||||||
virtual int Read(char *buffer, int length, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* GetLength
|
|
||||||
** Returns length of the entire file in BYTES, return -1 on unknown/infinite (as for a stream)
|
|
||||||
*/
|
|
||||||
virtual int GetLength(void)=0;
|
|
||||||
|
|
||||||
/* CanSeek
|
|
||||||
** Returns 1 if you can skip ahead in the file, 0 if not
|
|
||||||
*/
|
|
||||||
virtual int CanSeek(void)=0;
|
|
||||||
|
|
||||||
/* Seek
|
|
||||||
** Jump to a certain absolute position
|
|
||||||
*/
|
|
||||||
virtual int Seek(int position, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* GetHeader
|
|
||||||
** Retrieve header. Used in read_http to retrieve the HTTP header
|
|
||||||
*/
|
|
||||||
virtual char *GetHeader(char *name) { return 0; }
|
|
||||||
|
|
||||||
/* ~WReader
|
|
||||||
** WReader virtual destructor
|
|
||||||
*/
|
|
||||||
//virtual ~WReader() { }
|
|
||||||
virtual void Release(int)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* DLL PLUGINS EXPORT STRUCTURES */
|
|
||||||
|
|
||||||
#define READ_VER 0x100
|
|
||||||
#define IN_VER 0x100
|
|
||||||
#define OF_VER 0x100
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/* version
|
|
||||||
** Version revision number
|
|
||||||
*/
|
|
||||||
int version;
|
|
||||||
|
|
||||||
/* description
|
|
||||||
** Text description of the reader plug-in
|
|
||||||
*/
|
|
||||||
char *description;
|
|
||||||
|
|
||||||
/* create
|
|
||||||
** Function pointer to create a reader module
|
|
||||||
*/
|
|
||||||
WReader *(*create)();
|
|
||||||
|
|
||||||
/* ismine
|
|
||||||
** Determines whether or not a file should be read by this plug-in
|
|
||||||
*/
|
|
||||||
int (*ismine)(char *url);
|
|
||||||
|
|
||||||
} reader_source;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/* version
|
|
||||||
** Version revision number
|
|
||||||
*/
|
|
||||||
int version;
|
|
||||||
|
|
||||||
/* description
|
|
||||||
** Text description of the input plug-in
|
|
||||||
*/
|
|
||||||
char *description;
|
|
||||||
|
|
||||||
/* extension_list
|
|
||||||
** Defines all the supported filetypes by this input plug-in
|
|
||||||
** In semicolon delimited format ("ext;desc;ext;desc" etc).
|
|
||||||
*/
|
|
||||||
char *extension_list;
|
|
||||||
|
|
||||||
/* ismine
|
|
||||||
** called before extension checks, to allow detection of tone://,http://, etc
|
|
||||||
** Determines whether or not a file type should be decoded by this plug-in
|
|
||||||
*/
|
|
||||||
int (*ismine)(char *filename);
|
|
||||||
|
|
||||||
/* create
|
|
||||||
** Function pointer to create a decoder module
|
|
||||||
*/
|
|
||||||
WInputSource *(*create)(void);
|
|
||||||
|
|
||||||
/* createinfo
|
|
||||||
** Function pointer to create a decoder module information
|
|
||||||
*/
|
|
||||||
WInputInfo *(*createinfo)(void);
|
|
||||||
|
|
||||||
} input_source;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/* version
|
|
||||||
** Version revision number
|
|
||||||
*/
|
|
||||||
int version;
|
|
||||||
|
|
||||||
/* description
|
|
||||||
** Text description of the output plug-in
|
|
||||||
*/
|
|
||||||
char *description;
|
|
||||||
|
|
||||||
/* create
|
|
||||||
** Function pointer to create an Output Filter
|
|
||||||
*/
|
|
||||||
WOutputFilter *(*create)();
|
|
||||||
|
|
||||||
} output_filter;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,459 +0,0 @@
|
|||||||
#include "main.h"
|
|
||||||
#include "decoder.h"
|
|
||||||
#include <math.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#pragma warning(disable:4244)
|
|
||||||
#include "shaper.h"
|
|
||||||
#include "api__in_vorbis.h"
|
|
||||||
|
|
||||||
Decoder::~Decoder() {if (shaper) delete shaper;}
|
|
||||||
|
|
||||||
extern CfgInt
|
|
||||||
cfg_mc6_dm, cfg_mc6_map;
|
|
||||||
/*
|
|
||||||
if (vorbis_cfg.use_hq_preamp)
|
|
||||||
{
|
|
||||||
sample *= pow(10., preamp_db/20);
|
|
||||||
|
|
||||||
//hard 6dB limiting
|
|
||||||
if (sample < -0.5)
|
|
||||||
sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
|
|
||||||
else if (sample > 0.5)
|
|
||||||
sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static float q_tanh(float x)
|
|
||||||
{
|
|
||||||
double foo1, foo2;
|
|
||||||
foo1 = pow(2.71828182845904523536028747135266, x);
|
|
||||||
foo2 = 1.0 / foo1;
|
|
||||||
return (foo1 -foo2) / (foo1 + foo2);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define q_tanh tanh
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float VorbisFile::GetGain()
|
|
||||||
{
|
|
||||||
float peak;
|
|
||||||
|
|
||||||
vorbis_comment * c;
|
|
||||||
float scale = 1.0f;
|
|
||||||
c = ov_comment(&vf, -1);
|
|
||||||
peak = 0.99f;
|
|
||||||
if (c)
|
|
||||||
{
|
|
||||||
if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain", false))
|
|
||||||
{
|
|
||||||
char * _peak = 0, *_gain = 0;
|
|
||||||
float gain = 0;
|
|
||||||
bool have_rg = 0;
|
|
||||||
float lwing_gain = 0;
|
|
||||||
char *gain1 = 0, *gain2 = 0, *peak1 = 0, *peak2 = 0;
|
|
||||||
gain1 = vorbis_comment_query(c, "replaygain_album_gain", 0);
|
|
||||||
if (!gain1) gain1 = vorbis_comment_query(c, "rg_audiophile", 0);
|
|
||||||
gain2 = vorbis_comment_query(c, "replaygain_track_gain", 0);
|
|
||||||
if (!gain2) gain2 = vorbis_comment_query(c, "rg_radio", 0);
|
|
||||||
|
|
||||||
peak1 = vorbis_comment_query(c, "replaygain_album_peak", 0);
|
|
||||||
peak2 = vorbis_comment_query(c, "replaygain_track_peak", 0);
|
|
||||||
switch (AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"replaygain_source", 0))
|
|
||||||
{
|
|
||||||
case 0: // track
|
|
||||||
_gain = gain2;
|
|
||||||
if (!_gain && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
|
||||||
_gain = gain1;
|
|
||||||
_peak = peak2;
|
|
||||||
if (!_peak && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
|
||||||
_peak = peak1;
|
|
||||||
break;
|
|
||||||
case 1: // album
|
|
||||||
_gain = gain1;
|
|
||||||
if (!_gain && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
|
||||||
_gain = gain2;
|
|
||||||
_peak = peak1;
|
|
||||||
if (!_peak && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"replaygain_preferred_only", false))
|
|
||||||
_peak = peak2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_peak)
|
|
||||||
{
|
|
||||||
_peak = vorbis_comment_query(c, "rg_peak", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_locale_t C_locale = WASABI_API_LNG->Get_C_NumericLocale();
|
|
||||||
|
|
||||||
if (_peak) peak = _atof_l(_peak, C_locale);
|
|
||||||
if (_gain) gain = _atof_l(_gain, C_locale);
|
|
||||||
|
|
||||||
if (!_peak && !_gain)
|
|
||||||
{
|
|
||||||
char * l = vorbis_comment_query(c, "lwing_gain", 0);
|
|
||||||
if (l)
|
|
||||||
{
|
|
||||||
lwing_gain = _atof_l(l, C_locale);
|
|
||||||
have_rg = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else have_rg = 1;
|
|
||||||
|
|
||||||
if (!have_rg)
|
|
||||||
{
|
|
||||||
gain = AGAVE_API_CONFIG->GetFloat(playbackConfigGroupGUID, L"non_replaygain", -6.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
scale = powf(10, (gain) / 20.0f);
|
|
||||||
if (lwing_gain)
|
|
||||||
scale *= lwing_gain;
|
|
||||||
else if (have_rg)
|
|
||||||
switch (AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"replaygain_mode", 1))
|
|
||||||
{
|
|
||||||
case 1: // apply gain, but don't clip
|
|
||||||
if (scale*peak > 1.0) scale = 1.0 / peak;
|
|
||||||
break;
|
|
||||||
case 2: // normalize
|
|
||||||
scale = 1.0 / peak;
|
|
||||||
break;
|
|
||||||
case 3: // no clipping
|
|
||||||
if (peak > 1.0f)
|
|
||||||
scale = 1.0 / peak;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::process_rg()
|
|
||||||
{
|
|
||||||
scale = file->GetGain();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::setup_mc()
|
|
||||||
{
|
|
||||||
if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"mono", false))
|
|
||||||
nch = 1;
|
|
||||||
else if (src_nch == 6)
|
|
||||||
{
|
|
||||||
switch (cfg_mc6_dm)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
nch = 4;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
nch = 2;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
nch = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nch > 2 && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"surround", true))
|
|
||||||
nch = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::Flush()
|
|
||||||
{
|
|
||||||
bptr = 0;
|
|
||||||
pcmbuf = 0;
|
|
||||||
data = 0;
|
|
||||||
pos = 0;
|
|
||||||
if (shaper) {delete shaper;shaper = 0;}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::Init(VorbisFile * f, UINT _bits, UINT _nch, bool _useFloat, bool allowRG)
|
|
||||||
{
|
|
||||||
useFloat = _useFloat;
|
|
||||||
|
|
||||||
file = f;
|
|
||||||
vorbis_info * i = ov_info(&file->vf, -1);
|
|
||||||
|
|
||||||
if (allowRG)
|
|
||||||
process_rg();
|
|
||||||
else
|
|
||||||
scale = 1.0f;
|
|
||||||
|
|
||||||
if (useFloat)
|
|
||||||
{
|
|
||||||
dither = false;
|
|
||||||
bps = 32;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dither = AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"dither", true);
|
|
||||||
|
|
||||||
if (_bits)
|
|
||||||
bps = _bits;
|
|
||||||
else
|
|
||||||
bps = AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"bits", 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useFloat)
|
|
||||||
{
|
|
||||||
clipmin = -10000; // some arbitrarily large number
|
|
||||||
clipmax = 10000; // some arbitrarily large number
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clipmin = - (1 << (bps - 1));
|
|
||||||
clipmax = (1 << (bps - 1)) - 1;
|
|
||||||
}
|
|
||||||
sr = i->rate;
|
|
||||||
nch = src_nch = i->channels;
|
|
||||||
Flush();
|
|
||||||
cur_link = file->vf.current_link;
|
|
||||||
|
|
||||||
if (_nch)
|
|
||||||
nch = _nch;
|
|
||||||
else
|
|
||||||
setup_mc();
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT Decoder::DataAvailable()
|
|
||||||
{
|
|
||||||
return data * (bps >> 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Decoder::DoFrame()
|
|
||||||
{
|
|
||||||
need_reopen = 0;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
data = ov_read_float(&file->vf, &pcmbuf, 576, 0);
|
|
||||||
if ((int)data <= 0)
|
|
||||||
{
|
|
||||||
if (data == OV_HOLE) {continue;}
|
|
||||||
data = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
if (cur_link != file->vf.current_link)
|
|
||||||
{
|
|
||||||
vorbis_info* i = ov_info(&file->vf, -1);
|
|
||||||
if (sr != (UINT)i->rate || src_nch != (UINT)i->channels)
|
|
||||||
{
|
|
||||||
UINT old_nch = nch, old_sr = sr;
|
|
||||||
if (shaper) {delete shaper;shaper = 0;}
|
|
||||||
sr = i->rate;
|
|
||||||
src_nch = nch = i->channels;
|
|
||||||
setup_mc();
|
|
||||||
if (nch != old_nch || sr != old_sr)
|
|
||||||
{
|
|
||||||
need_reopen = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
process_rg();
|
|
||||||
cur_link = file->vf.current_link;
|
|
||||||
}
|
|
||||||
data *= nch;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Decoder::Read(UINT bytes, void * buf)
|
|
||||||
{
|
|
||||||
UINT wr = 0;
|
|
||||||
if (buf && bytes && data > 0)
|
|
||||||
{
|
|
||||||
char* out = (char*)buf;
|
|
||||||
UINT d;
|
|
||||||
double mul;
|
|
||||||
int ofs;
|
|
||||||
float * img;
|
|
||||||
|
|
||||||
d = bytes / (bps >> 3);
|
|
||||||
if (d > data) d = data;
|
|
||||||
if (!d) return 0;
|
|
||||||
data -= d;
|
|
||||||
if (useFloat)
|
|
||||||
{
|
|
||||||
mul = 1.0;
|
|
||||||
ofs = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mul = (double)( (1 << ((bps) - 1)) - 1 );
|
|
||||||
ofs = (bps == 8) ? 0x80 : 0;
|
|
||||||
}
|
|
||||||
wr += d * (bps >> 3);
|
|
||||||
|
|
||||||
img = (float*)alloca(sizeof(float) * nch);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UINT cur_ch;
|
|
||||||
if (nch == 1 && src_nch > 0)
|
|
||||||
{
|
|
||||||
UINT c;
|
|
||||||
img[0] = 0;
|
|
||||||
for (c = 0;c < src_nch;c++)
|
|
||||||
{
|
|
||||||
img[0] += pcmbuf[c][pos];
|
|
||||||
}
|
|
||||||
img[0] /= (float)src_nch;
|
|
||||||
}
|
|
||||||
else if (nch == src_nch && !(nch == 6 && cfg_mc6_dm == 1))
|
|
||||||
{
|
|
||||||
UINT c;
|
|
||||||
for (c = 0;c < nch;c++)
|
|
||||||
{
|
|
||||||
img[c] = pcmbuf[c][pos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (src_nch == 6)
|
|
||||||
{
|
|
||||||
UINT FL, FR, C;
|
|
||||||
if (cfg_mc6_map == 1)
|
|
||||||
{
|
|
||||||
FL = 0;
|
|
||||||
FR = 1;
|
|
||||||
C = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FL = 0;
|
|
||||||
C = 1;
|
|
||||||
FR = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nch == 6)
|
|
||||||
{ //remap order for correct 5.1 output
|
|
||||||
img[0] = pcmbuf[FL][pos];
|
|
||||||
img[1] = pcmbuf[FR][pos];
|
|
||||||
img[2] = pcmbuf[C][pos];
|
|
||||||
img[3] = pcmbuf[5][pos];
|
|
||||||
img[4] = pcmbuf[3][pos];
|
|
||||||
img[5] = pcmbuf[4][pos];
|
|
||||||
}
|
|
||||||
else if (nch == 2)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
FL FR C BL BR LFE
|
|
||||||
0 1 2 3 4 5
|
|
||||||
|
|
||||||
L,C,R,SL,SR,LFE
|
|
||||||
0 1 2 3 4 5
|
|
||||||
|
|
||||||
|
|
||||||
output:
|
|
||||||
FL FR C LFE BL BR
|
|
||||||
|
|
||||||
|
|
||||||
stereo:
|
|
||||||
Lt=L+0.707*(V-SL-SR+LFE)
|
|
||||||
Rt=R+0.707*(C+SL+SR+LFE)
|
|
||||||
|
|
||||||
|
|
||||||
Lt=L+0.707*(C+LFE)
|
|
||||||
Rt=R+0.707*(C+LFE)
|
|
||||||
SLt=SL
|
|
||||||
SRt=SR
|
|
||||||
|
|
||||||
*/
|
|
||||||
if (cfg_mc6_dm == 4) //ds2
|
|
||||||
{
|
|
||||||
const double a = pow(10., 1.5 / 20.), b = 1 / a;
|
|
||||||
img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] - a * pcmbuf[3][pos] - b * pcmbuf[4][pos] + pcmbuf[5][pos]);
|
|
||||||
img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + b * pcmbuf[3][pos] + a * pcmbuf[4][pos] + pcmbuf[5][pos]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] - pcmbuf[3][pos] - pcmbuf[4][pos] + pcmbuf[5][pos]);
|
|
||||||
img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[3][pos] + pcmbuf[4][pos] + pcmbuf[5][pos]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (nch == 4)
|
|
||||||
{
|
|
||||||
img[0] = pcmbuf[FL][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[5][pos]);
|
|
||||||
img[1] = pcmbuf[FR][pos] + 0.707 * (pcmbuf[C][pos] + pcmbuf[5][pos]);
|
|
||||||
img[2] = pcmbuf[3][pos];
|
|
||||||
img[3] = pcmbuf[4][pos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cur_ch = 0;cur_ch < nch;cur_ch++)
|
|
||||||
{
|
|
||||||
float v = img[cur_ch];
|
|
||||||
int val;
|
|
||||||
v *= scale;
|
|
||||||
v *= mul;
|
|
||||||
if (dither)
|
|
||||||
{
|
|
||||||
if (!shaper)
|
|
||||||
{
|
|
||||||
//Shaper(int freq,int _nch,int min,int max,int _dtype,int pdf,double noiseamp);
|
|
||||||
shaper = new Shaper(sr, nch, clipmin, clipmax, 2, DITHER_TRIANGLE, 0);
|
|
||||||
}
|
|
||||||
// double peak=0;
|
|
||||||
val = shaper->do_shaping(v /*,&peak*/, cur_ch);
|
|
||||||
//shaper clips for us
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val = (int)v;
|
|
||||||
if (val < clipmin) val = clipmin;
|
|
||||||
else if (val > clipmax) val = clipmax;
|
|
||||||
//1<<16 = 0x10000
|
|
||||||
|
|
||||||
}
|
|
||||||
val += ofs;
|
|
||||||
|
|
||||||
switch (bps)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
*(BYTE*)out = (UINT)val;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
*(short*)out = val;
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
{
|
|
||||||
((BYTE*)out)[0] = (UINT)val;
|
|
||||||
((BYTE*)out)[1] = (UINT)val >> 8;
|
|
||||||
((BYTE*)out)[2] = (UINT)val >> 16;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
if (useFloat)
|
|
||||||
{
|
|
||||||
*(float *)out = v;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//*(long*)out=val;
|
|
||||||
//break;
|
|
||||||
*(long*)out = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
out += (bps >> 3);
|
|
||||||
d--;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
while (d);
|
|
||||||
|
|
||||||
}
|
|
||||||
return wr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int VorbisFile::Seek(double p) { return ov_time_seek(&vf, p);}
|
|
||||||
|
|
||||||
int Decoder::Seek(double p)
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
return file->Seek(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
//char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count)
|
|
||||||
const char* VorbisFile::get_meta(const char* tag, UINT c)
|
|
||||||
{
|
|
||||||
return vorbis_comment_query(vf.seekable ? vf.vc + vf.current_link : vf.vc, (char*)tag, c);
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
class Shaper;
|
|
||||||
|
|
||||||
class Decoder
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
void process_rg();
|
|
||||||
void setup_mc();
|
|
||||||
float* bptr;
|
|
||||||
float** pcmbuf;
|
|
||||||
Shaper * shaper;
|
|
||||||
UINT data,pos;
|
|
||||||
float scale;
|
|
||||||
int cur_link;
|
|
||||||
int cur_preamp;
|
|
||||||
int clipmin,clipmax;
|
|
||||||
public:
|
|
||||||
VorbisFile * file;
|
|
||||||
|
|
||||||
UINT nch,sr,kbps,bps,src_nch;
|
|
||||||
|
|
||||||
Decoder()
|
|
||||||
{
|
|
||||||
memset(this,0,sizeof(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
~Decoder();
|
|
||||||
|
|
||||||
int Seek(double p);
|
|
||||||
int Read(UINT bytes,void * buf);
|
|
||||||
void Flush();
|
|
||||||
void Init(VorbisFile * f, UINT _bits=0, UINT _nch=0, bool _useFloat=false, bool allowRG=true);
|
|
||||||
void wa2_setinfo(UINT cur_bitrate);
|
|
||||||
|
|
||||||
UINT DataAvailable();
|
|
||||||
int DoFrame();
|
|
||||||
bool need_reopen;
|
|
||||||
int play_init();
|
|
||||||
bool play_inited;
|
|
||||||
bool dither;
|
|
||||||
bool useFloat;
|
|
||||||
};
|
|
@ -1,97 +0,0 @@
|
|||||||
#include <windows.h>
|
|
||||||
#include "genres.h"
|
|
||||||
#include <shlwapi.h>
|
|
||||||
|
|
||||||
extern const wchar_t *INI_DIRECTORY;
|
|
||||||
|
|
||||||
static void file_init(wchar_t *file_path, wchar_t *fn)
|
|
||||||
{
|
|
||||||
PathCombineW(file_path, INI_DIRECTORY, fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char eol[2]={13,10};
|
|
||||||
|
|
||||||
static char get_char(HANDLE f,BOOL * eof)
|
|
||||||
{
|
|
||||||
DWORD br=0;
|
|
||||||
char r=0;
|
|
||||||
ReadFile(f,&r,1,&br,0);
|
|
||||||
if (!br) *eof=1;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void genres_read(HWND wnd, wchar_t* fn)
|
|
||||||
{
|
|
||||||
char temp[MAX_GENRE] = {0};
|
|
||||||
char add[MAX_GENRE] = {0};
|
|
||||||
BOOL eof=0;
|
|
||||||
char c = 0;
|
|
||||||
wchar_t file_path[MAX_PATH] = {0};
|
|
||||||
HANDLE f;
|
|
||||||
|
|
||||||
file_init(file_path, fn);
|
|
||||||
|
|
||||||
f = CreateFileW(file_path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
|
||||||
if (f==INVALID_HANDLE_VALUE) return;
|
|
||||||
GetWindowTextA(wnd,add,MAX_GENRE);
|
|
||||||
while(!eof)
|
|
||||||
{
|
|
||||||
UINT ptr=0;
|
|
||||||
BOOL start=1;
|
|
||||||
while(ptr<MAX_GENRE-1)
|
|
||||||
{
|
|
||||||
c=get_char(f,&eof);
|
|
||||||
if (eof) break;
|
|
||||||
if (c==10 || c==13)
|
|
||||||
{
|
|
||||||
if (start) continue;
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
start=0;
|
|
||||||
temp[ptr++]=c;
|
|
||||||
}
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
temp[ptr]=0;
|
|
||||||
SendMessage(wnd,CB_ADDSTRING,0, (LPARAM)temp);
|
|
||||||
if (add[0])
|
|
||||||
{
|
|
||||||
if (!_stricmp(add,temp)) add[0]=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseHandle(f);
|
|
||||||
if (add[0]) SendMessage(wnd,CB_ADDSTRING,0,(LPARAM)add);
|
|
||||||
}
|
|
||||||
|
|
||||||
void genres_write(HWND wnd, wchar_t* fn)
|
|
||||||
{
|
|
||||||
wchar_t file_path[MAX_PATH] = {0};
|
|
||||||
char temp[MAX_GENRE] = {0};
|
|
||||||
UINT max = 0,n = 0;
|
|
||||||
DWORD bw = 0;
|
|
||||||
HANDLE f;
|
|
||||||
{
|
|
||||||
char add[MAX_GENRE] = {0};
|
|
||||||
GetWindowTextA(wnd,add,MAX_GENRE);
|
|
||||||
if (!add[0]) return;
|
|
||||||
max=(UINT)SendMessage(wnd,CB_GETCOUNT,0,0);
|
|
||||||
for(n=0;n<max;n++)
|
|
||||||
{
|
|
||||||
SendMessage(wnd,CB_GETLBTEXT,n,(LPARAM)temp);
|
|
||||||
if (!_stricmp(temp,add)) return;
|
|
||||||
}
|
|
||||||
SendMessage(wnd,CB_ADDSTRING,0,(LPARAM)add);
|
|
||||||
}
|
|
||||||
file_init(file_path, fn);
|
|
||||||
f = CreateFileW(file_path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
|
||||||
if (f==INVALID_HANDLE_VALUE) return;
|
|
||||||
max=(UINT)SendMessage(wnd,CB_GETCOUNT,0,0);
|
|
||||||
for(n=0;n<max;n++)
|
|
||||||
{
|
|
||||||
SendMessage(wnd,CB_GETLBTEXT,n,(LPARAM)temp);
|
|
||||||
bw = 0; WriteFile(f,temp,(DWORD)strlen(temp),&bw,0);
|
|
||||||
bw = 0; WriteFile(f,eol,2,&bw,0);
|
|
||||||
}
|
|
||||||
CloseHandle(f);
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
#ifndef NULLSOFT_IN_VORBIS_GENRES_H
|
|
||||||
#define NULLSOFT_IN_VORBIS_GENRES_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void genres_read(HWND wnd, wchar_t* fn);
|
|
||||||
void genres_write(HWND wnd, wchar_t* fn);
|
|
||||||
#define MAX_GENRE 256
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,596 +0,0 @@
|
|||||||
#include "api__in_vorbis.h"
|
|
||||||
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
|
|
||||||
#include "rf.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "../Winamp/wa_ipc.h"
|
|
||||||
#include <api/service/waservicefactory.h>
|
|
||||||
#include "../nu/AutoWide.h"
|
|
||||||
#include "../nu/AutoChar.h"
|
|
||||||
extern CfgInt cfg_fix0r,cfg_httpseek2,cfg_proxy_mode,cfg_prebuf1,cfg_prebuf2,cfg_fsave,cfg_http_bsize;
|
|
||||||
|
|
||||||
#define CANSEEK
|
|
||||||
|
|
||||||
WORD *wdup(const char * src);//info.c
|
|
||||||
|
|
||||||
#define zeromem(x) memset(&x,0,sizeof(x))
|
|
||||||
|
|
||||||
class StreamSave
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
ogg_sync_state oy_src;
|
|
||||||
ogg_stream_state os_src;
|
|
||||||
ogg_stream_state os_dst;
|
|
||||||
ogg_page og_src;
|
|
||||||
ogg_page og_dst;
|
|
||||||
ogg_packet op;
|
|
||||||
StringW tmp_fn;
|
|
||||||
BOOL is_temp;
|
|
||||||
BOOL got_streams,got_delta,use_fix0r;
|
|
||||||
ogg_int64_t pcm_delta;
|
|
||||||
int packets,serial;
|
|
||||||
HANDLE hFile;
|
|
||||||
public:
|
|
||||||
|
|
||||||
StreamSave()
|
|
||||||
{
|
|
||||||
zeromem(oy_src);
|
|
||||||
zeromem(os_src);
|
|
||||||
zeromem(os_dst);
|
|
||||||
zeromem(og_src);
|
|
||||||
zeromem(og_dst);
|
|
||||||
zeromem(op);
|
|
||||||
got_streams=0;
|
|
||||||
got_delta=0;
|
|
||||||
pcm_delta=0;
|
|
||||||
hFile=0;
|
|
||||||
packets=0;
|
|
||||||
serial=0;
|
|
||||||
is_temp=1;
|
|
||||||
|
|
||||||
tmp_fn=cfg_dumpdir;
|
|
||||||
if (tmp_fn[tmp_fn.Length()-1]!='\\') tmp_fn.AddChar('\\');
|
|
||||||
|
|
||||||
tmp_fn+=StringPrintfW(L"oggtemp%u.foo",GetTickCount64()&0xFFFF);
|
|
||||||
|
|
||||||
hFile=CreateFileW(tmp_fn,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_HIDDEN,0);
|
|
||||||
if (hFile==INVALID_HANDLE_VALUE) hFile=0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ogg_sync_init(&oy_src);
|
|
||||||
use_fix0r=cfg_fix0r;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void Write(void * ptr,UINT siz)
|
|
||||||
{
|
|
||||||
if (!hFile) return;
|
|
||||||
|
|
||||||
void * b=ogg_sync_buffer(&oy_src,siz);
|
|
||||||
memcpy(b,ptr,siz);
|
|
||||||
ogg_sync_wrote(&oy_src,siz);
|
|
||||||
|
|
||||||
while(ogg_sync_pageout(&oy_src,&og_src)>0)
|
|
||||||
{
|
|
||||||
if (!got_streams)
|
|
||||||
{
|
|
||||||
serial=ogg_page_serialno(&og_src);
|
|
||||||
ogg_stream_init(&os_src,serial);
|
|
||||||
ogg_stream_init(&os_dst,serial);
|
|
||||||
got_streams=1;
|
|
||||||
packets=0;
|
|
||||||
got_delta=0;
|
|
||||||
}
|
|
||||||
else if (serial!=ogg_page_serialno(&og_src))
|
|
||||||
{
|
|
||||||
if (got_streams)
|
|
||||||
{
|
|
||||||
/*while(ogg_stream_flush(&os_dst,&og_dst))
|
|
||||||
{
|
|
||||||
write_page(dst,&og_dst,&wb);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ogg_stream_clear(&os_src);
|
|
||||||
ogg_stream_clear(&os_dst);
|
|
||||||
}
|
|
||||||
serial=ogg_page_serialno(&og_src);
|
|
||||||
ogg_stream_init(&os_src,serial);
|
|
||||||
ogg_stream_init(&os_dst,serial);
|
|
||||||
|
|
||||||
packets=0;
|
|
||||||
got_delta=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ogg_stream_pagein(&os_src,&og_src);
|
|
||||||
while(ogg_stream_packetout(&os_src,&op)>0)
|
|
||||||
{
|
|
||||||
if (use_fix0r && !got_delta && packets>2 && op.granulepos>=0) //hack to fix saved streams
|
|
||||||
{
|
|
||||||
got_delta=1;
|
|
||||||
if (op.granulepos>4096*(packets-2)) pcm_delta=op.granulepos;
|
|
||||||
}
|
|
||||||
if (got_delta)
|
|
||||||
{
|
|
||||||
if (op.granulepos>=pcm_delta) op.granulepos-=pcm_delta;
|
|
||||||
else if (op.granulepos>0) op.granulepos=0;
|
|
||||||
}
|
|
||||||
ogg_stream_packetin(&os_dst,&op);
|
|
||||||
packets++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while((packets==3 ? ogg_stream_flush(&os_dst,&og_dst) : ogg_stream_pageout(&os_dst,&og_dst))>0)
|
|
||||||
{
|
|
||||||
DWORD bw = 0;
|
|
||||||
WriteFile(hFile,og_dst.header,og_dst.header_len,&bw,0);
|
|
||||||
bw = 0; WriteFile(hFile,og_dst.body,og_dst.body_len,&bw,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FixName(VorbisFile * vf,const char * streamname)
|
|
||||||
{
|
|
||||||
if (!hFile) return;
|
|
||||||
CloseHandle(hFile);
|
|
||||||
StringW fn(cfg_dumpdir);
|
|
||||||
|
|
||||||
if (fn[fn.Length()-1]!='\\') fn.AddChar('\\');
|
|
||||||
|
|
||||||
UINT n=fn.Length();
|
|
||||||
fn+=(wchar_t *)AutoWide(vf->get_meta("TITLE", 0), CP_UTF8);
|
|
||||||
UINT m=fn.Length();
|
|
||||||
|
|
||||||
while(n<m)
|
|
||||||
{
|
|
||||||
char * b="/\\:*?\"<>|";
|
|
||||||
while(b && *b)
|
|
||||||
{
|
|
||||||
if (fn[n]==*b) {fn.SetChar(n,'_');break;}
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
};
|
|
||||||
fn.AddStringA(".ogg");
|
|
||||||
if (!MoveFileW(tmp_fn,fn))
|
|
||||||
{
|
|
||||||
DeleteFileW(fn);
|
|
||||||
MoveFileW(tmp_fn,fn);
|
|
||||||
}
|
|
||||||
SetFileAttributesW(fn,FILE_ATTRIBUTE_NORMAL);
|
|
||||||
hFile=CreateFileW(fn,GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
|
|
||||||
|
|
||||||
if (hFile==INVALID_HANDLE_VALUE) {hFile=0;}
|
|
||||||
else SetFilePointer(hFile,0,0,FILE_END);
|
|
||||||
is_temp=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~StreamSave()
|
|
||||||
{
|
|
||||||
if (hFile)
|
|
||||||
{
|
|
||||||
/*if (got_streams)
|
|
||||||
{
|
|
||||||
while(ogg_stream_flush(&os_dst,&og_dst))
|
|
||||||
{
|
|
||||||
write_page(dst,&og_dst,&wb);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ogg_stream_clear(&os_src);
|
|
||||||
ogg_stream_clear(&os_dst);
|
|
||||||
|
|
||||||
SetFilePointer(hFile,0,0,FILE_CURRENT);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
if (is_temp) DeleteFileW(tmp_fn);
|
|
||||||
}
|
|
||||||
ogg_sync_clear(&oy_src);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char * do_proxy(const char * url)
|
|
||||||
{
|
|
||||||
switch(cfg_proxy_mode)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
const char * p=strstr(url,"://");
|
|
||||||
if (!p) p=url;
|
|
||||||
while(p && *p && *p!=':' && *p!='/') p++;
|
|
||||||
if (p && *p==':')
|
|
||||||
{
|
|
||||||
if (atoi(p+1)!=80) return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
char *x = (char *)SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GET_PROXY_STRING);
|
|
||||||
if (x == (char *)1 || !x || !*x)
|
|
||||||
return 0;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VorbisFile_HTTP : public VorbisFile
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
api_httpreceiver *get;
|
|
||||||
UINT bsize;
|
|
||||||
uint64_t len;
|
|
||||||
UINT pos;
|
|
||||||
UINT seekpos;
|
|
||||||
BOOL can_seek;
|
|
||||||
StreamSave * saver;
|
|
||||||
virtual void Idle();
|
|
||||||
virtual int f_seek(__int64 offset,int whence);
|
|
||||||
virtual size_t f_read(UINT siz,void * ptr);
|
|
||||||
virtual UINT f_tell();
|
|
||||||
virtual UINT FileSize() {return len;}
|
|
||||||
bool is_live;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual int GetType() {return TYPE_HTTP;}
|
|
||||||
virtual bool IsLive() {return is_live;}
|
|
||||||
bool http_init();
|
|
||||||
|
|
||||||
void do_prebuf() {VorbisFile::do_prebuf();fillbuf(bsize * cfg_prebuf1 / 100,0);}
|
|
||||||
|
|
||||||
VorbisFile_HTTP(UINT s, const wchar_t *u,bool is_info, bool hasauth) : VorbisFile(u,is_info), usedauth(hasauth)
|
|
||||||
{
|
|
||||||
get=0;
|
|
||||||
can_seek=0;
|
|
||||||
len=pos=seekpos=0;
|
|
||||||
bsize=s;
|
|
||||||
saver=0;
|
|
||||||
m_needs_auth=0;
|
|
||||||
lpinfo[0]=0;
|
|
||||||
force_lpinfo[0]=0;
|
|
||||||
is_live = false;
|
|
||||||
memset(dlg_realm, 0, sizeof(dlg_realm));
|
|
||||||
}
|
|
||||||
|
|
||||||
~VorbisFile_HTTP()
|
|
||||||
{
|
|
||||||
if (get)
|
|
||||||
{
|
|
||||||
waServiceFactory *sf = mod.service->service_getServiceByGuid(httpreceiverGUID);
|
|
||||||
if (sf)
|
|
||||||
sf->releaseInterface(get);
|
|
||||||
get=0;
|
|
||||||
}
|
|
||||||
if (saver) delete saver;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fillbuf(UINT max,bool shutup);
|
|
||||||
|
|
||||||
size_t _http_read(char* ptr,size_t total);
|
|
||||||
int reconnect(UINT ofs);
|
|
||||||
virtual void post_init()
|
|
||||||
{
|
|
||||||
if (saver) saver->FixName(this,get->getheader("ice-name"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CALLBACK httpDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
|
|
||||||
int m_needs_auth;
|
|
||||||
char dlg_realm[256];
|
|
||||||
char lpinfo[256];
|
|
||||||
char force_lpinfo[256];
|
|
||||||
bool usedauth;
|
|
||||||
};
|
|
||||||
|
|
||||||
int VorbisFile_HTTP::reconnect(UINT ofs)
|
|
||||||
{
|
|
||||||
// get.reset_headers();
|
|
||||||
get->addheader("User-Agent: WinampOGG/5.24(MPEG stream compatible)");
|
|
||||||
get->addheader("Accept:*/*");
|
|
||||||
if (ofs>0) get->addheader(StringPrintf("Range: bytes=%u-",ofs));
|
|
||||||
get->connect(AutoChar(url));
|
|
||||||
|
|
||||||
Status(WASABI_API_LNGSTRINGW(IDS_CONNECTING));
|
|
||||||
|
|
||||||
int st=get->run();
|
|
||||||
if (st<0)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VorbisFile_HTTP::fillbuf(UINT max,bool shutup)
|
|
||||||
{
|
|
||||||
if (len>0 && pos+max>len) max=len-pos;
|
|
||||||
while(!Aborting() && !abort_prebuf) //stop prebuffering if we wanna seek
|
|
||||||
{
|
|
||||||
if (!shutup)
|
|
||||||
{
|
|
||||||
Status(StringPrintfW(WASABI_API_LNGSTRINGW(IDS_PREBUFFERING), get->bytes_available()*100/bsize));
|
|
||||||
}
|
|
||||||
if (get->run()) break;
|
|
||||||
if (Aborting() || abort_prebuf || get->bytes_available()>=(int)max) break;
|
|
||||||
Sleep(2);
|
|
||||||
}
|
|
||||||
if (!shutup)
|
|
||||||
{
|
|
||||||
Status(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VorbisFile_HTTP::_http_read(char* ptr,size_t total)
|
|
||||||
{
|
|
||||||
#ifdef CANSEEK
|
|
||||||
if (seekpos!=-1)
|
|
||||||
{
|
|
||||||
UINT sp=seekpos;
|
|
||||||
seekpos=-1;
|
|
||||||
if (sp!=pos)
|
|
||||||
{
|
|
||||||
if (sp>pos && sp<=pos+get->bytes_available())
|
|
||||||
{
|
|
||||||
get->get_bytes(0,sp-pos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (reconnect(sp))
|
|
||||||
{
|
|
||||||
return 0;//oh well...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos=sp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
UINT wr=0;
|
|
||||||
while(!Aborting() && wr<total)
|
|
||||||
{
|
|
||||||
int st=get->run();
|
|
||||||
int d=get->get_bytes(ptr,(int)total-wr);
|
|
||||||
if (st && !d) break;
|
|
||||||
wr+=d;
|
|
||||||
ptr+=d;
|
|
||||||
pos+=d;
|
|
||||||
if ((len>0 && pos>=len) || wr>=total || Aborting()) break;
|
|
||||||
if (use_prebuf) fillbuf(bsize * cfg_prebuf2 / 100,0);
|
|
||||||
else Sleep(1);
|
|
||||||
}
|
|
||||||
return wr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VorbisFile_HTTP::Idle()
|
|
||||||
{
|
|
||||||
get->run();
|
|
||||||
Sleep(1);
|
|
||||||
get->run();
|
|
||||||
Sleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VorbisFile_HTTP::f_read(UINT siz,void* ptr)
|
|
||||||
{
|
|
||||||
if (Aborting()) return 0;//fixme
|
|
||||||
int i=(int)_http_read((char*)ptr,siz);
|
|
||||||
if (i>0 && saver) saver->Write(ptr,i);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
int VorbisFile_HTTP::f_seek(ogg_int64_t offset,int whence)
|
|
||||||
{
|
|
||||||
#ifdef CANSEEK
|
|
||||||
if (can_seek)
|
|
||||||
{
|
|
||||||
switch(whence)
|
|
||||||
{
|
|
||||||
case FILE_BEGIN:
|
|
||||||
seekpos=(int)offset;
|
|
||||||
break;
|
|
||||||
case FILE_END:
|
|
||||||
seekpos=len+(int)offset;
|
|
||||||
break;
|
|
||||||
case FILE_CURRENT:
|
|
||||||
seekpos=pos+(int)offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (seekpos>len) seekpos=len;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT VorbisFile_HTTP::f_tell()
|
|
||||||
{
|
|
||||||
#ifdef CANSEEK
|
|
||||||
if (can_seek)
|
|
||||||
{
|
|
||||||
if (seekpos!=-1) return seekpos;
|
|
||||||
else return pos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HWND GetDialogBoxParent()
|
|
||||||
{
|
|
||||||
HWND parent = (HWND)SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT);
|
|
||||||
if (!parent || parent == (HWND)1)
|
|
||||||
return mod.hMainWindow;
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VorbisFile_HTTP::http_init()
|
|
||||||
{
|
|
||||||
if (mod.service)
|
|
||||||
{
|
|
||||||
waServiceFactory *sf = mod.service->service_getServiceByGuid(httpreceiverGUID);
|
|
||||||
if (sf) get = (api_httpreceiver *)sf->getInterface();
|
|
||||||
}
|
|
||||||
if (!get) return false;
|
|
||||||
get->open(API_DNS_AUTODNS, bsize, do_proxy(AutoChar(url)));
|
|
||||||
|
|
||||||
if (reconnect(0))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CANSEEK
|
|
||||||
// if (cfg_httpseek)
|
|
||||||
{
|
|
||||||
//need to get http headers first
|
|
||||||
while(!memcmp(get->getallheaders(),"\0\0",2))
|
|
||||||
{
|
|
||||||
if (get->run()<0 || Aborting())
|
|
||||||
{
|
|
||||||
int reply = get->getreplycode();
|
|
||||||
if ( reply == 401 )
|
|
||||||
{
|
|
||||||
api_connection *mcon=get->GetConnection();
|
|
||||||
if ( mcon && mcon->GetReceiveBytesAvailable())
|
|
||||||
{
|
|
||||||
char p[1024]="";
|
|
||||||
while ( mcon->GetReceiveBytesAvailable() )
|
|
||||||
{
|
|
||||||
char b[2048]="";
|
|
||||||
mcon->ReceiveLine(b,2048);
|
|
||||||
if ( *b )
|
|
||||||
{
|
|
||||||
char *t= strstr(b,"WWW-Authenticate:");
|
|
||||||
if ( t && *t )
|
|
||||||
{
|
|
||||||
char *y = strstr(t,"\"");
|
|
||||||
if ( y && *y )
|
|
||||||
{
|
|
||||||
y++;
|
|
||||||
if ( *y )
|
|
||||||
{
|
|
||||||
char *u = strstr(y,"\"");
|
|
||||||
if ( u && *u )
|
|
||||||
{
|
|
||||||
*u = 0;
|
|
||||||
wsprintfA(p,"%s",y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( *p ) // found our realm
|
|
||||||
{
|
|
||||||
if (!force_lpinfo[0]) GetPrivateProfileStringA("HTTP-AUTH",p,"",force_lpinfo,sizeof(force_lpinfo),INI_FILE);
|
|
||||||
if (!force_lpinfo[0] || lpinfo[0] || usedauth )
|
|
||||||
{
|
|
||||||
lstrcpynA(dlg_realm,p,sizeof(dlg_realm));
|
|
||||||
if (!WASABI_API_DIALOGBOXPARAM(IDD_HTTPAUTH, GetDialogBoxParent(), httpDlgProc, (LPARAM)this))
|
|
||||||
{
|
|
||||||
force_lpinfo[0]=0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WritePrivateProfileStringA("HTTP-AUTH",p,force_lpinfo,INI_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Status(WASABI_API_LNGSTRINGW(IDS_AUTH_REQUIRED));
|
|
||||||
m_needs_auth=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//hg->get.wait(10);
|
|
||||||
Sleep(1);
|
|
||||||
}
|
|
||||||
len=get->content_length();
|
|
||||||
const char* poo=get->getheader("icy-name");
|
|
||||||
if (poo) stream_title=poo;
|
|
||||||
if (cfg_httpseek2 && len) can_seek=1;
|
|
||||||
is_live=(len<=0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//if (hg->len==0 || hg->len==-1) hg->can_seek=0;
|
|
||||||
seekpos=-1;
|
|
||||||
|
|
||||||
if (cfg_fsave && !can_seek)
|
|
||||||
{
|
|
||||||
saver=new StreamSave;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VorbisFile * VorbisFile::Create_HTTP(const char * url,bool is_info)
|
|
||||||
{
|
|
||||||
VorbisFile_HTTP * r=new VorbisFile_HTTP(cfg_http_bsize,AutoWide(url),is_info, false);
|
|
||||||
if (r)
|
|
||||||
{
|
|
||||||
if (!r->http_init())
|
|
||||||
{
|
|
||||||
int trys=0;
|
|
||||||
while ( r && r->m_needs_auth && trys++ < 2)
|
|
||||||
{
|
|
||||||
const char *p=strstr(url,"://");
|
|
||||||
if (p && *p)
|
|
||||||
{
|
|
||||||
p += 3;
|
|
||||||
if (p && *p)
|
|
||||||
{
|
|
||||||
char lurl[4096] = {0};
|
|
||||||
wsprintfA(lurl, "http://%s@%s", r->force_lpinfo, p);
|
|
||||||
delete r;
|
|
||||||
r = new VorbisFile_HTTP(cfg_http_bsize,AutoWide(lurl),is_info, true);
|
|
||||||
if (r && r->http_init())
|
|
||||||
{
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete r;
|
|
||||||
r=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CALLBACK VorbisFile_HTTP::httpDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
|
||||||
{
|
|
||||||
VorbisFile_HTTP *_this;
|
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
#ifdef WIN64
|
|
||||||
SetWindowLong(hwndDlg, GWLP_USERDATA, (LONG)lParam);
|
|
||||||
_this = (VorbisFile_HTTP*)(GetWindowLong(hwndDlg, GWLP_USERDATA));
|
|
||||||
#else
|
|
||||||
SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)lParam);
|
|
||||||
_this = (VorbisFile_HTTP*)GetWindowLong(hwndDlg, GWL_USERDATA);
|
|
||||||
#endif
|
|
||||||
if (_this->force_lpinfo[0])
|
|
||||||
SetDlgItemTextA(hwndDlg,IDC_EDITAUTH,_this->force_lpinfo);
|
|
||||||
else SetDlgItemTextA(hwndDlg,IDC_EDITAUTH,_this->lpinfo);
|
|
||||||
SetDlgItemTextA(hwndDlg,IDC_REALM,_this->dlg_realm);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
|
||||||
#ifdef WIN64
|
|
||||||
_this = (VorbisFile_HTTP*)GetWindowLong(hwndDlg, GWLP_USERDATA);
|
|
||||||
#else
|
|
||||||
_this = (VorbisFile_HTTP*)GetWindowLong(hwndDlg, GWL_USERDATA);
|
|
||||||
#endif
|
|
||||||
if (LOWORD(wParam) == IDOKAUTH)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
GetDlgItemTextA(hwndDlg,IDC_EDITAUTH,_this->force_lpinfo,sizeof(_this->force_lpinfo));
|
|
||||||
p = strstr(_this->force_lpinfo,"\r");
|
|
||||||
if ( p && *p ) *p=0;
|
|
||||||
p = strstr(_this->force_lpinfo,"\n");
|
|
||||||
if ( p && *p ) *p=0;
|
|
||||||
EndDialog(hwndDlg,1);
|
|
||||||
}
|
|
||||||
else if (LOWORD(wParam) == IDCANCELAUTH)
|
|
||||||
{
|
|
||||||
EndDialog(hwndDlg,0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,415 +0,0 @@
|
|||||||
// Microsoft Visual C++ generated resource script.
|
|
||||||
//
|
|
||||||
#include "resource.h"
|
|
||||||
|
|
||||||
#define APSTUDIO_READONLY_SYMBOLS
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
|
||||||
//
|
|
||||||
#include "afxres.h"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#undef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Polish resources
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK)
|
|
||||||
#ifdef _WIN32
|
|
||||||
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
|
|
||||||
#pragma code_page(1250)
|
|
||||||
#endif //_WIN32
|
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// TEXTINCLUDE
|
|
||||||
//
|
|
||||||
|
|
||||||
1 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"resource.h\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
2 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"#include ""afxres.h""\r\n"
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
3 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"#include ""version.rc2""\r\n"
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
#endif // Polish resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// English (U.S.) resources
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
|
||||||
#ifdef _WIN32
|
|
||||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|
||||||
#pragma code_page(1252)
|
|
||||||
#endif //_WIN32
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Dialog
|
|
||||||
//
|
|
||||||
|
|
||||||
IDD_ABOUT DIALOGEX 0, 0, 173, 113
|
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
|
||||||
FONT 8, "MS Shell Dlg", 0, 0, 0x1
|
|
||||||
BEGIN
|
|
||||||
CONTROL "",IDC_CUSTOM1,"XIPH_CLASS",0x0,6,8,44,40
|
|
||||||
CTEXT "",IDC_RPM,7,56,45,8
|
|
||||||
CTEXT "",IDC_RPM2,4,64,51,8
|
|
||||||
LTEXT "",IDC_ABOUT_TEXT,58,8,110,85
|
|
||||||
DEFPUSHBUTTON "OK",IDCANCEL,117,93,50,14
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_HTTPAUTH DIALOGEX 0, 0, 154, 70
|
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
|
||||||
CAPTION "Ogg Authentication"
|
|
||||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
|
||||||
BEGIN
|
|
||||||
LTEXT "Realm: ",IDC_STATIC,4,4,25,8
|
|
||||||
LTEXT "",IDC_REALM,37,4,113,8
|
|
||||||
LTEXT "Enter your login and password in the form of:\n\tlogin:password",IDC_STATIC,4,15,146,17
|
|
||||||
EDITTEXT IDC_EDITAUTH,4,35,146,12,ES_AUTOHSCROLL
|
|
||||||
DEFPUSHBUTTON "OK",IDOKAUTH,4,52,50,13
|
|
||||||
PUSHBUTTON "Cancel",IDCANCELAUTH,100,53,50,13
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_INFO_DLG_NEW DIALOGEX 0, 0, 329, 238
|
|
||||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
|
||||||
CAPTION "Ogg Vorbis Info"
|
|
||||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
|
||||||
BEGIN
|
|
||||||
LTEXT "File/URL :",-1,6,6,34,8
|
|
||||||
EDITTEXT IDC_URL,43,5,282,12,ES_AUTOHSCROLL | ES_READONLY
|
|
||||||
GROUPBOX "File / Stream Info",IDC_STATIC_MISC,224,20,101,120
|
|
||||||
EDITTEXT IDC_MISC,231,30,88,107,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER
|
|
||||||
GROUPBOX "Chained Streams",IDC_STATIC_CS,224,155,101,30
|
|
||||||
PUSHBUTTON "<= previous",IDC_PREV_STREAM,229,167,44,13
|
|
||||||
PUSHBUTTON "next =>",IDC_NEXT_STREAM,276,167,43,13
|
|
||||||
CONTROL "Hide special fields",IDC_HIDE_SPEC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,190,73,10
|
|
||||||
PUSHBUTTON "",IDC_MODE_TOGGLE,228,203,93,13
|
|
||||||
PUSHBUTTON "Close",IDCANCEL,273,220,48,13
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_INFO_PANEL_SIMPLE DIALOGEX 0, 0, 227, 218
|
|
||||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
|
|
||||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
|
||||||
BEGIN
|
|
||||||
GROUPBOX "Standard Tags",IDC_STATIC_STD,3,2,219,119
|
|
||||||
LTEXT "Title",IDC_STATIC,29,16,14,8
|
|
||||||
EDITTEXT IDC_TITLE,48,14,168,12,ES_AUTOHSCROLL
|
|
||||||
LTEXT "Artist",IDC_STATIC,27,32,16,8
|
|
||||||
EDITTEXT IDC_ARTIST,48,30,168,12,ES_AUTOHSCROLL
|
|
||||||
LTEXT "Album",IDC_STATIC,24,48,19,8
|
|
||||||
EDITTEXT IDC_ALBUM,48,46,124,12,ES_AUTOHSCROLL
|
|
||||||
LTEXT "Track:",IDC_STATIC_TRACK,175,48,21,8
|
|
||||||
EDITTEXT IDC_TRACK,198,46,18,12,ES_AUTOHSCROLL
|
|
||||||
LTEXT "Year",IDC_STATIC,28,64,16,8
|
|
||||||
EDITTEXT IDC_DATE,48,62,56,12,ES_AUTOHSCROLL
|
|
||||||
LTEXT "Genre",IDC_STATIC,117,64,22,8
|
|
||||||
COMBOBOX IDC_GENRE,140,62,77,68,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
|
|
||||||
LTEXT "Comment",IDC_STATIC,13,80,29,8
|
|
||||||
EDITTEXT IDC_COMMENT,48,78,169,37,ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL
|
|
||||||
GROUPBOX "Other",IDC_STATIC_TAGS,3,123,219,91
|
|
||||||
LISTBOX IDC_LIST,10,134,207,75,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_INFO_PANEL_ADVANCED DIALOGEX 0, 0, 227, 218
|
|
||||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
|
|
||||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
|
||||||
BEGIN
|
|
||||||
LISTBOX IDC_LIST,3,3,219,212,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_INFO DIALOGEX 0, 0, 341, 164
|
|
||||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
|
||||||
BEGIN
|
|
||||||
GROUPBOX "Advanced",IDC_STATIC,0,0,341,164
|
|
||||||
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,6,13,164,143
|
|
||||||
LTEXT "Name:",IDC_STATIC,175,13,22,8
|
|
||||||
EDITTEXT IDC_NAME,175,23,159,14,ES_AUTOHSCROLL
|
|
||||||
LTEXT "Value:",IDC_STATIC,175,39,21,8
|
|
||||||
EDITTEXT IDC_VALUE,175,49,159,90,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
|
|
||||||
PUSHBUTTON "Add New",IDC_BUTTON_ADD,176,142,50,13
|
|
||||||
PUSHBUTTON "Delete",IDC_BUTTON_DEL,230,142,50,13
|
|
||||||
PUSHBUTTON "Delete All",IDC_BUTTON_DELALL,284,142,50,13
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_CONFIG DIALOGEX 0, 0, 222, 261
|
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
|
||||||
BEGIN
|
|
||||||
GROUPBOX "Decoding",IDC_STATIC,4,4,214,93
|
|
||||||
CONTROL "Buffer full files from disk",IDC_FULLBUF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,17,89,10
|
|
||||||
CONTROL "Show average bitrate while playing",IDC_AVG_BR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,31,128,10
|
|
||||||
GROUPBOX "5.1-Channel Input Processing",IDC_STATIC,10,44,201,47
|
|
||||||
LTEXT "Apply conversion:",IDC_STATIC,16,58,72,8,0,WS_EX_RIGHT
|
|
||||||
COMBOBOX IDC_MC6_DM,95,56,110,96,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
|
||||||
LTEXT "Source channel order:",IDC_STATIC,16,75,72,8,0,WS_EX_RIGHT
|
|
||||||
COMBOBOX IDC_MC6_MAP,95,73,110,96,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
|
||||||
GROUPBOX "Streaming",IDC_STATIC,4,101,214,139
|
|
||||||
LTEXT "Buffer size",IDC_STATIC,10,115,34,8
|
|
||||||
EDITTEXT IDC_HTTP_BSIZE,48,113,28,12,ES_AUTOHSCROLL | ES_NUMBER
|
|
||||||
LTEXT "KB",IDC_STATIC,80,115,9,8
|
|
||||||
GROUPBOX "Prebuffering:",IDC_STATIC,10,129,201,44
|
|
||||||
LTEXT "At start:",IDC_STATIC,16,142,31,8
|
|
||||||
CONTROL "",IDC_SLIDER1,"msctls_trackbar32",TBS_NOTICKS | WS_TABSTOP,70,141,130,10
|
|
||||||
LTEXT "After underrun:",IDC_STATIC,16,153,54,8
|
|
||||||
CONTROL "",IDC_SLIDER2,"msctls_trackbar32",TBS_NOTICKS | WS_TABSTOP,70,152,130,10
|
|
||||||
LTEXT "0%",IDC_STATIC,71,161,13,8
|
|
||||||
LTEXT "50%",IDC_STATIC,122,161,18,8
|
|
||||||
LTEXT "100%",IDC_STATIC,185,161,20,8
|
|
||||||
LTEXT "Use Winamp's proxy server settings:",IDC_STATIC,10,179,120,8
|
|
||||||
COMBOBOX IDC_PROXY,134,177,77,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
|
||||||
GROUPBOX "",IDC_STATIC,10,191,201,43
|
|
||||||
CONTROL "Save streamed files to:",IDC_FSAVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,201,89,10
|
|
||||||
PUSHBUTTON "default",IDC_SSAVE_FMT_DEF,165,200,40,11
|
|
||||||
PUSHBUTTON "",IDC_STREAM_SAVE,15,215,105,13
|
|
||||||
EDITTEXT IDC_SSAVE_FMT,120,215,85,13,ES_AUTOHSCROLL
|
|
||||||
DEFPUSHBUTTON "OK",IDOK,124,244,45,13
|
|
||||||
PUSHBUTTON "Cancel",IDCANCEL,173,244,45,13
|
|
||||||
END
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// DESIGNINFO
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
GUIDELINES DESIGNINFO
|
|
||||||
BEGIN
|
|
||||||
IDD_ABOUT, DIALOG
|
|
||||||
BEGIN
|
|
||||||
LEFTMARGIN, 4
|
|
||||||
RIGHTMARGIN, 168
|
|
||||||
TOPMARGIN, 4
|
|
||||||
BOTTOMMARGIN, 107
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_HTTPAUTH, DIALOG
|
|
||||||
BEGIN
|
|
||||||
LEFTMARGIN, 4
|
|
||||||
RIGHTMARGIN, 150
|
|
||||||
TOPMARGIN, 4
|
|
||||||
BOTTOMMARGIN, 66
|
|
||||||
END
|
|
||||||
|
|
||||||
IDD_CONFIG, DIALOG
|
|
||||||
BEGIN
|
|
||||||
LEFTMARGIN, 4
|
|
||||||
RIGHTMARGIN, 218
|
|
||||||
TOPMARGIN, 4
|
|
||||||
BOTTOMMARGIN, 257
|
|
||||||
END
|
|
||||||
END
|
|
||||||
#endif // APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Bitmap
|
|
||||||
//
|
|
||||||
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP9$(DISABLED) BITMAP "oggdrop\\120.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP9 BITMAP "oggdrop\\120.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP8$(DISABLED) BITMAP "oggdrop\\119.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP8 BITMAP "oggdrop\\119.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP7$(DISABLED) BITMAP "oggdrop\\118.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP7 BITMAP "oggdrop\\118.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP6$(DISABLED) BITMAP "oggdrop\\117.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP6 BITMAP "oggdrop\\117.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP5$(DISABLED) BITMAP "oggdrop\\116.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP5 BITMAP "oggdrop\\116.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP4$(DISABLED) BITMAP "oggdrop\\115.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP4 BITMAP "oggdrop\\115.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP3$(DISABLED) BITMAP "oggdrop\\114.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP3 BITMAP "oggdrop\\114.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP2$(DISABLED) BITMAP "oggdrop\\113.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP2 BITMAP "oggdrop\\113.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP12$(DISABLED) BITMAP "oggdrop\\123.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP12 BITMAP "oggdrop\\123.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP11$(DISABLED) BITMAP "oggdrop\\122.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP11 BITMAP "oggdrop\\122.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP10$(DISABLED) BITMAP "oggdrop\\121.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP10 BITMAP "oggdrop\\121.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
|
|
||||||
#if defined(APSTUDIO_INVOKED)
|
|
||||||
IDB_BITMAP1$(DISABLED) BITMAP "oggdrop\\112.bmp"
|
|
||||||
#else
|
|
||||||
IDB_BITMAP1 BITMAP "oggdrop\\112.bmp"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// PNG
|
|
||||||
//
|
|
||||||
|
|
||||||
IDB_PNG1 PNG "oggdrop\\112.png"
|
|
||||||
IDB_PNG2 PNG "oggdrop\\113.png"
|
|
||||||
IDB_PNG3 PNG "oggdrop\\114.png"
|
|
||||||
IDB_PNG4 PNG "oggdrop\\115.png"
|
|
||||||
IDB_PNG5 PNG "oggdrop\\116.png"
|
|
||||||
IDB_PNG6 PNG "oggdrop\\117.png"
|
|
||||||
IDB_PNG7 PNG "oggdrop\\118.png"
|
|
||||||
IDB_PNG8 PNG "oggdrop\\119.png"
|
|
||||||
IDB_PNG9 PNG "oggdrop\\120.png"
|
|
||||||
IDB_PNG10 PNG "oggdrop\\121.png"
|
|
||||||
IDB_PNG11 PNG "oggdrop\\122.png"
|
|
||||||
IDB_PNG12 PNG "oggdrop\\123.png"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// String Table
|
|
||||||
//
|
|
||||||
|
|
||||||
STRINGTABLE
|
|
||||||
BEGIN
|
|
||||||
IDS_NULLSOFT_VORBIS_DECODER "Nullsoft Vorbis Decoder v%s"
|
|
||||||
65535 "{5C5BCA4E-279E-4867-8E24-58C8B186959A}"
|
|
||||||
END
|
|
||||||
|
|
||||||
STRINGTABLE
|
|
||||||
BEGIN
|
|
||||||
IDS_NULLSOFT_VORBIS_DECODER_OLD "Nullsoft Vorbis Decoder"
|
|
||||||
IDS_FILE_ERROR "file error"
|
|
||||||
IDS_LENGTH "Length: "
|
|
||||||
IDS_AVERAGE_BITRATE "Average bitrate: "
|
|
||||||
IDS_FILE_SIZE "File size: "
|
|
||||||
IDS_NOMINAL_BITRATE "Nominal bitrate: "
|
|
||||||
IDS_MIN_BITRATE "Min bitrate: "
|
|
||||||
IDS_MAX_BITRATE "Max bitrate: "
|
|
||||||
IDS_CHANNELS "Channels"
|
|
||||||
IDS_SAMPLING_RATE "Sampling rate"
|
|
||||||
IDS_SERIAL_NUMBER "Serial number"
|
|
||||||
IDS_VERSION "Version"
|
|
||||||
END
|
|
||||||
|
|
||||||
STRINGTABLE
|
|
||||||
BEGIN
|
|
||||||
IDS_VENDOR "Vendor"
|
|
||||||
IDS_TO_SIMPLE_MODE "<< to simple mode"
|
|
||||||
IDS_TO_ADVANCED_MODE "to advanced mode >>"
|
|
||||||
IDS_OGG_VORBIS_INFO "Ogg Vorbis info - %s"
|
|
||||||
IDS_BEST_RPM "Best: %u RPM"
|
|
||||||
IDS_LEAVE_AS_IS "leave as is"
|
|
||||||
IDS_REMAP_6_CHANNELS "remap 6 channels"
|
|
||||||
IDS_DOWNMIX_TO_4_CHANNELS "downmix to 4 channels"
|
|
||||||
IDS_DOWNMIX_TO_2_CHANNELS_DS "downmix to 2 channels (DS)"
|
|
||||||
IDS_DOWNMIX_TO_2_CHANNELS_DS2 "downmix to 2 channels (DS2)"
|
|
||||||
IDS_DOWNMIX_TO_MONO "downmix to mono"
|
|
||||||
IDS_CORRECT_FL_FC_FR_BL_BR_LFE "correct (FL FC FR BL BR LFE)"
|
|
||||||
IDS_BROKEN_FL_FR_FC_BL_BR_LFE "broken (FL FR FC BL BR LFE)"
|
|
||||||
END
|
|
||||||
|
|
||||||
STRINGTABLE
|
|
||||||
BEGIN
|
|
||||||
IDS_ABOUT_TEXT "%s\n© 2001-2023 Winamp SA\nWritten by: Peter Pawlowski\nBuild date: %hs\n\nThanks to:\n Craig Freer\n Tomi 'Nebularia' Jylhä-Ollila\n Jack Moffitt\n Szabolcs Péter"
|
|
||||||
IDS_TITLE_PREFERENCES "%s Preferences"
|
|
||||||
IDS_NEVER "never"
|
|
||||||
IDS_PORT_80_ONLY "port 80 only"
|
|
||||||
IDS_ALWAYS "always"
|
|
||||||
IDS_SELECT_OUTPUT_DIRECTORY "Select output directory:"
|
|
||||||
END
|
|
||||||
|
|
||||||
STRINGTABLE
|
|
||||||
BEGIN
|
|
||||||
IDS_CONNECTING "Connecting..."
|
|
||||||
IDS_PREBUFFERING "Prebuffering : %u%%"
|
|
||||||
IDS_AUTH_REQUIRED "Authentication Required"
|
|
||||||
IDS_OGG_FILES "Ogg Vorbis Files (*.OGG;*.OGA)"
|
|
||||||
IDS_NAME "Name"
|
|
||||||
IDS_VALUE "Value"
|
|
||||||
IDS_KBPS "kbps"
|
|
||||||
IDS_HZ "Hz"
|
|
||||||
IDS_GAME_SPEED "%u RPM"
|
|
||||||
IDS_BYTES "bytes"
|
|
||||||
IDS_FAMILY_STRING "Ogg Vorbis File"
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // English (U.S.) resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
|
||||||
//
|
|
||||||
#include "version.rc2"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#endif // not APSTUDIO_INVOKED
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 16
|
|
||||||
VisualStudioVersion = 16.0.29424.173
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_vorbis", "in_vorbis.vcxproj", "{7C58AC02-7941-42BE-8F97-9BF2064D6631}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9} = {4FC28B55-2A14-43D5-86F7-201054F338A9}
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8} = {49238ED1-3146-49AB-9523-E9826EE4A0C8}
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4} = {EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libogg", "..\libogg\libogg.vcxproj", "{4FC28B55-2A14-43D5-86F7-201054F338A9}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vorbis_static", "..\libvorbis\win32\vorbis_static.vcxproj", "{49238ED1-3146-49AB-9523-E9826EE4A0C8}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vorbisfile_static", "..\libvorbis\win32\vorbisfile_static.vcxproj", "{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{7C58AC02-7941-42BE-8F97-9BF2064D6631}.Release|x64.Build.0 = Release|x64
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{49238ED1-3146-49AB-9523-E9826EE4A0C8}.Release|x64.Build.0 = Release|x64
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{EC9475D2-FEE2-4F8C-9BB9-A11D5EB597C4}.Release|x64.Build.0 = Release|x64
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{4FC28B55-2A14-43D5-86F7-201054F338A9}.Release|x64.Build.0 = Release|x64
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {3248659F-0FFC-4CF4-A9BC-F7D10C713D5D}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,339 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{7C58AC02-7941-42BE-8F97-9BF2064D6631}</ProjectGuid>
|
|
||||||
<RootNamespace>in_vorbis</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
|
||||||
<IncludePath>$(IncludePath)</IncludePath>
|
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
|
||||||
<IncludePath>$(IncludePath)</IncludePath>
|
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
|
||||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Vcpkg">
|
|
||||||
<VcpkgEnableManifest>false</VcpkgEnableManifest>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<VcpkgInstalledDir>
|
|
||||||
</VcpkgInstalledDir>
|
|
||||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
|
||||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
|
||||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<VcpkgInstalledDir>
|
|
||||||
</VcpkgInstalledDir>
|
|
||||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
|
||||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<VcpkgInstalledDir>
|
|
||||||
</VcpkgInstalledDir>
|
|
||||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
|
||||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
|
||||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<VcpkgInstalledDir>
|
|
||||||
</VcpkgInstalledDir>
|
|
||||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
|
||||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WA2;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
|
||||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
|
||||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
||||||
</ClCompile>
|
|
||||||
<ResourceCompile>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<Culture>0x0415</Culture>
|
|
||||||
</ResourceCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
|
||||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
|
||||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
|
||||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;WA2;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
|
||||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
|
||||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
||||||
</ClCompile>
|
|
||||||
<ResourceCompile>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<Culture>0x0415</Culture>
|
|
||||||
</ResourceCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
|
||||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
|
||||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
|
||||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>MinSpace</Optimization>
|
|
||||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
|
||||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
|
||||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<StringPooling>true</StringPooling>
|
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
|
||||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
|
||||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
|
||||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<DebugInformationFormat>None</DebugInformationFormat>
|
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
|
||||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
||||||
</ClCompile>
|
|
||||||
<ResourceCompile>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<Culture>0x0415</Culture>
|
|
||||||
</ResourceCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
|
||||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
|
||||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
|
||||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
|
||||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
|
||||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<Optimization>MinSpace</Optimization>
|
|
||||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
|
||||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
|
||||||
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;TAGZ_UNICODE;UNICODE_INPUT_PLUGIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<StringPooling>true</StringPooling>
|
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
|
||||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
|
||||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
|
||||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
|
||||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<DebugInformationFormat>None</DebugInformationFormat>
|
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
|
||||||
<DisableSpecificWarnings>4090;4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
||||||
</ClCompile>
|
|
||||||
<ResourceCompile>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<Culture>0x0415</Culture>
|
|
||||||
</ResourceCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>shlwapi.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
|
||||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
|
||||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
|
||||||
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
|
||||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
|
||||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
|
||||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\external_dependencies\openmpt-trunk\include\vorbis\win32\vorbisfile_static.vcxproj">
|
|
||||||
<Project>{ec9475d2-fee2-4f8c-9bb9-a11d5eb597c4}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
|
|
||||||
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\..\nsmkv\Lacing.cpp" />
|
|
||||||
<ClCompile Include="..\..\..\nsmkv\vint.cpp" />
|
|
||||||
<ClCompile Include="about.cpp" />
|
|
||||||
<ClCompile Include="chainedstream_parse.cpp" />
|
|
||||||
<ClCompile Include="config.cpp" />
|
|
||||||
<ClCompile Include="c_string.cpp" />
|
|
||||||
<ClCompile Include="decoder.cpp" />
|
|
||||||
<ClCompile Include="ExtendedRead.cpp" />
|
|
||||||
<ClCompile Include="genres.c" />
|
|
||||||
<ClCompile Include="http.cpp" />
|
|
||||||
<ClCompile Include="infobox.cpp" />
|
|
||||||
<ClCompile Include="info_.cpp" />
|
|
||||||
<ClCompile Include="localfile.cpp" />
|
|
||||||
<ClCompile Include="mkv_vorbis_decoder.cpp" />
|
|
||||||
<ClCompile Include="shaper.cpp" />
|
|
||||||
<ClCompile Include="vcedit.c" />
|
|
||||||
<ClCompile Include="wa2.cpp" />
|
|
||||||
<ClCompile Include="winnt_helper.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="api__in_vorbis.h" />
|
|
||||||
<ClInclude Include="c_string.h" />
|
|
||||||
<ClInclude Include="decoder.h" />
|
|
||||||
<ClInclude Include="genres.h" />
|
|
||||||
<ClInclude Include="main.h" />
|
|
||||||
<ClInclude Include="mkv_vorbis_decoder.h" />
|
|
||||||
<ClInclude Include="resource.h" />
|
|
||||||
<ClInclude Include="shaper.h" />
|
|
||||||
<ClInclude Include="vcedit.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="in_vorbis.rc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Image Include="oggdrop\112.png" />
|
|
||||||
<Image Include="oggdrop\113.png" />
|
|
||||||
<Image Include="oggdrop\114.png" />
|
|
||||||
<Image Include="oggdrop\115.png" />
|
|
||||||
<Image Include="oggdrop\116.png" />
|
|
||||||
<Image Include="oggdrop\117.png" />
|
|
||||||
<Image Include="oggdrop\118.png" />
|
|
||||||
<Image Include="oggdrop\119.png" />
|
|
||||||
<Image Include="oggdrop\120.png" />
|
|
||||||
<Image Include="oggdrop\121.png" />
|
|
||||||
<Image Include="oggdrop\122.png" />
|
|
||||||
<Image Include="oggdrop\123.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
@ -1,145 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="winnt_helper.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="wa2.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="vcedit.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="shaper.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="mkv_vorbis_decoder.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="localfile.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="infobox.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="info_.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="http.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="genres.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="ExtendedRead.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="decoder.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="config.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="chainedstream_parse.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="c_string.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="about.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\nsmkv\Lacing.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\nsmkv\vint.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="api__in_vorbis.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="c_string.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="decoder.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="genres.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="main.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="mkv_vorbis_decoder.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="resource.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="shaper.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="vcedit.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Image Include="oggdrop\112.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\113.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\114.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\115.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\116.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\117.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\118.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\119.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\120.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\121.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\122.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
<Image Include="oggdrop\123.png">
|
|
||||||
<Filter>Image Files</Filter>
|
|
||||||
</Image>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Header Files">
|
|
||||||
<UniqueIdentifier>{7c471b36-309f-402b-a247-e640a094f9bc}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Ressource Files">
|
|
||||||
<UniqueIdentifier>{735fc214-c8e5-4619-8c70-a184a8373c92}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Source Files">
|
|
||||||
<UniqueIdentifier>{00aa1653-baa3-4e88-b6d1-fa408b0c4a85}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Image Files">
|
|
||||||
<UniqueIdentifier>{32126a2c-dd90-4901-a5e1-aee5b7363e37}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="in_vorbis.rc">
|
|
||||||
<Filter>Ressource Files</Filter>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,658 +0,0 @@
|
|||||||
//tag editor file i/o code, title formatting interface
|
|
||||||
#include "main.h"
|
|
||||||
#include "genres.h"
|
|
||||||
#include "../nu/AutoWide.h"
|
|
||||||
#include "../nu/AutoChar.h"
|
|
||||||
#include "../nu/ns_wc.h"
|
|
||||||
#include "api__in_vorbis.h"
|
|
||||||
#include <wchar.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <shlwapi.h>
|
|
||||||
#include "vcedit.h"
|
|
||||||
#include <strsafe.h>
|
|
||||||
#include "resource.h"
|
|
||||||
|
|
||||||
namespace ogg_helper //chainedstream_parse
|
|
||||||
{
|
|
||||||
int num_get_tracks(HANDLE hFile);
|
|
||||||
int query_chained_stream_offset(HANDLE hFile, int idx, __int64 * out_beginning, __int64 * out_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static void xfer(HANDLE src, HANDLE dst, __int64 size)
|
|
||||||
{
|
|
||||||
enum { BUFFER = 1024 * 1024 };
|
|
||||||
void * buffer = malloc((int)(BUFFER > size ? size : BUFFER));
|
|
||||||
while (size > 0)
|
|
||||||
{
|
|
||||||
int d = BUFFER;
|
|
||||||
if ((__int64)d > size) d = (int)size;
|
|
||||||
DWORD br = 0;
|
|
||||||
ReadFile(src, buffer, d, &br, 0);
|
|
||||||
WriteFile(dst, buffer, d, &br, 0);
|
|
||||||
size -= d;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
static void seek64(HANDLE src, __int64 offset)
|
|
||||||
{
|
|
||||||
__int64 temp = offset;
|
|
||||||
SetFilePointer(src, *(DWORD*)&temp, ((long*)&temp + 1), FILE_BEGIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern OSVERSIONINFO os_ver;
|
|
||||||
extern HANDLE hThread;
|
|
||||||
|
|
||||||
static DWORDLONG get_space(const wchar_t * url)
|
|
||||||
{
|
|
||||||
ULARGE_INTEGER free_space;
|
|
||||||
char zzz[4] = {(char)url[0], (char)url[1], (char)url[2], 0}; //"c:\";
|
|
||||||
|
|
||||||
free_space.QuadPart = 0;
|
|
||||||
|
|
||||||
if (os_ver.dwPlatformId == VER_PLATFORM_WIN32_NT || (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && LOWORD(os_ver.dwBuildNumber) > 1000))
|
|
||||||
{
|
|
||||||
static BOOL (WINAPI* pGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
|
|
||||||
if (!pGetDiskFreeSpaceEx)
|
|
||||||
{
|
|
||||||
pGetDiskFreeSpaceEx = (BOOL (WINAPI*)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER))GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetDiskFreeSpaceExA");
|
|
||||||
}
|
|
||||||
if (pGetDiskFreeSpaceEx)
|
|
||||||
{
|
|
||||||
ULARGE_INTEGER blah1, blah2;
|
|
||||||
pGetDiskFreeSpaceEx((LPCTSTR)zzz, &free_space, &blah1, &blah2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!free_space.QuadPart)
|
|
||||||
{
|
|
||||||
DWORD spc, bps, nfc, tnc;
|
|
||||||
GetDiskFreeSpaceA(zzz, &spc, &bps, &nfc, &tnc);
|
|
||||||
free_space.QuadPart = UInt32x32To64(spc * bps, nfc);
|
|
||||||
}
|
|
||||||
return free_space.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sync_movefile(const wchar_t * src, const wchar_t * dst);
|
|
||||||
|
|
||||||
struct vcedit_param
|
|
||||||
{
|
|
||||||
HANDLE hFile;
|
|
||||||
__int64 remaining;
|
|
||||||
};
|
|
||||||
|
|
||||||
static size_t callback_fread(void *ptr, size_t size, size_t nmemb, vcedit_param * param)
|
|
||||||
{
|
|
||||||
int to_read = (int)(nmemb *size);
|
|
||||||
if (to_read > param->remaining) to_read = (int)param->remaining;
|
|
||||||
DWORD br = 0;
|
|
||||||
ReadFile(param->hFile, ptr, to_read, &br, 0);
|
|
||||||
param->remaining -= br;
|
|
||||||
return br / size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t callback_write(const void *ptr, size_t size, size_t nmemb, HANDLE hFile)
|
|
||||||
{
|
|
||||||
DWORD bw = 0;
|
|
||||||
WriteFile(hFile, ptr, (DWORD)(size*nmemb), &bw, 0);
|
|
||||||
return bw / size;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL modify_file(const wchar_t* url, const vorbis_comment * comments, int links)
|
|
||||||
{ //also used for stream save fix
|
|
||||||
HANDLE dst = INVALID_HANDLE_VALUE;
|
|
||||||
int scream = 0;
|
|
||||||
StringW tmp;
|
|
||||||
|
|
||||||
winampGetExtendedFileInfoW_Cleanup();
|
|
||||||
|
|
||||||
tmp = url;
|
|
||||||
tmp += L".tmp";
|
|
||||||
|
|
||||||
HANDLE src = CreateFileW(url, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
|
||||||
|
|
||||||
if (src != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
ULARGE_INTEGER src_size;
|
|
||||||
src_size.LowPart = GetFileSize(src, &src_size.HighPart);
|
|
||||||
if (src_size.QuadPart > get_space(url))
|
|
||||||
{ //shit happens... try default temp location
|
|
||||||
StringW tempdir;
|
|
||||||
GetTempPathW(MAX_PATH, StringTempW(tempdir, MAX_PATH));
|
|
||||||
if (get_space(tempdir) < src_size.QuadPart)
|
|
||||||
{ //oh well
|
|
||||||
CloseHandle(src);
|
|
||||||
src = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
tmp = tempdir;
|
|
||||||
if (tmp[tmp.Length() - 1] != '\\') tmp.AddChar('\\');
|
|
||||||
|
|
||||||
StringCchPrintfW(StringTempW(tempdir, MAX_PATH), MAX_PATH, L"ogg%u_%u.tmp", GetTickCount(), GetCurrentProcessId());
|
|
||||||
tmp.AddString(tempdir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dst = CreateFileW(tmp, GENERIC_WRITE | GENERIC_READ, 0, 0, CREATE_ALWAYS, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst != INVALID_HANDLE_VALUE && src != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
FILETIME ct;
|
|
||||||
GetFileTime(src, &ct, 0, 0);
|
|
||||||
SetFileTime(dst, &ct, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int num_links = ogg_helper::num_get_tracks(src);
|
|
||||||
if (num_links < links) scream = 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int cur_link;
|
|
||||||
for (cur_link = 0; cur_link < links && !scream; cur_link++)
|
|
||||||
{
|
|
||||||
__int64 stream_beginning, stream_end;
|
|
||||||
if (ogg_helper::query_chained_stream_offset(src, cur_link, &stream_beginning, &stream_end))
|
|
||||||
{
|
|
||||||
seek64(src, stream_beginning);
|
|
||||||
vcedit_state *vs;
|
|
||||||
vcedit_param param;
|
|
||||||
param.hFile = src;
|
|
||||||
param.remaining = stream_end - stream_beginning;
|
|
||||||
vs = vcedit_new_state();
|
|
||||||
if (vcedit_open_callbacks(vs, ¶m, (vcedit_read_func)callback_fread, (vcedit_write_func)callback_write) < 0)
|
|
||||||
{
|
|
||||||
scream = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vorbis_comment * vc = vcedit_comments(vs);
|
|
||||||
vorbis_comment_clear(vc);
|
|
||||||
vorbis_comment_init(vc);
|
|
||||||
const vorbis_comment * vc_src = comments + cur_link;
|
|
||||||
|
|
||||||
int n;
|
|
||||||
for (n = 0;n < vc_src->comments;n++)
|
|
||||||
{
|
|
||||||
if (vc_src->user_comments[n])
|
|
||||||
vorbis_comment_add(vc, vc_src->user_comments[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
vcedit_write(vs, dst);
|
|
||||||
vcedit_clear(vs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else scream = 1;
|
|
||||||
if (src != INVALID_HANDLE_VALUE) CloseHandle(src);
|
|
||||||
if (dst != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(dst);
|
|
||||||
if (scream)
|
|
||||||
{
|
|
||||||
DeleteFileW(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!scream)
|
|
||||||
{
|
|
||||||
BOOL f_sync;
|
|
||||||
EnterCriticalSection(&sync);
|
|
||||||
|
|
||||||
f_sync = !_wcsicmp(url, cur_file) && hThread; //check for i/o conflict with currently played file
|
|
||||||
LeaveCriticalSection(&sync);
|
|
||||||
if (f_sync)
|
|
||||||
{ //drat, it's now playing
|
|
||||||
scream = !sync_movefile(tmp, url);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!DeleteFileW(url)) scream = 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!MoveFileW(tmp, url))
|
|
||||||
{
|
|
||||||
if (!CopyFileW(tmp, url, 0)) scream = 1;
|
|
||||||
DeleteFileW(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (scream) return 0;
|
|
||||||
else return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t *wdup(const char * src)
|
|
||||||
{
|
|
||||||
return _wcsdup(StringW(src));
|
|
||||||
}
|
|
||||||
|
|
||||||
extern StringW stat_disp;
|
|
||||||
|
|
||||||
void GetFileInfo(const wchar_t *file, wchar_t *title, int *len)
|
|
||||||
{
|
|
||||||
VorbisFile* vf = 0;
|
|
||||||
BOOL is_cur_file = 0;
|
|
||||||
BOOL is_vf_local = 1;
|
|
||||||
if (title) *title = 0;
|
|
||||||
if (len) *len = -1;
|
|
||||||
|
|
||||||
if (!file || !*file)
|
|
||||||
{
|
|
||||||
file = cur_file;
|
|
||||||
is_cur_file = 1;
|
|
||||||
}
|
|
||||||
else if (!lstrcmpiW(file, cur_file))
|
|
||||||
{
|
|
||||||
is_cur_file = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title && stat_disp.Length() > 0 && is_cur_file)
|
|
||||||
{
|
|
||||||
lstrcpynW(title, stat_disp, 256);
|
|
||||||
title = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!len && !title) return ;
|
|
||||||
|
|
||||||
if (is_cur_file)
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&sync);
|
|
||||||
if (theFile)
|
|
||||||
{
|
|
||||||
vf = theFile;
|
|
||||||
is_vf_local = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LeaveCriticalSection(&sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vf)
|
|
||||||
{
|
|
||||||
vf = VorbisFile::Create(file, 1);
|
|
||||||
if (!vf)
|
|
||||||
{
|
|
||||||
if (title)
|
|
||||||
{
|
|
||||||
lstrcpynW(title, PathFindFileNameW(file), 256);
|
|
||||||
wchar_t *blah = PathFindExtensionW(title);
|
|
||||||
*blah=0;
|
|
||||||
}
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len)
|
|
||||||
{
|
|
||||||
*len = (int)(vf->Length() * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title)
|
|
||||||
{
|
|
||||||
const char *t = vf->get_meta("ARTIST", 0);
|
|
||||||
if (t)
|
|
||||||
{
|
|
||||||
MultiByteToWideCharSZ(CP_UTF8, 0, t, -1, title, 256);
|
|
||||||
t = vf->get_meta("TITLE", 0);
|
|
||||||
if (t)
|
|
||||||
{
|
|
||||||
StringCchCatW(title, 256, L" - ");
|
|
||||||
StringCchCatW(title, 256, AutoWide(t, CP_UTF8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *t = vf->get_meta("TITLE", 0);
|
|
||||||
if (t)
|
|
||||||
MultiByteToWideCharSZ(CP_UTF8, 0, t, -1, title, 256);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lstrcpynW(title, PathFindFileNameW(file), 256);
|
|
||||||
wchar_t *blah = PathFindExtensionW(title);
|
|
||||||
*blah=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//q:
|
|
||||||
if (is_vf_local)
|
|
||||||
delete vf;
|
|
||||||
else
|
|
||||||
LeaveCriticalSection(&sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
void w9x_itow(wchar_t *dest, int value, int destlen)
|
|
||||||
{
|
|
||||||
StringCchPrintfW(dest, destlen, L"%d", value);
|
|
||||||
|
|
||||||
}
|
|
||||||
void w9x_utow(wchar_t *dest, int value, int destlen)
|
|
||||||
{
|
|
||||||
StringCchPrintfW(dest, destlen, L"%u", value);
|
|
||||||
}
|
|
||||||
void w9x_htow(wchar_t *dest, int value, int destlen)
|
|
||||||
{
|
|
||||||
StringCchPrintfW(dest, destlen, L"%08x", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_misc(VorbisFile * _vf,int link,wchar_t * out, int outlen)
|
|
||||||
{
|
|
||||||
OggVorbis_File * vf=&_vf->vf;
|
|
||||||
double t=ov_time_total(vf,link);
|
|
||||||
vorbis_info * vi=ov_info(vf,link);
|
|
||||||
vorbis_comment * vc=ov_comment(vf,link);
|
|
||||||
if (!vi || !vc) {WASABI_API_LNGSTRINGW_BUF(IDS_FILE_ERROR,out,outlen);return;}
|
|
||||||
|
|
||||||
wchar_t kbps_str[16] = {0};
|
|
||||||
WASABI_API_LNGSTRINGW_BUF(IDS_KBPS, kbps_str, 16);
|
|
||||||
|
|
||||||
wchar_t length[48]=L"", avgbitrate[48]=L"", filesize[48]=L"", nombitrate[48]=L"", maxbitrate[48]=L"", minbitrate[48]=L"";
|
|
||||||
if (t>0)
|
|
||||||
{
|
|
||||||
int h = (int)(t/3600.0);
|
|
||||||
int m = (int)(t/60.0)%60;
|
|
||||||
int s = (int)t%60;
|
|
||||||
|
|
||||||
if(h>0) StringCchPrintfW(length,48,L"%s%u:%02u:%02u\r\n",WASABI_API_LNGSTRINGW(IDS_LENGTH),h,m,s);
|
|
||||||
else if(m>0) StringCchPrintfW(length,48,L"%s%u:%02u\r\n",WASABI_API_LNGSTRINGW(IDS_LENGTH),m,s);
|
|
||||||
else if(s>0) StringCchPrintfW(length,48,L"%s%u\r\n",WASABI_API_LNGSTRINGW(IDS_LENGTH),s);
|
|
||||||
|
|
||||||
UINT fs=_vf->FileSize();
|
|
||||||
if (fs>0)
|
|
||||||
{
|
|
||||||
int kbps = (int)(((double)fs)/(t*125.0));
|
|
||||||
wchar_t tmp[32] = {0};
|
|
||||||
StringCchPrintfW(avgbitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_AVERAGE_BITRATE),kbps,kbps_str);
|
|
||||||
|
|
||||||
int fs1=fs/1000000;
|
|
||||||
int fs2=(fs/1000)%1000;
|
|
||||||
int fs3=fs%1000;
|
|
||||||
if(fs1)
|
|
||||||
StringCchPrintfW(filesize,48,L"%s%u%03u%03u %s\r\n",WASABI_API_LNGSTRINGW(IDS_FILE_SIZE),fs1,fs2,fs3,WASABI_API_LNGSTRINGW_BUF(IDS_BYTES,tmp,32));
|
|
||||||
else if(fs2)
|
|
||||||
StringCchPrintfW(filesize,48,L"%s%u%03u %s\r\n",WASABI_API_LNGSTRINGW(IDS_FILE_SIZE),fs2,fs3,WASABI_API_LNGSTRINGW_BUF(IDS_BYTES,tmp,32));
|
|
||||||
else
|
|
||||||
StringCchPrintfW(filesize,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_FILE_SIZE),fs3,WASABI_API_LNGSTRINGW_BUF(IDS_BYTES,tmp,32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vi->bitrate_nominal>0)
|
|
||||||
StringCchPrintfW(nombitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_NOMINAL_BITRATE),vi->bitrate_nominal/1000,kbps_str);
|
|
||||||
|
|
||||||
if (vi->bitrate_lower>0)
|
|
||||||
StringCchPrintfW(minbitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_MIN_BITRATE),vi->bitrate_lower/1000,kbps_str);
|
|
||||||
|
|
||||||
if (vi->bitrate_nominal>0)
|
|
||||||
StringCchPrintfW(maxbitrate,48,L"%s%u %s\r\n",WASABI_API_LNGSTRINGW(IDS_MAX_BITRATE),vi->bitrate_nominal/1000,kbps_str);
|
|
||||||
|
|
||||||
wchar_t tmp[32] = {0}, tmp2[32] = {0}, tmp3[32] = {0}, tmp4[32] = {0}, tmp5[32] = {0}, hzStr[8] = {0};
|
|
||||||
StringCchPrintfW(out,outlen,L"%s%s%s%s%s%s%s: %u\r\n%s: %u %s\r\n%s: %u\r\n%s: %u\r\n%s: \r\n%s",
|
|
||||||
length, avgbitrate, filesize, nombitrate, maxbitrate, minbitrate,
|
|
||||||
WASABI_API_LNGSTRINGW_BUF(IDS_CHANNELS,tmp,32),vi->channels,
|
|
||||||
WASABI_API_LNGSTRINGW_BUF(IDS_SAMPLING_RATE,tmp2,32),vi->rate, WASABI_API_LNGSTRINGW_BUF(IDS_HZ,hzStr,8),
|
|
||||||
WASABI_API_LNGSTRINGW_BUF(IDS_SERIAL_NUMBER,tmp3,32),ov_serialnumber(vf,link),
|
|
||||||
WASABI_API_LNGSTRINGW_BUF(IDS_VERSION,tmp4,32),vi->version,
|
|
||||||
WASABI_API_LNGSTRINGW_BUF(IDS_VENDOR,tmp5,32),(wchar_t*)AutoWide(vc->vendor,CP_UTF8));
|
|
||||||
}
|
|
||||||
|
|
||||||
static VorbisFile* last_vf = 0;
|
|
||||||
static wchar_t last_file[MAX_PATH] = {0};
|
|
||||||
static FILETIME ftLastWriteTime;
|
|
||||||
|
|
||||||
// is used to determine if the last write time of the file has changed when
|
|
||||||
// asked to get the metadata for the same cached file so we can update things
|
|
||||||
BOOL HasFileTimeChanged(const wchar_t *fn)
|
|
||||||
{
|
|
||||||
WIN32_FILE_ATTRIBUTE_DATA fileData = {0};
|
|
||||||
if (GetFileAttributesExW(fn, GetFileExInfoStandard, &fileData) == TRUE)
|
|
||||||
{
|
|
||||||
if(CompareFileTime(&ftLastWriteTime, &fileData.ftLastWriteTime))
|
|
||||||
{
|
|
||||||
ftLastWriteTime = fileData.ftLastWriteTime;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateFileTimeChanged(const wchar_t *fn)
|
|
||||||
{
|
|
||||||
WIN32_FILE_ATTRIBUTE_DATA fileData;
|
|
||||||
if (GetFileAttributesExW(fn, GetFileExInfoStandard, &fileData) == TRUE)
|
|
||||||
{
|
|
||||||
ftLastWriteTime = fileData.ftLastWriteTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to call this when we shut down just to make sure things are correctly cleaned up
|
|
||||||
//(the joys of caching for speed)
|
|
||||||
void winampGetExtendedFileInfoW_Cleanup(void)
|
|
||||||
{
|
|
||||||
if (last_vf)
|
|
||||||
{
|
|
||||||
delete last_vf;
|
|
||||||
last_vf = 0;
|
|
||||||
}
|
|
||||||
last_file[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CALLBACK winampGetExtendedFileInfoW_Timer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD elapsed)
|
|
||||||
{
|
|
||||||
// TODO need to do a better way of getting and caching the metadata
|
|
||||||
// this is _just_ a temp fix for the file being locked when it
|
|
||||||
// it really needs 'class Info' to be able to cache and read.
|
|
||||||
KillTimer(hwnd, eventId);
|
|
||||||
winampGetExtendedFileInfoW_Cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeywordMatch(const char *mainString, const char *keyword)
|
|
||||||
{
|
|
||||||
return !_stricmp(mainString, keyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define START_TAG_ALIAS(name, alias) if (KeywordMatch(data, name)) lookup=alias
|
|
||||||
#define TAG_ALIAS(name, alias) else if (KeywordMatch(data, name)) lookup=alias
|
|
||||||
extern "C" __declspec( dllexport ) int winampGetExtendedFileInfoW(const wchar_t *fn, const char *data, wchar_t *dest, int destlen)
|
|
||||||
{
|
|
||||||
if (!_stricmp(data, "type"))
|
|
||||||
{
|
|
||||||
dest[0] = '0';
|
|
||||||
dest[1] = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (!_stricmp(data, "rateable"))
|
|
||||||
{
|
|
||||||
dest[0] = '1';
|
|
||||||
dest[1] = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (!_stricmp(data, "streammetadata"))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fn || (fn && !fn[0])) return 0;
|
|
||||||
|
|
||||||
if (!_stricmp(data, "family"))
|
|
||||||
{
|
|
||||||
LPCWSTR e;
|
|
||||||
int pID = -1;
|
|
||||||
DWORD lcid;
|
|
||||||
e = PathFindExtensionW(fn);
|
|
||||||
if (L'.' != *e) return 0;
|
|
||||||
e++;
|
|
||||||
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
|
|
||||||
if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, e, -1, L"OGG", -1) ||
|
|
||||||
CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, e, -1, L"OGA", -1)) pID = IDS_FAMILY_STRING;
|
|
||||||
if (pID != -1 && S_OK == StringCchCopyW(dest, destlen, WASABI_API_LNGSTRINGW(pID))) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_stricmp(data, "mime"))
|
|
||||||
{
|
|
||||||
StringCchCopyW(dest, destlen, L"audio/ogg");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempt to cache/use a cached instance of VorbisFile to speed up metadata queries
|
|
||||||
// which is especially needed with large ogg files (like with a 4Mb embedded image!)
|
|
||||||
VorbisFile* vf = 0;
|
|
||||||
if(last_file[0] && !_wcsicmp(last_file, fn) && !HasFileTimeChanged(fn))
|
|
||||||
{
|
|
||||||
vf = last_vf;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// different file so clean up if there's a cached instance
|
|
||||||
if(last_vf)
|
|
||||||
{
|
|
||||||
delete last_vf;
|
|
||||||
last_vf = 0;
|
|
||||||
}
|
|
||||||
// open the new file and cache the current filename for subsequent query checks
|
|
||||||
vf = VorbisFile::Create(fn, 1);
|
|
||||||
lstrcpynW(last_file, fn, MAX_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vf) return 0;
|
|
||||||
else last_vf = vf;
|
|
||||||
|
|
||||||
// TODO need to do a better way of getting and caching the metadata
|
|
||||||
// this is _just_ a temp fix for the file being locked when it
|
|
||||||
// it really needs 'class Info' to be able to cache and read.
|
|
||||||
SetTimer(mod.hMainWindow, 256, 2000, winampGetExtendedFileInfoW_Timer);
|
|
||||||
|
|
||||||
const char *lookup = 0;
|
|
||||||
if (!_stricmp(data, "length"))
|
|
||||||
{
|
|
||||||
int len = (int)(vf->Length() * 1000);
|
|
||||||
w9x_itow(dest, len, destlen);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (!_stricmp(data, "bitrate"))
|
|
||||||
{
|
|
||||||
int br = vf->get_avg_bitrate();
|
|
||||||
w9x_itow(dest, br, destlen);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (!_stricmp(data, "SERIALNUMBER"))
|
|
||||||
{
|
|
||||||
w9x_utow(dest, ov_serialnumber(&vf->vf, -1), destlen);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (!_stricmp(data, "SERIALNUMBER_HEX"))
|
|
||||||
{
|
|
||||||
w9x_htow(dest, ov_serialnumber(&vf->vf, -1), destlen);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (!_stricmp(data, "gain"))
|
|
||||||
{
|
|
||||||
float gain = 20.0f*(float)log10(vf->GetGain());
|
|
||||||
StringCchPrintfW(dest, destlen, L"%-+.2f dB", gain);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if(!_stricmp(data,"formatinformation"))
|
|
||||||
{
|
|
||||||
print_misc(vf,0,dest,destlen);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
TAG_ALIAS("title", "TITLE");
|
|
||||||
TAG_ALIAS("artist", "ARTIST");
|
|
||||||
TAG_ALIAS("album", "ALBUM");
|
|
||||||
TAG_ALIAS("genre", "GENRE");
|
|
||||||
TAG_ALIAS("comment", "COMMENT");
|
|
||||||
TAG_ALIAS("year", "DATE");
|
|
||||||
TAG_ALIAS("track", "TRACKNUMBER");
|
|
||||||
TAG_ALIAS("albumartist", "ALBUMARTIST");
|
|
||||||
TAG_ALIAS("composer", "COMPOSER");
|
|
||||||
TAG_ALIAS("disc", "DISCNUMBER");
|
|
||||||
TAG_ALIAS("publisher", "PUBLISHER");
|
|
||||||
TAG_ALIAS("conductor", "CONDUCTOR");
|
|
||||||
TAG_ALIAS("tool", "ENCODED-BY");
|
|
||||||
TAG_ALIAS("replaygain_track_gain", "REPLAYGAIN_TRACK_GAIN");
|
|
||||||
TAG_ALIAS("replaygain_track_peak", "REPLAYGAIN_TRACK_PEAK");
|
|
||||||
TAG_ALIAS("replaygain_album_gain", "REPLAYGAIN_ALBUM_GAIN");
|
|
||||||
TAG_ALIAS("replaygain_album_peak", "REPLAYGAIN_ALBUM_PEAK");
|
|
||||||
TAG_ALIAS("GracenoteFileID", "GRACENOTEFILEID");
|
|
||||||
TAG_ALIAS("GracenoteExtData", "GRACENOTEEXTDATA");
|
|
||||||
TAG_ALIAS("bpm", "BPM");
|
|
||||||
TAG_ALIAS("remixing", "REMIXING");
|
|
||||||
TAG_ALIAS("subtitle", "VERSION");
|
|
||||||
TAG_ALIAS("isrc", "ISRC");
|
|
||||||
TAG_ALIAS("category", "CATEGORY");
|
|
||||||
TAG_ALIAS("rating", "RATING");
|
|
||||||
TAG_ALIAS("producer", "PRODUCER");
|
|
||||||
|
|
||||||
if (!lookup)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const char *value = vf->get_meta(lookup, 0);
|
|
||||||
|
|
||||||
if(KeywordMatch("comment",data)) {
|
|
||||||
if(!value || !*value) value = vf->get_meta("DESCRIPTION", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KeywordMatch("year",data)) {
|
|
||||||
if(!value || !*value) value = vf->get_meta("YEAR", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KeywordMatch("track",data)) {
|
|
||||||
if(!value || !*value) value = vf->get_meta("TRACK", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KeywordMatch("albumartist",data)) {
|
|
||||||
if(!value || !*value) value = vf->get_meta("ALBUM ARTIST", 0);
|
|
||||||
if(!value || !*value) value = vf->get_meta("ENSEMBLE", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KeywordMatch("publisher",data)) {
|
|
||||||
if(!value || !*value) value = vf->get_meta("ORGANIZATION", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KeywordMatch("category",data)) {
|
|
||||||
if(!value || !*value) value = vf->get_meta("CONTENTGROUP", 0);
|
|
||||||
if(!value || !*value) value = vf->get_meta("GROUPING", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KeywordMatch(data, "rating")) {
|
|
||||||
if(!value || !*value) value = vf->get_meta("RATING", 0);
|
|
||||||
if(value && *value) {
|
|
||||||
int rating = atoi(value);
|
|
||||||
// keeps things limited to our range of 0-100
|
|
||||||
if (rating >= 100) {
|
|
||||||
rating = 5;
|
|
||||||
}
|
|
||||||
// 1-100 case
|
|
||||||
else if (rating > 5 && rating < 100) {
|
|
||||||
rating /= 20;
|
|
||||||
// shift up by one rating when in next band
|
|
||||||
// 1-20 = 1, 21-40 = 2, 41-60 = 3, 61-80 = 4, 81-100 = 5
|
|
||||||
rating += ((atoi(value) - (rating * 20)) > 0);
|
|
||||||
}
|
|
||||||
// Remove support for old 1-10 range
|
|
||||||
/* or maybe we're dealing with a 1-10 range
|
|
||||||
else if (rating > 5) {
|
|
||||||
rating /= 2;
|
|
||||||
} */
|
|
||||||
|
|
||||||
// otherwise it is hopefully in the 0-5 range
|
|
||||||
else if (rating > 0 && rating <= 5) {
|
|
||||||
}
|
|
||||||
// otherwise just make sure and set zero
|
|
||||||
else {
|
|
||||||
rating = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringCchPrintfW(dest, destlen, L"%u", rating);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(value)
|
|
||||||
MultiByteToWideCharSZ(CP_UTF8, 0, value, -1, dest, destlen);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dest[0]=0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
@ -1,260 +0,0 @@
|
|||||||
#include "main.h"
|
|
||||||
#include "../nu/AutoChar.h"
|
|
||||||
|
|
||||||
extern CfgInt cfg_fullbuf;
|
|
||||||
|
|
||||||
int VorbisFile::_f_close(void *) {return 0;}
|
|
||||||
|
|
||||||
int VorbisFile::_f_seek(void* rs,__int64 offset,int whence)
|
|
||||||
{
|
|
||||||
return ((VorbisFile*)rs)->f_seek(offset,whence);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t VorbisFile::_f_read(void* ptr,size_t size,size_t nmemb,void * rs)
|
|
||||||
{
|
|
||||||
return ((VorbisFile*)rs)->f_read((UINT)(size*nmemb),ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
long VorbisFile::_f_tell(void* rs)
|
|
||||||
{
|
|
||||||
return ((VorbisFile*)rs)->f_tell();
|
|
||||||
}
|
|
||||||
|
|
||||||
ov_callbacks VorbisFile::oc={_f_read,_f_seek,_f_close,_f_tell};
|
|
||||||
|
|
||||||
static __int64 Seek64(HANDLE hf, __int64 distance, DWORD MoveMethod)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER li;
|
|
||||||
|
|
||||||
li.QuadPart = distance;
|
|
||||||
|
|
||||||
li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod);
|
|
||||||
|
|
||||||
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
|
||||||
{
|
|
||||||
li.QuadPart = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return li.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __int64 FileSize64(HANDLE file)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER position;
|
|
||||||
position.QuadPart=0;
|
|
||||||
position.LowPart = GetFileSize(file, (LPDWORD)&position.HighPart);
|
|
||||||
|
|
||||||
if (position.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
|
|
||||||
return INVALID_FILE_SIZE;
|
|
||||||
else
|
|
||||||
return position.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
class VorbisFile_Local : public VorbisFile
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
HANDLE hFile;
|
|
||||||
protected:
|
|
||||||
int f_seek(__int64 offset,int whence)
|
|
||||||
{
|
|
||||||
if(whence==SEEK_SET) offset+=baseoffs;
|
|
||||||
if (Seek64(hFile,offset,whence) != INVALID_SET_FILE_POINTER) return 0;
|
|
||||||
else return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t f_read(UINT siz,void * ptr)
|
|
||||||
{
|
|
||||||
DWORD bw=0;
|
|
||||||
ReadFile(hFile,ptr,siz,&bw,0);
|
|
||||||
return bw;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT f_tell()
|
|
||||||
{
|
|
||||||
return (UINT)(SetFilePointer(hFile,0,0,FILE_CURRENT)-baseoffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT FileSize()
|
|
||||||
{
|
|
||||||
return (UINT)(FileSize64(hFile)-baseoffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual int GetType() {return TYPE_LOCAL;}
|
|
||||||
VorbisFile_Local(HANDLE f,const wchar_t * u,bool is_info) : VorbisFile(u,is_info) {hFile=f;}
|
|
||||||
~VorbisFile_Local() {CloseHandle(hFile);}
|
|
||||||
};
|
|
||||||
|
|
||||||
class VorbisFile_Mem : public VorbisFile
|
|
||||||
{
|
|
||||||
BYTE * block;
|
|
||||||
UINT size,ptr;
|
|
||||||
protected:
|
|
||||||
int f_seek(__int64 offset,int whence)
|
|
||||||
{
|
|
||||||
switch(whence)
|
|
||||||
{
|
|
||||||
case SEEK_SET:
|
|
||||||
ptr=(UINT)(offset+baseoffs);
|
|
||||||
break;
|
|
||||||
case SEEK_CUR:
|
|
||||||
ptr+=(UINT)offset;
|
|
||||||
break;
|
|
||||||
case SEEK_END:
|
|
||||||
ptr=size+whence;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ptr<=size) return 0;
|
|
||||||
else {ptr=size;return -1;}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t f_read(UINT siz,void * out)
|
|
||||||
{
|
|
||||||
UINT d=size-ptr;
|
|
||||||
if (d>siz) d=siz;
|
|
||||||
memcpy(out,block+ptr,d);
|
|
||||||
ptr+=d;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT f_tell()
|
|
||||||
{
|
|
||||||
return (UINT)(ptr-baseoffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT FileSize()
|
|
||||||
{
|
|
||||||
return (UINT)(size-baseoffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual int GetType() {return TYPE_LOCAL;}
|
|
||||||
|
|
||||||
VorbisFile_Mem(HANDLE f,const wchar_t * u,bool is_info) : VorbisFile(u,is_info)
|
|
||||||
{
|
|
||||||
size=GetFileSize(f,0);
|
|
||||||
ptr=0;
|
|
||||||
block=(BYTE*)malloc(size);
|
|
||||||
DWORD br = 0;
|
|
||||||
ReadFile(f,block,size,&br,0);
|
|
||||||
CloseHandle(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
~VorbisFile_Mem() {free(block);}
|
|
||||||
};
|
|
||||||
|
|
||||||
VorbisFile * VorbisFile::Create(const wchar_t *url, bool is_info)
|
|
||||||
{
|
|
||||||
VorbisFile * r;
|
|
||||||
if (PathIsURLW(url))
|
|
||||||
{
|
|
||||||
if (is_info) return 0;
|
|
||||||
r=Create_HTTP(AutoChar(url),is_info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
__int64 baseoffs=0;
|
|
||||||
HANDLE f=CreateFileW(url,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
|
|
||||||
if (f==INVALID_HANDLE_VALUE) return 0;
|
|
||||||
{
|
|
||||||
DWORD dw = 0, br = 0;
|
|
||||||
ReadFile(f,&dw,4,&br,0);
|
|
||||||
if(br==4 && dw=='SggO')
|
|
||||||
{
|
|
||||||
SetFilePointer(f,0,0,FILE_BEGIN);
|
|
||||||
}
|
|
||||||
else if(br==4 && dw=='FFIR')
|
|
||||||
{
|
|
||||||
//RIFF file
|
|
||||||
DWORD wavhdr = 0, nb = 0;
|
|
||||||
SetFilePointer(f,4,0,FILE_CURRENT);
|
|
||||||
ReadFile(f,&wavhdr,4,&nb,0);
|
|
||||||
if(nb!=4 || wavhdr!='EVAW')
|
|
||||||
{
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
//find data starting point
|
|
||||||
char tmp[1024] = {0};
|
|
||||||
ReadFile(f,&tmp,1024,&nb,0);
|
|
||||||
for(int i=0;i<1020;i++)
|
|
||||||
if(tmp[i]=='d'&&tmp[i+1]=='a'&&tmp[i+2]=='t'&&tmp[i+3]=='a')
|
|
||||||
{
|
|
||||||
baseoffs=i+12+8;
|
|
||||||
Seek64(f, baseoffs, FILE_BEGIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!baseoffs) goto abort;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
abort:
|
|
||||||
CloseHandle(f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r=cfg_fullbuf ? (VorbisFile*)new VorbisFile_Mem(f,url,is_info) : (VorbisFile*)new VorbisFile_Local(f,url,is_info);
|
|
||||||
r->setBaseOffset(baseoffs);
|
|
||||||
}
|
|
||||||
if (r && !r->init())
|
|
||||||
{
|
|
||||||
delete r;
|
|
||||||
r=0;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VorbisFile::init()
|
|
||||||
{
|
|
||||||
if (ov_open_callbacks(this,&vf,0,0,oc)) return 0;
|
|
||||||
//TODO bitrate
|
|
||||||
UINT siz=FileSize();
|
|
||||||
double len=Length();
|
|
||||||
if (siz>0 && len>0)
|
|
||||||
{
|
|
||||||
UINT divisor = (UINT)(len*125.0);
|
|
||||||
if (divisor)
|
|
||||||
avg_kbps=siz/divisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
post_init();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_http(const char* url)
|
|
||||||
{
|
|
||||||
return (!_strnicmp(url,"http://",7) || !_strnicmp(url,"https://",8));
|
|
||||||
}
|
|
||||||
|
|
||||||
void VorbisFile::set_meta(const vorbis_comment * vc,int links)
|
|
||||||
{
|
|
||||||
if (links == vf.links)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
for(n=0;n<links;n++)
|
|
||||||
{
|
|
||||||
vorbis_comment_clear(vf.vc+n);
|
|
||||||
/*
|
|
||||||
extern void vorbis_comment_init(vorbis_comment *vc);
|
|
||||||
extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
|
|
||||||
extern void vorbis_comment_add_tag(vorbis_comment *vc,char *tag, char *contents);
|
|
||||||
extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
|
|
||||||
extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
|
|
||||||
extern void vorbis_comment_clear(vorbis_comment *vc);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
_ogg_free(vf.vc);
|
|
||||||
vf.vc = (vorbis_comment*) _ogg_calloc(links,sizeof(vorbis_comment));
|
|
||||||
for(n=0;n<links;n++)
|
|
||||||
{
|
|
||||||
vorbis_comment_init(vf.vc+n);
|
|
||||||
int c;
|
|
||||||
for(c=0;c<vc[n].comments;c++)
|
|
||||||
{
|
|
||||||
vorbis_comment_add(vf.vc+n,vc[n].user_comments[c]);
|
|
||||||
}
|
|
||||||
vf.vc[n].vendor = _strdup(vc[n].vendor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,220 +0,0 @@
|
|||||||
#ifndef IN_VORBIS_MAIN_H
|
|
||||||
#define IN_VORBIS_MAIN_H
|
|
||||||
|
|
||||||
#define WINSOCK_API_LINKAGE
|
|
||||||
|
|
||||||
#ifndef STRICT
|
|
||||||
#define STRICT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
extern int (*warand)();
|
|
||||||
extern float (*warandf)();
|
|
||||||
|
|
||||||
inline void * z_malloc(int x)
|
|
||||||
{
|
|
||||||
void* foo=malloc(x);
|
|
||||||
if (foo) memset(foo,0,x);
|
|
||||||
return foo;
|
|
||||||
}
|
|
||||||
#include <shlwapi.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#define uitoa(x,y) _itoa(x,y,10)
|
|
||||||
#define atoui atoi
|
|
||||||
|
|
||||||
#include <vorbis\vorbisfile.h>
|
|
||||||
#include "c_string.h"
|
|
||||||
#include "../Winamp/in2.h"
|
|
||||||
|
|
||||||
extern In_Module mod;
|
|
||||||
|
|
||||||
#include "resource.h"
|
|
||||||
|
|
||||||
#define VER L"1.79"
|
|
||||||
#define _NAME "Nullsoft Vorbis Decoder"
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
extern const char *INI_FILE;
|
|
||||||
extern const wchar_t *INI_DIRECTORY;
|
|
||||||
}
|
|
||||||
class CfgVar
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
String name;
|
|
||||||
CfgVar * next;
|
|
||||||
static CfgVar * list;
|
|
||||||
public:
|
|
||||||
|
|
||||||
static void ReadConfig();
|
|
||||||
static void WriteConfig();
|
|
||||||
|
|
||||||
//helpers
|
|
||||||
static bool read_struct(const char *inifile, const char *section, const char * name,void * ptr,UINT size);
|
|
||||||
static void write_struct(const char *inifile, const char *section, const char * name,void * ptr,UINT size);
|
|
||||||
static void write_int(const char *inifile, const char *section, const char * name,int val);
|
|
||||||
static int read_int(const char *inifile, const char *section,const char * name,int def);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CfgVar(const char * n) : name(n) {next=list;list=this;}
|
|
||||||
virtual void Read(const char * name)=0;
|
|
||||||
virtual void Write(const char * name)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CfgInt : private CfgVar
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
int def,value;
|
|
||||||
public:
|
|
||||||
CfgInt(const char * name,int _def) : CfgVar(name) {value=def=_def;}
|
|
||||||
inline int operator=(int x) {value=x;return value;}
|
|
||||||
inline operator int() {return value;}
|
|
||||||
private:
|
|
||||||
virtual void Read(const char * name);
|
|
||||||
virtual void Write(const char * name);
|
|
||||||
};
|
|
||||||
|
|
||||||
class CfgString : private CfgVar, public StringW
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
StringW def;
|
|
||||||
public:
|
|
||||||
CfgString(const char * name,const char * _def) : CfgVar(name), StringW(_def), def(_def) {}
|
|
||||||
private:
|
|
||||||
virtual void Read(const char * name);
|
|
||||||
virtual void Write(const char * name);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class CfgStructT : private CfgVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
T data;
|
|
||||||
CfgStructT(const char * name) : CfgVar(name) {}
|
|
||||||
private:
|
|
||||||
void Read(const char * name) { read_struct(INI_FILE, "in_vorbis",name,&data,sizeof(data));}
|
|
||||||
void Write(const char * name) {if (IsValueDefault()) WritePrivateProfileStringA("in_vorbis", name, 0, INI_FILE); else write_struct(INI_FILE, "in_vorbis", name, &data, sizeof(data));}
|
|
||||||
protected:
|
|
||||||
virtual bool IsValueDefault() {return 0;}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class CfgFont : public CfgStructT<LOGFONT>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
void get_def(LOGFONT * f) {memset(f,0,sizeof(LOGFONT));GetObject(GetStockObject(DEFAULT_GUI_FONT),sizeof(LOGFONT),f);}
|
|
||||||
virtual bool IsValueDefault()
|
|
||||||
{
|
|
||||||
LOGFONT t;
|
|
||||||
get_def(&t);
|
|
||||||
return !memcmp(&data,&t,sizeof(LOGFONT));
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
CfgFont(const char * name) : CfgStructT<LOGFONT>(name)
|
|
||||||
{
|
|
||||||
get_def(&data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int32_t priority_tab[7];
|
|
||||||
extern HINSTANCE hIns;
|
|
||||||
|
|
||||||
extern CfgString cfg_ssave_format,cfg_dumpdir;
|
|
||||||
|
|
||||||
int is_http(const char* url);
|
|
||||||
|
|
||||||
class VorbisFile
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
virtual int f_seek(__int64 offset,int whence)=0;
|
|
||||||
virtual size_t f_read(UINT siz,void * ptr)=0;
|
|
||||||
virtual UINT f_tell()=0;
|
|
||||||
static int _f_close(void *);
|
|
||||||
static int _f_seek(void* rs,__int64 offset,int whence);
|
|
||||||
static size_t _f_read(void* ptr,size_t size,size_t nmemb,void * rs);
|
|
||||||
static long _f_tell(void* rs);
|
|
||||||
static ov_callbacks oc;
|
|
||||||
static VorbisFile * Create_HTTP(const char * url,bool is_info);
|
|
||||||
VorbisFile(const wchar_t * u, bool is_info) : url(u) {memset(&vf,0,sizeof(vf));stopping=0;abort_prebuf=0;avg_kbps=0;use_prebuf=0;primary=!is_info; baseoffs=0;}
|
|
||||||
bool init();
|
|
||||||
virtual void post_init() {};
|
|
||||||
UINT avg_kbps;
|
|
||||||
bool Aborting();
|
|
||||||
|
|
||||||
__int64 baseoffs;
|
|
||||||
public:
|
|
||||||
enum {TYPE_LOCAL,TYPE_HTTP};
|
|
||||||
virtual int GetType()=0;
|
|
||||||
virtual bool IsLive() {return 0;}
|
|
||||||
virtual void do_prebuf() {use_prebuf=1;abort_prebuf=0;};
|
|
||||||
StringW url;
|
|
||||||
String withlp;
|
|
||||||
String stream_title;
|
|
||||||
bool stopping,abort_prebuf,use_prebuf;
|
|
||||||
bool primary;//display status messages or not
|
|
||||||
OggVorbis_File vf;
|
|
||||||
UINT get_avg_bitrate()
|
|
||||||
{
|
|
||||||
if (avg_kbps>0) return avg_kbps;
|
|
||||||
vorbis_info * vi=ov_info(&vf,-1);
|
|
||||||
if (!vi) return 0;
|
|
||||||
return vi->bitrate_nominal/1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* get_meta(const char* tag,UINT c);
|
|
||||||
void set_meta(const vorbis_comment * vc,int links);
|
|
||||||
|
|
||||||
static VorbisFile * Create(const wchar_t * url,bool is_info);
|
|
||||||
|
|
||||||
double Length() {return ov_time_total(&vf,-1);}
|
|
||||||
double GetPos() {return ov_time_tell(&vf);}
|
|
||||||
int Seek(double p);
|
|
||||||
void Status(const wchar_t * zzz);
|
|
||||||
virtual UINT FileSize()=0;
|
|
||||||
|
|
||||||
virtual ~VorbisFile() {ov_clear(&vf);}
|
|
||||||
virtual void Idle() {Sleep(10);}
|
|
||||||
|
|
||||||
virtual void setBaseOffset(__int64 offs) { baseoffs=offs; }
|
|
||||||
|
|
||||||
float GetGain();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern VorbisFile * theFile;
|
|
||||||
|
|
||||||
extern StringW cur_file;
|
|
||||||
|
|
||||||
extern CRITICAL_SECTION sync;
|
|
||||||
|
|
||||||
BOOL modify_file(const wchar_t* url,const vorbis_comment * comments,int links);
|
|
||||||
void winampGetExtendedFileInfoW_Cleanup(void);
|
|
||||||
void UpdateFileTimeChanged(const wchar_t *fn);
|
|
||||||
void do_cfg(int s);
|
|
||||||
bool KeywordMatch(const char *mainString, const char *keyword);
|
|
||||||
|
|
||||||
class Info
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Info(const wchar_t *filename);
|
|
||||||
~Info();
|
|
||||||
bool Save();
|
|
||||||
int Error() { return vc==0?1:0; }
|
|
||||||
int GetNumMetadataItems();
|
|
||||||
void EnumMetadata(int n,wchar_t *key,int keylen, wchar_t *val, int vallen);
|
|
||||||
void RemoveMetadata(wchar_t * key);
|
|
||||||
void RemoveMetadata(int n);
|
|
||||||
void SetMetadata(wchar_t *key, wchar_t *val);
|
|
||||||
void SetMetadata(int n, wchar_t *key, wchar_t *val);
|
|
||||||
void SetTag(int n,wchar_t *key); // changes the key name
|
|
||||||
private:
|
|
||||||
const wchar_t *filename;
|
|
||||||
vorbis_comment * vc;
|
|
||||||
int numstreams, stream;
|
|
||||||
};
|
|
||||||
|
|
||||||
// {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F}
|
|
||||||
static const GUID playbackConfigGroupGUID =
|
|
||||||
{ 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf } };
|
|
||||||
|
|
||||||
#endif //IN_VORBIS_MAIN_H
|
|
@ -1,194 +0,0 @@
|
|||||||
#include "mkv_vorbis_decoder.h"
|
|
||||||
#include "../nsmkv/Lacing.h"
|
|
||||||
#include "../nsmkv/Cluster.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
|
|
||||||
int MKVDecoderCreator::CreateAudioDecoder(const char *codec_id,
|
|
||||||
const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data,
|
|
||||||
unsigned int preferred_bits, unsigned int max_channels, bool floating_point,
|
|
||||||
ifc_mkvaudiodecoder **decoder)
|
|
||||||
{
|
|
||||||
if (!strcmp(codec_id, "A_VORBIS"))
|
|
||||||
{
|
|
||||||
MKVVorbis *vorbis = new MKVVorbis;
|
|
||||||
vorbis_info_init(&vorbis->info);
|
|
||||||
vorbis_comment_init(&vorbis->comment);
|
|
||||||
nsmkv::LacingState lacing_state;
|
|
||||||
if (nsmkv::Lacing::GetState(nsmkv::BlockBinary::XIPH_LACING, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &lacing_state))
|
|
||||||
{
|
|
||||||
const uint8_t *frame;
|
|
||||||
size_t frame_len;
|
|
||||||
uint16_t frame_number=0;
|
|
||||||
while (nsmkv::Lacing::GetFrame(frame_number, (const uint8_t *)track_entry_data->codec_private, track_entry_data->codec_private_len, &frame, &frame_len, &lacing_state))
|
|
||||||
{
|
|
||||||
ogg_packet packet = {const_cast<uint8_t *>(frame), (long)frame_len, (frame_number==0), 0, 0 /*-1?*/, vorbis->packet_number++};
|
|
||||||
int ret = vorbis_synthesis_headerin(&vorbis->info, &vorbis->comment, &packet);
|
|
||||||
if (ret != 0)
|
|
||||||
goto bail;
|
|
||||||
frame_number++;
|
|
||||||
}
|
|
||||||
if (vorbis_synthesis_init(&vorbis->dsp, &vorbis->info) == 0
|
|
||||||
&& vorbis_block_init(&vorbis->dsp, &vorbis->block) == 0)
|
|
||||||
{
|
|
||||||
vorbis->bps = preferred_bits?preferred_bits:16;
|
|
||||||
*decoder = vorbis;
|
|
||||||
return CREATEDECODER_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bail:
|
|
||||||
delete vorbis;
|
|
||||||
return CREATEDECODER_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CREATEDECODER_NOT_MINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CBCLASS MKVDecoderCreator
|
|
||||||
START_DISPATCH;
|
|
||||||
CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)
|
|
||||||
END_DISPATCH;
|
|
||||||
#undef CBCLASS
|
|
||||||
|
|
||||||
MKVVorbis::MKVVorbis()
|
|
||||||
{
|
|
||||||
bps=16;
|
|
||||||
packet_number=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PA_CLIP_( val, min, max )\
|
|
||||||
{ val = ((val) < (min)) ? (min) : (((val) > (max)) ? (max) : (val)); }
|
|
||||||
|
|
||||||
#if defined(_M_IX86)
|
|
||||||
static __inline long float_to_long(double t)
|
|
||||||
{
|
|
||||||
long r;
|
|
||||||
__asm fld t
|
|
||||||
__asm fistp r
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define float_to_long(x) ((long)( x ))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline static void clip(double &x, double a, double b)
|
|
||||||
{
|
|
||||||
double x1 = fabs (x - a);
|
|
||||||
double x2 = fabs (x - b);
|
|
||||||
x = x1 + (a + b);
|
|
||||||
x -= x2;
|
|
||||||
x *= 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Float32_To_Int24_Clip(void *destinationBuffer, void *sourceBuffer, size_t count, size_t channels, double gain)
|
|
||||||
{
|
|
||||||
float *src = (float*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
gain*=65536.*32768.;
|
|
||||||
while ( count-- )
|
|
||||||
{
|
|
||||||
/* convert to 32 bit and drop the low 8 bits */
|
|
||||||
double scaled = *src * gain;
|
|
||||||
clip( scaled, -2147483648., 2147483647.);
|
|
||||||
signed long temp = (signed long) scaled;
|
|
||||||
|
|
||||||
dest[0] = (unsigned char)(temp >> 8);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[2] = (unsigned char)(temp >> 24);
|
|
||||||
|
|
||||||
src++;
|
|
||||||
dest += 3*channels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Float32_To_Int16_Clip(void *destinationBuffer, void *sourceBuffer, size_t count, size_t channels, double gain)
|
|
||||||
{
|
|
||||||
float *src = (float*)sourceBuffer;
|
|
||||||
signed short *dest = (signed short*)destinationBuffer;
|
|
||||||
|
|
||||||
gain*=32768.0;
|
|
||||||
while ( count-- )
|
|
||||||
{
|
|
||||||
long samp = float_to_long((*src) * gain/* - 0.5*/);
|
|
||||||
|
|
||||||
PA_CLIP_( samp, -0x8000, 0x7FFF );
|
|
||||||
*dest = (signed short) samp;
|
|
||||||
|
|
||||||
src ++;
|
|
||||||
dest += channels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int MKVVorbis::DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
|
|
||||||
{
|
|
||||||
uint8_t *out = (uint8_t *)outputBuffer;
|
|
||||||
ogg_packet packet = {(uint8_t *)inputBuffer, (long)inputBufferBytes, 0, 0, 0 -1, packet_number++};
|
|
||||||
int ret = vorbis_synthesis(&block, &packet);
|
|
||||||
if (ret == 0)
|
|
||||||
{
|
|
||||||
vorbis_synthesis_blockin(&dsp,&block);
|
|
||||||
long channels = info.channels;
|
|
||||||
float **pcm;
|
|
||||||
int samples = vorbis_synthesis_pcmout(&dsp, &pcm);
|
|
||||||
if (samples)
|
|
||||||
{
|
|
||||||
switch(bps)
|
|
||||||
{
|
|
||||||
case 16:
|
|
||||||
for(int i=0;i<channels;i++)
|
|
||||||
{
|
|
||||||
Float32_To_Int16_Clip(out, pcm[i], samples, channels, 1.0 /*gain*/);
|
|
||||||
out+=2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
for(int i=0;i<channels;i++)
|
|
||||||
{
|
|
||||||
Float32_To_Int24_Clip(out, pcm[i], samples, channels, 1.0 /*gain*/);
|
|
||||||
out+=3;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*outputBufferBytes = samples*channels*bps/8;
|
|
||||||
// let the decoder know we're processed them
|
|
||||||
vorbis_synthesis_read(&dsp,samples);
|
|
||||||
return MKV_SUCCESS;
|
|
||||||
}
|
|
||||||
return MKV_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MKVVorbis::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
|
|
||||||
{
|
|
||||||
*sampleRate = info.rate;
|
|
||||||
*channels = info.channels;
|
|
||||||
*bitsPerSample = bps;
|
|
||||||
*isFloat = false; // TODO
|
|
||||||
return MKV_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MKVVorbis::Flush()
|
|
||||||
{
|
|
||||||
vorbis_synthesis_restart(&dsp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MKVVorbis::Close()
|
|
||||||
{
|
|
||||||
// TODO: benski> verify
|
|
||||||
vorbis_info_clear(&info);
|
|
||||||
vorbis_comment_clear(&comment);
|
|
||||||
vorbis_dsp_clear(&dsp);
|
|
||||||
vorbis_block_clear(&block);
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
#define CBCLASS MKVVorbis
|
|
||||||
START_DISPATCH;
|
|
||||||
//CB(OUTPUT_FRAME_SIZE, OutputFrameSize)
|
|
||||||
CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
|
|
||||||
CB(DECODE_BLOCK, DecodeBlock)
|
|
||||||
VCB(FLUSH, Flush)
|
|
||||||
VCB(CLOSE, Close)
|
|
||||||
END_DISPATCH;
|
|
||||||
#undef CBCLASS
|
|
@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "../in_mkv/ifc_mkvaudiodecoder.h"
|
|
||||||
#include "../in_mkv/svc_mkvdecoder.h"
|
|
||||||
#include <vorbis/codec.h>
|
|
||||||
|
|
||||||
// {6058D315-2F08-4b2f-903E-4C2E6B5EFFA9}
|
|
||||||
static const GUID mkv_vorbis_guid =
|
|
||||||
{ 0x6058d315, 0x2f08, 0x4b2f, { 0x90, 0x3e, 0x4c, 0x2e, 0x6b, 0x5e, 0xff, 0xa9 } };
|
|
||||||
|
|
||||||
|
|
||||||
class MKVDecoderCreator : public svc_mkvdecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const char *getServiceName() { return "Vorbis MKV Decoder"; }
|
|
||||||
static GUID getServiceGuid() { return mkv_vorbis_guid; }
|
|
||||||
int CreateAudioDecoder(const char *codec_id,
|
|
||||||
const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data,
|
|
||||||
unsigned int preferred_bits, unsigned int max_channels, bool floating_point,
|
|
||||||
ifc_mkvaudiodecoder **decoder);
|
|
||||||
protected:
|
|
||||||
RECVS_DISPATCH;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MKVVorbis : public ifc_mkvaudiodecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MKVVorbis();
|
|
||||||
int DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes);
|
|
||||||
int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat);
|
|
||||||
void Flush();
|
|
||||||
void Close();
|
|
||||||
//private:
|
|
||||||
unsigned int bps;
|
|
||||||
vorbis_info info;
|
|
||||||
vorbis_dsp_state dsp;
|
|
||||||
vorbis_block block;
|
|
||||||
vorbis_comment comment;
|
|
||||||
ogg_int64_t packet_number;
|
|
||||||
protected:
|
|
||||||
RECVS_DISPATCH;
|
|
||||||
};
|
|
Before Width: | Height: | Size: 782 B |
Before Width: | Height: | Size: 817 B |
Before Width: | Height: | Size: 753 B |
Before Width: | Height: | Size: 705 B |
Before Width: | Height: | Size: 725 B |
Before Width: | Height: | Size: 809 B |
Before Width: | Height: | Size: 824 B |
Before Width: | Height: | Size: 829 B |
Before Width: | Height: | Size: 720 B |
Before Width: | Height: | Size: 719 B |
Before Width: | Height: | Size: 727 B |
Before Width: | Height: | Size: 755 B |
@ -1,177 +0,0 @@
|
|||||||
//{{NO_DEPENDENCIES}}
|
|
||||||
// Microsoft Visual C++ generated include file.
|
|
||||||
// Used by ogg.rc
|
|
||||||
//
|
|
||||||
#define IDS_NULLSOFT_VORBIS_DECODER_OLD 0
|
|
||||||
#define IDS_PLEASE_ENTER_TAG_NAME 1
|
|
||||||
#define IDS_TAG_NAME_CONTAINS_INVALID_CHARS 2
|
|
||||||
#define IDOKAUTH 3
|
|
||||||
#define IDS_ERASE_ALL_FIELDS_ON_LIST 3
|
|
||||||
#define IDCANCELAUTH 4
|
|
||||||
#define IDS_WARNING 4
|
|
||||||
#define IDS_FILE_ERROR 5
|
|
||||||
#define IDS_LENGTH 6
|
|
||||||
#define IDS_AVERAGE_BITRATE 7
|
|
||||||
#define IDS_FILE_SIZE 8
|
|
||||||
#define IDS_NOMINAL_BITRATE 9
|
|
||||||
#define IDS_MIN_BITRATE 10
|
|
||||||
#define IDS_MAX_BITRATE 11
|
|
||||||
#define IDS_CHANNELS 12
|
|
||||||
#define IDS_SAMPLING_RATE 13
|
|
||||||
#define IDS_SERIAL_NUMBER 14
|
|
||||||
#define IDS_VERSION 15
|
|
||||||
#define IDS_Vendor 16
|
|
||||||
#define IDS_VENDOR 16
|
|
||||||
#define IDS_TO_SIMPLE_MODE 17
|
|
||||||
#define IDS_TO_ADVANCED_MODE 18
|
|
||||||
#define IDS_OGG_VORBIS_INFO 19
|
|
||||||
#define IDS_WRITE_ERROR 20
|
|
||||||
#define IDS_BEST_RPM 21
|
|
||||||
#define IDS_ABOUT 22
|
|
||||||
#define IDS_LEAVE_AS_IS 24
|
|
||||||
#define IDS_REMAP_6_CHANNELS 25
|
|
||||||
#define IDS_DOWNMIX_TO_4_CHANNELS 26
|
|
||||||
#define IDS_DOWNMIX_TO_2_CHANNELS_DS 27
|
|
||||||
#define IDS_DOWNMIX_TO_2_CHANNELS_DS2 28
|
|
||||||
#define IDS_DOWNMIX_TO_MONO 29
|
|
||||||
#define IDS_CORRECT_FL_FC_FR_BL_BR_LFE 30
|
|
||||||
#define IDS_BROKEN_FL_FR_FC_BL_BR_LFE 31
|
|
||||||
#define IDS_IDLE 32
|
|
||||||
#define IDS_ABOUT_TEXT 32
|
|
||||||
#define IDS_LOWEST 33
|
|
||||||
#define IDS_BELOW_NORMAL 34
|
|
||||||
#define IDS_NORMAL 35
|
|
||||||
#define IDS_ABOVE_NORMAL 36
|
|
||||||
#define IDS_HIGHEST 37
|
|
||||||
#define IDS_TIME_CRITICAL 38
|
|
||||||
#define IDS_TITLE_PREFERENCES 39
|
|
||||||
#define IDS_DO_NOT_ENABLE_24_BIT_OUTPUT 40
|
|
||||||
#define IDS_ONE_TIME_FAQ_REMINDER 41
|
|
||||||
#define IDS_RUNNING_ON_NT_OS 42
|
|
||||||
#define IDS_RUNNING_ON_WIN9X 43
|
|
||||||
#define IDS_NEVER 44
|
|
||||||
#define IDS_PORT_80_ONLY 45
|
|
||||||
#define IDS_ALWAYS 46
|
|
||||||
#define IDS_SELECT_OUTPUT_DIRECTORY 47
|
|
||||||
#define IDS_DECODING 48
|
|
||||||
#define IDS_DISPLAY 49
|
|
||||||
#define IDS_STREAMING 50
|
|
||||||
#define IDS_CONNECTING 51
|
|
||||||
#define IDS_PREBUFFERING 52
|
|
||||||
#define IDS_AUTH_REQUIRED 53
|
|
||||||
#define IDS_OGG_FILES 54
|
|
||||||
#define IDS_NAME 55
|
|
||||||
#define IDS_VALUE 56
|
|
||||||
#define IDS_KBPS 57
|
|
||||||
#define IDS_STRING2 58
|
|
||||||
#define IDS_HZ 58
|
|
||||||
#define IDS_GAME_SPEED 59
|
|
||||||
#define IDS_STRING1 60
|
|
||||||
#define IDS_BYTES 60
|
|
||||||
#define IDS_FAMILY_STRING 61
|
|
||||||
#define IDC_CONFIG_TAB1 101
|
|
||||||
#define IDD_INFO_DLG 102
|
|
||||||
#define IDC_CONFIG_TAB2 102
|
|
||||||
#define IDC_CONFIG_TAB3 103
|
|
||||||
#define IDD_INFO_DLG1 104
|
|
||||||
#define IDC_CONFIG_TAB4 104
|
|
||||||
#define IDD_ABOUT 112
|
|
||||||
#define IDB_BITMAP1 115
|
|
||||||
#define IDB_BITMAP2 116
|
|
||||||
#define IDB_BITMAP3 117
|
|
||||||
#define IDB_BITMAP4 118
|
|
||||||
#define IDB_BITMAP5 119
|
|
||||||
#define IDB_BITMAP6 120
|
|
||||||
#define IDB_BITMAP7 121
|
|
||||||
#define IDB_BITMAP8 122
|
|
||||||
#define IDB_BITMAP9 123
|
|
||||||
#define IDB_BITMAP10 124
|
|
||||||
#define IDB_BITMAP11 125
|
|
||||||
#define IDB_BITMAP12 126
|
|
||||||
#define IDD_HTTPAUTH 128
|
|
||||||
#define IDD_INFO 131
|
|
||||||
#define IDD_DIALOG1 132
|
|
||||||
#define IDD_CONFIG 132
|
|
||||||
#define IDD_INFO_DLG_NEW 133
|
|
||||||
#define IDD_INFO_PANEL_ADVANCED 134
|
|
||||||
#define IDD_INFO_PANEL_SIMPLE 135
|
|
||||||
#define IDB_PNG1 136
|
|
||||||
#define IDB_PNG2 137
|
|
||||||
#define IDB_PNG3 138
|
|
||||||
#define IDB_PNG4 139
|
|
||||||
#define IDB_PNG5 140
|
|
||||||
#define IDB_PNG6 141
|
|
||||||
#define IDB_PNG7 142
|
|
||||||
#define IDB_PNG8 143
|
|
||||||
#define IDB_PNG9 144
|
|
||||||
#define IDB_PNG10 145
|
|
||||||
#define IDB_PNG11 146
|
|
||||||
#define IDB_PNG12 147
|
|
||||||
#define IDC_LIST 1001
|
|
||||||
#define IDC_NAME 1002
|
|
||||||
#define IDC_TITLE 1002
|
|
||||||
#define IDC_VALUE 1003
|
|
||||||
#define IDC_ARTIST 1003
|
|
||||||
#define IDC_HTTP_BSIZE 1004
|
|
||||||
#define IDC_ALBUM 1004
|
|
||||||
#define IDC_STREAM_SAVE 1005
|
|
||||||
#define IDC_GENRE 1005
|
|
||||||
#define IDC_FSAVE 1006
|
|
||||||
#define IDC_YEAR 1006
|
|
||||||
#define IDC_DATE 1006
|
|
||||||
#define IDC_CUSTOM1 1007
|
|
||||||
#define IDC_MISC 1007
|
|
||||||
#define IDC_AVG_BR 1008
|
|
||||||
#define IDC_FIX0R 1009
|
|
||||||
#define IDC_PROXY 1012
|
|
||||||
#define IDC_URL 1012
|
|
||||||
#define IDC_SLIDER1 1013
|
|
||||||
#define IDC_SLIDER2 1014
|
|
||||||
#define IDC_BUTTON_ADD 1015
|
|
||||||
#define IDC_BUTTON_DEL 1016
|
|
||||||
#define IDC_BUTTON_DELALL 1017
|
|
||||||
#define IDC_RPM 1018
|
|
||||||
#define IDC_RPM2 1019
|
|
||||||
#define IDC_MC6_DM 1020
|
|
||||||
#define IDC_MC6_MAP 1021
|
|
||||||
#define IDC_SSAVE_FMT 1022
|
|
||||||
#define IDC_SSAVE_FMT_DEF 1023
|
|
||||||
#define IDC_FULLBUF 1025
|
|
||||||
#define IDC_EDITAUTH 1026
|
|
||||||
#define IDC_REALM 1027
|
|
||||||
#define IDC_TRACK 1028
|
|
||||||
#define IDC_STATIC_MISC 1034
|
|
||||||
#define IDC_STATIC_TAGS 1035
|
|
||||||
#define IDC_STATIC_STD 1036
|
|
||||||
#define IDC_STATIC_TRACK 1037
|
|
||||||
#define IDC_SEPARATE 1038
|
|
||||||
#define IDC_DELETE_ALL 1039
|
|
||||||
#define IDC_RG 1040
|
|
||||||
#define IDC_RG_MODE 1041
|
|
||||||
#define IDC_NOCLIP 1042
|
|
||||||
#define IDC_HARDLIMIT 1043
|
|
||||||
#define IDC_PREAMP_STAT 1044
|
|
||||||
#define IDC_TAB 1045
|
|
||||||
#define IDC_MODE_TOGGLE 1053
|
|
||||||
#define IDC_NEXT_STREAM 1054
|
|
||||||
#define IDC_PREV_STREAM 1055
|
|
||||||
#define IDC_STATIC_CS 1056
|
|
||||||
#define IDC_HIDE_SPEC 1058
|
|
||||||
#define IDC_COMMENT 1060
|
|
||||||
#define IDC_ABOUT_TEXT 1061
|
|
||||||
#define IDC_OS_BLAH 1062
|
|
||||||
#define IDC_REMEMBER_INFOSIZE 1063
|
|
||||||
#define IDC_FONTNAME 1064
|
|
||||||
#define IDC_PREAMP_RG 1065
|
|
||||||
#define IDS_NULLSOFT_VORBIS_DECODER 65534
|
|
||||||
|
|
||||||
// Next default values for new objects
|
|
||||||
//
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 148
|
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1067
|
|
||||||
#define _APS_NEXT_SYMED_VALUE 105
|
|
||||||
#endif
|
|
||||||
#endif
|
|
@ -1,108 +0,0 @@
|
|||||||
#ifndef _RF_H_
|
|
||||||
#define _RF_H_
|
|
||||||
|
|
||||||
//based on Tempura specs.
|
|
||||||
//NOT compatible with WA3 alphas
|
|
||||||
|
|
||||||
class WReader
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/* WReader
|
|
||||||
** WReader constructor
|
|
||||||
*/
|
|
||||||
WReader() : m_player(0) { }
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/* m_player
|
|
||||||
** Filled by Winamp. Pointer to Winamp 3 core interface
|
|
||||||
*/
|
|
||||||
/*WPlayer_callback*/ void *m_player; //PP: hack. read_file.dll doesn't call it at all. simply don't touch it
|
|
||||||
|
|
||||||
/* GetDescription
|
|
||||||
** Retrieves your plug-in's text description
|
|
||||||
*/
|
|
||||||
virtual char *GetDescription() { return "Unknown"; };
|
|
||||||
|
|
||||||
/* Open
|
|
||||||
** Used to open a file, return 0 on success
|
|
||||||
*/
|
|
||||||
virtual int Open(char *url, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* Read
|
|
||||||
** Returns number of BYTES read (if < length then eof or killswitch)
|
|
||||||
*/
|
|
||||||
virtual int Read(char *buffer, int length, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* GetLength
|
|
||||||
** Returns length of the entire file in BYTES, return -1 on unknown/infinite (as for a stream)
|
|
||||||
*/
|
|
||||||
virtual int GetLength(void)=0;
|
|
||||||
|
|
||||||
/* CanSeek
|
|
||||||
** Returns 1 if you can skip ahead in the file, 0 if not
|
|
||||||
*/
|
|
||||||
virtual int CanSeek(void)=0; //PP: currently available read_file.dll vesions can always seek in any direction
|
|
||||||
|
|
||||||
/* Seek
|
|
||||||
** Jump to a certain absolute position
|
|
||||||
*/
|
|
||||||
virtual int Seek(int position, bool *killswitch)=0;
|
|
||||||
|
|
||||||
/* GetHeader
|
|
||||||
** Retrieve header. Used in read_http to retrieve the HTTP header
|
|
||||||
*/
|
|
||||||
virtual char *GetHeader(char *name) { return 0; }
|
|
||||||
|
|
||||||
/* ~WReader
|
|
||||||
** WReader virtual destructor
|
|
||||||
*/
|
|
||||||
//virtual ~WReader() { }
|
|
||||||
virtual void Release(int) {};
|
|
||||||
//PP: hack - shut up linker when getting rid of evil CRT library; seems to work OK under Tempura
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define READ_VER 0x100
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/* version
|
|
||||||
** Version revision number
|
|
||||||
*/
|
|
||||||
int version;
|
|
||||||
|
|
||||||
/* description
|
|
||||||
** Text description of the reader plug-in
|
|
||||||
*/
|
|
||||||
char *description;
|
|
||||||
|
|
||||||
/* create
|
|
||||||
** Function pointer to create a reader module
|
|
||||||
*/
|
|
||||||
WReader *(*create)();
|
|
||||||
|
|
||||||
/* ismine
|
|
||||||
** Determines whether or not a file should be read by this plug-in
|
|
||||||
*/
|
|
||||||
int (*ismine)(char *url);
|
|
||||||
|
|
||||||
} reader_source;
|
|
||||||
|
|
||||||
//exported symbol is:
|
|
||||||
//int readerSource(HINSTANCE,reader_source**);
|
|
||||||
|
|
||||||
/*
|
|
||||||
(not a part of Tempura specs)
|
|
||||||
int _stdcall gzip_writefile(char* path,void* buf,DWORD size) - writes a memory block to a GZIP file - in_midi calls it from file info box
|
|
||||||
|
|
||||||
other hacks:
|
|
||||||
recent versions understand file://... urls, can do partial file access (eg. "partial://00006666-66660000:c:\foo\bar.dat\zzz.wav" (zzz.wav is the "display name" + extension to make winamp select correct plug-in) and auto-detect CD drive letter (eg. #:\x.mp3 will scan all drives for that file; also works with partial:// )
|
|
||||||
you can (for an example) build a playlist which will play Unreal soundtrack directly from the game CD on any system
|
|
||||||
latest read_file.dll is bundled with the midi plug-in: http://www.blorp.com/~peter/zips/in_midi.zip
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,245 +0,0 @@
|
|||||||
#include "Shaper.h"
|
|
||||||
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.1415926535897932384626433832795028842
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define RANDBUFLEN 65536
|
|
||||||
|
|
||||||
#define RINT(x) ((x) >= 0 ? ((int)((x) + 0.5)) : ((int)((x) - 0.5)))
|
|
||||||
|
|
||||||
const int scoeffreq[] =
|
|
||||||
{
|
|
||||||
0, 48000, 44100, 37800, 32000, 22050, 48000, 44100
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const int scoeflen[] =
|
|
||||||
{
|
|
||||||
1, 16, 20, 16, 16, 15, 16, 15
|
|
||||||
};
|
|
||||||
|
|
||||||
const int samp[] =
|
|
||||||
{
|
|
||||||
8, 18, 27, 8, 8, 8, 10, 9
|
|
||||||
};
|
|
||||||
|
|
||||||
const double shapercoefs[8][21] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
, /* triangular dither */
|
|
||||||
|
|
||||||
{ -2.8720729351043701172, 5.0413231849670410156, -6.2442994117736816406, 5.8483986854553222656,
|
|
||||||
-3.7067542076110839844, 1.0495119094848632812, 1.1830236911773681641, -2.1126792430877685547,
|
|
||||||
1.9094531536102294922, -0.99913084506988525391, 0.17090806365013122559, 0.32615602016448974609,
|
|
||||||
-0.39127644896507263184, 0.26876461505889892578, -0.097676105797290802002, 0.023473845794796943665,
|
|
||||||
}, /* 48k, N=16, amp=18 */
|
|
||||||
|
|
||||||
{ -2.6773197650909423828, 4.8308925628662109375, -6.570110321044921875, 7.4572014808654785156,
|
|
||||||
-6.7263274192810058594, 4.8481650352478027344, -2.0412089824676513672, -0.7006359100341796875,
|
|
||||||
2.9537565708160400391, -4.0800385475158691406, 4.1845216751098632812, -3.3311812877655029297,
|
|
||||||
2.1179926395416259766, -0.879302978515625, 0.031759146600961685181, 0.42382788658142089844,
|
|
||||||
-0.47882103919982910156, 0.35490813851356506348, -0.17496839165687561035, 0.060908168554306030273,
|
|
||||||
}, /* 44.1k, N=20, amp=27 */
|
|
||||||
|
|
||||||
{ -1.6335992813110351562, 2.2615492343902587891, -2.4077029228210449219, 2.6341717243194580078,
|
|
||||||
-2.1440362930297851562, 1.8153258562088012695, -1.0816224813461303711, 0.70302653312683105469,
|
|
||||||
-0.15991993248462677002, -0.041549518704414367676, 0.29416576027870178223, -0.2518316805362701416,
|
|
||||||
0.27766478061676025391, -0.15785403549671173096, 0.10165894031524658203, -0.016833892092108726501,
|
|
||||||
}, /* 37.8k, N=16 */
|
|
||||||
|
|
||||||
{ -0.82901298999786376953, 0.98922657966613769531, -0.59825712442398071289, 1.0028809309005737305,
|
|
||||||
-0.59938216209411621094, 0.79502451419830322266, -0.42723315954208374023, 0.54492527246475219727,
|
|
||||||
-0.30792605876922607422, 0.36871799826622009277, -0.18792048096656799316, 0.2261127084493637085,
|
|
||||||
-0.10573341697454452515, 0.11435490846633911133, -0.038800679147243499756, 0.040842197835445404053,
|
|
||||||
}, /* 32k, N=16 */
|
|
||||||
|
|
||||||
{ -0.065229974687099456787, 0.54981261491775512695, 0.40278548002243041992, 0.31783768534660339355,
|
|
||||||
0.28201797604560852051, 0.16985194385051727295, 0.15433363616466522217, 0.12507140636444091797,
|
|
||||||
0.08903945237398147583, 0.064410120248794555664, 0.047146003693342208862, 0.032805237919092178345,
|
|
||||||
0.028495194390416145325, 0.011695005930960178375, 0.011831838637590408325,
|
|
||||||
}, /* 22.05k, N=15 */
|
|
||||||
|
|
||||||
{ -2.3925774097442626953, 3.4350297451019287109, -3.1853709220886230469, 1.8117271661758422852,
|
|
||||||
0.20124770700931549072, -1.4759907722473144531, 1.7210904359817504883, -0.97746700048446655273,
|
|
||||||
0.13790138065814971924, 0.38185903429985046387, -0.27421241998672485352, -0.066584214568138122559,
|
|
||||||
0.35223302245140075684, -0.37672343850135803223, 0.23964276909828186035, -0.068674825131893157959,
|
|
||||||
}, /* 48k, N=16, amp=10 */
|
|
||||||
|
|
||||||
{ -2.0833916664123535156, 3.0418450832366943359, -3.2047898769378662109, 2.7571926116943359375,
|
|
||||||
-1.4978630542755126953, 0.3427594602108001709, 0.71733748912811279297, -1.0737057924270629883,
|
|
||||||
1.0225815773010253906, -0.56649994850158691406, 0.20968692004680633545, 0.065378531813621520996,
|
|
||||||
-0.10322438180446624756, 0.067442022264003753662, 0.00495197344571352005,
|
|
||||||
}, /* 44.1k, N=15, amp=9 */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
{ -3.0259189605712890625, 6.0268716812133789062, -9.195003509521484375, 11.824929237365722656,
|
|
||||||
-12.767142295837402344, 11.917946815490722656, -9.1739168167114257812, 5.3712320327758789062,
|
|
||||||
-1.1393624544143676758, -2.4484779834747314453, 4.9719839096069335938, -6.0392003059387207031,
|
|
||||||
5.9359521865844726562, -4.903278350830078125, 3.5527443885803222656, -2.1909697055816650391,
|
|
||||||
1.1672389507293701172, -0.4903914332389831543, 0.16519790887832641602, -0.023217858746647834778,
|
|
||||||
}, /* 44.1k, N=20 */
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#define POOLSIZE 97
|
|
||||||
|
|
||||||
Shaper::Shaper(int freq, int _nch, int min, int max, int _dtype, int pdf, double noiseamp)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
float pool[POOLSIZE] = {0};
|
|
||||||
|
|
||||||
nch = _nch;
|
|
||||||
dtype = _dtype;
|
|
||||||
|
|
||||||
for (i = 1;i < 6;i++) if (freq == scoeffreq[i]) break;
|
|
||||||
/* if ((dtype == 3 || dtype == 4) && i == 6) {
|
|
||||||
fprintf(stderr,"Warning: ATH based noise shaping for destination frequency %dHz is not available, using triangular dither\n",freq);
|
|
||||||
}*/
|
|
||||||
if (dtype == 2 || i == 6) i = 0;
|
|
||||||
if (dtype == 4 && (i == 1 || i == 2)) i += 5;
|
|
||||||
|
|
||||||
shaper_type = i;
|
|
||||||
|
|
||||||
shapebuf = (double**)malloc(sizeof(double *) * nch);
|
|
||||||
shaper_len = scoeflen[shaper_type];
|
|
||||||
|
|
||||||
for (i = 0;i < nch;i++)
|
|
||||||
shapebuf[i] = (double*)calloc(shaper_len, sizeof(double));
|
|
||||||
|
|
||||||
shaper_clipmin = min;
|
|
||||||
shaper_clipmax = max;
|
|
||||||
|
|
||||||
randbuf = (REAL*)malloc(sizeof(REAL) * RANDBUFLEN);
|
|
||||||
|
|
||||||
for (i = 0;i < POOLSIZE;i++) pool[i] = warandf();
|
|
||||||
|
|
||||||
switch (pdf)
|
|
||||||
{
|
|
||||||
case DITHER_RECTANGLE: // rectangular
|
|
||||||
for (i = 0;i < RANDBUFLEN;i++)
|
|
||||||
{
|
|
||||||
float r;
|
|
||||||
int p;
|
|
||||||
|
|
||||||
p = warand() % POOLSIZE;
|
|
||||||
r = pool[p]; pool[p] = warandf();
|
|
||||||
randbuf[i] = (REAL)(noiseamp * (((double)r) - 0.5));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DITHER_TRIANGLE:
|
|
||||||
for (i = 0;i < RANDBUFLEN;i++)
|
|
||||||
{
|
|
||||||
float r1, r2;
|
|
||||||
int p;
|
|
||||||
|
|
||||||
p = warand() % POOLSIZE;
|
|
||||||
r1 = pool[p]; pool[p] = warandf();
|
|
||||||
p = warand() % POOLSIZE;
|
|
||||||
r2 = pool[p]; pool[p] = warandf();
|
|
||||||
randbuf[i] = (REAL)(noiseamp * ((((double)r1)) - (((double)r2))));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#if 0
|
|
||||||
case DITHER_GAUSSIAN: // gaussian
|
|
||||||
for (i = 0;i < RANDBUFLEN;i++)
|
|
||||||
{
|
|
||||||
int sw = 0;
|
|
||||||
double t, u;
|
|
||||||
double r;
|
|
||||||
int p;
|
|
||||||
|
|
||||||
if (sw == 0)
|
|
||||||
{
|
|
||||||
sw = 1;
|
|
||||||
|
|
||||||
p = warand() % POOLSIZE;
|
|
||||||
r = ((double)pool[p]); pool[p] = warandf();
|
|
||||||
|
|
||||||
t = sqrt(-2 * log(1 - r));
|
|
||||||
|
|
||||||
p = warand() % POOLSIZE;
|
|
||||||
r = ((double)pool[p]); pool[p] = warandf();
|
|
||||||
|
|
||||||
u = 2 * M_PI * r;
|
|
||||||
|
|
||||||
randbuf[i] = noiseamp * t * cos(u);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sw = 0;
|
|
||||||
|
|
||||||
randbuf[i] = noiseamp * t * sin(u);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
randptr = 0;
|
|
||||||
|
|
||||||
// if (dtype == 0 || dtype == 1) return 1;
|
|
||||||
//return samp[shaper_type];
|
|
||||||
}
|
|
||||||
|
|
||||||
Shaper::~Shaper()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0;i < nch;i++) free(shapebuf[i]);
|
|
||||||
free(shapebuf);
|
|
||||||
free(randbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Shaper::do_shaping(double s,/*double *peak,*/int ch)
|
|
||||||
{
|
|
||||||
double u, h;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (dtype == 1)
|
|
||||||
{
|
|
||||||
s += randbuf[randptr++ & (RANDBUFLEN-1)];
|
|
||||||
|
|
||||||
if (s < shaper_clipmin)
|
|
||||||
{
|
|
||||||
//double d = (double)s / shaper_clipmin;
|
|
||||||
//*peak = *peak < d ? d : *peak;
|
|
||||||
s = shaper_clipmin;
|
|
||||||
}
|
|
||||||
if (s > shaper_clipmax)
|
|
||||||
{
|
|
||||||
//double d = (double)s / shaper_clipmax;
|
|
||||||
//*peak = *peak < d ? d : *peak;
|
|
||||||
s = shaper_clipmax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RINT(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
h = 0;
|
|
||||||
for (i = 0;i < shaper_len;i++)
|
|
||||||
h += shapercoefs[shaper_type][i] * shapebuf[ch][i];
|
|
||||||
s += h;
|
|
||||||
u = s;
|
|
||||||
s += randbuf[randptr++ & (RANDBUFLEN-1)];
|
|
||||||
if (s < shaper_clipmin)
|
|
||||||
{
|
|
||||||
//double d = (double)s / shaper_clipmin;
|
|
||||||
//*peak = *peak < d ? d : *peak;
|
|
||||||
s = shaper_clipmin;
|
|
||||||
}
|
|
||||||
if (s > shaper_clipmax)
|
|
||||||
{
|
|
||||||
//double d = (double)s / shaper_clipmax;
|
|
||||||
//*peak = *peak < d ? d : *peak;
|
|
||||||
s = shaper_clipmax;
|
|
||||||
}
|
|
||||||
s = RINT(s);
|
|
||||||
for (i = shaper_len - 2;i >= 0;i--) shapebuf[ch][i+1] = shapebuf[ch][i];
|
|
||||||
shapebuf[ch][0] = s - u;
|
|
||||||
|
|
||||||
return (int)s;
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
//from SSRC
|
|
||||||
#ifndef NULLSOFT_VORBIS_SHAPER_H
|
|
||||||
#define NULLSOFT_VORBIS_SHAPER_H
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
typedef float REAL;
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
DITHER_RECTANGLE=0,
|
|
||||||
DITHER_TRIANGLE=1,
|
|
||||||
DITHER_GAUSSIAN=2,
|
|
||||||
};
|
|
||||||
class Shaper
|
|
||||||
{
|
|
||||||
double **shapebuf;
|
|
||||||
int shaper_type,shaper_len,shaper_clipmin,shaper_clipmax;
|
|
||||||
REAL *randbuf;
|
|
||||||
int randptr;
|
|
||||||
int dtype;
|
|
||||||
int nch;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Shaper(int freq,int _nch,int min,int max,int _dtype,int pdf,double noiseamp);
|
|
||||||
|
|
||||||
int do_shaping(double s,/*double *peak,*/int ch);
|
|
||||||
|
|
||||||
~Shaper();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||||||
#include "main.h"
|
|
||||||
|
|
@ -1,491 +0,0 @@
|
|||||||
/* This program is licensed under the GNU Library General Public License, version 2,
|
|
||||||
* a copy of which is included with this program (LICENCE.LGPL).
|
|
||||||
*
|
|
||||||
* (c) 2000-2001 Michael Smith <msmith@labyrinth.net.au>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Comment editing backend, suitable for use by nice frontend interfaces.
|
|
||||||
*
|
|
||||||
* last modified: $Id: vcedit.c,v 1.3 2013/10/22 14:17:11 dromagod Exp $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ogg/ogg.h>
|
|
||||||
#include <vorbis/codec.h>
|
|
||||||
|
|
||||||
#include "vcedit.h"
|
|
||||||
//#include "i18n.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define CHUNKSIZE 4096
|
|
||||||
|
|
||||||
vcedit_state *vcedit_new_state(void)
|
|
||||||
{
|
|
||||||
vcedit_state *state = malloc(sizeof(vcedit_state));
|
|
||||||
memset(state, 0, sizeof(vcedit_state));
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *vcedit_error(vcedit_state *state)
|
|
||||||
{
|
|
||||||
return state->lasterror;
|
|
||||||
}
|
|
||||||
|
|
||||||
vorbis_comment *vcedit_comments(vcedit_state *state)
|
|
||||||
{
|
|
||||||
return state->vc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vcedit_clear_internals(vcedit_state *state)
|
|
||||||
{
|
|
||||||
if(state->vc)
|
|
||||||
{
|
|
||||||
vorbis_comment_clear(state->vc);
|
|
||||||
free(state->vc);
|
|
||||||
}
|
|
||||||
if(state->os)
|
|
||||||
{
|
|
||||||
ogg_stream_clear(state->os);
|
|
||||||
free(state->os);
|
|
||||||
}
|
|
||||||
if(state->oy)
|
|
||||||
{
|
|
||||||
ogg_sync_clear(state->oy);
|
|
||||||
free(state->oy);
|
|
||||||
}
|
|
||||||
if(state->vendor)
|
|
||||||
free(state->vendor);
|
|
||||||
if(state->mainbuf)
|
|
||||||
free(state->mainbuf);
|
|
||||||
if(state->bookbuf)
|
|
||||||
free(state->bookbuf);
|
|
||||||
if(state->vi) {
|
|
||||||
vorbis_info_clear(state->vi);
|
|
||||||
free(state->vi);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(state, 0, sizeof(*state));
|
|
||||||
}
|
|
||||||
|
|
||||||
void vcedit_clear(vcedit_state *state)
|
|
||||||
{
|
|
||||||
if(state)
|
|
||||||
{
|
|
||||||
vcedit_clear_internals(state);
|
|
||||||
free(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next two functions pulled straight from libvorbis, apart from one change
|
|
||||||
* - we don't want to overwrite the vendor string.
|
|
||||||
*/
|
|
||||||
static void _v_writestring(oggpack_buffer *o,char *s, int len)
|
|
||||||
{
|
|
||||||
while(len--)
|
|
||||||
{
|
|
||||||
oggpack_write(o,*s++,8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _commentheader_out(vorbis_comment *vc, char *vendor, ogg_packet *op)
|
|
||||||
{
|
|
||||||
oggpack_buffer opb;
|
|
||||||
|
|
||||||
oggpack_writeinit(&opb);
|
|
||||||
|
|
||||||
/* preamble */
|
|
||||||
oggpack_write(&opb,0x03,8);
|
|
||||||
_v_writestring(&opb,"vorbis", 6);
|
|
||||||
|
|
||||||
/* vendor */
|
|
||||||
oggpack_write(&opb,(unsigned long)strlen(vendor),32);
|
|
||||||
_v_writestring(&opb,vendor, (int)strlen(vendor));
|
|
||||||
|
|
||||||
/* comments */
|
|
||||||
oggpack_write(&opb,vc->comments,32);
|
|
||||||
if(vc->comments){
|
|
||||||
int i;
|
|
||||||
for(i=0;i<vc->comments;i++){
|
|
||||||
if(vc->user_comments[i]){
|
|
||||||
oggpack_write(&opb,vc->comment_lengths[i],32);
|
|
||||||
_v_writestring(&opb,vc->user_comments[i],
|
|
||||||
vc->comment_lengths[i]);
|
|
||||||
}else{
|
|
||||||
oggpack_write(&opb,0,32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
oggpack_write(&opb,1,1);
|
|
||||||
|
|
||||||
op->packet = _ogg_malloc(oggpack_bytes(&opb));
|
|
||||||
memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
|
|
||||||
|
|
||||||
op->bytes=oggpack_bytes(&opb);
|
|
||||||
op->b_o_s=0;
|
|
||||||
op->e_o_s=0;
|
|
||||||
op->granulepos=0;
|
|
||||||
|
|
||||||
oggpack_writeclear(&opb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _blocksize(vcedit_state *s, ogg_packet *p)
|
|
||||||
{
|
|
||||||
int this = vorbis_packet_blocksize(s->vi, p);
|
|
||||||
int ret = (this + s->prevW)/4;
|
|
||||||
|
|
||||||
if(!s->prevW)
|
|
||||||
{
|
|
||||||
s->prevW = this;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->prevW = this;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _fetch_next_packet(vcedit_state *s, ogg_packet *p, ogg_page *page)
|
|
||||||
{
|
|
||||||
int result = ogg_stream_packetout(s->os, p);
|
|
||||||
|
|
||||||
if(result > 0)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(s->eosin)
|
|
||||||
return 0;
|
|
||||||
while(ogg_sync_pageout(s->oy, page) <= 0)
|
|
||||||
{
|
|
||||||
char *buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
|
|
||||||
int bytes = (int)s->read(buffer,1, CHUNKSIZE, s->in);
|
|
||||||
ogg_sync_wrote(s->oy, bytes);
|
|
||||||
if(bytes == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(ogg_page_eos(page))
|
|
||||||
s->eosin = 1;
|
|
||||||
else if(ogg_page_serialno(page) != s->serial)
|
|
||||||
{
|
|
||||||
s->eosin = 1;
|
|
||||||
s->extrapage = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ogg_stream_pagein(s->os, page);
|
|
||||||
return _fetch_next_packet(s, p, page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int vcedit_open(vcedit_state *state, FILE *in)
|
|
||||||
{
|
|
||||||
return vcedit_open_callbacks(state, (void *)in,
|
|
||||||
(vcedit_read_func)fread, (vcedit_write_func)fwrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
int vcedit_open_callbacks(vcedit_state *state, void *in,
|
|
||||||
vcedit_read_func read_func, vcedit_write_func write_func)
|
|
||||||
{
|
|
||||||
|
|
||||||
char *buffer;
|
|
||||||
int bytes,i;
|
|
||||||
ogg_packet *header;
|
|
||||||
ogg_packet header_main;
|
|
||||||
ogg_packet header_comments;
|
|
||||||
ogg_packet header_codebooks;
|
|
||||||
ogg_page og;
|
|
||||||
|
|
||||||
state->in = in;
|
|
||||||
state->read = read_func;
|
|
||||||
state->write = write_func;
|
|
||||||
|
|
||||||
state->oy = malloc(sizeof(ogg_sync_state));
|
|
||||||
ogg_sync_init(state->oy);
|
|
||||||
|
|
||||||
buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
|
|
||||||
bytes = (int)state->read(buffer, 1, CHUNKSIZE, state->in);
|
|
||||||
|
|
||||||
ogg_sync_wrote(state->oy, bytes);
|
|
||||||
|
|
||||||
if(ogg_sync_pageout(state->oy, &og) != 1)
|
|
||||||
{
|
|
||||||
if(bytes<CHUNKSIZE)
|
|
||||||
state->lasterror = "Input truncated or empty.";
|
|
||||||
else
|
|
||||||
state->lasterror = "Input is not an Ogg bitstream.";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->serial = ogg_page_serialno(&og);
|
|
||||||
|
|
||||||
state->os = malloc(sizeof(ogg_stream_state));
|
|
||||||
ogg_stream_init(state->os, state->serial);
|
|
||||||
|
|
||||||
state->vi = malloc(sizeof(vorbis_info));
|
|
||||||
vorbis_info_init(state->vi);
|
|
||||||
|
|
||||||
state->vc = malloc(sizeof(vorbis_comment));
|
|
||||||
vorbis_comment_init(state->vc);
|
|
||||||
|
|
||||||
if(ogg_stream_pagein(state->os, &og) < 0)
|
|
||||||
{
|
|
||||||
state->lasterror = "Error reading first page of Ogg bitstream.";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ogg_stream_packetout(state->os, &header_main) != 1)
|
|
||||||
{
|
|
||||||
state->lasterror = "Error reading initial header packet.";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(vorbis_synthesis_headerin(state->vi, state->vc, &header_main) < 0)
|
|
||||||
{
|
|
||||||
state->lasterror = "Ogg bitstream does not contain vorbis data.";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->mainlen = header_main.bytes;
|
|
||||||
state->mainbuf = malloc(state->mainlen);
|
|
||||||
memcpy(state->mainbuf, header_main.packet, header_main.bytes);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
header = &header_comments;
|
|
||||||
while(i<2) {
|
|
||||||
while(i<2) {
|
|
||||||
int result = ogg_sync_pageout(state->oy, &og);
|
|
||||||
if(result == 0) break; /* Too little data so far */
|
|
||||||
else if(result == 1)
|
|
||||||
{
|
|
||||||
ogg_stream_pagein(state->os, &og);
|
|
||||||
while(i<2)
|
|
||||||
{
|
|
||||||
result = ogg_stream_packetout(state->os, header);
|
|
||||||
if(result == 0) break;
|
|
||||||
if(result == -1)
|
|
||||||
{
|
|
||||||
state->lasterror = "Corrupt secondary header.";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
vorbis_synthesis_headerin(state->vi, state->vc, header);
|
|
||||||
if(i==1)
|
|
||||||
{
|
|
||||||
state->booklen = header->bytes;
|
|
||||||
state->bookbuf = malloc(state->booklen);
|
|
||||||
memcpy(state->bookbuf, header->packet,
|
|
||||||
header->bytes);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
header = &header_codebooks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
|
|
||||||
bytes = (int)state->read(buffer, 1, CHUNKSIZE, state->in);
|
|
||||||
if(bytes == 0 && i < 2)
|
|
||||||
{
|
|
||||||
state->lasterror = "EOF before end of vorbis headers.";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
ogg_sync_wrote(state->oy, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the vendor tag */
|
|
||||||
bytes = (int)strlen(state->vc->vendor);
|
|
||||||
state->vendor = malloc(bytes +1);
|
|
||||||
strncpy(state->vendor, state->vc->vendor, bytes);
|
|
||||||
|
|
||||||
/* Headers are done! */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err:
|
|
||||||
vcedit_clear_internals(state);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vcedit_write(vcedit_state *state, void *out)
|
|
||||||
{
|
|
||||||
ogg_stream_state streamout;
|
|
||||||
ogg_packet header_main;
|
|
||||||
ogg_packet header_comments;
|
|
||||||
ogg_packet header_codebooks;
|
|
||||||
|
|
||||||
ogg_page ogout, ogin;
|
|
||||||
ogg_packet op;
|
|
||||||
ogg_int64_t granpos = 0;
|
|
||||||
int result;
|
|
||||||
char *buffer;
|
|
||||||
int bytes;
|
|
||||||
int needflush=0, needout=0;
|
|
||||||
|
|
||||||
state->eosin = 0;
|
|
||||||
state->extrapage = 0;
|
|
||||||
|
|
||||||
header_main.bytes = state->mainlen;
|
|
||||||
header_main.packet = state->mainbuf;
|
|
||||||
header_main.b_o_s = 1;
|
|
||||||
header_main.e_o_s = 0;
|
|
||||||
header_main.granulepos = 0;
|
|
||||||
|
|
||||||
header_codebooks.bytes = state->booklen;
|
|
||||||
header_codebooks.packet = state->bookbuf;
|
|
||||||
header_codebooks.b_o_s = 0;
|
|
||||||
header_codebooks.e_o_s = 0;
|
|
||||||
header_codebooks.granulepos = 0;
|
|
||||||
|
|
||||||
ogg_stream_init(&streamout, state->serial);
|
|
||||||
|
|
||||||
_commentheader_out(state->vc, state->vendor, &header_comments);
|
|
||||||
|
|
||||||
ogg_stream_packetin(&streamout, &header_main);
|
|
||||||
ogg_stream_packetin(&streamout, &header_comments);
|
|
||||||
ogg_stream_packetin(&streamout, &header_codebooks);
|
|
||||||
|
|
||||||
while((result = ogg_stream_flush(&streamout, &ogout)))
|
|
||||||
{
|
|
||||||
if(state->write(ogout.header,1,ogout.header_len, out) !=
|
|
||||||
(size_t) ogout.header_len)
|
|
||||||
goto cleanup;
|
|
||||||
if(state->write(ogout.body,1,ogout.body_len, out) !=
|
|
||||||
(size_t) ogout.body_len)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(_fetch_next_packet(state, &op, &ogin))
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
size = _blocksize(state, &op);
|
|
||||||
granpos += size;
|
|
||||||
|
|
||||||
if(needflush)
|
|
||||||
{
|
|
||||||
if(ogg_stream_flush(&streamout, &ogout))
|
|
||||||
{
|
|
||||||
if(state->write(ogout.header,1,ogout.header_len,
|
|
||||||
out) != (size_t) ogout.header_len)
|
|
||||||
goto cleanup;
|
|
||||||
if(state->write(ogout.body,1,ogout.body_len,
|
|
||||||
out) != (size_t) ogout.body_len)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(needout)
|
|
||||||
{
|
|
||||||
if(ogg_stream_pageout(&streamout, &ogout))
|
|
||||||
{
|
|
||||||
if(state->write(ogout.header,1,ogout.header_len,
|
|
||||||
out) != (size_t) ogout.header_len)
|
|
||||||
goto cleanup;
|
|
||||||
if(state->write(ogout.body,1,ogout.body_len,
|
|
||||||
out) != (size_t) ogout.body_len)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
needflush=needout=0;
|
|
||||||
|
|
||||||
if(op.granulepos == -1)
|
|
||||||
{
|
|
||||||
op.granulepos = granpos;
|
|
||||||
ogg_stream_packetin(&streamout, &op);
|
|
||||||
}
|
|
||||||
else /* granulepos is set, validly. Use it, and force a flush to
|
|
||||||
account for shortened blocks (vcut) when appropriate */
|
|
||||||
{
|
|
||||||
if(granpos > op.granulepos)
|
|
||||||
{
|
|
||||||
granpos = op.granulepos;
|
|
||||||
ogg_stream_packetin(&streamout, &op);
|
|
||||||
needflush=1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ogg_stream_packetin(&streamout, &op);
|
|
||||||
needout=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
streamout.e_o_s = 1;
|
|
||||||
while(ogg_stream_flush(&streamout, &ogout))
|
|
||||||
{
|
|
||||||
if(state->write(ogout.header,1,ogout.header_len,
|
|
||||||
out) != (size_t) ogout.header_len)
|
|
||||||
goto cleanup;
|
|
||||||
if(state->write(ogout.body,1,ogout.body_len,
|
|
||||||
out) != (size_t) ogout.body_len)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->extrapage)
|
|
||||||
{
|
|
||||||
if(state->write(ogin.header,1,ogin.header_len,
|
|
||||||
out) != (size_t) ogin.header_len)
|
|
||||||
goto cleanup;
|
|
||||||
if (state->write(ogin.body,1,ogin.body_len, out) !=
|
|
||||||
(size_t) ogin.body_len)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->eosin=0; /* clear it, because not all paths to here do */
|
|
||||||
while(!state->eosin) /* We reached eos, not eof */
|
|
||||||
{
|
|
||||||
/* We copy the rest of the stream (other logical streams)
|
|
||||||
* through, a page at a time. */
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
result = ogg_sync_pageout(state->oy, &ogout);
|
|
||||||
if(result==0)
|
|
||||||
break;
|
|
||||||
if(result<0)
|
|
||||||
state->lasterror = "Corrupt or missing data, continuing...";
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Don't bother going through the rest, we can just
|
|
||||||
* write the page out now */
|
|
||||||
if(state->write(ogout.header,1,ogout.header_len,
|
|
||||||
out) != (size_t) ogout.header_len) {
|
|
||||||
// fprintf(stderr, "Bumming out\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if(state->write(ogout.body,1,ogout.body_len, out) !=
|
|
||||||
(size_t) ogout.body_len) {
|
|
||||||
// fprintf(stderr, "Bumming out 2\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
|
|
||||||
bytes = (int)state->read(buffer,1, CHUNKSIZE, state->in);
|
|
||||||
ogg_sync_wrote(state->oy, bytes);
|
|
||||||
if(bytes == 0)
|
|
||||||
{
|
|
||||||
state->eosin = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
ogg_stream_clear(&streamout);
|
|
||||||
ogg_packet_clear(&header_comments);
|
|
||||||
|
|
||||||
free(state->mainbuf);
|
|
||||||
free(state->bookbuf);
|
|
||||||
state->mainbuf = state->bookbuf = NULL;
|
|
||||||
|
|
||||||
if(!state->eosin)
|
|
||||||
{
|
|
||||||
state->lasterror =
|
|
||||||
"Error writing stream to output. "
|
|
||||||
"Output stream may be corrupted or truncated.";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
/* This program is licensed under the GNU Library General Public License, version 2,
|
|
||||||
* a copy of which is included with this program (with filename LICENSE.LGPL).
|
|
||||||
*
|
|
||||||
* (c) 2000-2001 Michael Smith <msmith@labyrinth.net.au>
|
|
||||||
*
|
|
||||||
* VCEdit header.
|
|
||||||
*
|
|
||||||
* last modified: $ID:$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __VCEDIT_H
|
|
||||||
#define __VCEDIT_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <ogg/ogg.h>
|
|
||||||
#include <vorbis/codec.h>
|
|
||||||
|
|
||||||
typedef size_t (*vcedit_read_func)(void *, size_t, size_t, void *);
|
|
||||||
typedef size_t (*vcedit_write_func)(const void *, size_t, size_t, void *);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ogg_sync_state *oy;
|
|
||||||
ogg_stream_state *os;
|
|
||||||
|
|
||||||
vorbis_comment *vc;
|
|
||||||
vorbis_info *vi;
|
|
||||||
|
|
||||||
vcedit_read_func read;
|
|
||||||
vcedit_write_func write;
|
|
||||||
|
|
||||||
void *in;
|
|
||||||
long serial;
|
|
||||||
unsigned char *mainbuf;
|
|
||||||
unsigned char *bookbuf;
|
|
||||||
int mainlen;
|
|
||||||
int booklen;
|
|
||||||
char *lasterror;
|
|
||||||
char *vendor;
|
|
||||||
int prevW;
|
|
||||||
int extrapage;
|
|
||||||
int eosin;
|
|
||||||
} vcedit_state;
|
|
||||||
|
|
||||||
extern vcedit_state * vcedit_new_state(void);
|
|
||||||
extern void vcedit_clear(vcedit_state *state);
|
|
||||||
extern vorbis_comment * vcedit_comments(vcedit_state *state);
|
|
||||||
extern int vcedit_open(vcedit_state *state, FILE *in);
|
|
||||||
extern int vcedit_open_callbacks(vcedit_state *state, void *in,
|
|
||||||
vcedit_read_func read_func, vcedit_write_func write_func);
|
|
||||||
extern int vcedit_write(vcedit_state *state, void *out);
|
|
||||||
extern char * vcedit_error(vcedit_state *state);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __VCEDIT_H */
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Version
|
|
||||||
//
|
|
||||||
#include "../../../Winamp/buildType.h"
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION 1,79,0,0
|
|
||||||
PRODUCTVERSION WINAMP_PRODUCTVER
|
|
||||||
FILEFLAGSMASK 0x17L
|
|
||||||
#ifdef _DEBUG
|
|
||||||
FILEFLAGS 0x1L
|
|
||||||
#else
|
|
||||||
FILEFLAGS 0x0L
|
|
||||||
#endif
|
|
||||||
FILEOS 0x4L
|
|
||||||
FILETYPE 0x2L
|
|
||||||
FILESUBTYPE 0x0L
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904b0"
|
|
||||||
BEGIN
|
|
||||||
VALUE "CompanyName", "Winamp SA"
|
|
||||||
VALUE "FileDescription", "Winamp Input Plug-in"
|
|
||||||
VALUE "FileVersion", "1,79,0,0"
|
|
||||||
VALUE "InternalName", "Nullsoft Vorbis Decoder"
|
|
||||||
VALUE "LegalCopyright", "Copyright © 2001-2023 Winamp SA"
|
|
||||||
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
|
|
||||||
VALUE "OriginalFilename", "in_vorbis.dll"
|
|
||||||
VALUE "ProductName", "Winamp"
|
|
||||||
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x409, 1200
|
|
||||||
END
|
|
||||||
END
|
|
@ -1,2 +0,0 @@
|
|||||||
#include "main.h"
|
|
||||||
#include "api__in_vorbis.h"
|
|
@ -1,114 +0,0 @@
|
|||||||
libdiscid ChangeLog:
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
libdiscid-0.6.2:
|
|
||||||
|
|
||||||
- ISRC and MCN support on BSD
|
|
||||||
- LIB-60: fix make check for default device on generic/unknown platform
|
|
||||||
- make Doxygen output reproducible (no timestamps)
|
|
||||||
- remove newline for Linux device "1" from proc
|
|
||||||
|
|
||||||
libdiscid-0.6.1:
|
|
||||||
|
|
||||||
- LIB-59: windows: fix bug preventing ISRC reads
|
|
||||||
|
|
||||||
libdiscid-0.6.0:
|
|
||||||
|
|
||||||
- LIB-41: add discid_get_troc_string() for fuzzy toc lookup
|
|
||||||
- LIB-54: add libmusicbrainz example with fuzzy toc lookup
|
|
||||||
- LIB-43: windows: the default drive is the first cd drive letter
|
|
||||||
- LIB-45: Linux/BSD/Solaris: try several possible default device names
|
|
||||||
- LIB-28: Mac: allow drive numbers as devices, default now "1"
|
|
||||||
- LIB-55, LIB-56: allow drive numbers for Windows and Linux
|
|
||||||
- LIB-53: discid_get_submission_url() returns the new NGS url
|
|
||||||
currently no functional change, the old url was redirected
|
|
||||||
- LIB-52: more validation for parameters of discid_put()
|
|
||||||
- LIB-48: assert successful read/put when API is used
|
|
||||||
- the discisrc example prints the name of the device used
|
|
||||||
|
|
||||||
libdiscid-0.5.2:
|
|
||||||
|
|
||||||
- LIB-51: fix ISRC reading on Mac OS X again
|
|
||||||
- LIB-50: fix segfault in mb_disc_load_toc on Solaris
|
|
||||||
- LIB-26: add a better test suite, including valgrind memcheck target
|
|
||||||
- print time information in the discid example
|
|
||||||
|
|
||||||
libdiscid-0.5.1:
|
|
||||||
|
|
||||||
- LIB-40: discid_get_webservice_url() (web service version 1) is deprecated
|
|
||||||
please use libmusicbrainz to gather metadata by disc ID
|
|
||||||
- LIB-7: rewrote data track handling, releases with multiple data tracks
|
|
||||||
This also fixes LIB-18 (no ID for DVDs) and LIB-9 (PS/PS2 CDs)
|
|
||||||
- LIB-44: fix invalid disc IDs on first read of multi-session discs
|
|
||||||
- LIB-37: Autotools optimization (non-recursive build etc.)
|
|
||||||
- LIB-42: remove Windows 9x platform code
|
|
||||||
- renamed openbsd platform code to netbsd, still used by both.
|
|
||||||
|
|
||||||
libdiscid-0.5.0:
|
|
||||||
|
|
||||||
- LIB-29: add read_sparse() for faster reading again
|
|
||||||
- LIB-35: add HAVE_SPARSE_READ and VERSION_* defines
|
|
||||||
- LIB-36: hide internal symbols on Linux/Unix
|
|
||||||
- LIB-34: distmac and distwin32 cmake targets
|
|
||||||
|
|
||||||
libdiscid-0.4.1:
|
|
||||||
|
|
||||||
- fix distribution: include disc_generic.c in Autotools dist
|
|
||||||
|
|
||||||
libdiscid-0.4.0:
|
|
||||||
|
|
||||||
- LIB-23: add has_feature() and get_feature_list() to API (platform check)
|
|
||||||
- add get_version_string() to API
|
|
||||||
- CMake : add FreeBSD, NetBSD, OpenBSD -> all platforms supported
|
|
||||||
- LIB-24: support generic platform (discid_put() only)
|
|
||||||
- Win32 : Added versioninfo resource to DLL
|
|
||||||
- LIB-32: change libtool from -version-info to -version-name
|
|
||||||
- LIB-27: fix (k)FreeBSD includes
|
|
||||||
- fix lots of compiler warnings
|
|
||||||
|
|
||||||
libdiscid-0.3.2:
|
|
||||||
|
|
||||||
- fix distribution so it works for autotools AND cmake
|
|
||||||
|
|
||||||
libdiscid-0.3.1:
|
|
||||||
|
|
||||||
- ISRC and MCN support on Linux
|
|
||||||
- Autotools: fix Windows, remove unneeded libs on SunOS
|
|
||||||
- CMake: add Cygwin, add SunOS, fix Mac OS X
|
|
||||||
- updated docs, created INSTALL file
|
|
||||||
|
|
||||||
libdiscid-0.3.0:
|
|
||||||
|
|
||||||
- Fixed reading of 99 track CDs on Mac OS X.
|
|
||||||
- Added API for reading ISRCs and MCNs (implemented on Windows and Mac OS X).
|
|
||||||
- Added Solaris, OpenBSD and kFreeBSD support.
|
|
||||||
|
|
||||||
libdiscid-0.2.2:
|
|
||||||
|
|
||||||
- Set libtool version number to 2:1:2 because it is backwards compatible
|
|
||||||
with versions 0.1.x. Thanks to Luks for spotting this.
|
|
||||||
|
|
||||||
|
|
||||||
libdiscid-0.2.1:
|
|
||||||
|
|
||||||
- Added code for automatic CD drive detection on darwin (Rob).
|
|
||||||
|
|
||||||
|
|
||||||
libdiscid-0.2.0:
|
|
||||||
|
|
||||||
- Use accurate TOC reading method for multi-session CDs on
|
|
||||||
Windows NT/2000/XP (Lukas).
|
|
||||||
- Replace custom MSVC makefile with CMake build system (Lukas).
|
|
||||||
- Added support for FreeBSD (Patrick Hurrelmann).
|
|
||||||
- Addded the discid_get_webservice_url() function (Rob).
|
|
||||||
|
|
||||||
|
|
||||||
libdiscid-0.1.1:
|
|
||||||
|
|
||||||
- Use generic 'cdaudio' device name on windows (Lukas).
|
|
||||||
|
|
||||||
|
|
||||||
libdiscid-0.1.0:
|
|
||||||
|
|
||||||
- Initial public release.
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
A Library for creating MusicBrainz DiscIDs
|
|
||||||
------------------------------------------
|
|
||||||
|
|
||||||
libdiscid is a C library for creating MusicBrainz DiscIDs from audio CDs.
|
|
||||||
It reads a CD's table of contents (TOC) and generates an identifier which
|
|
||||||
can be used to lookup the CD at MusicBrainz (http://musicbrainz.org).
|
|
||||||
Additionally, it provides a submission URL for adding the DiscID to the
|
|
||||||
database.
|
|
||||||
|
|
||||||
The library also provides FreeDB disc IDs, and MCN + ISRCs, if available.
|
|
||||||
|
|
||||||
The interface of this library is new, but the DiscID algorithm and the
|
|
||||||
operating system dependent CD-ROM/DVD-ROM access code have been ported
|
|
||||||
from libmusicbrainz version 2.
|
|
||||||
|
|
||||||
|
|
||||||
Please report all bugs you find via the MusicBrainz bug tracker.
|
|
||||||
Don't forget to state which OS and what version you are using:
|
|
||||||
|
|
||||||
http://tickets.musicbrainz.org/browse/LIB
|
|
||||||
|
|
||||||
Questions about this package may be posted to the MusicBrainz
|
|
||||||
development mailing list (mb-devel):
|
|
||||||
|
|
||||||
http://musicbrainz.org/doc/Communication/Mailing_Lists
|
|
||||||
|
|
||||||
More information can be found at the package's official homepage:
|
|
||||||
|
|
||||||
http://musicbrainz.org/doc/libdiscid
|
|
||||||
|
|
@ -1,486 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2013 Johannes Dewender
|
|
||||||
Copyright (C) 2006-2010 Lukas Lalinsky
|
|
||||||
Copyright (C) 2006 Matthias Friedrich
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
#ifndef MUSICBRAINZ_DISC_ID_H
|
|
||||||
#define MUSICBRAINZ_DISC_ID_H
|
|
||||||
|
|
||||||
#if (defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__))
|
|
||||||
# ifdef libdiscid_EXPORTS
|
|
||||||
# define LIBDISCID_API __declspec(dllexport)
|
|
||||||
# else
|
|
||||||
# define LIBDISCID_API __declspec(dllimport)
|
|
||||||
# endif
|
|
||||||
# define LIBDISCID_INTERNAL
|
|
||||||
#elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
|
||||||
# define LIBDISCID_API
|
|
||||||
# define LIBDISCID_INTERNAL __attribute__((visibility("hidden")))
|
|
||||||
#elif defined(__SUNPRO_C)
|
|
||||||
# define LIBDISCID_API __global
|
|
||||||
# define LIBDISCID_INTERNAL __hidden
|
|
||||||
#else
|
|
||||||
# define LIBDISCID_API
|
|
||||||
# define LIBDISCID_INTERNAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__))
|
|
||||||
#define LIBDISCID_DEPRECATED __declspec(deprecated)
|
|
||||||
#elif (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) || defined(__clang__)
|
|
||||||
#define LIBDISCID_DEPRECATED __attribute__((deprecated))
|
|
||||||
#else
|
|
||||||
#define LIBDISCID_DEPRECATED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DISCID_VERSION_MAJOR @libdiscid_MAJOR@
|
|
||||||
#define DISCID_VERSION_MINOR @libdiscid_MINOR@
|
|
||||||
#define DISCID_VERSION_PATCH @libdiscid_PATCH@
|
|
||||||
#define DISCID_VERSION_NUM @libdiscid_VERSION_NUM@
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \mainpage libdiscid
|
|
||||||
* \section intro Introduction
|
|
||||||
*
|
|
||||||
* Libdiscid is a C library for calculating DiscIDs
|
|
||||||
* (<a href="http://musicbrainz.org/doc/Disc ID">MusicBrainz</a>
|
|
||||||
* and <a href="http://freedb.org">freedb</a>)
|
|
||||||
* for Audio CDs.
|
|
||||||
* Additionally the library can extract the MCN/UPC/EAN and the
|
|
||||||
* <a href="http://musicbrainz.org/doc/ISRC">ISRCs</a> from disc.
|
|
||||||
*
|
|
||||||
* The idea is to have an easy to use library without any dependencies
|
|
||||||
* that can be used from scripting languages.
|
|
||||||
*
|
|
||||||
* The API is documented in discid.h.
|
|
||||||
*
|
|
||||||
* \section examples Examples
|
|
||||||
*
|
|
||||||
* This is an example of the most basic usage:
|
|
||||||
*
|
|
||||||
* \code
|
|
||||||
*
|
|
||||||
* DiscId *disc = discid_new();
|
|
||||||
*
|
|
||||||
* if ( discid_read_sparse(disc, "/dev/cdrom", 0) == 0 ) {
|
|
||||||
* fprintf(stderr, "Error: %s\n", discid_get_error_msg(disc));
|
|
||||||
* return 1;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* printf("DiscID : %s\n", discid_get_id(disc));
|
|
||||||
* printf("Submit via : %s\n", discid_get_submission_url(disc));
|
|
||||||
*
|
|
||||||
* discid_free(disc);
|
|
||||||
*
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* \section Building
|
|
||||||
*
|
|
||||||
* libdiscid provides a pkg-config script that returns the necessary compiler and linker flags, as well as the
|
|
||||||
* version number. To build a small sample program one would use:
|
|
||||||
*
|
|
||||||
* @par
|
|
||||||
* <tt>gcc libdiscid-test.c \`pkg-config libdiscid --cflags --libs\` -o libdiscid-test</tt>
|
|
||||||
*
|
|
||||||
* \section Contact
|
|
||||||
*
|
|
||||||
* - <a href="http://lists.musicbrainz.org/mailman/listinfo/musicbrainz-devel">MusicBrainz Development Mailing List</a>
|
|
||||||
* - <a href="http://tickets.musicbrainz.org/browse/LIB">MusicBrainz Bug Tracker</a>
|
|
||||||
* - <a href="http://musicbrainz.org/doc/libdiscid">MusicBrainz Documentation</a>
|
|
||||||
* - <a href="https://github.com/metabrainz/libdiscid">Github Repository</a>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A transparent handle for an Audio CD.
|
|
||||||
*
|
|
||||||
* This is returned by discid_new() and has to be passed as the first
|
|
||||||
* parameter to all discid_*() functions.
|
|
||||||
*/
|
|
||||||
typedef void *DiscId;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a handle for a new DiscId object.
|
|
||||||
*
|
|
||||||
* If no memory could be allocated, NULL is returned. Don't use the created
|
|
||||||
* DiscId object before calling discid_read() or discid_put().
|
|
||||||
*
|
|
||||||
* @return a DiscId object, or NULL.
|
|
||||||
*/
|
|
||||||
LIBDISCID_API DiscId *discid_new();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release the memory allocated for the DiscId object.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
*/
|
|
||||||
LIBDISCID_API void discid_free(DiscId *d);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all supported features of the disc in the given CD-ROM/DVD-ROM drive.
|
|
||||||
*
|
|
||||||
* This function reads the disc in the drive specified by the given device
|
|
||||||
* identifier. If the device is NULL, the default drive, as returned by
|
|
||||||
* discid_get_default_device() is used.
|
|
||||||
*
|
|
||||||
* If you do not require all features provided by libdiscid, such as MCN
|
|
||||||
* or ISRC reading, you should consider using discid_read_sparse() instead
|
|
||||||
* of discid_read() for performance reasons.
|
|
||||||
*
|
|
||||||
* On error, this function returns false and sets the error message which you
|
|
||||||
* can access using discid_get_error_msg(). In this case, the other functions
|
|
||||||
* won't return meaningful values and should not be used.
|
|
||||||
*
|
|
||||||
* This function may be used multiple times with the same DiscId object.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @param device an operating system dependent device identifier, or NULL
|
|
||||||
* @return true if successful, or false on error.
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_read(DiscId *d, const char *device);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the disc in the given CD-ROM/DVD-ROM drive
|
|
||||||
* extracting only the TOC and additionally specified features.
|
|
||||||
*
|
|
||||||
* This function will always read the TOC, but additional features
|
|
||||||
* like ::DISCID_FEATURE_MCN and ::DISCID_FEATURE_ISRC can be set
|
|
||||||
* using the features parameter.
|
|
||||||
* Multiple features can be set using bitwise OR.
|
|
||||||
*
|
|
||||||
* If you only want to generate a disc ID, you only need the TOC,
|
|
||||||
* so set features to 0:
|
|
||||||
* \code
|
|
||||||
* discid_read_sparse(disc, device, 0)
|
|
||||||
* \endcode
|
|
||||||
* This is a bit more verbose, but equivalent since ::DISCID_FEATURE_READ
|
|
||||||
* is always implied:
|
|
||||||
* \code
|
|
||||||
* discid_read_sparse(disc, device, DISCID_FEATURE_READ)
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* If you want to read all features available, you can use discid_read().
|
|
||||||
*
|
|
||||||
* On error, this function returns false and sets the error message which you
|
|
||||||
* can access using discid_get_error_msg(). In this case, the other functions
|
|
||||||
* won't return meaningful values and should not be used.
|
|
||||||
*
|
|
||||||
* This function may be used multiple times with the same DiscId object.
|
|
||||||
*
|
|
||||||
* \since libdiscid 0.5.0
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @param device an operating system dependent device identifier, or NULL
|
|
||||||
* @param features a list of bit flags from the enum ::discid_feature
|
|
||||||
* @return true if successful, or false on error.
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_read_sparse(DiscId *d, const char *device,
|
|
||||||
unsigned int features);
|
|
||||||
|
|
||||||
#define DISCID_HAVE_SPARSE_READ
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the TOC of a known CD.
|
|
||||||
*
|
|
||||||
* This function may be used if the TOC has been read earlier and you
|
|
||||||
* want to calculate the disc ID afterwards, without accessing the disc
|
|
||||||
* drive. It replaces the discid_read function in this case.
|
|
||||||
*
|
|
||||||
* On error, this function returns false and sets the error message which you
|
|
||||||
* can access using discid_get_error_msg(). In this case, the other functions
|
|
||||||
* won't return meaningful values and should not be used.
|
|
||||||
*
|
|
||||||
* The offsets parameter points to an array which contains the track offsets
|
|
||||||
* for each track. The first element, offsets[0], is the leadout track. It
|
|
||||||
* must contain the total number of sectors on the disc.
|
|
||||||
*
|
|
||||||
* For discs with additional data tracks, the trailing data tracks
|
|
||||||
* should be ignored. offset[0] should then be the last sector of the last
|
|
||||||
* audio track.
|
|
||||||
* Make sure the length of the last audio track as returned by libdiscid
|
|
||||||
* after a put is the same as the length of your last audio track.
|
|
||||||
* Depending on your tools you might need to substract 11400 (2:32 min.).
|
|
||||||
* See also:
|
|
||||||
* <a href="http://musicbrainz.org/doc/Disc_ID_Calculation">Disc ID Calculation</a>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param d a DiscID object created by discid_new()
|
|
||||||
* @param first the number of the first audio track on disc (usually one)
|
|
||||||
* @param last the number of the last audio track on the disc
|
|
||||||
* @param offsets a pointer to an array of 100 track offsets
|
|
||||||
* @return true if the given data was valid, and false on error
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_put(DiscId *d, int first, int last, int *offsets);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a human-readable error message.
|
|
||||||
*
|
|
||||||
* This function may only be used if discid_read() failed. The returned
|
|
||||||
* error message is only valid as long as the DiscId object exists.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return a string describing the error that occurred
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char *discid_get_error_msg(DiscId *d);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a MusicBrainz DiscID.
|
|
||||||
*
|
|
||||||
* The returned string is only valid as long as the DiscId object exists.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return a string containing a MusicBrainz DiscID
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char *discid_get_id(DiscId *d);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a FreeDB DiscID.
|
|
||||||
*
|
|
||||||
* The returned string is only valid as long as the DiscId object exists.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return a string containing a FreeDB DiscID
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char *discid_get_freedb_id(DiscId *d);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a string representing CD Table Of Contents (TOC).
|
|
||||||
*
|
|
||||||
* The string has following values separated by space:
|
|
||||||
* first track number
|
|
||||||
* last track number
|
|
||||||
* total length in sectors
|
|
||||||
* offset of 1st track
|
|
||||||
* offset of 2nd track
|
|
||||||
* ...
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* 1 7 164900 150 22460 50197 80614 100828 133318 144712
|
|
||||||
*
|
|
||||||
* The returned string is only valid as long as the DiscId object exists.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return a string containing TOC information
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char *discid_get_toc_string(DiscId *d);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an URL for submitting the DiscID to MusicBrainz.
|
|
||||||
*
|
|
||||||
* The URL leads to an interactive disc submission wizard that guides the
|
|
||||||
* user through the process of associating this disc's DiscID with a
|
|
||||||
* release in the MusicBrainz database.
|
|
||||||
*
|
|
||||||
* The returned string is only valid as long as the DiscId object exists.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return a string containing an URL
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char *discid_get_submission_url(DiscId *d);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an URL for retrieving CD information from MusicBrainz' web service
|
|
||||||
*
|
|
||||||
* The URL provides the CD information in XML.
|
|
||||||
* See http://musicbrainz.org/development/mmd for details.
|
|
||||||
*
|
|
||||||
* The returned string is only valid as long as the DiscId object exists.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return a string containing an URL
|
|
||||||
*
|
|
||||||
* @deprecated This function is deprecated. Please use libmusicbrainz instead
|
|
||||||
* since this function returns an URL referring the deprecated webservice.
|
|
||||||
*/
|
|
||||||
LIBDISCID_API LIBDISCID_DEPRECATED char *discid_get_webservice_url(DiscId *d);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of the default disc drive for this machine.
|
|
||||||
* This isn't constant, but possibly depends on the drives currently
|
|
||||||
* attached, depending on the platform.
|
|
||||||
* For this reason you should call this once and save it
|
|
||||||
* when you want to make sure to use the same drive for
|
|
||||||
* multiple operations.
|
|
||||||
*
|
|
||||||
* The returned string is thread local and owned by libdiscid internally.
|
|
||||||
*
|
|
||||||
* @return a string containing an operating system dependent device identifier
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char *discid_get_default_device(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the number of the first track on this disc.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return the number of the first track
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_get_first_track_num(DiscId *d);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the number of the last audio track on this disc.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return the number of the last track
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_get_last_track_num(DiscId *d);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the length of the disc in sectors.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return the length of the disc in sectors
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_get_sectors(DiscId *d);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the sector offset of a track.
|
|
||||||
*
|
|
||||||
* Only track numbers between (and including) discid_get_first_track_num()
|
|
||||||
* and discid_get_last_track_num() may be used.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @param track_num the number of a track
|
|
||||||
* @return sector offset of the specified track
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_get_track_offset(DiscId *d, int track_num);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the length of a track in sectors.
|
|
||||||
*
|
|
||||||
* Only track numbers between (and including) discid_get_first_track_num()
|
|
||||||
* and discid_get_last_track_num() may be used.
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @param track_num the number of a track
|
|
||||||
* @return length of the specified track
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_get_track_length(DiscId *d, int track_num);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Media Catalogue Number (MCN) for the disc.
|
|
||||||
*
|
|
||||||
* This is essentially an EAN (= UPC with 0 prefix).
|
|
||||||
*
|
|
||||||
* \since libdiscid 0.3.0
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @return a string containing an Media Catalogue Number of the disk
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char* discid_get_mcn(DiscId *d);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the ISRC for a track.
|
|
||||||
*
|
|
||||||
* Only track numbers between (and including) discid_get_first_track_num()
|
|
||||||
* and discid_get_last_track_num() may be used.
|
|
||||||
*
|
|
||||||
* \since libdiscid 0.3.0
|
|
||||||
*
|
|
||||||
* @param d a DiscId object created by discid_new()
|
|
||||||
* @param track_num the number of a track
|
|
||||||
* @return a string containing an ISRC for the specified track
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char* discid_get_track_isrc(DiscId *d, int track_num);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PLATFORM-DEPENDENT FEATURES
|
|
||||||
*
|
|
||||||
* The platform dependent features are currently:
|
|
||||||
* - "read" read TOC from disc
|
|
||||||
* - "mcn" read MCN from disc
|
|
||||||
* - "isrc" read ISRC from disc
|
|
||||||
*
|
|
||||||
* A table in the
|
|
||||||
* <a href="http://musicbrainz.org/doc/libdiscid">MusicBrainz Documentation</a>
|
|
||||||
* specifies which features are available on which platform in what version.
|
|
||||||
*
|
|
||||||
* In the code you can use discid_get_feature_list() or discid_has_feature()
|
|
||||||
* below to get the features for your platform in this version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum discid_feature {
|
|
||||||
DISCID_FEATURE_READ = 1 << 0,
|
|
||||||
DISCID_FEATURE_MCN = 1 << 1,
|
|
||||||
DISCID_FEATURE_ISRC = 1 << 2,
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Check if a certain feature is implemented on the current platform.
|
|
||||||
*
|
|
||||||
* This only works for single features, not bit masks with multiple features.
|
|
||||||
*
|
|
||||||
* \since libdiscid 0.4.0
|
|
||||||
*
|
|
||||||
* @param feature as enum ::discid_feature
|
|
||||||
* @return 1 if the feature is implemented and 0 if not.
|
|
||||||
*/
|
|
||||||
LIBDISCID_API int discid_has_feature(enum discid_feature feature);
|
|
||||||
|
|
||||||
#define DISCID_FEATURE_STR_READ "read"
|
|
||||||
#define DISCID_FEATURE_STR_MCN "mcn"
|
|
||||||
#define DISCID_FEATURE_STR_ISRC "isrc"
|
|
||||||
#define DISCID_FEATURE_LENGTH 32
|
|
||||||
/**
|
|
||||||
* Return a list of features supported by the current platform.
|
|
||||||
* The array of length ::DISCID_FEATURE_LENGTH should be allocated by the user.
|
|
||||||
* After the call each element of the array is either NULL
|
|
||||||
* or a pointer to a static string.
|
|
||||||
*
|
|
||||||
* \since libdiscid 0.4.0
|
|
||||||
*
|
|
||||||
* @param[out] features a static string array of length ::DISCID_FEATURE_LENGTH
|
|
||||||
*/
|
|
||||||
LIBDISCID_API void discid_get_feature_list(
|
|
||||||
char *features[DISCID_FEATURE_LENGTH]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the full version string of this library, including the name.
|
|
||||||
* This can be used for debug output.
|
|
||||||
* Don't use this to test for features, see discid_has_feature().
|
|
||||||
*
|
|
||||||
* \since libdiscid 0.4.0
|
|
||||||
*
|
|
||||||
* @return a string containing the version of libdiscid.
|
|
||||||
*/
|
|
||||||
LIBDISCID_API char *discid_get_version_string(void);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* MUSICBRAINZ_DISC_ID_H */
|
|
@ -1,139 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2006 Matthias Friedrich
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
/*
|
|
||||||
* For internal use only. This header file is not installed.
|
|
||||||
*/
|
|
||||||
#ifndef MUSICBRAINZ_DISC_ID_PRIVATE_H
|
|
||||||
#define MUSICBRAINZ_DISC_ID_PRIVATE_H
|
|
||||||
|
|
||||||
#include "discid/discid.h"
|
|
||||||
|
|
||||||
/* Length of toc string, "xxx+xxx" + 100 tracks 7 bytes each ("+xxxxxx")
|
|
||||||
* The highest possible offset is 90 minutes * 60 seconds/minute * 75 frames/second = 405000.
|
|
||||||
* That is 6 digits plus one plus sign = 7 characters per track.
|
|
||||||
* So 3 + 3 (first and last) + 100*7 (disc length plus 99 tracks) = 706
|
|
||||||
*/
|
|
||||||
#define MB_TOC_STRING_LENGTH (3 + 3 + 100*7)
|
|
||||||
|
|
||||||
/* Length of a MusicBrainz DiscID in bytes (without a trailing '\0'-byte). */
|
|
||||||
#define MB_DISC_ID_LENGTH 32
|
|
||||||
|
|
||||||
/* Length of a FreeDB DiscID in bytes (without a trailing '\0'-byte). */
|
|
||||||
#define FREEDB_DISC_ID_LENGTH 8
|
|
||||||
|
|
||||||
/* The maximum permitted length for an error message (without the '\0'-byte). */
|
|
||||||
#define MB_ERROR_MSG_LENGTH 255
|
|
||||||
|
|
||||||
/* Length of url prefixes */
|
|
||||||
#define MB_URL_PREFIX_LENGTH 300
|
|
||||||
|
|
||||||
/* Maximum length of any url (including query string) */
|
|
||||||
#define MB_MAX_URL_LENGTH (MB_URL_PREFIX_LENGTH + MB_DISC_ID_LENGTH + MB_TOC_STRING_LENGTH)
|
|
||||||
|
|
||||||
/* The URL that can be used for submitting DiscIDs (no parameters yet) */
|
|
||||||
#define MB_SUBMISSION_URL "http://musicbrainz.org/cdtoc/attach"
|
|
||||||
|
|
||||||
/* The URL that can be used for retrieving XML for a CD */
|
|
||||||
#define MB_WEBSERVICE_URL "http://musicbrainz.org/ws/1/release"
|
|
||||||
|
|
||||||
/* Maximum length of a Media Catalogue Number string */
|
|
||||||
#define MCN_STR_LENGTH 13
|
|
||||||
|
|
||||||
/* Maximum length of a ISRC code string */
|
|
||||||
#define ISRC_STR_LENGTH 12
|
|
||||||
|
|
||||||
/* Maximum disc length in frames/sectors
|
|
||||||
* This is already not according to spec, but many players might still work
|
|
||||||
* Spec is 79:59.75 = 360000 + lead-in + lead-out */
|
|
||||||
#define MAX_DISC_LENGTH (90 * 60 * 75)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This data structure represents an audio disc.
|
|
||||||
*
|
|
||||||
* We use fixed length strings here because that way the user doesn't have to
|
|
||||||
* check for memory exhaustion conditions. As soon as the mb_disc object has
|
|
||||||
* been created, all calls returning strings will be successful.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int first_track_num;
|
|
||||||
int last_track_num;
|
|
||||||
int track_offsets[100];
|
|
||||||
char id[MB_DISC_ID_LENGTH+1];
|
|
||||||
char freedb_id[FREEDB_DISC_ID_LENGTH+1];
|
|
||||||
char submission_url[MB_MAX_URL_LENGTH+1];
|
|
||||||
char webservice_url[MB_MAX_URL_LENGTH+1];
|
|
||||||
char toc_string[MB_TOC_STRING_LENGTH+1];
|
|
||||||
char error_msg[MB_ERROR_MSG_LENGTH+1];
|
|
||||||
char isrc[100][ISRC_STR_LENGTH+1];
|
|
||||||
char mcn[MCN_STR_LENGTH+1];
|
|
||||||
int success;
|
|
||||||
} mb_disc_private;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int control;
|
|
||||||
int address;
|
|
||||||
} mb_disc_toc_track;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int first_track_num;
|
|
||||||
int last_track_num;
|
|
||||||
mb_disc_toc_track tracks[100];
|
|
||||||
} mb_disc_toc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function has to be implemented once per operating system.
|
|
||||||
*
|
|
||||||
* The caller guarantees that both the disc and device parameters are
|
|
||||||
* not NULL.
|
|
||||||
*
|
|
||||||
* Implementors have to set mb_disc_private's first_track_num, last_track_num,
|
|
||||||
* and track_offsets attributes. If there is an error, the error_msg attribute
|
|
||||||
* has to be set to a human-readable error message.
|
|
||||||
*
|
|
||||||
* On error, 0 is returned. On success, 1 is returned.
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_read_unportable(mb_disc_private *disc, const char *device, unsigned int features);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This should return the name of the default/preferred CDROM/DVD device
|
|
||||||
* on this operating system. It has to be in a format usable for the second
|
|
||||||
* parameter of mb_disc_read_unportable().
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL char *mb_disc_get_default_device_unportable(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This should return 1 if the feature is supported by the platform
|
|
||||||
* and 0 if not.
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_has_feature_unportable(enum discid_feature feature);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load data to the mb_disc_private structure based on mb_disc_toc.
|
|
||||||
*
|
|
||||||
* On error, 0 is returned. On success, 1 is returned.
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_load_toc(mb_disc_private *disc, mb_disc_toc *toc);
|
|
||||||
|
|
||||||
#endif /* MUSICBRAINZ_DISC_ID_PRIVATE_H */
|
|
@ -1,110 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2000 Robert Kaye
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------*/
|
|
||||||
/*
|
|
||||||
* Program: RFC-822 routines (originally from SMTP)
|
|
||||||
*
|
|
||||||
* Author: Mark Crispin
|
|
||||||
* Networks and Distributed Computing
|
|
||||||
* Computing & Communications
|
|
||||||
* University of Washington
|
|
||||||
* Administration Building, AG-44
|
|
||||||
* Seattle, WA 98195
|
|
||||||
* Internet: MRC@CAC.Washington.EDU
|
|
||||||
*
|
|
||||||
* Date: 27 July 1988
|
|
||||||
* Last Edited: 10 September 1998
|
|
||||||
*
|
|
||||||
* Sponsorship: The original version of this work was developed in the
|
|
||||||
* Symbolic Systems Resources Group of the Knowledge Systems
|
|
||||||
* Laboratory at Stanford University in 1987-88, and was funded
|
|
||||||
* by the Biomedical Research Technology Program of the National
|
|
||||||
* Institutes of Health under grant number RR-00785.
|
|
||||||
*
|
|
||||||
* Original version Copyright 1988 by The Leland Stanford Junior University
|
|
||||||
* Copyright 1998 by the University of Washington
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software and its
|
|
||||||
* documentation for any purpose and without fee is hereby granted, provided
|
|
||||||
* that the above copyright notices appear in all copies and that both the
|
|
||||||
* above copyright notices and this permission notice appear in supporting
|
|
||||||
* documentation, and that the name of the University of Washington or The
|
|
||||||
* Leland Stanford Junior University not be used in advertising or publicity
|
|
||||||
* pertaining to distribution of the software without specific, written prior
|
|
||||||
* permission. This software is made available "as is", and
|
|
||||||
* THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
|
|
||||||
* DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
|
|
||||||
* WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
|
|
||||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
||||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
|
||||||
* CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
/* NOTE: This is not true RFC822 anymore. The use of the characters
|
|
||||||
'/', '+', and '=' is no bueno when the ID will be used as part of a URL.
|
|
||||||
'_', '.', and '-' have been used instead
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Convert binary contents to BASE64
|
|
||||||
* Accepts: source
|
|
||||||
* length of source
|
|
||||||
* pointer to return destination length
|
|
||||||
* Returns: destination as BASE64
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len)
|
|
||||||
{
|
|
||||||
unsigned char *ret,*d;
|
|
||||||
unsigned char *s = (unsigned char *) src;
|
|
||||||
char *v = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
|
|
||||||
unsigned long i = ((srcl + 2) / 3) * 4;
|
|
||||||
*len = i += 2 * ((i / 60) + 1);
|
|
||||||
d = ret = (unsigned char *) malloc ((size_t) ++i);
|
|
||||||
for (i = 0; srcl; s += 3) { /* process tuplets */
|
|
||||||
*d++ = v[s[0] >> 2]; /* byte 1: high 6 bits (1) */
|
|
||||||
/* byte 2: low 2 bits (1), high 4 bits (2) */
|
|
||||||
*d++ = v[((s[0] << 4) + (--srcl ? (s[1] >> 4) : 0)) & 0x3f];
|
|
||||||
/* byte 3: low 4 bits (2), high 2 bits (3) */
|
|
||||||
*d++ = srcl ? v[((s[1] << 2) + (--srcl ? (s[2] >> 6) : 0)) & 0x3f] : '-';
|
|
||||||
/* byte 4: low 6 bits (3) */
|
|
||||||
*d++ = srcl ? v[s[2] & 0x3f] : '-';
|
|
||||||
if (srcl) srcl--; /* count third character if processed */
|
|
||||||
if ((++i) == 15) { /* output 60 characters? */
|
|
||||||
i = 0; /* restart line break count, insert CRLF */
|
|
||||||
*d++ = '\015'; *d++ = '\012';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*d = '\0'; /* tie off string */
|
|
||||||
|
|
||||||
return ret; /* return the resulting string */
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2000 Robert Kaye
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------*/
|
|
||||||
/*
|
|
||||||
* Program: RFC-822 routines (originally from SMTP)
|
|
||||||
*
|
|
||||||
* Author: Mark Crispin
|
|
||||||
* Networks and Distributed Computing
|
|
||||||
* Computing & Communications
|
|
||||||
* University of Washington
|
|
||||||
* Administration Building, AG-44
|
|
||||||
* Seattle, WA 98195
|
|
||||||
* Internet: MRC@CAC.Washington.EDU
|
|
||||||
*
|
|
||||||
* Date: 27 July 1988
|
|
||||||
* Last Edited: 10 September 1998
|
|
||||||
*
|
|
||||||
* Sponsorship: The original version of this work was developed in the
|
|
||||||
* Symbolic Systems Resources Group of the Knowledge Systems
|
|
||||||
* Laboratory at Stanford University in 1987-88, and was funded
|
|
||||||
* by the Biomedical Research Technology Program of the National
|
|
||||||
* Institutes of Health under grant number RR-00785.
|
|
||||||
*
|
|
||||||
* Original version Copyright 1988 by The Leland Stanford Junior University
|
|
||||||
* Copyright 1998 by the University of Washington
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software and its
|
|
||||||
* documentation for any purpose and without fee is hereby granted, provided
|
|
||||||
* that the above copyright notices appear in all copies and that both the
|
|
||||||
* above copyright notices and this permission notice appear in supporting
|
|
||||||
* documentation, and that the name of the University of Washington or The
|
|
||||||
* Leland Stanford Junior University not be used in advertising or publicity
|
|
||||||
* pertaining to distribution of the software without specific, written prior
|
|
||||||
* permission. This software is made available "as is", and
|
|
||||||
* THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
|
|
||||||
* DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
|
|
||||||
* WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
|
|
||||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
||||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
|
||||||
* CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BASE64_H
|
|
||||||
#define BASE64_H
|
|
||||||
|
|
||||||
#include "discid/discid.h" /* for LIBDISCID_INTERNAL */
|
|
||||||
|
|
||||||
LIBDISCID_INTERNAL unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,508 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2006 Matthias Friedrich
|
|
||||||
Copyright (C) 2000 Robert Kaye
|
|
||||||
Copyright (C) 1999 Marc E E van Woerkom
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include "sha1.h"
|
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
#include "discid/discid.h"
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define TRACK_NUM_IS_VALID(disc, i) \
|
|
||||||
( i >= disc->first_track_num && i <= disc->last_track_num )
|
|
||||||
|
|
||||||
|
|
||||||
static void create_disc_id(mb_disc_private *d, char buf[]);
|
|
||||||
static void create_freedb_disc_id(mb_disc_private *d, char buf[]);
|
|
||||||
static char *create_toc_string(mb_disc_private *d, char *sep);
|
|
||||||
static void create_submission_url(mb_disc_private *d, char buf[]);
|
|
||||||
static void create_webservice_url(mb_disc_private *d, char buf[]);
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
*
|
|
||||||
* Implementation of the public interface.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
DiscId *discid_new() {
|
|
||||||
/* initializes everything to zero */
|
|
||||||
return calloc(1, sizeof(mb_disc_private));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void discid_free(DiscId *d) {
|
|
||||||
free(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *discid_get_error_msg(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
|
|
||||||
return disc->error_msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *discid_get_id(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (strlen(disc->id) == 0)
|
|
||||||
create_disc_id(disc, disc->id);
|
|
||||||
|
|
||||||
return disc->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *discid_get_freedb_id(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (strlen(disc->freedb_id) == 0)
|
|
||||||
create_freedb_disc_id(disc, disc->freedb_id);
|
|
||||||
|
|
||||||
return disc->freedb_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *discid_get_toc_string(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert( disc != NULL );
|
|
||||||
assert( disc->success );
|
|
||||||
|
|
||||||
if ( ! disc->success )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ( strlen(disc->toc_string) == 0 ) {
|
|
||||||
char *toc = create_toc_string(disc, " ");
|
|
||||||
if (toc) {
|
|
||||||
memcpy(disc->toc_string, toc, strlen(toc) + 1);
|
|
||||||
free(toc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return disc->toc_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *discid_get_submission_url(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (strlen(disc->submission_url) == 0)
|
|
||||||
create_submission_url(disc, disc->submission_url);
|
|
||||||
|
|
||||||
return disc->submission_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *discid_get_webservice_url(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (strlen(disc->webservice_url) == 0)
|
|
||||||
create_webservice_url(disc, disc->webservice_url);
|
|
||||||
|
|
||||||
return disc->webservice_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
int discid_read(DiscId *d, const char *device) {
|
|
||||||
return discid_read_sparse(d, device, UINT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
int discid_read_sparse(DiscId *d, const char *device, unsigned int features) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
|
|
||||||
if (device == NULL)
|
|
||||||
device = discid_get_default_device();
|
|
||||||
|
|
||||||
assert(device != NULL);
|
|
||||||
|
|
||||||
/* Necessary, because the disc handle could have been used before. */
|
|
||||||
memset(disc, 0, sizeof(mb_disc_private));
|
|
||||||
|
|
||||||
/* pre-read the TOC to reduce "not-ready" problems
|
|
||||||
* See LIB-44 (issues with multi-session discs)
|
|
||||||
*/
|
|
||||||
if (!mb_disc_read_unportable(disc, device, DISCID_FEATURE_READ)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memset(disc, 0, sizeof(mb_disc_private));
|
|
||||||
|
|
||||||
return disc->success = mb_disc_read_unportable(disc, device, features);
|
|
||||||
}
|
|
||||||
|
|
||||||
int discid_put(DiscId *d, int first, int last, int *offsets) {
|
|
||||||
int i, disc_length;
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
|
|
||||||
/* Necessary, because the disc handle could have been used before. */
|
|
||||||
memset(disc, 0, sizeof(mb_disc_private));
|
|
||||||
|
|
||||||
/* extensive checking of given parameters */
|
|
||||||
if (first > last || first < 1
|
|
||||||
|| first > 99 || last < 1 || last > 99) {
|
|
||||||
|
|
||||||
sprintf(disc->error_msg, "Illegal track limits");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (offsets == NULL) {
|
|
||||||
sprintf(disc->error_msg, "No offsets given");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
disc_length = offsets[0];
|
|
||||||
if (disc_length > MAX_DISC_LENGTH) {
|
|
||||||
sprintf(disc->error_msg, "Disc too long");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
for (i = 0; i <= last; i++) {
|
|
||||||
if (offsets[i] > disc_length) {
|
|
||||||
sprintf(disc->error_msg, "Invalid offset");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (i > 1 && offsets[i-1] > offsets[i]) {
|
|
||||||
sprintf(disc->error_msg, "Invalid order");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
disc->first_track_num = first;
|
|
||||||
disc->last_track_num = last;
|
|
||||||
|
|
||||||
memcpy(disc->track_offsets, offsets, sizeof(int) * (last+1));
|
|
||||||
|
|
||||||
disc->success = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *discid_get_default_device(void) {
|
|
||||||
return mb_disc_get_default_device_unportable();
|
|
||||||
}
|
|
||||||
|
|
||||||
int discid_get_first_track_num(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return disc->first_track_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int discid_get_last_track_num(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return disc->last_track_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int discid_get_sectors(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return disc->track_offsets[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int discid_get_track_offset(DiscId *d, int i) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
assert(TRACK_NUM_IS_VALID(disc, i));
|
|
||||||
|
|
||||||
if (!disc->success || !TRACK_NUM_IS_VALID(disc, i))
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return disc->track_offsets[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int discid_get_track_length(DiscId *d, int i) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
assert(TRACK_NUM_IS_VALID(disc, i));
|
|
||||||
|
|
||||||
if (!disc->success || !TRACK_NUM_IS_VALID(disc, i))
|
|
||||||
return -1;
|
|
||||||
else if (i < disc->last_track_num)
|
|
||||||
return disc->track_offsets[i+1] - disc->track_offsets[i];
|
|
||||||
else
|
|
||||||
return disc->track_offsets[0] - disc->track_offsets[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
char *discid_get_mcn(DiscId *d) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
|
|
||||||
if (!disc->success)
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return disc->mcn;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* discid_get_track_isrc(DiscId *d, int i) {
|
|
||||||
mb_disc_private *disc = (mb_disc_private *) d;
|
|
||||||
assert(disc != NULL);
|
|
||||||
assert(disc->success);
|
|
||||||
assert(TRACK_NUM_IS_VALID(disc, i));
|
|
||||||
|
|
||||||
if (!disc->success || i == 0 || !TRACK_NUM_IS_VALID(disc, i))
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return disc->isrc[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
int discid_has_feature(enum discid_feature feature) {
|
|
||||||
return mb_disc_has_feature_unportable(feature);
|
|
||||||
}
|
|
||||||
|
|
||||||
void discid_get_feature_list(char *features[DISCID_FEATURE_LENGTH]) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* for the code, the parameter is actually only a pointer */
|
|
||||||
memset(features, 0, sizeof(char *) * DISCID_FEATURE_LENGTH);
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
if (discid_has_feature(DISCID_FEATURE_READ)) {
|
|
||||||
features[i++] = DISCID_FEATURE_STR_READ;
|
|
||||||
}
|
|
||||||
if (discid_has_feature(DISCID_FEATURE_MCN)) {
|
|
||||||
features[i++] = DISCID_FEATURE_STR_MCN;
|
|
||||||
}
|
|
||||||
if (discid_has_feature(DISCID_FEATURE_ISRC)) {
|
|
||||||
features[i++] = DISCID_FEATURE_STR_ISRC;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *discid_get_version_string(void) {
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
return PACKAGE_STRING;
|
|
||||||
#else
|
|
||||||
return "";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
*
|
|
||||||
* Private utilities, not exported.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a DiscID based on the TOC data found in the DiscId object.
|
|
||||||
* The DiscID is placed in the provided string buffer.
|
|
||||||
*/
|
|
||||||
static void create_disc_id(mb_disc_private *d, char buf[]) {
|
|
||||||
SHA_INFO sha;
|
|
||||||
unsigned char digest[20], *base64;
|
|
||||||
unsigned long size;
|
|
||||||
char tmp[17]; /* for 8 hex digits (16 to avoid trouble) */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
assert(d != NULL);
|
|
||||||
assert(d->success);
|
|
||||||
|
|
||||||
sha_init(&sha);
|
|
||||||
|
|
||||||
sprintf(tmp, "%02X", d->first_track_num);
|
|
||||||
sha_update(&sha, (unsigned char *) tmp, strlen(tmp));
|
|
||||||
|
|
||||||
sprintf(tmp, "%02X", d->last_track_num);
|
|
||||||
sha_update(&sha, (unsigned char *) tmp, strlen(tmp));
|
|
||||||
|
|
||||||
for (i = 0; i < 100; i++) {
|
|
||||||
sprintf(tmp, "%08X", d->track_offsets[i]);
|
|
||||||
sha_update(&sha, (unsigned char *) tmp, strlen(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
sha_final(digest, &sha);
|
|
||||||
|
|
||||||
base64 = rfc822_binary(digest, sizeof(digest), &size);
|
|
||||||
|
|
||||||
memcpy(buf, base64, size);
|
|
||||||
buf[size] = '\0';
|
|
||||||
|
|
||||||
free(base64);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a FreeDB DiscID based on the TOC data found in the DiscId object.
|
|
||||||
* The DiscID is placed in the provided string buffer.
|
|
||||||
*/
|
|
||||||
static void create_freedb_disc_id(mb_disc_private *d, char buf[]) {
|
|
||||||
int i, n, m, t;
|
|
||||||
|
|
||||||
assert(d != NULL);
|
|
||||||
assert(d->success);
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
for (i = 0; i < d->last_track_num; i++) {
|
|
||||||
m = d->track_offsets[i + 1] / 75;
|
|
||||||
while (m > 0) {
|
|
||||||
n += m % 10;
|
|
||||||
m /= 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t = d->track_offsets[0] / 75 - d->track_offsets[1] / 75;
|
|
||||||
sprintf(buf, "%08x", ((n % 0xff) << 24 | t << 8 | d->last_track_num));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a string based on the TOC data found in the mb_disc_private
|
|
||||||
* object. The returned string is allocated, caller has to free() it.
|
|
||||||
* On failure, it returns NULL.
|
|
||||||
*
|
|
||||||
* Format is:
|
|
||||||
* [1st track num][sep][last track num][sep][length in sectors][sep][1st track offset][sep]...
|
|
||||||
*/
|
|
||||||
static char *create_toc_string(mb_disc_private *d, char *sep) {
|
|
||||||
char tmp[16];
|
|
||||||
char *toc;
|
|
||||||
int i, size;
|
|
||||||
|
|
||||||
assert( d != NULL );
|
|
||||||
|
|
||||||
/* number of tracks */
|
|
||||||
size = 1 + d->last_track_num - d->first_track_num;
|
|
||||||
/* first&last track num and total length */
|
|
||||||
size += 3;
|
|
||||||
/* number + separator */
|
|
||||||
size *= (6 + strlen(sep));
|
|
||||||
/* nul */
|
|
||||||
size++;
|
|
||||||
|
|
||||||
toc = calloc(size, sizeof(char));
|
|
||||||
if (!toc) return NULL;
|
|
||||||
|
|
||||||
sprintf(toc, "%d%s%d%s%d",
|
|
||||||
d->first_track_num,
|
|
||||||
sep,
|
|
||||||
d->last_track_num,
|
|
||||||
sep,
|
|
||||||
d->track_offsets[0]);
|
|
||||||
|
|
||||||
for (i = d->first_track_num; i <= d->last_track_num; i++) {
|
|
||||||
sprintf(tmp, "%s%d", sep, d->track_offsets[i]);
|
|
||||||
strcat(toc, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return toc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append &toc=... to buf, calling create_toc_string() */
|
|
||||||
static void cat_toc_param(mb_disc_private *d, char *buf) {
|
|
||||||
char *toc = create_toc_string(d, "+");
|
|
||||||
if (toc) {
|
|
||||||
strcat(buf, "&toc=");
|
|
||||||
strcat(buf, toc);
|
|
||||||
free(toc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a submission URL based on the TOC data found in the mb_disc_private
|
|
||||||
* object. The URL is placed in the provided string buffer.
|
|
||||||
*/
|
|
||||||
static void create_submission_url(mb_disc_private *d, char buf[]) {
|
|
||||||
char tmp[16];
|
|
||||||
|
|
||||||
assert(d != NULL);
|
|
||||||
assert(d->success);
|
|
||||||
|
|
||||||
strcpy(buf, MB_SUBMISSION_URL);
|
|
||||||
|
|
||||||
strcat(buf, "?id=");
|
|
||||||
strcat(buf, discid_get_id((DiscId *) d));
|
|
||||||
|
|
||||||
sprintf(tmp, "&tracks=%d", d->last_track_num);
|
|
||||||
strcat(buf, tmp);
|
|
||||||
|
|
||||||
cat_toc_param(d, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a web service URL based on the TOC data found in the mb_disc_private
|
|
||||||
* object. The URL is placed in the provided string buffer.
|
|
||||||
*/
|
|
||||||
static void create_webservice_url(mb_disc_private *d, char buf[]) {
|
|
||||||
assert(d != NULL);
|
|
||||||
assert(d->success);
|
|
||||||
|
|
||||||
strcpy(buf, MB_WEBSERVICE_URL);
|
|
||||||
|
|
||||||
strcat(buf, "?type=xml&discid=");
|
|
||||||
strcat(buf, discid_get_id((DiscId *) d));
|
|
||||||
|
|
||||||
cat_toc_param(d, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
@ -1,194 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2008 Patrick Hurrelmann
|
|
||||||
Copyright (C) 2006 Matthias Friedrich
|
|
||||||
Copyright (C) 2000 Robert Kaye
|
|
||||||
Copyright (C) 1999 Marc E E van Woerkom
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/cdio.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
|
||||||
#include <netinet/in.h> /* for ntohl() */
|
|
||||||
#else
|
|
||||||
#include <util.h> /* for getrawpartition() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
#include "unix.h"
|
|
||||||
|
|
||||||
#define MAX_DEV_LEN 15
|
|
||||||
|
|
||||||
static int get_device(int n, char* device_name, size_t device_name_length) {
|
|
||||||
#if !defined(__FreeBSD__) /* /dev/rcdNX, where X is the letter for the raw partition */
|
|
||||||
snprintf(device_name, device_name_length, "/dev/rcd%d%c", n - 1, 'a' + getrawpartition());
|
|
||||||
#else /* on FreeBSD it's just /dev/cdN */
|
|
||||||
snprintf(device_name, device_name_length, "/dev/cd%d", n - 1);
|
|
||||||
#endif
|
|
||||||
return mb_disc_unix_exists(device_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) {
|
|
||||||
struct ioc_toc_header th;
|
|
||||||
struct cd_toc_entry te[100];
|
|
||||||
struct ioc_read_toc_entry rte;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
memset(&th, 0, sizeof th);
|
|
||||||
if (ioctl(fd, CDIOREADTOCHEADER, &th) < 0)
|
|
||||||
return 0; /* error */
|
|
||||||
|
|
||||||
toc->first_track_num = th.starting_track;
|
|
||||||
toc->last_track_num = th.ending_track;
|
|
||||||
|
|
||||||
if (toc->last_track_num == 0)
|
|
||||||
return 1; /* no entries to read */
|
|
||||||
|
|
||||||
/* Read all the TOC entries in one icotl() call */
|
|
||||||
|
|
||||||
memset(&te, 0, sizeof te);
|
|
||||||
memset(&rte, 0, sizeof rte);
|
|
||||||
rte.address_format = CD_LBA_FORMAT;
|
|
||||||
rte.data = &te[0];
|
|
||||||
rte.data_len = sizeof te;
|
|
||||||
rte.starting_track = toc->first_track_num;
|
|
||||||
|
|
||||||
if (ioctl(fd, CDIOREADTOCENTRYS, &rte) < 0)
|
|
||||||
return 0; /* error */
|
|
||||||
|
|
||||||
for (i = toc->first_track_num; i <= toc->last_track_num; ++i) {
|
|
||||||
assert(te[i - toc->first_track_num].track == i);
|
|
||||||
#if defined(__FreeBSD__) /* LBA address is in network byte order */
|
|
||||||
toc->tracks[i].address = ntohl(te[i - toc->first_track_num].addr.lba);
|
|
||||||
#else
|
|
||||||
toc->tracks[i].address = te[i - toc->first_track_num].addr.lba;
|
|
||||||
#endif
|
|
||||||
toc->tracks[i].control = te[i - toc->first_track_num].control;
|
|
||||||
}
|
|
||||||
/* leadout - track number 170 (0xAA) */
|
|
||||||
assert(te[i - toc->first_track_num].track == 0xAA);
|
|
||||||
#if defined(__FreeBSD__) /* LBA address is in network byte order */
|
|
||||||
toc->tracks[0].address = ntohl(te[i - toc->first_track_num].addr.lba);
|
|
||||||
#else
|
|
||||||
toc->tracks[0].address = te[i - toc->first_track_num].addr.lba;
|
|
||||||
#endif
|
|
||||||
toc->tracks[0].control = te[i - toc->first_track_num].control;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) {
|
|
||||||
/* All TOC entries were already read by mb_disc_unix_read_toc_header() */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) {
|
|
||||||
struct cd_sub_channel_info sci;
|
|
||||||
struct ioc_read_subchannel rsc;
|
|
||||||
|
|
||||||
memset(&sci, 0, sizeof sci);
|
|
||||||
memset(&rsc, 0, sizeof rsc);
|
|
||||||
rsc.address_format = CD_LBA_FORMAT; /* not technically relevant */
|
|
||||||
rsc.data_format = CD_MEDIA_CATALOG;
|
|
||||||
rsc.data_len = sizeof sci;
|
|
||||||
rsc.data = &sci;
|
|
||||||
|
|
||||||
if ( ioctl(fd, CDIOCREADSUBCHANNEL, &rsc) < 0 )
|
|
||||||
perror ("Warning: Unable to read the disc's media catalog number");
|
|
||||||
else {
|
|
||||||
if (sci.what.media_catalog.mc_valid)
|
|
||||||
strncpy( disc->mcn,
|
|
||||||
(const char *) sci.what.media_catalog.mc_number,
|
|
||||||
MCN_STR_LENGTH );
|
|
||||||
else
|
|
||||||
memset( disc->mcn, 0, MCN_STR_LENGTH );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) {
|
|
||||||
struct cd_sub_channel_info sci;
|
|
||||||
struct ioc_read_subchannel rsc;
|
|
||||||
|
|
||||||
memset(&sci, 0, sizeof sci);
|
|
||||||
memset(&rsc, 0, sizeof rsc);
|
|
||||||
rsc.address_format = CD_LBA_FORMAT; /* not technically relevant */
|
|
||||||
rsc.data_format = CD_TRACK_INFO;
|
|
||||||
rsc.track = track_num;
|
|
||||||
rsc.data_len = sizeof sci;
|
|
||||||
rsc.data = &sci;
|
|
||||||
|
|
||||||
if ( ioctl(fd, CDIOCREADSUBCHANNEL, &rsc) < 0 )
|
|
||||||
perror ("Warning: Unable to read track info (ISRC)");
|
|
||||||
else {
|
|
||||||
if (sci.what.track_info.ti_valid)
|
|
||||||
strncpy( disc->isrc[track_num],
|
|
||||||
(const char *) sci.what.track_info.ti_number,
|
|
||||||
ISRC_STR_LENGTH );
|
|
||||||
else
|
|
||||||
memset( disc->isrc[track_num], 0, ISRC_STR_LENGTH );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
|
||||||
switch(feature) {
|
|
||||||
case DISCID_FEATURE_READ:
|
|
||||||
case DISCID_FEATURE_MCN:
|
|
||||||
case DISCID_FEATURE_ISRC:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
|
||||||
unsigned int features) {
|
|
||||||
char device_name[MAX_DEV_LEN] = "";
|
|
||||||
int device_number;
|
|
||||||
|
|
||||||
device_number = (int) strtol(device, NULL, 10);
|
|
||||||
|
|
||||||
if (device_number > 0) {
|
|
||||||
if(!get_device(device_number, device_name, MAX_DEV_LEN)) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot find cd device with the number '%d'",
|
|
||||||
device_number);
|
|
||||||
return 0; /* error */
|
|
||||||
}
|
|
||||||
device = device_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mb_disc_unix_read(disc, device, features);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *mb_disc_get_default_device_unportable(void) {
|
|
||||||
static char result[MAX_DEV_LEN + 1];
|
|
||||||
/* No error check here, so we always return the appropriate device for cd0 */
|
|
||||||
get_device(1, result, sizeof result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
@ -1,242 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2013 Johannes Dewender
|
|
||||||
Copyright (C) 2006 Robert Kaye
|
|
||||||
Copyright (C) 1999 Marc E E van Woerkom
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <paths.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
#include <IOKit/IOKitLib.h>
|
|
||||||
#include <IOKit/IOBSD.h>
|
|
||||||
#include <IOKit/storage/IOCDBlockStorageDevice.h>
|
|
||||||
#include <IOKit/storage/IOCDMediaBSDClient.h>
|
|
||||||
|
|
||||||
#include "discid/discid.h"
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
#include "unix.h"
|
|
||||||
|
|
||||||
#define MB_DEFAULT_DEVICE "1" /* first disc drive (empty or not) */
|
|
||||||
#define TOC_BUFFER_LEN 2048
|
|
||||||
|
|
||||||
|
|
||||||
static int find_cd_block_devices(io_iterator_t *device_iterator)
|
|
||||||
{
|
|
||||||
mach_port_t master_port;
|
|
||||||
CFMutableDictionaryRef matching_dictionary;
|
|
||||||
|
|
||||||
if (IOMasterPort(MACH_PORT_NULL, &master_port) != KERN_SUCCESS)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
matching_dictionary = IOServiceMatching(kIOCDBlockStorageDeviceClass);
|
|
||||||
|
|
||||||
if (IOServiceGetMatchingServices(master_port, matching_dictionary,
|
|
||||||
device_iterator) != KERN_SUCCESS)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_device_from_entry(io_registry_entry_t entry,
|
|
||||||
char *device_path, int max_len)
|
|
||||||
{
|
|
||||||
int return_value = 0;
|
|
||||||
size_t dev_path_len;;
|
|
||||||
CFStringRef cf_device_name;;
|
|
||||||
*device_path = '\0';
|
|
||||||
|
|
||||||
cf_device_name = IORegistryEntrySearchCFProperty(entry,
|
|
||||||
kIOServicePlane, CFSTR(kIOBSDNameKey),
|
|
||||||
kCFAllocatorDefault, kIORegistryIterateRecursively);
|
|
||||||
|
|
||||||
if (cf_device_name) {
|
|
||||||
strcpy(device_path, _PATH_DEV);
|
|
||||||
/* Add "r" before the device name to use the raw disk node
|
|
||||||
* without the buffering cache. */
|
|
||||||
strcat(device_path, "r");
|
|
||||||
dev_path_len = strlen(device_path);
|
|
||||||
if (CFStringGetCString(cf_device_name,
|
|
||||||
device_path + dev_path_len,
|
|
||||||
max_len - dev_path_len - 1,
|
|
||||||
kCFStringEncodingASCII))
|
|
||||||
return_value = 1;
|
|
||||||
|
|
||||||
CFRelease(cf_device_name);
|
|
||||||
}
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_device_from_number(int device_number,
|
|
||||||
char * buffer, int buffer_len) {
|
|
||||||
int return_value = 0;
|
|
||||||
int index = 0;
|
|
||||||
io_iterator_t device_iterator;
|
|
||||||
io_object_t device_object = IO_OBJECT_NULL;
|
|
||||||
|
|
||||||
if (!find_cd_block_devices(&device_iterator))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (index < device_number
|
|
||||||
&& (device_object = IOIteratorNext(device_iterator)))
|
|
||||||
index++;
|
|
||||||
|
|
||||||
if (index != device_number) {
|
|
||||||
return_value = 0;
|
|
||||||
} else {
|
|
||||||
return_value = get_device_from_entry(device_object,
|
|
||||||
buffer, buffer_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
IOObjectRelease(device_object);
|
|
||||||
IOObjectRelease(device_iterator);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc)
|
|
||||||
{
|
|
||||||
dk_cd_read_mcn_t cd_read_mcn;
|
|
||||||
bzero(&cd_read_mcn, sizeof(cd_read_mcn));
|
|
||||||
|
|
||||||
if(ioctl(fd, DKIOCCDREADMCN, &cd_read_mcn) == -1) {
|
|
||||||
fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n");
|
|
||||||
} else {
|
|
||||||
strncpy( disc->mcn, cd_read_mcn.mcn, MCN_STR_LENGTH );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track)
|
|
||||||
{
|
|
||||||
dk_cd_read_isrc_t cd_read_isrc;
|
|
||||||
bzero(&cd_read_isrc, sizeof(cd_read_isrc));
|
|
||||||
cd_read_isrc.track = track;
|
|
||||||
|
|
||||||
if(ioctl(fd, DKIOCCDREADISRC, &cd_read_isrc) == -1) {
|
|
||||||
fprintf(stderr, "Warning: Unable to read the international standard recording code (ISRC) for track %i\n", track);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
strncpy( disc->isrc[track], cd_read_isrc.isrc, ISRC_STR_LENGTH );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
|
||||||
switch(feature) {
|
|
||||||
case DISCID_FEATURE_READ:
|
|
||||||
case DISCID_FEATURE_MCN:
|
|
||||||
case DISCID_FEATURE_ISRC:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *mb_disc_get_default_device_unportable(void)
|
|
||||||
{
|
|
||||||
return MB_DEFAULT_DEVICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *mb_toc) {
|
|
||||||
dk_cd_read_toc_t toc;
|
|
||||||
CDTOC *cdToc;
|
|
||||||
mb_disc_toc_track *track;
|
|
||||||
int i, numDesc;
|
|
||||||
int track_num, min_track, max_track;
|
|
||||||
|
|
||||||
memset(&toc, 0, sizeof(toc));
|
|
||||||
toc.format = kCDTOCFormatTOC;
|
|
||||||
toc.formatAsTime = 0;
|
|
||||||
toc.buffer = (char *)malloc(TOC_BUFFER_LEN);
|
|
||||||
toc.bufferLength = TOC_BUFFER_LEN;
|
|
||||||
if (ioctl(fd, DKIOCCDREADTOC, &toc) < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (toc.bufferLength < sizeof(CDTOC)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cdToc = (CDTOC *)toc.buffer;
|
|
||||||
numDesc = CDTOCGetDescriptorCount(cdToc);
|
|
||||||
min_track = -1;
|
|
||||||
max_track = -1;
|
|
||||||
for(i = 0; i < numDesc; i++) {
|
|
||||||
CDTOCDescriptor *desc = &cdToc->descriptors[i];
|
|
||||||
track = NULL;
|
|
||||||
|
|
||||||
/* A2 is the code for the lead-out position in the lead-in */
|
|
||||||
if (desc->point == 0xA2 && desc->adr == 1) {
|
|
||||||
track = &mb_toc->tracks[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* actual track data, (adr 2-3 are for MCN and ISRC data) */
|
|
||||||
if (desc->point <= 99 && desc->adr == 1) {
|
|
||||||
track_num = desc->point;
|
|
||||||
track = &mb_toc->tracks[track_num];
|
|
||||||
if (min_track < 0 || min_track > track_num) {
|
|
||||||
min_track = track_num;
|
|
||||||
}
|
|
||||||
if (max_track < track_num) {
|
|
||||||
max_track = track_num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (track) {
|
|
||||||
track->address = CDConvertMSFToLBA(desc->p);
|
|
||||||
track->control = desc->control;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mb_toc->first_track_num = min_track;
|
|
||||||
mb_toc->last_track_num = max_track;
|
|
||||||
|
|
||||||
free(toc.buffer);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *toc) {
|
|
||||||
/* On Darwin the tracks are already filled along with the header */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
|
||||||
unsigned int features) {
|
|
||||||
int device_number;
|
|
||||||
char device_name[MAXPATHLEN] = "\0";
|
|
||||||
|
|
||||||
device_number = (int) strtol(device, NULL, 10);
|
|
||||||
if (device_number > 0) {
|
|
||||||
if (!get_device_from_number(device_number,
|
|
||||||
device_name, MAXPATHLEN)) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"no disc in drive number: %d", device_number);
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return mb_disc_unix_read(disc, device_name, features);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return mb_disc_unix_read(disc, device, features);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2013 Johannes Dewender
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "discid/discid.h"
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
|
|
||||||
|
|
||||||
char *mb_disc_get_default_device_unportable(void) {
|
|
||||||
return "/dev/null";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device, unsigned int features) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"disc reading not implemented on this platform");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
@ -1,275 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2013 Johannes Dewender
|
|
||||||
Copyright (C) 2006 Matthias Friedrich
|
|
||||||
Copyright (C) 2000 Robert Kaye
|
|
||||||
Copyright (C) 1999 Marc E E van Woerkom
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <linux/cdrom.h>
|
|
||||||
#include <scsi/sg.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "discid/discid.h"
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
#include "unix.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* timeout better shouldn't happen for scsi commands -> device is reset */
|
|
||||||
#define DEFAULT_TIMEOUT 30000 /* in ms */
|
|
||||||
|
|
||||||
#ifndef SG_MAX_SENSE
|
|
||||||
#define SG_MAX_SENSE 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MB_DEFAULT_DEVICE "/dev/cdrom"
|
|
||||||
#define MAX_DEV_LEN 50
|
|
||||||
|
|
||||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
|
||||||
# define THREAD_LOCAL __thread
|
|
||||||
#else
|
|
||||||
# define THREAD_LOCAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static THREAD_LOCAL char default_device[MAX_DEV_LEN] = "";
|
|
||||||
|
|
||||||
|
|
||||||
static int get_device(int number, char *device, int device_len) {
|
|
||||||
FILE *proc_file;
|
|
||||||
char *current_device;
|
|
||||||
char *lineptr = NULL;
|
|
||||||
char *saveptr = NULL;
|
|
||||||
size_t bufflen;
|
|
||||||
int i, count, counter;
|
|
||||||
int return_value = 0;
|
|
||||||
|
|
||||||
proc_file = fopen("/proc/sys/dev/cdrom/info", "r");
|
|
||||||
if (proc_file != NULL) {
|
|
||||||
/* skip to line containing device names */
|
|
||||||
do {
|
|
||||||
if (getline(&lineptr, &bufflen, proc_file) < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} while (strstr(lineptr, "drive name:") == NULL);
|
|
||||||
|
|
||||||
/* count number of devices = number of tabs - 1*/
|
|
||||||
count = -1;
|
|
||||||
for (i = 0; i < strlen(lineptr); i++) {
|
|
||||||
if (lineptr[i] == '\t') count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* go through devices, they are in reverse order */
|
|
||||||
current_device = strtok_r(lineptr, "\t", &saveptr);
|
|
||||||
/* skip column title */
|
|
||||||
current_device = strtok_r(NULL, "\t", &saveptr);
|
|
||||||
counter = count;
|
|
||||||
while (current_device != NULL && counter >= number) {
|
|
||||||
if (counter == number) {
|
|
||||||
snprintf(device, device_len,
|
|
||||||
"/dev/%s", current_device);
|
|
||||||
return_value = 1;
|
|
||||||
}
|
|
||||||
/* go to next in list */
|
|
||||||
current_device = strtok_r(NULL, "\t", &saveptr);
|
|
||||||
counter--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* trim the trailing \n for the last entry = first device */
|
|
||||||
if (return_value && device[strlen(device)-1] == '\n') {
|
|
||||||
device[strlen(device)-1] = '\0';
|
|
||||||
}
|
|
||||||
free(lineptr);
|
|
||||||
fclose(proc_file);
|
|
||||||
}
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) {
|
|
||||||
struct cdrom_tochdr th;
|
|
||||||
|
|
||||||
int ret = ioctl(fd, CDROMREADTOCHDR, &th);
|
|
||||||
|
|
||||||
if ( ret < 0 )
|
|
||||||
return 0; /* error */
|
|
||||||
|
|
||||||
toc->first_track_num = th.cdth_trk0;
|
|
||||||
toc->last_track_num = th.cdth_trk1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) {
|
|
||||||
struct cdrom_tocentry te;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
te.cdte_track = track_num;
|
|
||||||
te.cdte_format = CDROM_LBA;
|
|
||||||
|
|
||||||
ret = ioctl(fd, CDROMREADTOCENTRY, &te);
|
|
||||||
assert( te.cdte_format == CDROM_LBA );
|
|
||||||
|
|
||||||
if ( ret < 0 )
|
|
||||||
return 0; /* error */
|
|
||||||
|
|
||||||
track->address = te.cdte_addr.lba;
|
|
||||||
track->control = te.cdte_ctrl;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *mb_disc_get_default_device_unportable(void) {
|
|
||||||
/* prefer the default device symlink to the internal names */
|
|
||||||
if (mb_disc_unix_exists(MB_DEFAULT_DEVICE)) {
|
|
||||||
return MB_DEFAULT_DEVICE;
|
|
||||||
} else {
|
|
||||||
if (get_device(1, default_device, MAX_DEV_LEN)) {
|
|
||||||
return default_device;
|
|
||||||
} else {
|
|
||||||
return MB_DEFAULT_DEVICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) {
|
|
||||||
struct cdrom_mcn mcn;
|
|
||||||
memset(&mcn, 0, sizeof mcn);
|
|
||||||
|
|
||||||
if(ioctl(fd, CDROM_GET_MCN, &mcn) == -1) {
|
|
||||||
fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n");
|
|
||||||
} else {
|
|
||||||
strncpy( disc->mcn,
|
|
||||||
(const char *)mcn.medium_catalog_number,
|
|
||||||
MCN_STR_LENGTH );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a scsi command and receive data. */
|
|
||||||
static int scsi_cmd(int fd, unsigned char *cmd, int cmd_len,
|
|
||||||
unsigned char *data, int data_len) {
|
|
||||||
unsigned char sense_buffer[SG_MAX_SENSE]; /* for "error situations" */
|
|
||||||
sg_io_hdr_t io_hdr;
|
|
||||||
|
|
||||||
memset(&io_hdr, 0, sizeof io_hdr);
|
|
||||||
|
|
||||||
assert(cmd_len <= 16);
|
|
||||||
|
|
||||||
io_hdr.interface_id = 'S'; /* must always be 'S' (SCSI generic) */
|
|
||||||
io_hdr.cmd_len = cmd_len;
|
|
||||||
io_hdr.cmdp = cmd;
|
|
||||||
io_hdr.timeout = DEFAULT_TIMEOUT; /* timeout in ms */
|
|
||||||
io_hdr.sbp = sense_buffer;/* only used when status is CHECK_CONDITION */
|
|
||||||
io_hdr.mx_sb_len = sizeof sense_buffer;
|
|
||||||
io_hdr.flags = SG_FLAG_DIRECT_IO;
|
|
||||||
|
|
||||||
io_hdr.dxferp = (void*)data;
|
|
||||||
io_hdr.dxfer_len = data_len;
|
|
||||||
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
|
||||||
|
|
||||||
if (ioctl(fd, SG_IO, &io_hdr) != 0) {
|
|
||||||
return errno;
|
|
||||||
} else {
|
|
||||||
return io_hdr.status; /* 0 = success */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) {
|
|
||||||
int i;
|
|
||||||
unsigned char cmd[10];
|
|
||||||
unsigned char data[24];
|
|
||||||
char buffer[ISRC_STR_LENGTH+1];
|
|
||||||
|
|
||||||
memset(cmd, 0, sizeof cmd);
|
|
||||||
memset(data, 0, sizeof data);
|
|
||||||
memset(buffer, 0, sizeof buffer);
|
|
||||||
|
|
||||||
/* data read from the last appropriate sector encountered
|
|
||||||
* by a current or previous media access operation.
|
|
||||||
* The Logical Unit accesses the media when there is/was no access.
|
|
||||||
* TODO: force access at a specific block? -> no duplicate ISRCs?
|
|
||||||
*/
|
|
||||||
cmd[0] = 0x42; /* READ SUB-CHANNEL */
|
|
||||||
/* cmd[1] reserved / MSF bit (unused) */
|
|
||||||
cmd[2] = 1 << 6; /* 6th bit set (SUBQ) -> get sub-channel data */
|
|
||||||
cmd[3] = 0x03; /* get ISRC (ADR 3, Q sub-channel Mode-3) */
|
|
||||||
/* 4+5 reserved */
|
|
||||||
cmd[6] = track_num;
|
|
||||||
/* cmd[7] = upper byte of the transfer length */
|
|
||||||
cmd[8] = sizeof data; /* transfer length in bytes (4 header, 20 data)*/
|
|
||||||
/* cmd[9] = control byte */
|
|
||||||
|
|
||||||
if (scsi_cmd(fd, cmd, sizeof cmd, data, sizeof data) != 0) {
|
|
||||||
fprintf(stderr, "Warning: Cannot get ISRC code for track %d\n",
|
|
||||||
track_num);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* data[1:4] = sub-q channel data header (audio status, data length) */
|
|
||||||
if (data[8] & (1 << 7)) { /* TCVAL is set -> ISRCs valid */
|
|
||||||
for (i = 0; i < ISRC_STR_LENGTH; i++) {
|
|
||||||
buffer[i] = data[9 + i];
|
|
||||||
}
|
|
||||||
buffer[ISRC_STR_LENGTH] = 0;
|
|
||||||
strncpy(disc->isrc[track_num], buffer, ISRC_STR_LENGTH);
|
|
||||||
}
|
|
||||||
/* data[21:23] = zero, AFRAME, reserved */
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
|
||||||
switch(feature) {
|
|
||||||
case DISCID_FEATURE_READ:
|
|
||||||
case DISCID_FEATURE_MCN:
|
|
||||||
case DISCID_FEATURE_ISRC:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
|
||||||
unsigned int features) {
|
|
||||||
char device_name[MAX_DEV_LEN] = "";
|
|
||||||
int device_number;
|
|
||||||
|
|
||||||
device_number = (int) strtol(device, NULL, 10);
|
|
||||||
if (device_number > 0) {
|
|
||||||
if(!get_device(device_number, device_name, MAX_DEV_LEN)) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot find cd device with the number '%d'",
|
|
||||||
device_number);
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return mb_disc_unix_read(disc, device_name, features);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return mb_disc_unix_read(disc, device, features);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
@ -1,108 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2009 Shunsuke Kuroda
|
|
||||||
Copyright (C) 2006 Matthias Friedrich
|
|
||||||
Copyright (C) 2000 Robert Kaye
|
|
||||||
Copyright (C) 1999 Marc E E van Woerkom
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/cdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "discid/discid.h"
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
#include "unix.h"
|
|
||||||
|
|
||||||
#define NUM_CANDIDATES 2
|
|
||||||
|
|
||||||
static char *device_candidates[NUM_CANDIDATES] = {"/vol/dev/aliases/cdrom0",
|
|
||||||
"/volumes/dev/aliases/cdrom0"};
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc) {
|
|
||||||
struct cdrom_tochdr th;
|
|
||||||
|
|
||||||
int ret = ioctl(fd, CDROMREADTOCHDR, &th);
|
|
||||||
|
|
||||||
if ( ret < 0 )
|
|
||||||
return ret; /* error */
|
|
||||||
|
|
||||||
toc->first_track_num = th.cdth_trk0;
|
|
||||||
toc->last_track_num = th.cdth_trk1;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc_entry(int fd, int track_num, mb_disc_toc_track *track) {
|
|
||||||
struct cdrom_tocentry te;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
memset(&te, 0, sizeof te);
|
|
||||||
te.cdte_track = track_num;
|
|
||||||
te.cdte_format = CDROM_LBA;
|
|
||||||
|
|
||||||
ret = ioctl(fd, CDROMREADTOCENTRY, &te);
|
|
||||||
|
|
||||||
if ( ret < 0 )
|
|
||||||
return 0; /* error */
|
|
||||||
|
|
||||||
assert( te.cdte_format == CDROM_LBA );
|
|
||||||
track->address = te.cdte_addr.lba;
|
|
||||||
track->control = te.cdte_ctrl;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc, int track_num) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *mb_disc_get_default_device_unportable(void) {
|
|
||||||
return mb_disc_unix_find_device(device_candidates, NUM_CANDIDATES);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
|
||||||
switch(feature) {
|
|
||||||
case DISCID_FEATURE_READ:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
|
||||||
unsigned int features) {
|
|
||||||
return mb_disc_unix_read(disc, device, features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
@ -1,247 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2007-2008 Lukas Lalinsky
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#if (_MSC_VER < 1900)
|
|
||||||
#define snprintf _snprintf
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined(__CYGWIN__)
|
|
||||||
#include <ntddcdrm.h>
|
|
||||||
#elif defined(__MINGW32__)
|
|
||||||
#include <ddk/ntddcdrm.h>
|
|
||||||
#else
|
|
||||||
#include "ntddcdrm.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "discid/discid.h"
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define MB_DEFAULT_DEVICE "D:"
|
|
||||||
#define MAX_DEV_LEN 3
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
# define THREAD_LOCAL __declspec(thread)
|
|
||||||
#elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
|
||||||
# define THREAD_LOCAL __thread
|
|
||||||
#else
|
|
||||||
# define THREAD_LOCAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static THREAD_LOCAL char default_device[MAX_DEV_LEN] = "\0";
|
|
||||||
|
|
||||||
static int address_to_sectors(UCHAR address[4]) {
|
|
||||||
return address[1] * 4500 + address[2] * 75 + address[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
static HANDLE create_device_handle(mb_disc_private *disc, const char *device) {
|
|
||||||
HANDLE hDevice;
|
|
||||||
char filename[128];
|
|
||||||
const char* colon;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
strcpy(filename, "\\\\.\\");
|
|
||||||
len = strlen(device);
|
|
||||||
colon = strchr(device, ':');
|
|
||||||
if (colon) {
|
|
||||||
len = colon - device + 1;
|
|
||||||
}
|
|
||||||
strncat(filename, device, len > 120 ? 120 : len);
|
|
||||||
|
|
||||||
hDevice = CreateFile(filename, GENERIC_READ,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
||||||
NULL, OPEN_EXISTING, 0, NULL);
|
|
||||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot open the CD audio device '%s'", device);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_disc_mcn(HANDLE hDevice, mb_disc_private *disc) {
|
|
||||||
DWORD dwReturned;
|
|
||||||
BOOL bResult;
|
|
||||||
CDROM_SUB_Q_DATA_FORMAT format;
|
|
||||||
SUB_Q_CHANNEL_DATA data;
|
|
||||||
|
|
||||||
format.Track = 0;
|
|
||||||
format.Format = IOCTL_CDROM_MEDIA_CATALOG;
|
|
||||||
bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_Q_CHANNEL,
|
|
||||||
&format, sizeof(format),
|
|
||||||
&data, sizeof(data),
|
|
||||||
&dwReturned, NULL);
|
|
||||||
if (bResult == FALSE) {
|
|
||||||
fprintf(stderr, "Warning: Unable to read the disc's media catalog number.\n");
|
|
||||||
} else {
|
|
||||||
strncpy(disc->mcn, (char *) data.MediaCatalog.MediaCatalog,
|
|
||||||
MCN_STR_LENGTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_disc_isrc(HANDLE hDevice, mb_disc_private *disc, int track) {
|
|
||||||
DWORD dwReturned;
|
|
||||||
BOOL bResult;
|
|
||||||
CDROM_SUB_Q_DATA_FORMAT format;
|
|
||||||
SUB_Q_CHANNEL_DATA data;
|
|
||||||
|
|
||||||
format.Track = track;
|
|
||||||
format.Format = IOCTL_CDROM_TRACK_ISRC;
|
|
||||||
bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_Q_CHANNEL,
|
|
||||||
&format, sizeof(format),
|
|
||||||
&data, sizeof(data),
|
|
||||||
&dwReturned, NULL);
|
|
||||||
if (bResult == FALSE) {
|
|
||||||
fprintf(stderr, "Warning: Unable to read the international standard recording code (ISRC) for track %i\n", track);
|
|
||||||
} else {
|
|
||||||
strncpy(disc->isrc[track], (char *) data.TrackIsrc.TrackIsrc,
|
|
||||||
ISRC_STR_LENGTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_nth_device(int number, char* device, int device_length) {
|
|
||||||
int i, counter = 0;
|
|
||||||
char tmpDevice[MAX_DEV_LEN];
|
|
||||||
DWORD mask = GetLogicalDrives();
|
|
||||||
|
|
||||||
for (i = 0; i <= 25; i++) {
|
|
||||||
if (mask >> i & 1) {
|
|
||||||
snprintf(tmpDevice, MAX_DEV_LEN, "%c:", i + 'A');
|
|
||||||
if (GetDriveType(tmpDevice) == DRIVE_CDROM) {
|
|
||||||
counter++;
|
|
||||||
if (counter == number) {
|
|
||||||
strncpy(device, tmpDevice, device_length);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *mb_disc_get_default_device_unportable(void) {
|
|
||||||
if (!get_nth_device(1, default_device, MAX_DEV_LEN)) {
|
|
||||||
return MB_DEFAULT_DEVICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return default_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_has_feature_unportable(enum discid_feature feature) {
|
|
||||||
switch(feature) {
|
|
||||||
case DISCID_FEATURE_READ:
|
|
||||||
case DISCID_FEATURE_MCN:
|
|
||||||
case DISCID_FEATURE_ISRC:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mb_disc_winnt_read_toc(HANDLE device, mb_disc_private *disc, mb_disc_toc *toc) {
|
|
||||||
DWORD dwReturned;
|
|
||||||
BOOL bResult;
|
|
||||||
CDROM_TOC cd;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
bResult = DeviceIoControl(device, IOCTL_CDROM_READ_TOC,
|
|
||||||
NULL, 0,
|
|
||||||
&cd, sizeof(cd),
|
|
||||||
&dwReturned, NULL);
|
|
||||||
if (bResult == FALSE) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"error while reading the CD TOC");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
toc->first_track_num = cd.FirstTrack;
|
|
||||||
toc->last_track_num = cd.LastTrack;
|
|
||||||
|
|
||||||
/* Get info about all tracks */
|
|
||||||
for (i = toc->first_track_num; i <= toc->last_track_num; i++) {
|
|
||||||
toc->tracks[i].address = address_to_sectors(cd.TrackData[i - 1].Address) - 150;
|
|
||||||
toc->tracks[i].control = cd.TrackData[i - 1].Control;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lead-out is stored after the last track */
|
|
||||||
toc->tracks[0].address = address_to_sectors(cd.TrackData[toc->last_track_num].Address) - 150;
|
|
||||||
toc->tracks[0].control = cd.TrackData[toc->last_track_num].Control;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_read_unportable(mb_disc_private *disc, const char *device,
|
|
||||||
unsigned int features) {
|
|
||||||
mb_disc_toc toc;
|
|
||||||
char tmpDevice[MAX_DEV_LEN];
|
|
||||||
HANDLE hDevice;
|
|
||||||
int i, device_number;
|
|
||||||
|
|
||||||
device_number = (int) strtol(device, NULL, 10);
|
|
||||||
|
|
||||||
if (device_number > 0) {
|
|
||||||
if (!get_nth_device(device_number, tmpDevice, MAX_DEV_LEN)) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot find the CD audio device '%i'", device_number);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
device = tmpDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
hDevice = create_device_handle(disc, device);
|
|
||||||
if (hDevice == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!mb_disc_winnt_read_toc(hDevice, disc, &toc)) {
|
|
||||||
CloseHandle(hDevice);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mb_disc_load_toc(disc, &toc)) {
|
|
||||||
CloseHandle(hDevice);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (features & DISCID_FEATURE_MCN) {
|
|
||||||
read_disc_mcn(hDevice, disc);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = disc->first_track_num; i <= disc->last_track_num; i++) {
|
|
||||||
if (features & DISCID_FEATURE_ISRC) {
|
|
||||||
read_disc_isrc(hDevice, disc, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(hDevice);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
@ -1,320 +0,0 @@
|
|||||||
/*
|
|
||||||
* ntddcdrm.h
|
|
||||||
*
|
|
||||||
* CDROM IOCTL interface.
|
|
||||||
*
|
|
||||||
* This file is part of the w32api package.
|
|
||||||
*
|
|
||||||
* Contributors:
|
|
||||||
* Created by Casper S. Hornstrup <chorns@users.sourceforge.net>
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS NOT COPYRIGHTED
|
|
||||||
*
|
|
||||||
* This source code is offered for use in the public domain. You may
|
|
||||||
* use, modify or distribute it freely.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful but
|
|
||||||
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
|
|
||||||
* DISCLAIMED. This includes but is not limited to warranties of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NTDDCDRM_H
|
|
||||||
#define __NTDDCDRM_H
|
|
||||||
|
|
||||||
#if __GNUC__ >=3
|
|
||||||
#pragma GCC system_header
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma pack(push,4)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_CHECK_VERIFY \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_FIND_NEW_DEVICES \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_GET_CONTROL \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_GET_LAST_SESSION \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_GET_VOLUME \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_PAUSE_AUDIO \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_PLAY_AUDIO_MSF \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_RAW_READ \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_READ_Q_CHANNEL \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_READ_TOC \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_READ_TOC_EX \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_RESUME_AUDIO \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_SEEK_AUDIO_MSF \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_SET_VOLUME \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_SIMBAD \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
#define IOCTL_CDROM_STOP_AUDIO \
|
|
||||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS)
|
|
||||||
|
|
||||||
|
|
||||||
#define MAXIMUM_NUMBER_TRACKS 100
|
|
||||||
#define MAXIMUM_CDROM_SIZE 804
|
|
||||||
#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2
|
|
||||||
|
|
||||||
typedef struct _TRACK_DATA {
|
|
||||||
UCHAR Reserved;
|
|
||||||
UCHAR Control : 4;
|
|
||||||
UCHAR Adr : 4;
|
|
||||||
UCHAR TrackNumber;
|
|
||||||
UCHAR Reserved1;
|
|
||||||
UCHAR Address[4];
|
|
||||||
} TRACK_DATA, *PTRACK_DATA;
|
|
||||||
|
|
||||||
/* CDROM_DISK_DATA.DiskData flags */
|
|
||||||
#define CDROM_DISK_AUDIO_TRACK 0x00000001
|
|
||||||
#define CDROM_DISK_DATA_TRACK 0x00000002
|
|
||||||
|
|
||||||
typedef struct _CDROM_DISK_DATA {
|
|
||||||
ULONG DiskData;
|
|
||||||
} CDROM_DISK_DATA, *PCDROM_DISK_DATA;
|
|
||||||
|
|
||||||
typedef struct _CDROM_PLAY_AUDIO_MSF {
|
|
||||||
UCHAR StartingM;
|
|
||||||
UCHAR StartingS;
|
|
||||||
UCHAR StartingF;
|
|
||||||
UCHAR EndingM;
|
|
||||||
UCHAR EndingS;
|
|
||||||
UCHAR EndingF;
|
|
||||||
} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF;
|
|
||||||
|
|
||||||
/* CDROM_READ_TOC_EX.Format constants */
|
|
||||||
#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00
|
|
||||||
#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01
|
|
||||||
#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02
|
|
||||||
#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03
|
|
||||||
#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04
|
|
||||||
#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05
|
|
||||||
|
|
||||||
typedef struct _CDROM_READ_TOC_EX {
|
|
||||||
UCHAR Format : 4;
|
|
||||||
UCHAR Reserved1 : 3;
|
|
||||||
UCHAR Msf : 1;
|
|
||||||
UCHAR SessionTrack;
|
|
||||||
UCHAR Reserved2;
|
|
||||||
UCHAR Reserved3;
|
|
||||||
} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX;
|
|
||||||
|
|
||||||
typedef struct _CDROM_SEEK_AUDIO_MSF {
|
|
||||||
UCHAR M;
|
|
||||||
UCHAR S;
|
|
||||||
UCHAR F;
|
|
||||||
} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF;
|
|
||||||
|
|
||||||
/* CDROM_SUB_Q_DATA_FORMAT.Format constants */
|
|
||||||
#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00
|
|
||||||
#define IOCTL_CDROM_CURRENT_POSITION 0x01
|
|
||||||
#define IOCTL_CDROM_MEDIA_CATALOG 0x02
|
|
||||||
#define IOCTL_CDROM_TRACK_ISRC 0x03
|
|
||||||
|
|
||||||
typedef struct _CDROM_SUB_Q_DATA_FORMAT {
|
|
||||||
UCHAR Format;
|
|
||||||
UCHAR Track;
|
|
||||||
} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT;
|
|
||||||
|
|
||||||
typedef struct _CDROM_TOC {
|
|
||||||
UCHAR Length[2];
|
|
||||||
UCHAR FirstTrack;
|
|
||||||
UCHAR LastTrack;
|
|
||||||
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS];
|
|
||||||
} CDROM_TOC, *PCDROM_TOC;
|
|
||||||
|
|
||||||
#define CDROM_TOC_SIZE sizeof(CDROM_TOC)
|
|
||||||
|
|
||||||
typedef struct _CDROM_TOC_ATIP_DATA_BLOCK {
|
|
||||||
UCHAR CdrwReferenceSpeed : 3;
|
|
||||||
UCHAR Reserved3 : 1;
|
|
||||||
UCHAR WritePower : 3;
|
|
||||||
UCHAR True1 : 1;
|
|
||||||
UCHAR Reserved4 : 6;
|
|
||||||
UCHAR UnrestrictedUse : 1;
|
|
||||||
UCHAR Reserved5 : 1;
|
|
||||||
UCHAR A3Valid : 1;
|
|
||||||
UCHAR A2Valid : 1;
|
|
||||||
UCHAR A1Valid : 1;
|
|
||||||
UCHAR Reserved6 : 3;
|
|
||||||
UCHAR IsCdrw : 1;
|
|
||||||
UCHAR True2 : 1;
|
|
||||||
UCHAR Reserved7;
|
|
||||||
UCHAR LeadInMsf[3];
|
|
||||||
UCHAR Reserved8;
|
|
||||||
UCHAR LeadOutMsf[3];
|
|
||||||
UCHAR Reserved9;
|
|
||||||
UCHAR A1Values[3];
|
|
||||||
UCHAR Reserved10;
|
|
||||||
UCHAR A2Values[3];
|
|
||||||
UCHAR Reserved11;
|
|
||||||
UCHAR A3Values[3];
|
|
||||||
UCHAR Reserved12;
|
|
||||||
} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK;
|
|
||||||
|
|
||||||
/* CDROM_TOC_CD_TEXT_DATA_BLOCK.PackType constants */
|
|
||||||
#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80
|
|
||||||
#define CDROM_CD_TEXT_PACK_PERFORMER 0x81
|
|
||||||
#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82
|
|
||||||
#define CDROM_CD_TEXT_PACK_COMPOSER 0x83
|
|
||||||
#define CDROM_CD_TEXT_PACK_ARRANGER 0x84
|
|
||||||
#define CDROM_CD_TEXT_PACK_MESSAGES 0x85
|
|
||||||
#define CDROM_CD_TEXT_PACK_DISC_ID 0x86
|
|
||||||
#define CDROM_CD_TEXT_PACK_GENRE 0x87
|
|
||||||
#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88
|
|
||||||
#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89
|
|
||||||
#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e
|
|
||||||
#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f
|
|
||||||
|
|
||||||
typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK {
|
|
||||||
UCHAR PackType;
|
|
||||||
UCHAR TrackNumber : 7;
|
|
||||||
UCHAR ExtensionFlag : 1;
|
|
||||||
UCHAR SequenceNumber;
|
|
||||||
UCHAR CharacterPosition : 4;
|
|
||||||
UCHAR BlockNumber : 3;
|
|
||||||
UCHAR Unicode : 1;
|
|
||||||
union {
|
|
||||||
UCHAR Text[12];
|
|
||||||
WCHAR WText[6];
|
|
||||||
};
|
|
||||||
UCHAR CRC[2];
|
|
||||||
} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK;
|
|
||||||
|
|
||||||
/* CDROM_TOC_FULL_TOC_DATA_BLOCK.Adr constants */
|
|
||||||
#define ADR_NO_MODE_INFORMATION 0x0
|
|
||||||
#define ADR_ENCODES_CURRENT_POSITION 0x1
|
|
||||||
#define ADR_ENCODES_MEDIA_CATALOG 0x2
|
|
||||||
#define ADR_ENCODES_ISRC 0x3
|
|
||||||
|
|
||||||
typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK {
|
|
||||||
UCHAR SessionNumber;
|
|
||||||
UCHAR Control : 4;
|
|
||||||
UCHAR Adr : 4;
|
|
||||||
UCHAR Reserved1;
|
|
||||||
UCHAR Point;
|
|
||||||
UCHAR MsfExtra[3];
|
|
||||||
UCHAR Zero;
|
|
||||||
UCHAR Msf[3];
|
|
||||||
} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK;
|
|
||||||
|
|
||||||
/* SUB_Q_HEADER.AudioStatus constants */
|
|
||||||
#define AUDIO_STATUS_NOT_SUPPORTED 0x00
|
|
||||||
#define AUDIO_STATUS_IN_PROGRESS 0x11
|
|
||||||
#define AUDIO_STATUS_PAUSED 0x12
|
|
||||||
#define AUDIO_STATUS_PLAY_COMPLETE 0x13
|
|
||||||
#define AUDIO_STATUS_PLAY_ERROR 0x14
|
|
||||||
#define AUDIO_STATUS_NO_STATUS 0x15
|
|
||||||
|
|
||||||
typedef struct _SUB_Q_HEADER {
|
|
||||||
UCHAR Reserved;
|
|
||||||
UCHAR AudioStatus;
|
|
||||||
UCHAR DataLength[2];
|
|
||||||
} SUB_Q_HEADER, *PSUB_Q_HEADER;
|
|
||||||
|
|
||||||
typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER {
|
|
||||||
SUB_Q_HEADER Header;
|
|
||||||
UCHAR FormatCode;
|
|
||||||
UCHAR Reserved[3];
|
|
||||||
UCHAR Reserved1 : 7;
|
|
||||||
UCHAR Mcval :1;
|
|
||||||
UCHAR MediaCatalog[15];
|
|
||||||
} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER;
|
|
||||||
|
|
||||||
typedef struct _SUB_Q_TRACK_ISRC {
|
|
||||||
SUB_Q_HEADER Header;
|
|
||||||
UCHAR FormatCode;
|
|
||||||
UCHAR Reserved0;
|
|
||||||
UCHAR Track;
|
|
||||||
UCHAR Reserved1;
|
|
||||||
UCHAR Reserved2 : 7;
|
|
||||||
UCHAR Tcval : 1;
|
|
||||||
UCHAR TrackIsrc[15];
|
|
||||||
} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC;
|
|
||||||
|
|
||||||
typedef struct _SUB_Q_CURRENT_POSITION {
|
|
||||||
SUB_Q_HEADER Header;
|
|
||||||
UCHAR FormatCode;
|
|
||||||
UCHAR Control : 4;
|
|
||||||
UCHAR ADR : 4;
|
|
||||||
UCHAR TrackNumber;
|
|
||||||
UCHAR IndexNumber;
|
|
||||||
UCHAR AbsoluteAddress[4];
|
|
||||||
UCHAR TrackRelativeAddress[4];
|
|
||||||
} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION;
|
|
||||||
|
|
||||||
typedef union _SUB_Q_CHANNEL_DATA {
|
|
||||||
SUB_Q_CURRENT_POSITION CurrentPosition;
|
|
||||||
SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog;
|
|
||||||
SUB_Q_TRACK_ISRC TrackIsrc;
|
|
||||||
} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA;
|
|
||||||
|
|
||||||
/* CDROM_AUDIO_CONTROL.LbaFormat constants */
|
|
||||||
#define AUDIO_WITH_PREEMPHASIS 0x1
|
|
||||||
#define DIGITAL_COPY_PERMITTED 0x2
|
|
||||||
#define AUDIO_DATA_TRACK 0x4
|
|
||||||
#define TWO_FOUR_CHANNEL_AUDIO 0x8
|
|
||||||
|
|
||||||
typedef struct _CDROM_AUDIO_CONTROL {
|
|
||||||
UCHAR LbaFormat;
|
|
||||||
USHORT LogicalBlocksPerSecond;
|
|
||||||
} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL;
|
|
||||||
|
|
||||||
typedef struct _VOLUME_CONTROL {
|
|
||||||
UCHAR PortVolume[4];
|
|
||||||
} VOLUME_CONTROL, *PVOLUME_CONTROL;
|
|
||||||
|
|
||||||
typedef enum _TRACK_MODE_TYPE {
|
|
||||||
YellowMode2,
|
|
||||||
XAForm2,
|
|
||||||
CDDA
|
|
||||||
} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE;
|
|
||||||
|
|
||||||
typedef struct __RAW_READ_INFO {
|
|
||||||
LARGE_INTEGER DiskOffset;
|
|
||||||
ULONG SectorCount;
|
|
||||||
TRACK_MODE_TYPE TrackMode;
|
|
||||||
} RAW_READ_INFO, *PRAW_READ_INFO;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __NTDDCDRM_H */
|
|
@ -1,329 +0,0 @@
|
|||||||
/* (PD) 2001 The Bitzi Corporation
|
|
||||||
* Please see file COPYING or http://bitzi.com/publicdomain
|
|
||||||
* for more info.
|
|
||||||
*
|
|
||||||
* NIST Secure Hash Algorithm
|
|
||||||
* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu>
|
|
||||||
* from Peter C. Gutmann's implementation as found in
|
|
||||||
* Applied Cryptography by Bruce Schneier
|
|
||||||
* Further modifications to include the "UNRAVEL" stuff, below
|
|
||||||
*
|
|
||||||
* This code is in the public domain
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "sha1.h"
|
|
||||||
|
|
||||||
/* UNRAVEL should be fastest & biggest */
|
|
||||||
/* UNROLL_LOOPS should be just as big, but slightly slower */
|
|
||||||
/* both undefined should be smallest and slowest */
|
|
||||||
|
|
||||||
#define UNRAVEL
|
|
||||||
/* #define UNROLL_LOOPS */
|
|
||||||
|
|
||||||
/* SHA f()-functions */
|
|
||||||
|
|
||||||
#define f1(x,y,z) ((x & y) | (~x & z))
|
|
||||||
#define f2(x,y,z) (x ^ y ^ z)
|
|
||||||
#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
|
|
||||||
#define f4(x,y,z) (x ^ y ^ z)
|
|
||||||
|
|
||||||
/* SHA constants */
|
|
||||||
|
|
||||||
#define CONST1 0x5a827999L
|
|
||||||
#define CONST2 0x6ed9eba1L
|
|
||||||
#define CONST3 0x8f1bbcdcL
|
|
||||||
#define CONST4 0xca62c1d6L
|
|
||||||
|
|
||||||
/* truncate to 32 bits -- should be a null op on 32-bit machines */
|
|
||||||
|
|
||||||
#define T32(x) ((x) & 0xffffffffL)
|
|
||||||
|
|
||||||
/* 32-bit rotate */
|
|
||||||
|
|
||||||
#define R32(x,n) T32(((x << n) | (x >> (32 - n))))
|
|
||||||
|
|
||||||
/* the generic case, for when the overall rotation is not unraveled */
|
|
||||||
|
|
||||||
#define FG(n) \
|
|
||||||
T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \
|
|
||||||
E = D; D = C; C = R32(B,30); B = A; A = T
|
|
||||||
|
|
||||||
/* specific cases, for when the overall rotation is unraveled */
|
|
||||||
|
|
||||||
#define FA(n) \
|
|
||||||
T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
|
|
||||||
|
|
||||||
#define FB(n) \
|
|
||||||
E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
|
|
||||||
|
|
||||||
#define FC(n) \
|
|
||||||
D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
|
|
||||||
|
|
||||||
#define FD(n) \
|
|
||||||
C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
|
|
||||||
|
|
||||||
#define FE(n) \
|
|
||||||
B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
|
|
||||||
|
|
||||||
#define FT(n) \
|
|
||||||
A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
|
|
||||||
|
|
||||||
/* do SHA transformation */
|
|
||||||
|
|
||||||
static void sha_transform(SHA_INFO *sha_info)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
SHA_BYTE *dp;
|
|
||||||
SHA_LONG T, A, B, C, D, E, W[80], *WP;
|
|
||||||
|
|
||||||
dp = sha_info->data;
|
|
||||||
|
|
||||||
/*
|
|
||||||
the following makes sure that at least one code block below is
|
|
||||||
traversed or an error is reported, without the necessity for nested
|
|
||||||
preprocessor if/else/endif blocks, which are a great pain in the
|
|
||||||
nether regions of the anatomy...
|
|
||||||
*/
|
|
||||||
#undef SWAP_DONE
|
|
||||||
|
|
||||||
#if (SHA_BYTE_ORDER == 1234)
|
|
||||||
#define SWAP_DONE
|
|
||||||
for (i = 0; i < 16; ++i) {
|
|
||||||
T = *((SHA_LONG *) dp);
|
|
||||||
dp += 4;
|
|
||||||
W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
|
||||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
|
||||||
}
|
|
||||||
#endif /* SHA_BYTE_ORDER == 1234 */
|
|
||||||
|
|
||||||
#if (SHA_BYTE_ORDER == 4321)
|
|
||||||
#define SWAP_DONE
|
|
||||||
for (i = 0; i < 16; ++i) {
|
|
||||||
T = *((SHA_LONG *) dp);
|
|
||||||
dp += 4;
|
|
||||||
W[i] = T32(T);
|
|
||||||
}
|
|
||||||
#endif /* SHA_BYTE_ORDER == 4321 */
|
|
||||||
|
|
||||||
#if (SHA_BYTE_ORDER == 12345678)
|
|
||||||
#define SWAP_DONE
|
|
||||||
for (i = 0; i < 16; i += 2) {
|
|
||||||
T = *((SHA_LONG *) dp);
|
|
||||||
dp += 8;
|
|
||||||
W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
|
||||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
|
||||||
T >>= 32;
|
|
||||||
W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
|
||||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
|
||||||
}
|
|
||||||
#endif /* SHA_BYTE_ORDER == 12345678 */
|
|
||||||
|
|
||||||
#if (SHA_BYTE_ORDER == 87654321)
|
|
||||||
#define SWAP_DONE
|
|
||||||
for (i = 0; i < 16; i += 2) {
|
|
||||||
T = *((SHA_LONG *) dp);
|
|
||||||
dp += 8;
|
|
||||||
W[i] = T32(T >> 32);
|
|
||||||
W[i+1] = T32(T);
|
|
||||||
}
|
|
||||||
#endif /* SHA_BYTE_ORDER == 87654321 */
|
|
||||||
|
|
||||||
#ifndef SWAP_DONE
|
|
||||||
#error Unknown byte order -- you need to add code here
|
|
||||||
#endif /* SWAP_DONE */
|
|
||||||
|
|
||||||
for (i = 16; i < 80; ++i) {
|
|
||||||
W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
|
|
||||||
#if (SHA_VERSION == 1)
|
|
||||||
W[i] = R32(W[i], 1);
|
|
||||||
#endif /* SHA_VERSION */
|
|
||||||
}
|
|
||||||
A = sha_info->digest[0];
|
|
||||||
B = sha_info->digest[1];
|
|
||||||
C = sha_info->digest[2];
|
|
||||||
D = sha_info->digest[3];
|
|
||||||
E = sha_info->digest[4];
|
|
||||||
WP = W;
|
|
||||||
#ifdef UNRAVEL
|
|
||||||
FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
|
|
||||||
FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
|
|
||||||
FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
|
|
||||||
FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
|
|
||||||
FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
|
|
||||||
FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
|
|
||||||
FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
|
|
||||||
FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
|
|
||||||
sha_info->digest[0] = T32(sha_info->digest[0] + E);
|
|
||||||
sha_info->digest[1] = T32(sha_info->digest[1] + T);
|
|
||||||
sha_info->digest[2] = T32(sha_info->digest[2] + A);
|
|
||||||
sha_info->digest[3] = T32(sha_info->digest[3] + B);
|
|
||||||
sha_info->digest[4] = T32(sha_info->digest[4] + C);
|
|
||||||
#else /* !UNRAVEL */
|
|
||||||
#ifdef UNROLL_LOOPS
|
|
||||||
FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
|
|
||||||
FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
|
|
||||||
FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
|
|
||||||
FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
|
|
||||||
FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
|
|
||||||
FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
|
|
||||||
FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
|
|
||||||
FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
|
|
||||||
#else /* !UNROLL_LOOPS */
|
|
||||||
for (i = 0; i < 20; ++i) { FG(1); }
|
|
||||||
for (i = 20; i < 40; ++i) { FG(2); }
|
|
||||||
for (i = 40; i < 60; ++i) { FG(3); }
|
|
||||||
for (i = 60; i < 80; ++i) { FG(4); }
|
|
||||||
#endif /* !UNROLL_LOOPS */
|
|
||||||
sha_info->digest[0] = T32(sha_info->digest[0] + A);
|
|
||||||
sha_info->digest[1] = T32(sha_info->digest[1] + B);
|
|
||||||
sha_info->digest[2] = T32(sha_info->digest[2] + C);
|
|
||||||
sha_info->digest[3] = T32(sha_info->digest[3] + D);
|
|
||||||
sha_info->digest[4] = T32(sha_info->digest[4] + E);
|
|
||||||
#endif /* !UNRAVEL */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize the SHA digest */
|
|
||||||
|
|
||||||
void sha_init(SHA_INFO *sha_info)
|
|
||||||
{
|
|
||||||
sha_info->digest[0] = 0x67452301L;
|
|
||||||
sha_info->digest[1] = 0xefcdab89L;
|
|
||||||
sha_info->digest[2] = 0x98badcfeL;
|
|
||||||
sha_info->digest[3] = 0x10325476L;
|
|
||||||
sha_info->digest[4] = 0xc3d2e1f0L;
|
|
||||||
sha_info->count_lo = 0L;
|
|
||||||
sha_info->count_hi = 0L;
|
|
||||||
sha_info->local = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update the SHA digest */
|
|
||||||
|
|
||||||
void sha_update(SHA_INFO *sha_info, SHA_BYTE *buffer, size_t count)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
SHA_LONG clo;
|
|
||||||
|
|
||||||
clo = T32(sha_info->count_lo + ((SHA_LONG) count << 3));
|
|
||||||
if (clo < sha_info->count_lo) {
|
|
||||||
++sha_info->count_hi;
|
|
||||||
}
|
|
||||||
sha_info->count_lo = clo;
|
|
||||||
sha_info->count_hi += (SHA_LONG) count >> 29;
|
|
||||||
if (sha_info->local) {
|
|
||||||
i = SHA_BLOCKSIZE - sha_info->local;
|
|
||||||
if (i > count) {
|
|
||||||
i = count;
|
|
||||||
}
|
|
||||||
memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
|
|
||||||
count -= i;
|
|
||||||
buffer += i;
|
|
||||||
sha_info->local += i;
|
|
||||||
if (sha_info->local == SHA_BLOCKSIZE) {
|
|
||||||
sha_transform(sha_info);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (count >= SHA_BLOCKSIZE) {
|
|
||||||
memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
|
|
||||||
buffer += SHA_BLOCKSIZE;
|
|
||||||
count -= SHA_BLOCKSIZE;
|
|
||||||
sha_transform(sha_info);
|
|
||||||
}
|
|
||||||
memcpy(sha_info->data, buffer, count);
|
|
||||||
sha_info->local = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* finish computing the SHA digest */
|
|
||||||
|
|
||||||
void sha_final(unsigned char digest[20], SHA_INFO *sha_info)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
SHA_LONG lo_bit_count, hi_bit_count;
|
|
||||||
|
|
||||||
lo_bit_count = sha_info->count_lo;
|
|
||||||
hi_bit_count = sha_info->count_hi;
|
|
||||||
count = (int) ((lo_bit_count >> 3) & 0x3f);
|
|
||||||
((SHA_BYTE *) sha_info->data)[count++] = 0x80;
|
|
||||||
if (count > SHA_BLOCKSIZE - 8) {
|
|
||||||
memset(((SHA_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
|
|
||||||
sha_transform(sha_info);
|
|
||||||
memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
|
|
||||||
} else {
|
|
||||||
memset(((SHA_BYTE *) sha_info->data) + count, 0,
|
|
||||||
SHA_BLOCKSIZE - 8 - count);
|
|
||||||
}
|
|
||||||
sha_info->data[56] = (unsigned char) ((hi_bit_count >> 24) & 0xff);
|
|
||||||
sha_info->data[57] = (unsigned char) ((hi_bit_count >> 16) & 0xff);
|
|
||||||
sha_info->data[58] = (unsigned char) ((hi_bit_count >> 8) & 0xff);
|
|
||||||
sha_info->data[59] = (unsigned char) ((hi_bit_count >> 0) & 0xff);
|
|
||||||
sha_info->data[60] = (unsigned char) ((lo_bit_count >> 24) & 0xff);
|
|
||||||
sha_info->data[61] = (unsigned char) ((lo_bit_count >> 16) & 0xff);
|
|
||||||
sha_info->data[62] = (unsigned char) ((lo_bit_count >> 8) & 0xff);
|
|
||||||
sha_info->data[63] = (unsigned char) ((lo_bit_count >> 0) & 0xff);
|
|
||||||
sha_transform(sha_info);
|
|
||||||
digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
|
|
||||||
digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
|
|
||||||
digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
|
|
||||||
digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
|
|
||||||
digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
|
|
||||||
digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
|
|
||||||
digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
|
|
||||||
digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
|
|
||||||
digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
|
|
||||||
digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
|
|
||||||
digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
|
|
||||||
digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
|
|
||||||
digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
|
|
||||||
digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
|
|
||||||
digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
|
|
||||||
digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
|
|
||||||
digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
|
|
||||||
digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
|
|
||||||
digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
|
|
||||||
digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute the SHA digest of a FILE stream */
|
|
||||||
|
|
||||||
#define BLOCK_SIZE 8192
|
|
||||||
|
|
||||||
void sha_stream(unsigned char digest[20], SHA_INFO *sha_info, FILE *fin)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
SHA_BYTE data[BLOCK_SIZE];
|
|
||||||
|
|
||||||
sha_init(sha_info);
|
|
||||||
while ((i = fread(data, 1, BLOCK_SIZE, fin)) > 0) {
|
|
||||||
sha_update(sha_info, data, i);
|
|
||||||
}
|
|
||||||
sha_final(digest, sha_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print a SHA digest */
|
|
||||||
|
|
||||||
void sha_print(unsigned char digest[20])
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
for (j = 0; j < 5; ++j) {
|
|
||||||
for (i = 0; i < 4; ++i) {
|
|
||||||
printf("%02x", *digest++);
|
|
||||||
}
|
|
||||||
printf("%c", (j < 4) ? ' ' : '\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *sha_version(void)
|
|
||||||
{
|
|
||||||
#if (SHA_VERSION == 1)
|
|
||||||
static char *version = "SHA-1";
|
|
||||||
#else
|
|
||||||
static char *version = "SHA";
|
|
||||||
#endif
|
|
||||||
return(version);
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
|||||||
/* NIST Secure Hash Algorithm */
|
|
||||||
/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
|
|
||||||
/* from Peter C. Gutmann's implementation as found in */
|
|
||||||
/* Applied Cryptography by Bruce Schneier */
|
|
||||||
/* This code is in the public domain */
|
|
||||||
/* $Id$ */
|
|
||||||
|
|
||||||
#ifndef SHA_H
|
|
||||||
#define SHA_H
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "discid/discid.h" /* for LIBDISCID_INTERNAL */
|
|
||||||
|
|
||||||
/* Useful defines & typedefs */
|
|
||||||
typedef unsigned char SHA_BYTE; /* 8-bit quantity */
|
|
||||||
typedef unsigned long SHA_LONG; /* 32-or-more-bit quantity */
|
|
||||||
|
|
||||||
#define SHA_BLOCKSIZE 64
|
|
||||||
#define SHA_DIGESTSIZE 20
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SHA_LONG digest[5]; /* message digest */
|
|
||||||
SHA_LONG count_lo, count_hi; /* 64-bit bit count */
|
|
||||||
SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
|
|
||||||
size_t local; /* unprocessed amount in data */
|
|
||||||
} SHA_INFO;
|
|
||||||
|
|
||||||
LIBDISCID_INTERNAL void sha_init(SHA_INFO *);
|
|
||||||
LIBDISCID_INTERNAL void sha_update(SHA_INFO *, SHA_BYTE *, size_t);
|
|
||||||
LIBDISCID_INTERNAL void sha_final(unsigned char [20], SHA_INFO *);
|
|
||||||
|
|
||||||
LIBDISCID_INTERNAL void sha_stream(unsigned char [20], SHA_INFO *, FILE *);
|
|
||||||
LIBDISCID_INTERNAL void sha_print(unsigned char [20]);
|
|
||||||
LIBDISCID_INTERNAL char *sha_version(void);
|
|
||||||
|
|
||||||
#define SHA_VERSION 1
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
# if SIZEOF_LONG == 4
|
|
||||||
# define SHA_BYTE_ORDER 4321
|
|
||||||
# elif SIZEOF_LONG == 8
|
|
||||||
# define SHA_BYTE_ORDER 87654321
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# if SIZEOF_LONG == 4
|
|
||||||
# define SHA_BYTE_ORDER 1234
|
|
||||||
# elif SIZEOF_LONG == 8
|
|
||||||
# define SHA_BYTE_ORDER 12345678
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define SHA_BYTE_ORDER 1234
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* SHA_H */
|
|
@ -1,116 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2006 Lukas Lalinsky
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#if (_MSC_VER < 1900)
|
|
||||||
#define snprintf _snprintf
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
|
|
||||||
#define XA_INTERVAL ((60 + 90 + 2) * 75)
|
|
||||||
#define DATA_TRACK 0x04
|
|
||||||
|
|
||||||
|
|
||||||
int mb_disc_load_toc(mb_disc_private *disc, mb_disc_toc *toc) {
|
|
||||||
int first_audio_track, last_audio_track, i;
|
|
||||||
mb_disc_toc_track *track;
|
|
||||||
|
|
||||||
if (toc->first_track_num < 1) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"invalid CD TOC - first track number must be 1 or higher");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toc->last_track_num < 1) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"invalid CD TOC - last track number must be 99 or lower");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we can't just skip data tracks at the front
|
|
||||||
* releases are always expected to start with track 1 by MusicBrainz
|
|
||||||
*/
|
|
||||||
first_audio_track = toc->first_track_num;
|
|
||||||
last_audio_track = -1;
|
|
||||||
/* scan the TOC for audio tracks */
|
|
||||||
for (i = toc->first_track_num; i <= toc->last_track_num; i++) {
|
|
||||||
track = &toc->tracks[i];
|
|
||||||
if ( !(track->control & DATA_TRACK) ) {
|
|
||||||
last_audio_track = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last_audio_track < 0) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"no actual audio tracks on disc: CDROM or DVD?");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
disc->first_track_num = first_audio_track;
|
|
||||||
disc->last_track_num = last_audio_track;
|
|
||||||
|
|
||||||
/* get offsets for all found data tracks */
|
|
||||||
for (i = first_audio_track; i <= last_audio_track; i++) {
|
|
||||||
track = &toc->tracks[i];
|
|
||||||
if (track->address > 0) {
|
|
||||||
disc->track_offsets[i] = track->address + 150;
|
|
||||||
} else {
|
|
||||||
/* this seems to happen on "copy-protected" discs */
|
|
||||||
disc->track_offsets[i] = 150;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if the last audio track is not the last track on the CD,
|
|
||||||
* use the offset of the next data track as the "lead-out" offset */
|
|
||||||
if (last_audio_track < toc->last_track_num) {
|
|
||||||
track = &toc->tracks[last_audio_track + 1];
|
|
||||||
disc->track_offsets[0] = track->address - XA_INTERVAL + 150;
|
|
||||||
} else {
|
|
||||||
/* use the regular lead-out track */
|
|
||||||
track = &toc->tracks[0];
|
|
||||||
disc->track_offsets[0] = track->address + 150;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* as long as the lead-out isn't actually bigger than
|
|
||||||
* the position of the last track, the last track is invalid.
|
|
||||||
* This happens on "copy-protected"/invalid discs.
|
|
||||||
* The track is then neither a valid audio track, nor data track.
|
|
||||||
*/
|
|
||||||
while (disc->track_offsets[0] < disc->track_offsets[last_audio_track]) {
|
|
||||||
disc->last_track_num = --last_audio_track;
|
|
||||||
disc->track_offsets[last_audio_track + 1] = 0;
|
|
||||||
track = &toc->tracks[last_audio_track + 1];
|
|
||||||
disc->track_offsets[0] = track->address - XA_INTERVAL + 150;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
@ -1,151 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2006 Matthias Friedrich
|
|
||||||
Copyright (C) 2000 Robert Kaye
|
|
||||||
Copyright (C) 1999 Marc E E van Woerkom
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
#include "unix.h"
|
|
||||||
|
|
||||||
|
|
||||||
int mb_disc_unix_exists(const char *device) {
|
|
||||||
int fd;
|
|
||||||
fd = open(device, O_RDONLY | O_NONBLOCK);
|
|
||||||
if (fd < 0) {
|
|
||||||
/* we only check for existance, access should fail later on */
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
close(fd);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *mb_disc_unix_find_device(char *candidates[], int num_candidates) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < num_candidates; i++) {
|
|
||||||
if (mb_disc_unix_exists(candidates[i])) {
|
|
||||||
return candidates[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* use the first name for the error message later on */
|
|
||||||
return candidates[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_open(mb_disc_private *disc, const char *device) {
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = open(device, O_RDONLY | O_NONBLOCK);
|
|
||||||
if (fd < 0) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot open device `%s'", device);
|
|
||||||
}
|
|
||||||
/* fd < 0 check needs to be made by caller */
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_read_toc(int fd, mb_disc_private *disc, mb_disc_toc *toc) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Find the numbers of the first track (usually 1) and the last track. */
|
|
||||||
if ( !mb_disc_unix_read_toc_header(fd, toc) ) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot read table of contents");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* basic error checking */
|
|
||||||
if ( toc->last_track_num == 0 ) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"this disc has no tracks");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the TOC entry for every track.
|
|
||||||
*/
|
|
||||||
for (i = toc->first_track_num; i <= toc->last_track_num; i++) {
|
|
||||||
if ( !mb_disc_unix_read_toc_entry(fd, i, &toc->tracks[i]) ) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot read TOC entry for track %d", i);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !mb_disc_unix_read_toc_entry(fd, 0xAA, &toc->tracks[0]) ) {
|
|
||||||
snprintf(disc->error_msg, MB_ERROR_MSG_LENGTH,
|
|
||||||
"cannot read TOC entry for lead-out");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mb_disc_unix_read(mb_disc_private *disc, const char *device,
|
|
||||||
unsigned int features) {
|
|
||||||
mb_disc_toc toc;
|
|
||||||
int fd;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
fd = mb_disc_unix_open(disc, device);
|
|
||||||
if (fd < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
|
||||||
if ( !mb_disc_unix_read_toc(fd, disc, &toc) ) {
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !mb_disc_load_toc(disc, &toc) ) {
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read in the media catalog number */
|
|
||||||
if (features & DISCID_FEATURE_MCN
|
|
||||||
&& mb_disc_has_feature_unportable(DISCID_FEATURE_MCN)) {
|
|
||||||
mb_disc_unix_read_mcn(fd, disc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the ISRC for the track */
|
|
||||||
if (features & DISCID_FEATURE_ISRC
|
|
||||||
&& mb_disc_has_feature_unportable(DISCID_FEATURE_ISRC)) {
|
|
||||||
for (i = disc->first_track_num; i <= disc->last_track_num; i++) {
|
|
||||||
mb_disc_unix_read_isrc(fd, disc, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* EOF */
|
|
@ -1,103 +0,0 @@
|
|||||||
/* --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MusicBrainz -- The Internet music metadatabase
|
|
||||||
|
|
||||||
Copyright (C) 2013 Johannes Dewender
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#include "discid/discid_private.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* required functions
|
|
||||||
* ------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the TOC header from disc
|
|
||||||
*
|
|
||||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_unix_read_toc_header(int fd, mb_disc_toc *toc);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a TOC entry for a certain track from disc
|
|
||||||
*
|
|
||||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_unix_read_toc_entry(int fd, int track_num,
|
|
||||||
mb_disc_toc_track *track);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the MCN from the disc
|
|
||||||
*
|
|
||||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL void mb_disc_unix_read_mcn(int fd, mb_disc_private *disc);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the ISRC for a certain track from disc
|
|
||||||
*
|
|
||||||
* THIS FUNCTION HAS TO BE IMPLEMENTED FOR THE PLATFORM
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL void mb_disc_unix_read_isrc(int fd, mb_disc_private *disc,
|
|
||||||
int track_num);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* provided functions
|
|
||||||
* ------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function is implemented in unix.c and can be used
|
|
||||||
* for most platforms to implement mb_disc_read_unportable
|
|
||||||
* after the above functions are implemented on the platform.
|
|
||||||
* Returns 1 on success and 0 on failure.
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_unix_read(mb_disc_private *disc,
|
|
||||||
const char *device, unsigned int features);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function is implemented in unix.c and can be used
|
|
||||||
* after the above functions are implemented on the platform.
|
|
||||||
* This uses mb_disc_unix_read_toc_* and adds some error checking.
|
|
||||||
* Returns 1 on success and 0 on failure.
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_unix_read_toc(int fd, mb_disc_private *disc,
|
|
||||||
mb_disc_toc *toc);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* utility function to find an existing device from a candidate list
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_unix_exists(const char *device);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* utility function to find an existing device from a candidate list
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL char *mb_disc_unix_find_device(char *candidates[],
|
|
||||||
int num_candidates);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* utility function to try opening the device with open()
|
|
||||||
* returns a non-negative file descriptor on success.
|
|
||||||
* On failure a negative integer is returned and error_msg filled
|
|
||||||
* with an appropriate string.
|
|
||||||
*/
|
|
||||||
LIBDISCID_INTERNAL int mb_disc_unix_open(mb_disc_private *disc,
|
|
||||||
const char *device);
|
|