Ejemplo n.º 1
0
//------------------------------------------------------------------------------
size_t MpqHandler::addFile( const std::string &filename ) {
  mpq_archive_s *mpq_arc = NULL;
  uint8_t *buffer = NULL;
  char *context = NULL;
  
  // get file list from MPQ archive
  if ( getListFile( filename, &mpq_arc, &buffer ) < 0 ) return false;

  size_t num_files = _mpqArchiveMap.size();
  std::string add_fn;
  // get all filenames from the buffer
  for( const char *fn = strtok_r( (char*)buffer, "\r\n", &context );
        fn != NULL;
        fn = strtok_r( NULL, "\r\n", &context ) ) {
    // transform filename to lower case
    add_fn = fn;
    std::transform( add_fn.begin(), add_fn.end(), add_fn.begin(), ::tolower );
    // insert filename in map and associate mpq archive with it so we can get the
    // correct version of the file
    _mpqArchiveMap.insert( MpqArchivePair_t( add_fn, mpq_arc ) );
  }

  delete [] buffer;
  
  // return the number of files we've added
  return _mpqArchiveMap.size() - num_files;
}
Ejemplo n.º 2
0
static int recordAudio(char *pkgName, char *cursor) {
	int handle, ret = -1;
	char temp[PATH_LENGTH];
	char filepath[PATH_LENGTH];
	long start, end, prev;
	CtnrFile *file;
	int key;
	
	strcpy(filepath,USER_PATH);
	strcat(filepath,pkgName);
	strcat(filepath,AUDIO_FILE_EXT);
		
	file = getListFile(cursor);
	insertSound(file,NULL,TRUE);
	start = getRTCinSeconds();
	strcpy(temp,"\x0d\x0a");
	longToDecimalString(start,temp+2,5);
	strcat(temp,(const char *)": RECORD ");
	LBstrncat(temp,pkgName,60);
	LBstrncat(temp," -> ",60);
	LBstrncat(temp,cursor,60);	
	logString(temp,BUFFER);
	insertSound(&pkgSystem.files[SPEAK_SOUND_FILE_IDX],NULL,TRUE);
	stop();
	start = getRTCinSeconds();
	prev = end = start;
	handle = tbOpen((LPSTR)filepath,O_CREAT|O_RDWR);
	if (handle != -1) {
		setLED(LED_RED,TRUE);
		playBip();
		while (SACM_Status());
		Snd_SACM_RecFAT(handle, C_CODEC_AUDIO1800, BIT_RATE);
		do {
			end = getRTCinSeconds();	
			if (0==(end%2) && (prev != end)) { // blink LED every three seconds
				prev = end;
				setLED(LED_RED,FALSE);
				wait (100);
				setLED(LED_RED,TRUE);
			}
			key = keyCheck(0);
			if (key == KEY_PLAY) { // pause  TODO: this key press to pause shouldn't be hard coded
				SACM_Pause();
				setLED(LED_RED,FALSE);
				do
					key = keyCheck(0);
				while (key != KEY_PLAY && key != KEY_STAR);					
				setLED(LED_RED,TRUE);
				SACM_Resume();
			}
		} while (key != KEY_STAR); // TODO: this key press to stop shouldn't be hard coded
//		while ((end - start) < 3) { // must be at least 2.0 second recording
//			end = getRTCinSeconds();			
//		}
		SACM_Stop();		//Snd_Stop(); // no need to call stop() and flush the log
		//lseek(handle, 6, SEEK_SET );			//Seek to the start of the file input
		//write(handle,(LPSTR)header<<1,6);
		close(handle);
//		*P_WatchDog_Ctrl &= ~0x8000; // clear bit 15 to disable
		setLED(LED_RED,FALSE);
		insertSound(&pkgSystem.files[BEEP_SOUND_FILE_IDX],NULL,TRUE); 
		insertSound(file,NULL,TRUE);  // replay subject

		strcpy(temp,"TIME RECORDED (secs): ");
		longToDecimalString((long)end-start,temp+strlen(temp),4);
		strcat(temp,"\x0d\x0a");
		logString(temp,BUFFER);

		strcpy(lastFilenameRecorded,filepath);
		ret = 0;  // used to set this based on fileExists() check, but too slow
	} else {
		logException(16, filepath,RESET);  //can't open file for new recording
	}
	return ret;
}	
Ejemplo n.º 3
0
static void takeAction (Action *action, EnumAction actionCode) {
	unsigned int newTime, oldTime; 
	unsigned long longNewTime, longOldTime;
	int newIdxTimeframe, tempTime;
	CtnrFile *newFile;
	CtnrBlock *newBlock, *soundInsertBlock;
	int newIdxAction;
	EnumAction newActionCode;
	EnumBorderCrossing direction;
	signed long l;	
	int destination, aux, i, ret;
	int status;
	BOOL reposition = FALSE;
	BOOL isTooFar = FALSE;
	ListItem *list, *tempList;
	char filename[PATH_LENGTH];
	char *cursor, *cursor2;
	CtnrFile *replayFile;
		
	replayFile = NULL;
	list = NULL;
	oldTime = compressTime(Snd_A1800_GetCurrentTime(),context.package->timePrecision);
	newFile = 0;
	newTime = -1;
	newBlock = 0;
		
	if (actionCode == -1)
		actionCode = getActionCode(action);
	if (action) {
		aux = action->aux;
		destination = action->destination;
	}
		
	switch (actionCode) {
		case JUMP_LIST:
			stop();
			list = &context.package->lists[destination];
			context.idxActiveList = destination;
			switch (getListRotation(aux)) {
				case 0:
				    cursor = getCurrentList(list);
				    strcpy(filename,cursor);
					break;
				case 1:
				    strcpy(filename,getNextList(list,TRUE));
					break;
				case -1:
				    strcpy(filename,getPreviousList(list));
					break;
			}
			if (!filename[0]) { 
				// empty list
				insertSound(&pkgSystem.files[EMPTY_LIST_FILE_IDX],NULL,FALSE);
				// empty list of packages; redirect to current point in list of lists
				list = &context.package->lists[0];
				context.idxActiveList = 0;
			    cursor = getCurrentList(list);
			    strcpy(filename,cursor);
			} 
			if (list->listType == LIST_OF_PACKAGES) {
				// load package
				switch (filename[0]) {
					case SYS_PKG_CHAR:
						context.queuedPackageType = PKG_SYS;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					case APP_PKG_CHAR:
						context.queuedPackageType = PKG_APP;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					default:
						context.queuedPackageType = PKG_MSG;
						destination = replaceStack(filename,&pkgSystem);
						break;
				}
				context.queuedPackageNameIndex = destination;
			} else { // list->listType != LIST_OF_PACKAGES
				// play sound of subject
				newFile = getListFile(filename);
				newTime = 0;
				reposition = TRUE;
			}
			break;
		
		case JUMP_PACKAGE:
			if (aux == PKG_VARIABLE) {
				strcpy(filename,getCurrentList(&pkgSystem.lists[destination]));
				switch (filename[0]) {
					case SYS_PKG_CHAR:
						aux = PKG_SYS;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					case APP_PKG_CHAR:
						aux = PKG_APP;
						destination = replaceStack(filename+1,&pkgSystem);
						break;
					default:
						aux = PKG_MSG;
						destination = replaceStack(filename,&pkgSystem);
						break;
				}
			}
			context.queuedPackageType = aux;
			context.queuedPackageNameIndex = destination;
			break;  // sets up main loop to handle this, rather than building up a stack overflow

		case COPY:
			stop();
			tempList = &context.package->lists[destination];
			getListFilename(filename,destination,FALSE);
			cursor = getCurrentList(tempList);
			if (PRE_COPY_FILE_IDX)
				insertSound(&pkgSystem.files[PRE_COPY_FILE_IDX],NULL,TRUE);  
			ret = d2dCopy((const char *)filename,(const char *)cursor);
			if (ret == 0 && POST_COPY_FILE_IDX) 
				insertSound(&pkgSystem.files[POST_COPY_FILE_IDX],NULL,TRUE); 
//			newBlock = &context.package->blocks[aux];
//			newTime = newBlock->startTime;
//			reposition = TRUE;
			break;		

		case DELETE:
			stop();
			tempList = &context.package->lists[destination];
			getListFilename(filename,destination,TRUE);
			cursor = getCurrentList(tempList);			
			ret = findDeleteStringFromFile(LIST_PATH,filename,cursor,TRUE);
			tempList->currentFilePosition = -1; // forces next list action to reload
			if (ret != -1)
				ret = deletePackage(cursor);
			else
				logException(29,cursor,0);

			list = &context.package->lists[aux];
			context.idxActiveList = aux;
			newFile = getListFile(getCurrentList(list));
			newTime = 0;
			reposition = TRUE;

//			newBlock = &context.package->blocks[aux];
//			newTime = newBlock->startTime;
//			reposition = TRUE;
			break;
			
		case TRIM:
			stop();
			tempList = &context.package->lists[destination];
			cursor = getCurrentList(tempList);
			strcpy(filename,USER_PATH);
			strcat(filename,cursor);  //todo: address application packages
			strcat(filename,AUDIO_FILE_EXT);
			edit(filename);
			context.queuedPackageType = PKG_MSG;
			destination = replaceStack(cursor,context.package);
			context.queuedPackageNameIndex = destination;
			break;
			
		case SPEED_UP:
			adjustSpeed(SPEED_INCREMENT,TRUE);
			break;

		case SPEED_DOWN:
			adjustSpeed(-SPEED_INCREMENT,TRUE);
			break;

		case SPEED_NORMAL:
			adjustSpeed(NORMAL_SPEED,FALSE);
			break;

		case VOLUME_UP:
			adjustVolume(VOLUME_INCREMENT,TRUE,FALSE);
			break;

		case VOLUME_DOWN:
			adjustVolume(-VOLUME_INCREMENT,TRUE,FALSE);
			break;

		case VOLUME_NORMAL:
			adjustVolume(NORMAL_VOLUME,FALSE,FALSE);
			break;

		case LED_RED_ON:
			setLED(LED_RED,TRUE);
			break;	
			
		case LED_RED_OFF:
			setLED(LED_RED,FALSE);
			break;	

		case LED_GREEN_ON:
			setLED(LED_GREEN,TRUE);
			break;
			
		case LED_GREEN_OFF:	
			setLED(LED_GREEN,FALSE);
			break;

		case LED_ALL_ON:
			setLED(LED_ALL,TRUE);	
			break;	

		case LED_ALL_OFF:
			setLED(LED_ALL,TRUE);
			break;
			
		case USB_DEVICE_ON:
			setUSBDevice(TRUE);
			newBlock = &context.package->blocks[destination];
			newTime = newBlock->startTime;
			reposition = TRUE;
			break;	
					
		case USB_HOST_ON:
/*			stop();
			setUSBDevice(TRUE);
			newBlock = &context.package->blocks[destination];
			newTime = newBlock->startTime;
			reposition = TRUE;
*/			break;	
					
		case STOP:
			stop();
			enterOrExitAllBlocks(context.idxTimeframe,EXITING);
			break;

		case PLAY_PAUSE:
			status = SACM_Status();
			switch (status) {
				case 0:
//					if (context.package->pkg_type != PKG_SYS)
						markStartPlay(Snd_A1800_GetCurrentTime(),context.package->strHeapStack+context.package->idxName);
					if (context.idxActiveList == -1) {
						enterOrExitAllBlocks(context.idxTimeframe,ENTERING);
						i = getStartingBlockIdxFromTimeline(context.idxTimeframe);
						if (i != -1) 
							processStartBlock(i);
						play(context.file,getCurrentTimeframeStart());
					} else
						play(context.file,0);
					break;
				case C_SACM_RECORD:
				case C_SACM_PLAY:
					context.isPaused = TRUE;
					pause();
					break;
				case C_SACM_PAUSE:
					context.isPaused = FALSE;
					resume();	
					break;
				default:
					if (context.isPaused) {
						context.isPaused = FALSE;
						resume();	
					} else {
						context.isPaused = TRUE;
						pause();
					}		
					break;
			}
			break;
			
		case PAUSE:
			pause();
			context.isPaused = TRUE;
			break;
			
		case RECORD_TITLE: // deprecated
		case RECORD_MSG:
			stop();
/*			// Not currently allowing sound inserts before record commands since aux is used for recording from another headphone jack
			// Although the SPINS part of the headphone jack thing isn't currently working.
			if (action && hasSoundInsert(action)) {
				soundInsertBlock = &pkgSystem.blocks[getSoundInsertIdxFromAux(aux)];
				insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,TRUE);
				wait(500);
			}
*/
			if(vCur_1 < V_MIN_RECORD_VOLTAGE) {
				refuse_lowvoltage(0);
				break;
			}
			
			cursor = getCurrentList(&pkgSystem.lists[context.package->idxMasterList]);
			do {
				strcpy(filename,USER_PATH);
				getPkgNumber(filename+strlen(USER_PATH),TRUE);
				strcat(filename,(const char *)CATEGORY_DELIM_STR);
				strcat(filename,cursor); // adds current listname to new recording name
				cursor2 = filename + strlen(filename);
				strcat(filename,AUDIO_FILE_EXT);
				ret = fileExists((LPSTR)filename); // this causes approx 1 sec delay!
			} while (ret);
			*cursor2 = 0; // remove extension
			strcpy(filename,filename+strlen(USER_PATH)); //remove path
			
			ret = createRecording(filename,aux,cursor);
			if (ret != -1) {
				destination = replaceStack(filename,context.package);
				context.queuedPackageNameIndex = destination;
				context.queuedPackageType = PKG_MSG;
			} else
				logException(28,"recording failed",RESET); //todo: add voice error msg?
			break;	

		case CALL_BLOCK:
			// TODO: handle error (return of -1) if stack is full
			stackPush(context.package,context.file,oldTime - getRewind(aux)); // times are compressed
			// this is designed to fall through
			
		case JUMP_BLOCK:
			newBlock = &context.package->blocks[destination];
			newTime = newBlock->startTime;
			reposition = TRUE;
			break;
	
		case RETURN:
			if (stackPop(&context.package,&newFile,&newTime))  // times are compressed 
				reposition = TRUE;
			break;

		case FWD:
			newActionCode = getStartEndCodeFromTimeframe(context.idxTimeframe,FORWARD_JUMPING, &newTime, &newIdxAction);
			switch (newActionCode) {
				case NOP:
				case PAUSE:
					break;
				case STOP:
					//rewind to give context before stopping
					newTime -= compressTime(BLOCK_END_LEADER,context.package->timePrecision);
					break;
				case JUMP_BLOCK:
					//follow this link
					newBlock = &context.package->blocks[context.package->actions[newIdxAction].destination];
					newTime = newBlock->startTime;
					break;
				case RETURN:
					stackPop(&context.package,&newFile,&newTime); //todo: double verify there was something on stack (shouldn't have gotten RETURN if not) 
					break;
				default:
					//no action needed
					break;
			}
			reposition = TRUE;
			break;
			
		case BACK:
			// test whether within the start leader to determine whether to go to last start or to previous start before that
			if ((oldTime - getCurrentTimeframeStart()) > compressTime(BLOCK_START_LEADER, context.package->timePrecision)) {
				// just move to start time of same timeframe 
				newTime = getCurrentTimeframeStart(); // must make sure we call the Start event 
			} else {
				newActionCode = getStartEndCodeFromTimeframe(context.idxTimeframe,BACKWARD_JUMPING, &newTime, &newIdxAction);
				switch (newActionCode) {
					case NOP:
					case PAUSE:
					case STOP:
						break;
					case JUMP_BLOCK:
						//follow this link
						newBlock = &context.package->blocks[context.package->actions[newIdxAction].destination];
						newTime = newBlock->startTime;
						break;  
					case RETURN:
						stackPop(&context.package,&newFile,&newTime); //todo: double verify there was something on stack (shouldn't have gotten RETURN if not) 
						break;
					default:
						//no action needed
						break;						
				}
			}
			reposition = TRUE;
			break;

		case JUMP_TIME:
			// skip forward/back from relative position
			// observe block boundary when they exist, but leap beyond them
			// todo:do not leap over newFile boundaries
			// if system package action, reset context to user package for this action
			if (context.returnPackage)
				context.package = context.returnPackage;
			if (context.package != &pkgSystem) {
				longOldTime = Snd_A1800_GetCurrentTime();
				l = (signed long)extractSignedTime(destination,context.package->timePrecision); // hoping this brings back an originally negative number
				longNewTime = longOldTime + l;
				if (l >= 0) 
					direction = FORWARD_JUMPING;
				else {
					direction = BACKWARD_JUMPING;
					if (abs(l) > longOldTime)
						longNewTime = 0;
				}
				newTime = compressTime(longNewTime,context.package->timePrecision);
	
				// check for interfering block events
				newIdxTimeframe = context.idxTimeframe;
				do {
					newActionCode = getStartEndCodeFromTimeframe(newIdxTimeframe,direction, &tempTime, &newIdxAction);
					if (direction == FORWARD_JUMPING) 
						isTooFar = blockTimeline[++newIdxTimeframe].time > newTime;
					else
						isTooFar = blockTimeline[--newIdxTimeframe].time < newTime;
				} while (!isTooFar && newActionCode == NOP);
				switch (newActionCode) {
					case JUMP_BLOCK:
						newBlock = &context.package->blocks[context.package->actions[newIdxAction].destination];
						newTime = newBlock->startTime;
						newFile = getFileFromBlock(newBlock);
						break;  
					case RETURN:
						stackPop(&context.package,&newFile,&newTime); //todo: double verify there was something on stack (shouldn't have gotten RETURN if not) 
						break;
					default:
						//no action needed
						break;
				}
				playActionSound(JUMP_TIME);
				reposition = TRUE;
			} // context is not system file
			break;
		case SLEEP:
			// call sleep function
			setOperationalMode((int)P_SLEEP); 
			break;
		case HALT:
			// call sleep function
			setOperationalMode((int)P_HALT); 
			break;
		case NOP:
			// no operation
			break;
		default:
			//nothing should default here
			logException(1,0,USB_MODE);
			break;
	}
		
	if (reposition) {
		//todo: am i catching every possible change in file?		
		if (newBlock && !newFile) 
			newFile = getFileFromBlock(newBlock);
		if (newFile && newFile != context.file) {
			enterOrExitAllBlocks(context.idxTimeframe,EXITING);
			context.file = newFile;
			if (!list)
				buildBlockTimelines(newFile);
			context.idxTimeframe = -1; // to signal it hasn't been set yet
			context.timeNextTimeframe = -1; // resets this -- necessary for lists that dont go to processTimelineJump
		}
		if (!list) {
			context.idxActiveList = -1;
			newIdxTimeframe = getIdxTimeline(newTime);
			if (newIdxTimeframe != context.idxTimeframe) 
				processTimelineJump(context.idxTimeframe, newIdxTimeframe);  // this resets context.idxTimeframe and context.timeNextTimeframe
		}
	}
	
	// now that context.idxTimeframe has been set for repositions, we can insert sounds
	if (action && hasSoundInsert(action)) {
		if (reposition) 
			stop();  // stop currently playing audio first or insertSound() will return to it
		if (actionCode == JUMP_TIME) {
			if (context.returnPackage)
				context.package = &pkgSystem;
			soundInsertBlock = &context.package->blocks[getSoundInsertIdxFromAux(aux)];
			insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,TRUE);
		}
		else {
			soundInsertBlock = &context.package->blocks[getSoundInsertIdxFromAux(aux)];
			insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,FALSE);
		}
	}
	// process start block action if landing on the start of a new block
	if (reposition && newBlock && newTime == newBlock->startTime)
		processStartBlock(newBlock - context.package->blocks);
	if (list) {
		soundInsertBlock = getStartInsert(list->actionStartEnd, list->idxFirstAction);
		if (soundInsertBlock)
			insertSound(getFileFromBlock(soundInsertBlock),soundInsertBlock,FALSE);
	}		
	if (actionCode == JUMP_TIME && context.returnPackage) {  // returning to user package after possibly inserting a system sound above
		context.package = context.returnPackage;
		context.returnPackage = NULL;
	}
	if (actionCode == SPEED_UP || actionCode == SPEED_DOWN) {
		context.isPaused = FALSE;
		resume();	
	}
	if (reposition)
		play(context.file,newTime); //todo: chg to seek if same file
	//todo: maybe for JUMP_BLOCK (not CALL_BLOCK) , allow offsets within a block (stored in first 13 bits of aux)
}