mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-10-31 14:13:50 +01: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);
 | |
| }
 |