Beispiel #1
0
int flowm_say_text(TCHAR *text)
{
    char *s;
    int ns;
    cst_voice *v;

    if (previous_wave)
    {
        delete_wave(previous_wave);
        previous_wave = NULL;
    }

    s = cst_wstr2cstr(text);               /* text to synthesize */
    v = VoxDefs[flowm_selected_voice].v;   /* voice to synthesize with */

    feat_remove(v->features,"print_info_relation");
    if (flowm_selected_relation == 1)
        feat_set_string(v->features, "print_info_relation", "Word");
    if (flowm_selected_relation == 2)
        feat_set_string(v->features, "print_info_relation", "Segment");

    /* Do the synthesis */
    previous_wave = flite_text_to_wave(s,v);

    ns = cst_wave_num_samples(previous_wave);

    cst_free(s);
    audio_flush(fl_ad);
    audio_close(fl_ad); 
    fl_ad = NULL;

    return ns;
}
Beispiel #2
0
/**
 * Notification that some other connection has started playing on this account.
 * Playback has been stopped.
 *
 * @sa sp_session_callbacks#play_token_lost
 */
static void SP_CALLCONV play_token_lost(sp_session *sess)
{
    audio_flush();

    if (g_currenttrack != NULL) {
        sp_session_player_unload(g_sess);
        g_currenttrack = NULL;
    }
}
Beispiel #3
0
static int audio_in_open(struct inode *inode, struct file *file)
{
	struct audio_in *audio = &the_audio_in;
	int rc;

	mutex_lock(&audio->lock);
	if (audio->opened) {
		rc = -EBUSY;
		goto done;
	}

	/* Settings will be re-config at AUDIO_SET_CONFIG,
	 * but at least we need to have initial config
	 */
	audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_11025;
	audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_11025;
	audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
	audio->buffer_size = MONO_DATA_SIZE;
	audio->type = AUDREC_CMD_TYPE_0_INDEX_WAV;

	/* For AAC, bit rate hard coded, default settings is
	 * sample rate (11025) x channel count (1) x recording quality (1.75)
	 * = 19293 bps  */
	audio->bit_rate = 19293;
	audio->record_quality = 0x1c00;

	rc = audmgr_open(&audio->audmgr);
	if (rc)
		goto done;
	rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
				&audpre_adsp_ops, audio);
	if (rc)
		goto done;
	rc = msm_adsp_get("AUDRECTASK", &audio->audrec,
			   &audrec_adsp_ops, audio);
	if (rc)
		goto done;

	audio->dsp_cnt = 0;
	audio->stopped = 0;
	audio->buffer_cfg_ioctl = 0; /* No valid ioctl set */

	audio_flush(audio);

	file->private_data = audio;
	audio->opened = 1;
	rc = 0;
done:
	mutex_unlock(&audio->lock);
	return rc;
}
Beispiel #4
0
static int audio_open(struct inode *inode, struct file *file)
{
	struct audio *audio = &the_audio;
	int rc, cnt;

	mutex_lock(&audio->lock);

	if (audio->opened) {
		MM_ERR("busy as driver already in open state\n");
		rc = -EBUSY;
		goto done;
	}

	if (!audio->data) {
		audio->data = kmalloc(BUFSZ, GFP_KERNEL);
		if (!audio->data) {
			MM_ERR("could not allocate buffers\n");
			rc = -ENOMEM;
			goto done;
		}
	}

	audio->client = msm_rpc_register_client("voice_pcm_interface_client",
				SND_VOC_PCM_INTERFACE_PROG,
				SND_VOC_PCM_INTERFACE_VERS, 1,
				pcm_interface_process_callback_routine);
	if (IS_ERR(audio->client)) {
		MM_ERR("Failed to register voice pcm interface client"\
			"to 0x%8x\n", SND_VOC_PCM_INTERFACE_PROG);
		kfree(audio->data);
		audio->data = NULL;
		rc = -ENODEV;
		goto done;
	}
	MM_INFO("voice pcm client registred %p\n", audio->client);
	for (cnt = 0; cnt < MAX_VOC_FRAMES; cnt++) {
		audio->out[cnt].data = (audio->data +\
					((MAX_VOC_FRAME_SIZE * 2) * cnt));
		audio->out[cnt].size = MAX_VOC_FRAME_SIZE * 2;
		MM_DBG("data ptr = %p\n", audio->out[cnt].data);
	}
	file->private_data = audio;
	audio_flush(audio);
	audio->opened = 1;
	rc = 0;
done:
	mutex_unlock(&audio->lock);
	return rc;
}
Beispiel #5
0
static int audio_in_release(struct inode *inode, struct file *file)
{
	struct audio_in *audio = file->private_data;

	mutex_lock(&audio->lock);
	audio_in_disable(audio);
	audio_flush(audio);
	msm_adsp_put(audio->audrec);
	msm_adsp_put(audio->audpre);
	audio->audrec = NULL;
	audio->audpre = NULL;
	audio->opened = 0;
	mutex_unlock(&audio->lock);
	return 0;
}
Beispiel #6
0
CShairPlay::~CShairPlay(void)
{
	audio_flush(this, NULL);
	initialized = false;
	*active = false;
	sem_post(&sem);
	sem_post(&audioSem);
	while (threadId && audioThreadId)
		usleep(100000);
	g_RCInput->killTimer(secTimer);
	g_RCInput->killTimer(coverArtTimer);
	sem_destroy(&sem);
	sem_destroy(&audioSem);
	pthread_mutex_destroy(&videoMutex);
	pthread_mutex_destroy(&audioMutex);
}
static int audio_in_open(struct inode *inode, struct file *file)
{
	struct audio_in *audio = &the_audio_in;
	int rc;

	mutex_lock(&audio->lock);
	if (audio->opened) {
		rc = -EBUSY;
		goto done;
	}

	/* Settings will be re-config at AUDIO_SET_CONFIG,
	 * but at least we need to have initial config
	 */
	audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_11025;
	audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_11025;
	audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
	audio->buffer_size = MONO_DATA_SIZE;
	audio->type = AUDREC_CMD_TYPE_0_INDEX_WAV;

	rc = audmgr_open(&audio->audmgr);
	if (rc)
		goto done;
	rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
			&audpre_adsp_ops, audio);
	if (rc)
		goto done;
	rc = msm_adsp_get("AUDRECTASK", &audio->audrec,
			&audrec_adsp_ops, audio);
	if (rc)
		goto done;

	audio->audmgr.handle = 0xFFFF;
	audio->dsp_cnt = 0;
	audio->stopped = 0;

	audio_flush(audio);

	file->private_data = audio;
	audio->opened = 1;
	rc = 0;
done:
	mutex_unlock(&audio->lock);
	return rc;
}
Beispiel #8
0
/**
 * Called on various events to start playback if it hasn't been started already.
 *
 * The function simply starts playing the first track of the playlist.
 */
static void try_jukebox_start(void)
{
    sp_track *t;

    if (!g_jukeboxlist)
        return;

    if (!sp_playlist_num_tracks(g_jukeboxlist)) {
        fprintf(stderr, "jukebox: No tracks in playlist. Waiting\n");
        return;
    }

    if (sp_playlist_num_tracks(g_jukeboxlist) < g_track_index) {
        fprintf(stderr, "jukebox: No more tracks in playlist. Waiting\n");
        return;
    }

    t = sp_playlist_track(g_jukeboxlist, g_track_index);

    if (g_currenttrack && t != g_currenttrack) {
        /* Someone changed the current track */
        audio_flush();
        sp_session_player_unload(g_sess);
        g_currenttrack = NULL;
    }

    if (!t)
        return;

    if (sp_track_error(t) != SP_ERROR_OK)
        return;

    if (g_currenttrack == t)
        return;

    g_currenttrack = t;

    printf("jukebox: Now playing \"%s\"...\n", sp_track_name(t));
    fflush(stdout);

    sp_session_player_load(g_sess, t);
    sp_session_player_play(g_sess, 1);
}
Beispiel #9
0
int do_layer2(struct mpstr *mp,struct frame *fr,int outmode,struct audio_info_struct *ai)
{
  int clip=0;
  int i,j;
  int stereo = fr->stereo;
  real fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */
  unsigned int bit_alloc[64];
  int scale[192];
  int single = fr->single;

  II_select_table(fr);
  fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ?
     (fr->mode_ext<<2)+4 : fr->II_sblimit;

  if(stereo == 1 || single == 3)
    single = 0;

  II_step_one(bit_alloc, scale, fr);

  for (i=0;i<SCALE_BLOCK;i++) 
  {
    II_step_two(bit_alloc,fraction,scale,fr,i>>2);
    for (j=0;j<3;j++) 
    {
      if(single >= 0)
      {
        clip += (fr->synth_mono) (fraction[single][j],pcm_sample,&pcm_point);
      }
      else {
          int p1 = pcm_point;
          clip += (fr->synth) (fraction[0][j],0,pcm_sample,&p1);
          clip += (fr->synth) (fraction[1][j],1,pcm_sample,&pcm_point);
      }

      if(pcm_point >= audiobufsize)
        audio_flush(outmode,ai);
    }
  }

  return clip;
}
Beispiel #10
0
int flowm_say_file(TCHAR *tfilename)
{
    int rc = 0;
    char *filename;
    cst_voice *v;
    
    if (previous_wave)
    {   /* This is really tidy up from Play -- but might say space */
        delete_wave(previous_wave);
        previous_wave = NULL;
    }

    if (fl_ad)
    {
        MessageBoxW(0,L"audio fd still open",L"SayFile",0);
        audio_close(fl_ad); 
        fl_ad = NULL;
    }

    v = VoxDefs[flowm_selected_voice].v;

    /* Where we want to start from */
    feat_set_int(v->features, "file_start_position", flowm_file_pos);

    /* Only do print_info in play mode */
    feat_remove(v->features,"print_info_relation");

    filename = cst_wstr2cstr(tfilename);
    rc = flite_file_to_speech(filename, v, "stream");
    cst_free(filename);

    audio_flush(fl_ad);
    audio_close(fl_ad); 
    fl_ad = NULL;

    return rc;

}
Beispiel #11
0
static long audio_in_ioctl(struct file *file,
				unsigned int cmd, unsigned long arg)
{
	struct audio_in *audio = file->private_data;
	int rc;

	if (cmd == AUDIO_GET_STATS) {
		struct msm_audio_stats stats;
		memset(&stats, 0, sizeof(stats));
		stats.byte_count = atomic_read(&audio->in_bytes);
		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
			return -EFAULT;
		return 0;
	}

	mutex_lock(&audio->lock);
	switch (cmd) {
	case AUDIO_START:
		rc = audio_in_enable(audio);
		break;
	case AUDIO_STOP:
		rc = audio_in_disable(audio);
		audio->stopped = 1;
		break;
	case AUDIO_FLUSH:
		if (audio->stopped) {
			/* Make sure we're stopped and we wake any threads
			 * that might be blocked holding the read_lock.
			 * While audio->stopped read threads will always
			 * exit immediately.
			 */
			wake_up(&audio->wait);
			mutex_lock(&audio->read_lock);
			audio_flush(audio);
			mutex_unlock(&audio->read_lock);
		}
	case AUDIO_SET_CONFIG: {
		struct msm_audio_config cfg;
		/* The below code is to make mutual exclusive between
		 * AUDIO_SET_CONFIG and AUDIO_SET_STREAM_CONFIG.
		 * Allow any one IOCTL.
		 */
		if (audio->buffer_cfg_ioctl == AUDIO_SET_STREAM_CONFIG) {
			rc = -EINVAL;
			break;
		}
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		if (cfg.channel_count == 1) {
			cfg.channel_count = AUDREC_CMD_STEREO_MODE_MONO;
		} else if (cfg.channel_count == 2) {
			cfg.channel_count = AUDREC_CMD_STEREO_MODE_STEREO;
		} else {
			rc = -EINVAL;
			break;
		}

		if (cfg.type == 0) {
			cfg.type = AUDREC_CMD_TYPE_0_INDEX_WAV;
		} else if (cfg.type == 1) {
			cfg.type = AUDREC_CMD_TYPE_0_INDEX_AAC;
		} else {
			rc = -EINVAL;
			break;
		}
		audio->samp_rate = convert_samp_rate(cfg.sample_rate);
		audio->samp_rate_index =
		  convert_dsp_samp_index(cfg.sample_rate);
		audio->channel_mode = cfg.channel_count;
		audio->buffer_size =
				audio->channel_mode ? STEREO_DATA_SIZE
							: MONO_DATA_SIZE;
		audio->type = cfg.type;
		audio->buffer_cfg_ioctl = AUDIO_SET_CONFIG;
		rc = 0;
		break;
	}
	case AUDIO_GET_CONFIG: {
		struct msm_audio_config cfg;
		cfg.buffer_size = audio->buffer_size;
		cfg.buffer_count = FRAME_NUM;
		cfg.sample_rate = convert_samp_index(audio->samp_rate);
		if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
			cfg.channel_count = 1;
		else
			cfg.channel_count = 2;
		if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
			cfg.type = 0;
		else
			cfg.type = 1;
		cfg.unused[0] = 0;
		cfg.unused[1] = 0;
		cfg.unused[2] = 0;
		if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		else
			rc = 0;
		break;
	}
	case AUDIO_GET_STREAM_CONFIG: {
		struct msm_audio_stream_config cfg;
		cfg.buffer_size = audio->buffer_size;
		cfg.buffer_count = FRAME_NUM;
		if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		else
			rc = 0;
		break;
	}
	case AUDIO_SET_STREAM_CONFIG: {
		struct msm_audio_stream_config cfg;
		/* The below code is to make mutual exclusive between
		 * AUDIO_SET_CONFIG and AUDIO_SET_STREAM_CONFIG.
		 * Allow any one IOCTL.
		 */
		if (audio->buffer_cfg_ioctl == AUDIO_SET_CONFIG) {
			rc = -EINVAL;
			break;
		}
		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		} else
			rc = 0;
		audio->buffer_size = cfg.buffer_size;
		/* The IOCTL is only of AAC, set the encoder as AAC */
		audio->type = 1;
		audio->buffer_cfg_ioctl = AUDIO_SET_STREAM_CONFIG;
		break;
	}
	case AUDIO_GET_AAC_ENC_CONFIG: {
		struct msm_audio_aac_enc_config cfg;
		if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
			cfg.channels = 1;
		else
			cfg.channels = 2;
		cfg.sample_rate = convert_samp_index(audio->samp_rate);
		cfg.bit_rate = audio->bit_rate;
		cfg.stream_format = AUDIO_AAC_FORMAT_RAW;
		if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		else
			rc = 0;
		break;
	}
	case AUDIO_SET_AAC_ENC_CONFIG: {
		struct msm_audio_aac_enc_config cfg;
		unsigned int record_quality;
		if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		if (cfg.stream_format != AUDIO_AAC_FORMAT_RAW) {
			MM_ERR("unsupported AAC format\n");
			rc = -EINVAL;
			break;
		}
		record_quality = bitrate_to_record_quality(cfg.sample_rate,
					cfg.channels, cfg.bit_rate);
		/* Range of Record Quality Supported by DSP, Q12 format */
		if ((record_quality < 0x800) || (record_quality > 0x4000)) {
			MM_ERR("Unsupported bit rate \n");
			rc = -EINVAL;
			break;
		}
		if (cfg.channels == 1) {
			cfg.channels = AUDREC_CMD_STEREO_MODE_MONO;
		} else if (cfg.channels == 2) {
			cfg.channels = AUDREC_CMD_STEREO_MODE_STEREO;
		} else {
			rc = -EINVAL;
			break;
		}
		audio->samp_rate = convert_samp_rate(cfg.sample_rate);
		audio->samp_rate_index =
		  convert_dsp_samp_index(cfg.sample_rate);
		audio->channel_mode = cfg.channels;
		audio->bit_rate = cfg.bit_rate;
		audio->record_quality = record_quality;
		MM_DBG(" Record Quality = 0x%8x \n", audio->record_quality);
		rc = 0;
		break;
	}
	default:
		rc = -EINVAL;
	}
	mutex_unlock(&audio->lock);
	return rc;
}
static long audio_in_ioctl(struct file *file,
		unsigned int cmd, unsigned long arg)
{
	struct audio_in *audio = file->private_data;
	int rc;

	if (cmd == AUDIO_GET_STATS) {
		struct msm_audio_stats stats;
		stats.byte_count = atomic_read(&audio->in_bytes);
		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
			return -EFAULT;
		return 0;
	}

	mutex_lock(&audio->lock);
	switch (cmd) {
	case AUDIO_START:
		rc = audio_in_enable(audio);
		break;
	case AUDIO_STOP:
		rc = audio_in_disable(audio);
		audio->stopped = 1;
		break;
	case AUDIO_FLUSH:
		if (audio->stopped) {
			/* Make sure we're stopped and we wake any threads
			 * that might be blocked holding the read_lock.
			 * While audio->stopped read threads will always
			 * exit immediately.
			 */
			wake_up(&audio->wait);
			mutex_lock(&audio->read_lock);
			audio_flush(audio);
			mutex_unlock(&audio->read_lock);
		}
	case AUDIO_SET_CONFIG: {
		struct msm_audio_config cfg;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		if (cfg.channel_count == 1) {
			cfg.channel_count = AUDREC_CMD_STEREO_MODE_MONO;
		} else if (cfg.channel_count == 2) {
			cfg.channel_count = AUDREC_CMD_STEREO_MODE_STEREO;
		} else {
			rc = -EINVAL;
			break;
		}

		if (cfg.type == 0) {
			cfg.type = AUDREC_CMD_TYPE_0_INDEX_WAV;
		} else if (cfg.type == 1) {
			cfg.type = AUDREC_CMD_TYPE_0_INDEX_AAC;
		} else {
			rc = -EINVAL;
			break;
		}
		audio->samp_rate = convert_samp_rate(cfg.sample_rate);
		audio->samp_rate_index = convert_dsp_samp_index(cfg.sample_rate);
		audio->channel_mode = cfg.channel_count;
		audio->buffer_size =
				audio->channel_mode ?
					STEREO_DATA_SIZE : MONO_DATA_SIZE;
		audio->type = cfg.type;
		rc = 0;
		break;
	}
	case AUDIO_GET_CONFIG: {
		struct msm_audio_config cfg;
		cfg.buffer_size = audio->buffer_size;
		cfg.buffer_count = FRAME_NUM;
		cfg.sample_rate = convert_samp_index(audio->samp_rate);
		if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO)
			cfg.channel_count = 1;
		else
			cfg.channel_count = 2;

		if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV)
			cfg.type = 0;
		else
			cfg.type = 1;
		cfg.unused[0] = 0;
		cfg.unused[1] = 0;
		cfg.unused[2] = 0;
		if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		else
			rc = 0;
		break;
	}
	default:
		rc = -EINVAL;
	}
	mutex_unlock(&audio->lock);
	return rc;
}
Beispiel #13
0
void CShairPlay::exec(void)
{
	CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
	g_Zapit->lockPlayBack();

	showingCoverArt = false;
        videoDecoder->ShowPicture(DATADIR "/neutrino/icons/mp3.jpg");
#if 0
        g_Sectionsd->setPauseScanning(true);
#endif

	if (!initialized) {
		lock(&audioMutex);
		while (!audioQueue.empty()) {
			std::list<audioQueueStruct *>::iterator it = audioQueue.begin();
			free(*it);
			audioQueue.pop_front();
		}
		while(!sem_trywait(&audioSem));
		unlock(&audioMutex);
		initialized = true;
		playing = true;
	}

	if (!access(COVERART, R_OK)) {
		g_RCInput->killTimer(coverArtTimer);
		gotCoverArt = true;
		md5_file(COVERART, 1, last_md5sum);
		showCoverArt();
	}

	g_InfoViewer->killTitle();
	showInfoViewer(true);

	int qe_count = 0;
	while (*active && *enabled) {
		neutrino_msg_t msg;
		neutrino_msg_data_t data;
		g_RCInput->getMsg(&msg, &data, 50, false);
		switch(msg) {
			case CRCInput::RC_home:
				*enabled = false;
				*active = false;
				if (threadId) {
					sem_post(&sem);
					pthread_join(threadId, NULL);
					threadId = 0;
				}
				break;
			case CRCInput::RC_plus:
			case CRCInput::RC_minus:
			case CRCInput::RC_spkr:
				CNeutrinoApp::getInstance()->handleMsg(msg, data);
				break;
			case CRCInput::RC_ok:
			case CRCInput::RC_info:
				if (secTimer)
					hideInfoViewer();
				else
					showInfoViewer(true);
				break;
			case CRCInput::RC_standby:
				*enabled = false;
				*active = false;
        			g_RCInput->postMsg(msg, 0 );
				break;
			case NeutrinoMessages::EVT_TIMER:
				if (data == secTimer) {
					infoViewerPeriod--;
					if (infoViewerPeriod < 1)
						hideInfoViewer();
					else
						showInfoViewer();
				} else if (data == coverArtTimer) {
					hideCoverArt();
					g_RCInput->killTimer(coverArtTimer);
				}
				// break;
			case CRCInput::RC_timeout:
				lock(&audioMutex);
				if (audioQueue.empty()) {
					qe_count++;
					if (qe_count > 3)
						*active = false;
				} else
					qe_count = 0;
				unlock(&audioMutex);
				break;
			default:
				;
		}
	}
	audio_flush(this, NULL);
	gotCoverArt = false;
	hideCoverArt();
	if (initialized) {
		initialized = false;
	}
	if (secTimer) {
		hideInfoViewer();
		secTimer = 0;
	}
	g_RCInput->killTimer(coverArtTimer);
	lock(&videoMutex);
        CNeutrinoApp::getInstance()->handleMsg(NeutrinoMessages::EVT_PROGRAMLOCKSTATUS, (neutrino_msg_data_t) 0x200);
#if 0
        g_Sectionsd->setPauseScanning(false);
#endif
        videoDecoder->StopPicture();
	firstAudioPacket = true;
	unlock(&videoMutex);
	g_Zapit->Rezap();
	CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
}
Beispiel #14
0
static int video_do_keystroke(GR_EVENT * event)
{
	int ret = 0;

	switch(event->type) {
	case GR_EVENT_TYPE_KEY_DOWN:
		switch (event->keystroke.ch) {
		case 'm': /* Free and exit */
			video_status = VIDEO_CONTROL_MODE_EXITING;
			break;
		case '2':
		case 'r': /* Scroll right/down */
			if (video_status==VIDEO_CONTROL_MODE_SEARCH) {
				video_curPosition+=(.01*mainHeader.dwTotalFrames);
			} else  {
				video_vol_delta++;
			}
			if (video_curPosition > mainHeader.dwTotalFrames) {
				video_curPosition = mainHeader.dwTotalFrames;
			}
			break;
		case '3':
		case 'l': /* Scroll left/up */
			if (video_status==VIDEO_CONTROL_MODE_SEARCH) {
				video_curPosition-=(.01*mainHeader.dwTotalFrames);
			} else {
				video_vol_delta--;
			}

			if (video_curPosition < 0) {
				video_curPosition = 0;
			}
			break;
		case '\r':
		case '\n':
			if ((video_status == VIDEO_CONTROL_MODE_RUNNING) || (video_status==VIDEO_CONTROL_MODE_GLOBALPAUSED)) {
				video_status = VIDEO_CONTROL_MODE_SEARCH;
			}
			else if (video_status == VIDEO_CONTROL_MODE_SEARCH) {
				audio_flush();	
				video_seek(((double)video_curPosition/mainHeader.dwTotalFrames) * (frameendoff - framestartoff) + framestartoff);
				video_status = VIDEO_CONTROL_MODE_RUNNING;
			} else {
				video_status = VIDEO_CONTROL_MODE_RUNNING;
			}
		case 'w': /* Zoom out */
			break;
		case 'f': /* Zoom in */
			break;
		case '1':
		case 'd': /* Zoom fit/actual */
			if (video_status == VIDEO_CONTROL_MODE_GLOBALPAUSED) {
				audio_flush();
				video_status = VIDEO_CONTROL_MODE_RUNNING;
			}
			else if (video_status != VIDEO_CONTROL_MODE_SEARCH) {
				video_status = VIDEO_CONTROL_MODE_GLOBALPAUSED;
			}
			break;
		default:
			ret = 0;
			break;
		}
		break;
	}
	
	return ret;
}