mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 07:39:42 +02:00
412 lines
9.3 KiB
C++
412 lines
9.3 KiB
C++
/*
|
|
* PortBurn
|
|
* Windows XP IMAPI implementation
|
|
*
|
|
* Authors:
|
|
* Leland Lucius
|
|
*
|
|
* The following MSDN page was used as a guide:
|
|
* http://msdn2.microsoft.com/en-us/library/aa366236.aspx
|
|
*
|
|
* License: LGPL
|
|
*/
|
|
|
|
#include "portburn.h"
|
|
|
|
#define _WIN32_WINNT 0x0400
|
|
|
|
#include <windows.h>
|
|
#include <imapi.h>
|
|
#include <imapi2.h>
|
|
|
|
typedef struct {
|
|
int ver;
|
|
void *realhandle;
|
|
} PBHandle;
|
|
|
|
#define PBFUNC(r,f) \
|
|
extern r PortBurn_v1_ ## f; \
|
|
extern r PortBurn_v2_ ## f;
|
|
|
|
PBFUNC(void *, Open());
|
|
PBFUNC(void, Close(void *handle));
|
|
PBFUNC(char *, LastError(void *handle));
|
|
PBFUNC(int, GetNumDevices(void *handle));
|
|
PBFUNC(char *, GetDeviceName(void *handle, int index));
|
|
PBFUNC(int, OpenDevice(void *handle, int index));
|
|
PBFUNC(int, CloseDevice(void *handle));
|
|
PBFUNC(int, EjectDevice(void *handle));
|
|
PBFUNC(int, StartErasing(void *handle, int type));
|
|
PBFUNC(int, GetEraseStatus(void *handle, float *out_fraction_complete));
|
|
PBFUNC(int, StartStaging(void *handle, const char *tmpdir));
|
|
PBFUNC(int, StartTrack(void *handle, const char *name));
|
|
PBFUNC(int, AddFrame(void *handle, short *buffer));
|
|
PBFUNC(int, EndTrack(void *handle));
|
|
PBFUNC(int, StartBurning(void *handle));
|
|
PBFUNC(int, CancelBurning(void *handle));
|
|
PBFUNC(int, GetStatus(void *handle, float *out_fraction_complete));
|
|
PBFUNC(int, GetOption(void *handle, int option, int *value));
|
|
PBFUNC(int, SetOption(void *handle, int option, int value));
|
|
PBFUNC(int, GetSupportedSpeeds(void *handle, int *cnt, int *option[]));
|
|
PBFUNC(int, GetMediaState(void *handle, int *state));
|
|
|
|
enum {
|
|
IMAPI_V1,
|
|
IMAPI_V2,
|
|
IMAPI_VERS
|
|
};
|
|
|
|
struct
|
|
{
|
|
void *(*Open)();
|
|
void (*Close)(void *handle);
|
|
char *(*LastError)(void *handle);
|
|
int (*GetNumDevices)(void *handle);
|
|
char *(*GetDeviceName)(void *handle, int index);
|
|
int (*OpenDevice)(void *handle, int index);
|
|
int (*CloseDevice)(void *handle);
|
|
int (*EjectDevice)(void *handle);
|
|
int (*StartErasing)(void *handle, int type);
|
|
int (*GetEraseStatus)(void *handle, float *out_fraction_complete);
|
|
int (*StartStaging)(void *handle, const char *tmpdir);
|
|
int (*StartTrack)(void *handle, const char *name);
|
|
int (*AddFrame)(void *handle, short *buffer);
|
|
int (*EndTrack)(void *handle);
|
|
int (*StartBurning)(void *handle);
|
|
int (*CancelBurning)(void *handle);
|
|
int (*GetStatus)(void *handle, float *out_fraction_complete);
|
|
int (*GetOption)(void *handle, int option, int *value);
|
|
int (*SetOption)(void *handle, int option, int value);
|
|
int (*GetSupportedSpeeds)(void *handle, int *cnt, int *option[]);
|
|
int (*GetMediaState)(void *handle, int *state);
|
|
}
|
|
vectors[IMAPI_VERS] =
|
|
{
|
|
{
|
|
PortBurn_v1_Open,
|
|
PortBurn_v1_Close,
|
|
PortBurn_v1_LastError,
|
|
PortBurn_v1_GetNumDevices,
|
|
PortBurn_v1_GetDeviceName,
|
|
PortBurn_v1_OpenDevice,
|
|
PortBurn_v1_CloseDevice,
|
|
PortBurn_v1_EjectDevice,
|
|
PortBurn_v1_StartErasing,
|
|
PortBurn_v1_GetEraseStatus,
|
|
PortBurn_v1_StartStaging,
|
|
PortBurn_v1_StartTrack,
|
|
PortBurn_v1_AddFrame,
|
|
PortBurn_v1_EndTrack,
|
|
PortBurn_v1_StartBurning,
|
|
PortBurn_v1_CancelBurning,
|
|
PortBurn_v1_GetStatus,
|
|
PortBurn_v1_GetOption,
|
|
PortBurn_v1_SetOption,
|
|
PortBurn_v1_GetSupportedSpeeds,
|
|
PortBurn_v1_GetMediaState,
|
|
},
|
|
{
|
|
PortBurn_v2_Open,
|
|
PortBurn_v2_Close,
|
|
PortBurn_v2_LastError,
|
|
PortBurn_v2_GetNumDevices,
|
|
PortBurn_v2_GetDeviceName,
|
|
PortBurn_v2_OpenDevice,
|
|
PortBurn_v2_CloseDevice,
|
|
PortBurn_v2_EjectDevice,
|
|
PortBurn_v2_StartErasing,
|
|
PortBurn_v2_GetEraseStatus,
|
|
PortBurn_v2_StartStaging,
|
|
PortBurn_v2_StartTrack,
|
|
PortBurn_v2_AddFrame,
|
|
PortBurn_v2_EndTrack,
|
|
PortBurn_v2_StartBurning,
|
|
PortBurn_v2_CancelBurning,
|
|
PortBurn_v2_GetStatus,
|
|
PortBurn_v2_GetOption,
|
|
PortBurn_v2_SetOption,
|
|
PortBurn_v2_GetSupportedSpeeds,
|
|
PortBurn_v2_GetMediaState,
|
|
}
|
|
};
|
|
|
|
void *PortBurn_Open()
|
|
{
|
|
PBHandle *h;
|
|
HRESULT hres;
|
|
IDiscMaster *pV1;
|
|
IDiscMaster2 *pV2;
|
|
|
|
hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
|
|
if (FAILED(hres)) {
|
|
return NULL;
|
|
}
|
|
|
|
h = (PBHandle *) HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(PBHandle));
|
|
if (h == NULL) {
|
|
CoUninitialize();
|
|
return NULL;
|
|
}
|
|
|
|
hres = CoCreateInstance(__uuidof(MsftDiscMaster2),
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
IID_IDiscMaster2,
|
|
(void **)&pV2);
|
|
|
|
if (FAILED(hres)) {
|
|
hres = CoCreateInstance(__uuidof(MSDiscMasterObj),
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
IID_IDiscMaster,
|
|
(void **)&pV1);
|
|
if (FAILED(hres)) {
|
|
HeapFree(GetProcessHeap(), 0, h);
|
|
CoUninitialize();
|
|
return NULL;
|
|
}
|
|
pV1->Release();
|
|
h->ver = IMAPI_V1;
|
|
}
|
|
else {
|
|
pV2->Release();
|
|
h->ver = IMAPI_V2;
|
|
}
|
|
|
|
//h->ver = IMAPI_V1;
|
|
|
|
h->realhandle = vectors[h->ver].Open();
|
|
if (h->realhandle == NULL) {
|
|
HeapFree(GetProcessHeap(), 0, h);
|
|
CoUninitialize();
|
|
return NULL;
|
|
}
|
|
|
|
return h;
|
|
}
|
|
|
|
/* Cleanup */
|
|
void PortBurn_Close(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return;
|
|
}
|
|
|
|
vectors[h->ver].Close(h->realhandle);
|
|
|
|
HeapFree(GetProcessHeap(), 0, h);
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
char *PortBurn_LastError(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return vectors[h->ver].LastError(h->realhandle);
|
|
}
|
|
|
|
int PortBurn_GetNumDevices(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return vectors[h->ver].GetNumDevices(h->realhandle);
|
|
}
|
|
|
|
/* Get the name of the device with a given index. Only valid
|
|
after a call to GetNumDevices. */
|
|
char *PortBurn_GetDeviceName(void *handle, int index)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return vectors[h->ver].GetDeviceName(h->realhandle, index);
|
|
}
|
|
|
|
int PortBurn_OpenDevice(void *handle, int index)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].OpenDevice(h->realhandle, index);
|
|
}
|
|
|
|
int PortBurn_CloseDevice(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].CloseDevice(h->realhandle);
|
|
}
|
|
|
|
int PortBurn_EjectDevice(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].EjectDevice(h->realhandle);
|
|
}
|
|
|
|
int PortBurn_StartStaging(void *handle, const char *tmpdir)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].StartStaging(h->realhandle, tmpdir);
|
|
}
|
|
|
|
int PortBurn_StartTrack(void *handle, const char *name)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].StartTrack(h->realhandle, name);
|
|
}
|
|
|
|
int PortBurn_AddFrame(void *handle, short *buffer)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].AddFrame(h->realhandle, buffer);
|
|
}
|
|
|
|
int PortBurn_EndTrack(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].EndTrack(h->realhandle);
|
|
}
|
|
|
|
int PortBurn_StartBurning(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].StartBurning(h->realhandle);
|
|
}
|
|
|
|
int PortBurn_CancelBurning(void *handle)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].CancelBurning(h->realhandle);
|
|
}
|
|
|
|
int PortBurn_GetStatus(void *handle, float *out_fraction_complete)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].GetStatus(h->realhandle, out_fraction_complete);
|
|
}
|
|
|
|
int PortBurn_GetOption(void *handle, int option, int *value)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].GetOption(h->realhandle, option, value);
|
|
}
|
|
|
|
int PortBurn_SetOption(void *handle, int option, int value)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].SetOption(h->realhandle, option, value);
|
|
}
|
|
|
|
int PortBurn_GetSpeeds(void *handle, int *cnt, int *speeds[])
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/* Erase the media in the currently opened device */
|
|
int PortBurn_StartErasing(void *handle, int type)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].StartErasing(h->realhandle, type);
|
|
}
|
|
|
|
int PortBurn_GetEraseStatus(void *handle, float *out_fraction_complete)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].GetEraseStatus(h->realhandle, out_fraction_complete);
|
|
}
|
|
|
|
/* */
|
|
int PortBurn_GetMediaState(void *handle, int *state)
|
|
{
|
|
PBHandle *h = (PBHandle *) handle;
|
|
|
|
if (h == NULL) {
|
|
return pbErrNoHandle;
|
|
}
|
|
|
|
return vectors[h->ver].GetMediaState(h->realhandle, state);
|
|
}
|