I have made an sqlite3 database that saves entries that sensors create. I am checking on leaks with valgrind, now I was wondering how to 'simulate' a broken SQL server. I am using this function:
rc = sqlite3_prepare_v2(conn, sql, -1, &res, 0);
This function works correctly, is there a way to simulate it failing? Setting rc to another value manually is an option, but doesn't make sense since a database does get created while the program thinks it doesn't.
I will add the code bellow, although I don't think this is necessary for this question.
This is the insert function that inserts a sensor into the database. This is where I want to test what happens when the prepare function fails.
void *insert_sensor(void *argument) {
storagemgr_insert_argument_t *storagemgr_insert_argument = (storagemgr_insert_argument_t *) argument;
DBCONN *conn = storagemgr_insert_argument->db_connection;
sqlite3_stmt *res = NULL;
uint16_t sensor_id_read;
double temperature_value_read;
time_t timestamp_read;
sensor_data_t data;
int buffer_working_check;
data.id = 0;
data.value = 0;
data.ts = 0;
buffer_working_check = 1;
while (connmgr_loopt_bool == 1 || buffer_working_check == 0) { //connmgr aan -> moet blijven lopen, connmgr uit maar nog data beschikbaar -> moet blijven lopen
pthread_mutex_lock(&lock);
// printf("gelockt in storagemgr\n");
buffer_working_check = sbuffer_read(shared_buffer, &data, 0, 1);
pthread_mutex_unlock(&lock);
int failed_tries = 0;
if (data.id != 0 && buffer_working_check != -1 && buffer_working_check != 1) {
res = NULL;
sensor_id_read = data.id;
temperature_value_read = data.value;
timestamp_read = data.ts;
while(failed_tries<3) {
char *sql = "INSERT INTO "TO_STRING(TABLE_NAME)" (sensor_id, sensor_value, timestamp) VALUES (#sensor_id, #sensor_value, #timestamp)";
rc = sqlite3_prepare_v2(conn, sql, -1, &res, 0);
if (rc == SQLITE_OK) {
int idx1 = sqlite3_bind_parameter_index(res, "#sensor_id");
sqlite3_bind_int(res, idx1, sensor_id_read);
int idx2 = sqlite3_bind_parameter_index(res, "#sensor_value");
sqlite3_bind_double(res, idx2, temperature_value_read);
int idx = sqlite3_bind_parameter_index(res, "#timestamp");
sqlite3_bind_int(res, idx, timestamp_read);
break;
}
else {
write_to_fifo("Insert to the SQL server failed, trying again. ", 4);
failed_tries++;
// char *err_msg = 0;
//
// fprintf(stderr, "Failed to execute statement: %s\n", sqlite3_errmsg(conn));
// sqlite3_free(err_msg);
// sqlite3_close(conn);
// return NULL;
}
sleep(2);
}
}
if (0<failed_tries && failed_tries <= 2) { //het mag =2, want als het =2 en de db faalt dan wordt het eerst geincrementeert naar 3
write_to_fifo("Connection to SQL server re-established. ", 5);
}
if(failed_tries>2) {
db_connection_failed_bool = 1;
sqlite3_close(conn);
write_to_fifo("Connection to SQL server lost. ", 6);
break;
}
if (res != NULL) {
sqlite3_step(res);
sqlite3_finalize(res);
res = NULL;
}
}
return NULL;
}
If you want to keep the code pure, you could always pass the insert function an invalid file path or invalid file name. If you are trying to test the recovery loop, and still want it to remain pure, you can pass the invalid file path and have the recovery loop try to build the path. SQLite won’t build a database in a folder that doesn’t exist when using sqlite3_prepare_v2.
Related
My C application uses SQLite 3.36. I am using WAL mode for my DB. But on inserting ~50K records with 7 columns, the WAL file grows up to 1.5 GB.
I have disabled auto checkpointing and doing manual checkpointing after all insertions.
I already went through many articles which blame checkpointing for the huge WAL size.
But,I guess checkpointing is not the issue here because other tables exist in the same DB where the record count is more than 50k but the WAL file size remains in MBs on insertion.
Before insertion, I am doing deletion but in that case, table contains hardly 2-3 records so WAL size is not impacted much (Confirmed by debugging the code).
During debugging I observed, the WAL size increasing very fast in for loop used for insertion (See below code). Loop completed within seconds.
Below is the code - (Added comments for a few local methods and macros )
Note- Code is running fine without any error and on checkpointing, I am getting desired records in the original DB. No other read operation going on this table during the execution of this routine.
Kindly, help me to know what I am doing wrong here which is causing the WAL file to grow up to 1.5GB.
Is insert after delete causing some issues?
int generatefMap(struct ixdb* xdb)
{
struct fmap* fmap;
uint64_t max_id, size;
int status = 0;
sqlite3_stmt* stmt = NULL;
int stmt_id = 0;
int retry_count = 0;
char* sql = NULL;
max_id = 0;
fmap = NULL;
status = ixdb_largest_id(xdb, &max_id);
if (status != 0 || max_id == 0) {
if (status == E_NOTFOUND) {
status = 0;
}
else {
return E_INVALID;
}
}
sql = "DELETE FROM fmap; ";
status = sqlite3_exec(xdb->dbh->db, sql, NULL, NULL, NULL);
if (status != 0) {
return status;
}
size = (max_id + 1) * sizeof(struct fnode);
fmap = (struct fmap*)mem_alloc(sizeof(struct fmap)); // #define mem_alloc(size) calloc(1, (size))
if (fmap == NULL) {
status = E_MEM;
return status;
}
fmap->hash = (struct fnode*)mem_alloc((size_t)size);// #define mem_alloc(size) calloc(1, (size))
if (fmap->hash == NULL) {
free(fmap);
status = E_MEM;
return status;
}
fmap->size = size;
fmap->max_id = max_id;
status = __fmap_gen(fmap, xdb); //Gives fmap by selecting/querying data from other table in same DB
if (status != 0) {
free(fmap->hash);
free(fmap);
return status;
}
//Insert into DB
stmt_id = XDB_FMAP_INSERT; //INSERT OR REPLACE INTO fmap(id,pid,xt,size,xtime,ytime,selected) values (:id,:pid,:xt,:size,:xtime,:ytime,:selected);
stmt = get_prepared_stmt(xdb, stmt_id); // This will get me prepared statement for above query
for (uint64_t i = 0; i < max_id + 1; ++i) {
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
sqlite3_bind_int64(stmt, 1, (uint64_t)(i + 1));
sqlite3_bind_int64(stmt, 2, fmap->hash[i].pid);
sqlite3_bind_int64(stmt, 3, fmap->hash[i].xtid);
sqlite3_bind_int64(stmt, 4, fmap->hash[i].size);
sqlite3_bind_int64(stmt, 5, fmap->hash[i].xtime);
sqlite3_bind_int64(stmt, 6, fmap->hash[i].ytime);
sqlite3_bind_int64(stmt, 7, fmap->hash[i].selected);
retry:
status = sqlite3_step(stmt);
if (status == SQLITE_BUSY || status == SQLITE_IOERR_BLOCKED) {
printf("sqlite_step returned: %d . Hence retrying ", status);
++retry_count;
if (retry_count <= ATTEMPTS) { //#define ATTEMPTS 5
sleep(SLEEP); //#define SLEEP 1
goto retry;
}
printf("Maximum number of retries(%d) exhausted|stmt=%s|err=%d", ATTEMPTS, sqlite3_expanded_sql(stmt), status);
goto err;
}
else if (status != SQLITE_DONE) {
printf("\nsqlite3_step() failed with error[%d].\n", status);
status = ERR_SQLITE;
goto err;
}
status = 0;
}
if (stmt) {
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
}
err:
if (fmap->hash) {
free(fmap->hash);
fmap->hash = NULL;
}
if (fmap) {
free(fmap);
fmap = NULL;
}
return status;
}
So I have a this program in windows that relies on each other. And I have a loop that checks a certain condition and spawns GTime_mod.exe if the condition is true. As you can see in my code below it has an aux variable coming from a database, the variables default value is 1. Now if GTime_mod.exe is executed the and then when the user were able to give the right username and password, the value of aux will change to 0. Then when the user logout aux will change to 1 again. Now my problem is, I wan't the aux value to change to 1 again besides logging-out. Because there are cases when the **[case 1]** user will just press (X) button to close the program. Or the **[case 2]** user might stop the program by pressing Ctrl + C. And lastly **[case 3]** the user might close the program via task manager. Can anyone please help me or give me a suggestion on how to tackle this problem, your help will be highly appreciated.
int main(void){
sqlite3 *db;
time_t now;
struct tm *local;
int er;
char *sqlCom;
char *errMsg = 0;
hr_mn high,low;
int sdur = 0;
int opt = 0;
int cond = 0;
int aux = 0;
er = sqlite3_open("GTime.db",&db);
if(er != SQLITE_OK) sqlite3_close(db),Err(sqlite3_errmsg(db));
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 1;",hrmn,&low,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 2;",hrmn,&high,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 3;",hrmn,&aux,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
time(&now);
local = localtime(&now);
sdur = 30 - (local->tm_sec <= 30 ? local->tm_sec : (local->tm_sec - 30));
do{
cond = (local->tm_hour >= low.hrs && local->tm_min < low.min) ||
(local->tm_hour <= high.hrs && local->tm_min < high.min);
if(!cond && aux){
spawnl(P_WAIT,"C:\\WINDOWS\\System32\\shutdown.exe","C:\\WINDOWS\\System32\\shutdown.exe","/r /f /t 60 /c \" \"",NULL);
opt = MessageBoxA( NULL, "System is shutting down", "GTime", MB_OKCANCEL|MB_ICONSTOP|MB_SYSTEMMODAL|MB_SETFOREGROUND|MB_TOPMOST );
if(opt == 2){
spawnl(P_WAIT,"GTime_mod.exe","GTime_mod.exe",NULL,NULL);
}else
exit(0);
time(&now);
local = localtime(&now);
sleep(30 - (local->tm_sec <= 30 ? local->tm_sec : (local->tm_sec - 30)));
}else
sleep(sdur);
time(&now);
local = localtime(&now);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 1;",hrmn,&low,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 2;",hrmn,&high,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
er = sqlite3_exec(db,"SELECT * FROM TIMELIM WHERE ROWID = 3;",hrmn,&aux,&errMsg);
if(er != SQLITE_OK) sqlite3_close(db),Err(errMsg);
sdur = 30;
}while(1);
return 0;
}
[Edit]
As for me case 1 is the highest priority to be solved as it is the most likely scenario
From reading the spawnl documentaion you can get the exit value by using the P_WAIT flag.
So you just need to check that response value:
int exit_val;
[...]
exit_val = spawnl( P_WAIT, "GTime_mod.exe","GTime_mod.exe", NULL, NULL);
if ( exit_val == 1 )
{
// manage exit
}
Move the code that changes the value back to 1 to a function, and register the function with atexit so it is always called when exiting the program.
I want to copy data from another thread to struct and print. _tpintf() doesnt show russian letters corret.
in concole I see this, but I expect to see "IN THREAD текст клиент1". Please explain why tchar doesnt work? Also I noticed that if I use _tcprintf, "клиент1" shows correct, but "текст" become wrong
Code of thread function which tries to copy data from another
static DWORD WINAPI StdinInfo(LPVOID param)
{
struct msg msg;
TCHAR buf[1280] = { 0 };
parameters* p = (parameters*)param;
while (TRUE)
{
_fgetts(buf, 1280, stdin);
while (_tcslen(buf) > 0 && buf[_tcslen(buf) - 1] == TEXT('\n'))
buf[_tcslen(buf) - 1] = TEXT('\0');
buf[128] = TEXT('\0');
if (!_tcscmp(buf, TEXT("stop")))
{
//printf("Terminating...\n");
msg.isEmpty = 0;
msg.type = STOP;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
SendMessage(p, &msg);
break;
}
else if (!_tcscmp(buf, TEXT("exit")))
{
msg.isEmpty = 0;
msg.type = DISCONNECT;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
SendMessage(p, &msg);
break;
}
msg.isEmpty = 0;
msg.type = MESSAGE;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
_tprintf(TEXT(" IN TREAD %s %s\n"), msg.message, p->nickName);
SendMessage(p, &msg);
}
return 0;
}
I am completely new to working with PLCs, but I have a project that need fetch data from an OPC client server, then send it to an Access database table. The bulk of the code minus OPCWriteGroupItems was from someone else. I am just lost on transferring the data that the get from OPCReadGroupItems to the proper variables in my function OPCWriteGroupItems. I just want to get the values that are read into the variables. Thanks.
F.Y.I.
My query statement I know needs to be tweaked so that it will read the variables correctly but that is anouther problem that I am working on. This is the more pressing concern.
Below are the two functions that I spoke of:
//---------------------------------------------------------
// Read items from an OPC Group
//---------------------------------------------------------
OPCStat OPCReadGroupItems (int iGrp, struct Var_Stru v[] )
{
HRESULT r1;
HRESULT *hr;
OPCITEMSTATE *is;
int iItem;
OPCStat RetVal=OPCSuccess;
if (pGRPTagSIO[iGrp]) {
if (bOPCDebug) printf("Reading data .... \n");
r1 = pGRPTagSIO[iGrp]->Read(OPC_DS_CACHE,
OPCDataGroup[iGrp].iNumItems,
OPCDataGroup[iGrp].hItem,
&is,
&hr);
if (FAILED(r1)) {
printf("Error from Read(%lx)\n", r1);
RetVal = OPCError;
} else {
// if the read worked then copy results to the v structure based on type
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++ ) {
//printf("Read item= %d, hr= %lx, Quality= %2x", iItem, hr[iItem], is[iItem].wQuality);
if(!FAILED(hr[iItem])) {
// printf("%d", is[iItem].vDataValue.vt);
//printf("%d", iGrp);
switch(is[iItem].vDataValue.vt) {
case VT_I2: // 2
v[iItem].iVal = is[iItem].vDataValue.iVal;
break;
case VT_I4: // 3
v[iItem].lVal = is[iItem].vDataValue.lVal;
break;
case VT_R4: // 4
// printf("Z");
v[iItem].fVal = is[iItem].vDataValue.fltVal;
break;
case VT_R8: // 5
v[iItem].dblVal = is[iItem].vDataValue.dblVal;
break;
case VT_BOOL: // 11
v[iItem].bVal = is[iItem].vDataValue.boolVal;
break;
case VT_UI1: // 11
printf("TEST");
sprintf(v[iItem].cVal, "%s", is[iItem].vDataValue.cVal);
printf("%s", v[iItem].cVal);
printf("%c", v[iItem].cVal);
break;
case VT_BSTR: // 8
// printf("TEST");
sprintf(v[iItem].cVal,"%-.*ls", kOPCStringSize,is[iItem].vDataValue.bstrVal );
//printf("\n STRING STRING %s \n", v[iItem].cVal);
break;
default:
break;
}
}
if(iGrp >= 0 && iGrp <=)
{
stuct_double[iGrp-1][iItem] = v[iItem].dblVal;
// printf("group %d ", iGrp);
// printf("Tag %i: %10.2f\n", iItem, root_plc[iItem]);
}
if(iGrp > 0 && iGrp <= 44)
{
struc_floats[iGrp-1][iItem] = v[iItem].fVal;
//printf("GROUP %d ", iGrp);
//printf("Tag %i: %10.2f\n", iItem, struc_floats[iGrp-1][iItem]);
}
else
{
printf("Error reading data item %d\n", iItem);
//RetVal=OPCError; //Make not as severe -- rjf 06/03/02
RetVal=OPCWarning;
//break; //Escape the for-loop -- rjf- 5/13/02
}
*/
pIMalloc->Free(hr);
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem)
{
VariantClear($is[iItem].vdatavalue)
}
pIMalloc->Free(is);
}
}
else{
RetVal=OPCError;
}
return (RetVal);
}
//-----------------------------------------
// Write items contained in an OPC Group
//-----------------------------------------
OPCStat OPCWriteGroupItems (int iGrp, struct Var_Stru vOut[] )
{
/* Data Access Method used in this sample */
const char* DAM = "Direct ODBC";
/* Connection string for Direct ODBC */
char szDSN[256] = "DSN=Gas_Meter_check;";
HRESULT r1,r2;
HRESULT *hr;
VARIANT v[nMaxOPCItems];
int iItem;
OPCStat RetVal=OPCSuccess;
if (pGRPTagSIO[iGrp]) {
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++) {
v[iItem].vt = OPCDataGroup[iGrp].iType;
switch(OPCDataGroup[iGrp].iType) {
case VT_I2: // 2
v[iItem].iVal = vOut[iItem].iVal;
break;
case VT_I4: // 3
v[iItem].lVal = vOut[iItem].lVal;
break;
case VT_R4: // 4
v[iItem].fltVal = vOut[iItem].fVal;
break;
case VT_R8: // 5
v[iItem].dblVal = vOut[iItem].dblVal;
HENV hEnv; HDBC hDbc;
/* ODBC API return status */ RETCODE rc;
int iConnStrLength2Ptr;
char szConnStrOut[256];
int i= 0;
char datetime[256];
double HMCO=1.0;
double HMR,HMT;
unsigned char* InsertQuery = "INSERT INTO Data ( [Date / Time], [Hot Strip Mill rate], [Hot Strip Mill Comm Okay], [Hot Strip Mill Total] ) SELECT #datetime# AS Expr1, HMR AS Expr2, 1 AS Expr3, HMCO AS Expr4, HMT AS Expr5;";
SQLCHAR chval1[128], chval2[128], colName[128];
int ret1;
int ret2;
/* Number of rows and columns in result set */
SQLINTEGER rowCount = 0;
SQLSMALLINT fieldCount = 0, currentField = 0;
HSTMT hStmt;
/* Allocate an environment handle */
rc = SQLAllocEnv(&hEnv);
/* Allocate a connection handle */
rc = SQLAllocConnect(hEnv, &hDbc);
/* Connect to the TakeCharge database */
rc = SQLDriverConnect(hDbc, NULL, (unsigned char*)szDSN,
SQL_NTS, (unsigned char*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc))
{
printf("%s: Successfully connected to database. Data source name: \n %s\n",
DAM, szConnStrOut);
/* Prepare SQL query */
printf("%s: SQL InsertQuery:\n %s\n", DAM, InsertQuery);
rc = SQLAllocStmt(hDbc,&hStmt);
rc = SQLPrepare(hStmt, InsertQuery, SQL_NTS);
/* Excecute the query and create a record set */
rc = SQLExecute(hStmt);
if (SQL_SUCCEEDED(rc))
{
printf("Executing query...");
printf("\n");
}
while (SQL_SUCCEEDED(rc))
{
printf(" insert passed\n");
rc = SQLFetch(hStmt);
rowCount++;
};
}
else
{
printf("%s: Couldn't connect to %s.\n", DAM, szDSN);
}
/* Disconnect*/
SQLDisconnect(hDbc);
printf("%s: Cleanup. Done.\n", DAM);
break;
case VT_BOOL: // 11
v[iItem].bVal = vOut[iItem].bVal;
break;
case VT_BSTR: // 8
// printf(" In Message value (VT_BSTR) = %s \n",vOut[iItem].cVal );
r2 = LPTSTR_to_BSTR ( &v[iItem].bstrVal , vOut[iItem].cVal);
if ( r2 != S_OK ) {
printf ("error in memory \n");
RetVal = OPCError;
}
// printf(" Write Msg value(VT_BSTR) = %ls \n", v[iItem].bstrVal );
report(0,0,0, "STRINGS data %s",vOut[iItem].cVal);
break;
default:
printf(" value(unknown type:%d) ", OPCDataGroup[iGrp].iType );
RetVal = OPCError;
break;
}
//if (bOPCDebug) DumpVariant(OPCDataGroup[iGrp].cTagNames[iItem], &v[iItem]);
}
r1 = pGRPTagSIO[iGrp]->Write(
OPCDataGroup[iGrp].iNumItems,
OPCDataGroup[iGrp].hItem,
v,
&hr);
if (FAILED(r1))
{
printf("Error from Write(%lx)\n", r1);
RetVal = OPCError;
} else {
//if (bOPCDebug) printf("Successful Write ... \n");
// Clear the Variant
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++) {
VariantClear(&v[iItem]);
}
pIMalloc->Free(hr);
}
} else {
RetVal = OPCError;
}
return(RetVal);
}
C/C++ is not my first language, and I am not familiar with your specific OPC library (there are so many), but according to my understanding of the code you are reading some kind of a variant variable, and with case statements you determine it's type and store it to proper property of v[iItem]. You repeat that in a loop for all tags in that group. There must be some property that tells you the name of the tag you have just read, and you can use it to solve the problem.
For example, if the current tag you are reading is of single float type, then this case section will be executed:
case VT_R4:
v[iItem].fVal = is[iItem].vDataValue.fltVal;
break;
So v[iItem].fVal contains the 4 bytes single float value of the OPC tag. If the current tag you are reading is of double float type, then this case section will be executed:
case VT_R8:
v[iItem].dblVal = is[iItem].vDataValue.dblVal;
break;
and v[iItem].dblVal contains the 8 bytes double float value of the OPC tag. I think you get the picture.
You should really spend some time with OPC DA tutorials on http://www.opcfoundation.org.
I recently inherited a code base that uses quicktime, I've noticed when importing moves using the function below it works most of the time, but then it will occasionally crash. It's weird when it crashes because it work 10 times in a row and then after it would crash the application.
I am using winapi in C for my application.
IDE: Visual Studio 8
OS: Windows 7
Quicktime version: Latest
This is from the Quicktime API Docs:
PutMovieIntoTypedHandle
Takes a movie, or a single track from within that movie, and converts it into a handle of a specified type.
OSErr PutMovieIntoTypedHandle (
Movie theMovie,
Track targetTrack,
OSType handleType,
Handle publicMovie,
TimeValue start,
TimeValue dur,
long flags,
ComponentInstance userComp
);
The Code:
Track newTrack;
FSSpec audioFile;
Movie audioFileMovie;
Track audioFileTrack;
Media audioFileMedia;
TimeValue audioTrackDuration;
long trackCount;
short audioRefNum;
TimeScale audioTimeScale;
OSErr err;
SoundDescriptionHandle outDesc, inDesc;
ComponentInstance soundComp =0;
SndListResource * slr;
SoundHeader * sh;
Handle soundData = NewHandle(0);
long i,sampleOffset,actualSamples, sampleCount;
//Create dataRef from audioFilePath
if((err = NativePathNameToFSSpec(audioFilePath, &audioFile, kErrorIfFileNotFound)) != noErr) {
if(err != fnfErr) {
printf("NativePathNameToFSSpec failed. Error: %d\n", err);
return 0;
}
}
if(noErr != OpenMovieFile(&audioFile, &audioRefNum, fsRdPerm)){
fprintf(stderr, "Couldn't open movie file\n");
return 0;
}
NewMovieFromFile(&audioFileMovie, audioRefNum, NULL, (StringPtr)NULL, newMovieActive, NULL);
if (audioRefNum != 0)
CloseMovieFile(audioRefNum);
//see how many tracks there are in the audioFileMovie
trackCount = GetMovieTrackCount(audioFileMovie);
//Obtain audio track from audio movie
audioFileTrack = GetMovieIndTrack(audioFileMovie, 1);
//Obtain audio media from audioFileTrack so that we can figure out how long it is
audioFileMedia = GetTrackMedia(audioFileTrack);
audioTrackDuration = GetMediaDuration(audioFileMedia);
audioTimeScale = GetMediaTimeScale(audioFileMedia);
soundComp = OpenDefaultComponent('spit', 'snd ');
if(!soundComp)
{
return 1;
}
inDesc=(SoundDescriptionHandle)NewHandle(0);
outDesc=nil;
GetMediaSampleDescription(GetTrackMedia(audioFileTrack),1,(SampleDescriptionHandle)inDesc);
outDesc = (SoundDescriptionHandle) NewHandleClear(sizeof(SoundDescription));
if(!outDesc)
{
CloseComponent(soundComp);
return 1;
}
outDesc[0]->descSize = sizeof(SoundDescription);
outDesc[0]->dataFormat = k8BitOffsetBinaryFormat;
outDesc[0]->numChannels = 1;
outDesc[0]->sampleSize = 8;
outDesc[0]->sampleRate = inDesc[0]->sampleRate;
MovieExportSetSampleDescription(soundComp, (SampleDescriptionHandle)outDesc, 'soun');
DisposeHandle((Handle)inDesc);
DisposeHandle((Handle)outDesc);
if( audioFileMovie && soundData && soundComp )
{
MessageBox(NULL, "Entering \"PutMovieIntoTypedHandle\".\n", "Checkpoint" ,MB_OK);
OSErr result = PutMovieIntoTypedHandle(audioFileMovie,0, 'snd ', soundData, 0, // frameTime,
GetMovieDuration(audioFileMovie), 0, soundComp);
MessageBox(NULL, "Made it passed \"PutMovieIntoTypedHandle\".\n", "Checkpoint" ,MB_OK);
}
else
{
return 1;
}