© Sonic Solutions. All Rights Reserved.
This chapter provides information about working with the functions used to accomplish common tasks handled by PrimoSDK. Example code is provided for two such tasks. The following topics are covered:
For a complete look at the calls required to perform various tasks, refer to the PrimoSDK Function Reference.
3.1 Using Handles | go: top |
PrimoSDK allows use of up to 64 drives simultaneously for a given task, as well as supporting the use of a theoretically unlimited number of devices for different, independent tasks at the same time. The key mechanism enabling this capability is the use of handles (unique resource identifiers) to control each operation. Handles are assigned using PrimoSDK_GetHandle, and released with PrimoSDK_ReleaseHandle.
The following table illustrates the calls involved in setting up two parallel operations, each with their own handle:
PrimoSDK_Init(...) | |
PrimoSDK_GetHandle(&Handle1) | PrimoSDK_GetHandle(&Handle2) |
... operations with Handle1... | ... operations with Handle2... |
PrimoSDK_ReleaseHandle(Handle1) | PrimoSDK_ReleaseHandle(Handle2) |
PrimoSDK_End() |
NOTES:
» It's important for the caller to ensure that different operations associated with different handles do not engage the same drive (or the same SCSI/IDE bus) simultaneously in a way that might disrupt recording.
» In actual practice, PrimoSDK's support for multiple simultaneous operations will be limited by the following hardware-related factors:
- Operations that involve streaming are limited by the data transfer rate of the buss. Streaming performance will suffer if the buss is overloaded with devices (usually much fewer than 64 depending on the buss type).
- The more simultaneous processes, the higher the memory requirements.
- The source of the data is limited by processor speed and source device speed, whether hard drive or optical disc.
3.2 Retrieving Information | go: top |
PrimoSDK functions allow retrieval of several different types of information about drives, discs, and process status:
3.3 Getting Data from Disc | go: top |
PrimoSDK offers a variety of functions that allow the host application to access various forms of content contained on disc (see Reading and Extracting from Disc in Chapter 6):
3.4 Recording to Disc | go: top |
PrimoSDK supports a comprehensive set of operations related to the writing of CDs and DVDs:
3.5 Creating Image Files | go: top |
PrimoSDK supports the building of data structures that may be either written directly to disc (see Data CD Example Code below) or saved to hard disk as a generic or Global Image (.GI) file. The procedure for saving a data structure as an image file involves the following steps:
If the save operation is PrimoSDK_SaveGI, the type (CD or DVD) of image to save is determined by settings in the PrimoSDK_NewImage or PrimoSDK_NewImageWCS call that created the structure:
If the save operation is PrimoSDK_SaveImage, the data structure is saved without any media information (including image type), so values of the PrimoSDK_NewImage/PrimoSDK_NewImageWCS parameters pdwUnits and dwFlags have no effect.
NOTE: To discover the media type and media format of an existing Global Image file, see PrimoSDK_GIInfoEx.
3.6 Data CD Example Code | go: top |
This section illustrates the creation in C of a simple data disc containing one folder (Test Folder) and two files (File1.sys and File2.sys). The code covers the following general steps:
Example C code for the set of operations described above is as follows:
// [1a] DECLARATIONS
DWORD dwRel, dwReply, dwUnit, dwHandle, dwMediumType, dwFlags;
DWORD dwMediumFormat, dwErasable, dwTracks, dwUsed, dwFree, dwSize, dwCur, dwTot;
DWORD dwCommand, dwSense, dwASC, dwASCQ;
DWORD dwUnits[16];
BYTE szBuf[256];
// [1b] INITIALIZE AND GET AN HANDLE
dwReply = PrimoSDK_Init(&dwRel);
dwReply = PrimoSDK_GetHandle(&dwHandle);
// [2] SEE IF DRIVE E: (MUST BE A RECORDER) CONTAINS
// A DISC VALID FOR ADDING DATA
dwUnit = 0x46;
dwReply = PrimoSDK_UnitReady(dwHandle,&dwUnit);
dwReply = PrimoSDK_DiscInfoEx(dwHandle,&dwUnit,&dwFlags, &dwMediumType,&dwMediumFormat,&dwErasable,&dwTracks,&dwUsed,&dwFree);
if ( dwMediumType != PRIMOSDK_BLANK && dwMediumType != PRIMOSDK_COMPLIANTGOLD ) {
MessageBox(hWnd, "We want a blank or an open data disc!", "PrimoSDK Test",MB_OK);
dwReply = PrimoSDK_ReleaseHandle(dwHandle);
dwReply = PrimoSDK_End();
break;
}
// [3] TEST DRIVE STATUS, RESERVE IF AVAILABLE
dwReply = PrimoSDK_UnitVxBlock(dwHandle,&dwUnit,PRIMOSDK_TEST,szAppName);
if (dwReply == PRIMOSDK_NOTREADY) // DRIVE NOT AVAILABLE
{
// ALERT USER THAT DEVICE IS IN USE BY szAppName, END OPERATION
}
if (dwReply == PRIMOSDK_OK) // DRIVE IS AVAILABLE
{
// CALL VXBLOCK TO RESERVE THE DRIVE(S).
dwReply = PrimoSDK_UnitVxBlock(dwHandle, pdwUnit, PRIMOSDK_LOCK, "PrimoSDK Test Application");
}
// [4] BLOCK AIN AND FILE SYSTEM ACTIVITY
dwReply = PrimoSDK_UnitAIN(dwHandle,&dwUnit,PRIMOSDK_LOCK);
// [5a] CREATE A NEW DATA STRUCTURE
dwUnits[0] = 0x46;
dwUnits[1] = 0xFFFFFFFF;
dwReply = PrimoSDK_NewImage(dwHandle,dwUnits,"TESTVOLUME",0,PRIMOSDK_JOLIET,0,"C:\\");
// [5b] ADD A FOLDER AND TWO FILES
dwReply = PrimoSDK_AddFolder(dwHandle,"\\Test Folder");
dwReply = PrimoSDK_AddFile(dwHandle,"\\Test Folder\\File1.sys","c:\\IO.SYS");
dwReply = PrimoSDK_AddFile(dwHandle,"\\Test Folder\\File2.sys","c:\\MSDOS.SYS");
// [6a] START RECORDING
dwReply = PrimoSDK_WriteImage(dwHandle,PRIMOSDK_TEST,PRIMOSDK_MAX,&dwSize);
// [6b] QUERY STATUS WHILE OPERATION IS RUNNING
while ( PrimoSDK_RunningStatus(dwHandle,PRIMOSDK_GETSTATUS,
&dwCur,&dwTot) == PRIMOSDK_RUNNING ) {
wsprintf(szBuf,"Sector %d of %d",dwCur,dwTot);
SetDlgItemText(hWnd,IDC_PROGRESS,szBuf);
Sleep(1000);
}
// [6c] BURN COMPLETED; CHECK IF SUCCESSFUL
dwReply = PrimoSDK_UnitStatus(dwHandle, &dwUnit, &dwCommand, &dwSense, &dwASC, &dwASCQ);
if (dwReply != PRIMOSDK_OK) {
// Notify user that burn failed, providing information
// about dwReply and ASC/ASCQ as necessary.
}
// [7a] OPEN THE DRIVE TRAY
dwReply = PrimoSDK_MoveMedium(dwHandle,&dwUnit,
PRIMOSDK_OPENTRAYEJECT|PRIMOSDK_IMMEDIATE);
// [7b] CLOSE DATA STRUCTURE
dwReply = PrimoSDK_CloseImage(dwHandle);
// [8a] UNBLOCK AIN AND FILE SYSTEM ACTIVITY,
dwReply = PrimoSDK_UnitAIN(dwHandle,&dwUnit,PRIMOSDK_UNLOCK);
// [8b] RELEASE DRIVE
dwReply = PrimoSDK_UnitVxBlock(dwHandle, &dwUnit, PRIMOSDK_UNLOCK, szAppName);
// [9] RELEASE THE HANDLE AND CLOSE PRIMOSDK
dwReply = PrimoSDK_ReleaseHandle(dwHandle);
dwReply = PrimoSDK_End();
3.7 Audio CD Example Code | go: top |
This section illustrates the creation in C of a simple audio disc containing two tracks from source files Chopin.wav and Mina.wav. The code covers the following general steps:
Example C code for the set of operations described above is as follows:
// [1a] DECLARATIONS
DWORD dwRel, dwReply, dwUnit, dwHandle, dwMediumType, dwFlags;
DWORD dwMediumFormat, dwErasable, dwTracks, dwUsed, dwFree, dwSize, dwCur, dwTot;
DWORD dwCommand, dwSense, dwASC, dwASCQ;
DWORD dwUnits[16];
BYTE szBuf[256];
// [1b] INITIALIZE AND GET AN HANDLE
dwReply = PrimoSDK_Init(&dwRel);
dwReply = PrimoSDK_GetHandle(&dwHandle);
// [2] SEE IF DRIVE E: (MUST BE A RECORDER) CONTAINS
// A BLANK DISC
dwUnit = 0x45;
dwReply = PrimoSDK_UnitReady(dwHandle,&dwUnit);
dwReply = PrimoSDK_DiscInfoEx(dwHandle,&dwUnit,&dwFlags, &dwMediumType,&dwMediumFormat,&dwErasable,&dwTracks,&dwUsed,&dwFree);
if ( dwMediumType != PRIMOSDK_BLANK ) {
MessageBox(hWnd, "We want a blank!", "PrimoSDK Test",MB_OK);
dwReply = PrimoSDK_ReleaseHandle(dwHandle);
dwReply = PrimoSDK_End();
break;
}
// [3] TEST DRIVE STATUS, RESERVE IF AVAILABLE
dwReply = PrimoSDK_UnitVxBlock(dwHandle,&dwUnit,PRIMOSDK_TEST,szAppName);
if (dwReply == PRIMOSDK_NOTREADY) // DRIVE NOT AVAILABLE
{
// ALERT USER THAT DEVICE IS IN USE BY szAppName, END OPERATION
}
if (dwReply == PRIMOSDK_OK) // DRIVE IS AVAILABLE
{
// CALL VXBLOCK TO RESERVE THE DRIVE(S).
dwReply = PrimoSDK_UnitVxBlock(dwHandle, pdwUnit, PRIMOSDK_LOCK, "PrimoSDK Test Application");
}
// [4] BLOCK AIN AND FILE SYSTEM ACTIVITY
dwReply = PrimoSDK_UnitAIN(dwHandle,&dwUnit,PRIMOSDK_LOCK);
// [5a] CREATE A NEW AUDIO STRUCTURE
dwUnits[0] = 0x45;
dwUnits[1] = 0xFFFFFFFF;
dwReply = PrimoSDK_NewAudio(dwHandle,dwUnits);
// [5b] ADD TWO TRACKS
dwReply = PrimoSDK_AddAudioTrack(dwHandle,"d:\\data\\class\\Chopin.wav",150,&dwSize);
dwReply = PrimoSDK_AddAudioTrack(dwHandle,"d:\\data\\waves\\Mina.wav",150,&dwSize);
// [6a] START RECORDING
dwReply = PrimoSDK_WriteAudio(dwHandle,PRIMOSDK_TEST,PRIMOSDK_MAX);
// [6b] QUERY STATUS WHILE OPERATION IS RUNNING
while ( PrimoSDK_RunningStatus(dwHandle,PRIMOSDK_GETSTATUS,
&dwCur,&dwTot) == PRIMOSDK_RUNNING ) {
wsprintf(szBuf,"Sector %d of %d",dwCur,dwTot);
SetDlgItemText(hWnd,IDC_PROGRESS,szBuf);
Sleep(1000);
}
// [6c] BURN COMPLETED; CHECK IF SUCCESSFUL
dwReply = PrimoSDK_UnitStatus(dwHandle, &dwUnit, &dwCommand, &dwSense, &dwASC, &dwASCQ);
if (dwReply != PRIMOSDK_OK) {
// Notify user that burn failed, providing information
// about dwReply and ASC/ASCQ as necessary.
}
// [7a] OPEN THE DRIVE TRAY
dwReply = PrimoSDK_MoveMedium(dwHandle,&dwUnit,
PRIMOSDK_OPENTRAYEJECT|PRIMOSDK_IMMEDIATE);
// [7b] CLOSE AUDIO STRUCTURE
dwReply = PrimoSDK_CloseAudio(dwHandle);
// [8a] UNBLOCK AIN AND FILE SYSTEM ACTIVITY,
dwReply = PrimoSDK_UnitAIN(dwHandle,&dwUnit,PRIMOSDK_UNLOCK);
// [8b] RELEASE DRIVE
dwReply = PrimoSDK_UnitVxBlock(dwHandle, &dwUnit, PRIMOSDK_UNLOCK, szAppName);
// [9] RELEASE THE HANDLE AND CLOSE PRIMOSDK
dwReply = PrimoSDK_ReleaseHandle(dwHandle);
dwReply = PrimoSDK_End();
3.8 Trace Logging | go: top |
PrimoSDK's built-in logging capabilities may be used during development to help determine the result of a given call or set of calls, and may also be utilized to support troubleshooting of end-user issues. PrimoSDK currently supports two distinct types of logging:
NOTE: CDB command trace is supported in PrimoSDK version 2.0 or higher.
PrimoSDK's CDB command trace logging has the following characteristics:
The following is an example of CDB command trace logging:
Px::Cmd [ad 00 00 00 00 00 00 00 08 04 00 00 ] <- (no data)
Px::Cmd Sense Error = (SC/SQ=30/02) 70 00 05 00 00 00 00 0a 00 00 00 00 30 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Px::Cmd [bb 00 ff ff ff ff 00 00 00 00 00 00 ]
Px::Cmd [be 00 00 00 00 00 00 00 01 58 00 00 ] <- 00 00 08 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Px::Cmd [55 10 00 00 00 00 00 00 14 00 ] -> 00 00 14 00 00 00 00 00 01 0a 21 01 00 00 00 00 00 00 00 00
Px::Cmd Sense Error = (SC/SQ=26/00) 70 00 05 00 00 00 00 0a 00 00 00 00 26 00 00 80 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00