void SjPlayer::DoGetTime(long& totalMs, long& elapsedMs) { if( m_impl->m_currStream ) { totalMs = -1; // if there is a stream, the pos/length may be unknown elapsedMs = -1; int pos_stream = -1, pos_time_ms = -1, length_time_ms = -1; if( xine_get_pos_length(m_impl->m_currStream->GetXineStream(), &pos_stream, &pos_time_ms, &length_time_ms) ) { // for HTTP-streams, xine sometimes returns bad values as 1083696000 or 285440000 for the length, // so, do not allow length > 1 day if( length_time_ms >= 0 && length_time_ms < (24*60*60*1000) ) { totalMs = length_time_ms; } if( pos_time_ms >= 0 ) { elapsedMs = pos_time_ms; } } } else { totalMs = 0; // "no stream" has a length of "0" elapsedMs = 0; } }
gint go (MediaModule *module, gint pos_stream, gint pos_time, gboolean actual) { RfMediaXine *media = RF_MEDIA_XINE (module->widget); gint ps = 0, pt = 0; switch (actual) { case 0: xine_play (media->stream, pos_stream, pos_time); xine_set_param (media->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); xine_set_param (media->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); break; case 1: xine_get_pos_length (media->stream, &ps, &pt, NULL); if (pos_stream == 0) xine_play (media->stream, 0, pt+pos_time); else xine_play (media->stream, ps+pos_stream, 0); xine_set_param (media->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); break; } return (0); }
static void xine_open_and_play(char * file) { int tmp; if(file == NULL){ return; } char * tmp3 = malloc(((sizeof(char) * strlen(file) * 3)) + 1); char * tmp2 = malloc(((sizeof(char) * strlen(file) * 3)) + 7); if(file[0] == '/'){ url_encode(file, tmp3); sprintf(tmp2, "file:/%s", tmp3); }else{ sprintf(tmp2, "%s", file); } xine_close ( stream ); log_debug(tmp2); free(tmp3); if(!xine_open ( stream, tmp2)){ return; } free(tmp2); if(!xine_play ( stream, 0, 0 )){ return; } int count = 0; while ( !xine_get_pos_length ( stream, &tmp, &tmp, &length ) ) // The header file states: "probably because it's not known yet... try again later" { sleepTS.tv_sec = 0; sleepTS.tv_nsec = 10000000; nanosleep(&sleepTS,NULL); //Just try until you get some usefull info count++; if(count>5) break; //log_debug("Sleeping"); } }
static void engine_fwd(int mill, int expFactor, char forward) { if ( engine_state == engine_playing ) { int pos_stream, pos_time; int speedUp = 5; sleepTS.tv_sec = 0; sleepTS.tv_nsec = 20000000; time_t currentWind; time(¤tWind); int count = 0; while( !xine_get_pos_length ( stream, &pos_stream , &pos_time , &length ) ) { nanosleep(&sleepTS,NULL); count++; if(count>5) return; if(engine_state != engine_playing) return; } if ( difftime(currentWind,previousWind) < 2) { windFactor *= (1 + (float) expFactor/1000); } else { windFactor = 1; } time(&previousWind); speedUp = speedUp * (int) windFactor; if(forward){ xine_play( stream , 0 , pos_time + ( mill * speedUp) ); }else{ xine_play( stream , 0 , pos_time - ( mill * speedUp) ); } nanosleep(&sleepTS,NULL); } }
int engine_get_remaining ( void ) { int a, b; if ( !xine_get_pos_length ( stream, &a, &b, &length ) && !length) { return 0; } return ( length - b ) / 1000; }
int engine_get_elapsed ( void ) { int a, b; if ( !xine_get_pos_length ( stream, &a, &b, &length ) ) { return 0; } return b / 1000; }
static int icvSeekRatioAVI_XINE( CvCaptureAVI_XINE* capture, double ratio ) { #ifndef NDEBUG fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... start\n" ); #endif OPENCV_ASSERT ( capture, "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture"); OPENCV_ASSERT ( capture->stream, "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->stream"); OPENCV_ASSERT ( capture->vo_port, "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->vo_port"); // not needed tnx to asserts... // we need a valid capture context and it's stream to seek through // if ( !capture || !capture->stream ) return 0; /// ratio must be [0..1] if ( ratio > 1 || ratio < 0 ) return 0; if ( capture->seekable ) { // TODO: FIX IT, DOESN'T WORK PROPERLY, YET...! int pos_t, pos_l, length; xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length ); fprintf( stderr, "ratio on GetProperty(): %d\n", pos_l ); /// use xinelib's seek functionality if ( xine_play( capture->stream, (int)(ratio*(float)length), 0 ) ) { capture->frame_number = ( int ) ( ratio*length / capture->frame_duration ); } else { #ifndef NDEBUG fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" ); #endif return 0; } } else { /// TODO: fill it ! fprintf( stderr, "icvSeekRatioAVI_XINE(): Seek not supported by stream !\n" ); fprintf( stderr, "icvSeekRatioAVI_XINE(): (seek in stream with NO seek support NOT implemented...yet!)\n" ); #ifndef NDEBUG fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" ); #endif return 0; } #ifndef NDEBUG fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... end!\n" ); #endif return 1; }
gint play (MediaModule *module) { RfMediaXine *media = RF_MEDIA_XINE (module->widget); gint ps=0; xine_get_pos_length (media->stream, &ps, NULL, NULL); xine_play (media->stream, ps, 0); xine_set_param (media->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); return (0); }
gint get_position (MediaModule *module, gint *pos_stream, gint *pos_time, gint *time) { RfMediaXine *media = RF_MEDIA_XINE (module->widget); gint ptime, ttime, w; w = xine_get_pos_length (media->stream, pos_stream, &ptime, &ttime); *pos_time = ptime / 1000; *time = ttime / 1000; return w; }
void Xine::gather_info_internal(){ if (quitting) return; if (!validate_stream()) return; if (file.type == "media-track"){ _title = ""; _artist = ""; _album = ""; } else{ const char *meta_info = xine_get_meta_info(stream, XINE_META_INFO_TITLE); _title = (meta_info) ? meta_info : ""; meta_info = xine_get_meta_info(stream, XINE_META_INFO_ARTIST); _artist = (meta_info) ? meta_info : ""; meta_info = xine_get_meta_info(stream, XINE_META_INFO_ALBUM); _album = (meta_info) ? meta_info : ""; meta_info = xine_get_meta_info(stream, XINE_META_INFO_INPUT_PLUGIN); if (meta_info) /* If it is not a local file, _artist = _album, so that mms doesn't just show the filename */ if (strcasecmp(meta_info, "pluginfile") != 0){ _artist = _album; _album = ""; } } int position_, length_ = 0; for (int t = 0; t < 5; t++){ /* sometimes xine doesn't return a valid position, especially after a seek while playing an audio CD (it sucks) */ xine_get_pos_length(stream, 0, &position_, &length_); if (position_ > 0) break; mmsUsleep(50000); } if (position_ > 0){ _cur_time = position_/1000; _total_time = length_/1000; } /* else { _title = ""; _artist =""; _album = "Buffering..."; } */ //fprintf(stderr, "Gather info internal (position %d)\n", _cur_time); }
void music_pause () { int state; state = xine_get_status (stream); if (state != XINE_STATUS_IDLE) { int pos, time, length; /* length = 0 for streams */ if (!(xine_get_pos_length (stream, &pos, &time, &length) && length)) pos = 0; stream_pos = pos; g_message ("stream_pos: %d", pos); xine_close (stream); } music_playing = FALSE; music_notify_paused (); }
RESULT eServiceXine::getPlayPosition(pts_t &pts) { pts = -1; if (m_state == stError) return 1; ASSERT(stream); int pos_stream, pos_time, length_time; if (!xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time)) return 1; eDebug("pos_time: %d", pos_time); pts = pos_time * 90; // GET POSITION return 0; }
static void xine_open_and_play(char * file) { if(file == NULL) { return; } char * file_uri = malloc(((sizeof(char) * strlen(file) * 3)) + 7); if(file[0] == '/') { char * file_encoded = malloc(((sizeof(char) * strlen(file) * 3)) + 1); url_encode(file, file_encoded); sprintf(file_uri, "file:/%s", file_encoded); free(file_encoded); } else { sprintf(file_uri, "%s", file); } xine_close ( stream ); log_debug_format("engine: %s\n", file_uri); if(!xine_open ( stream, file_uri)){ return; } free(file_uri); if(!xine_play ( stream, 0, 0 )){ return; } int count = 0; int dummy1, dummy2; // The header file states: "probably because it's not known yet... try again later" while ( !xine_get_pos_length ( stream, &dummy1, &dummy2, &length ) ) { sleepTS.tv_sec = 0; sleepTS.tv_nsec = 10000000; nanosleep(&sleepTS,NULL); //Just try until you get some usefull info count++; if(count>5) break; } }
RESULT eServiceXine::getLength(pts_t &pts) { pts = -1; if (m_state == stError) return 1; ASSERT(stream); int pos_stream, pos_time, length_time; if (!xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time)) { eDebug("xine_get_pos_length failed!"); return 1; } eDebug("length: %d ms", length_time); pts = length_time * 90; return 0; }
int framecatcher::open(const std::string& fileName){ int errorCode = 0; /* ensure resources used previous stream have been released */ if(stream != NULL) close(); stream = xine_stream_new(xine,NULL,vo_port); if(stream == NULL) return 0; // open stream if(!xine_open(stream,fileName.c_str())){ errorCode= xine_get_error(stream); return errorCode; } // get length of video file stream is attached to if(!xine_get_pos_length(stream,0,0,&length)){ errorCode = xine_get_error(stream); return errorCode; } xine_play(stream,0,0); const char* temp_codec=xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC); if(temp_codec == NULL) return 0; codec = temp_codec; return 1; }
void SjPlayer::DoGetTime(long& totalMs, long& elapsedMs) { if( m_impl->m_currStream ) { totalMs = -1; // if there is a stream, the pos/length may be unknown elapsedMs = -1; int pos_stream, pos_time_ms, length_time_ms; if( xine_get_pos_length(m_impl->m_currStream->GetXineStream(), &pos_stream, &pos_time_ms, &length_time_ms) ) { if( length_time_ms >= 0 ) { totalMs = length_time_ms; } if( pos_time_ms >= 0 ) { elapsedMs = pos_time_ms; } } } else { totalMs = 0; // "no stream" has a length of "0" elapsedMs = 0; } }
void Xine::run(){ /* this is the main thread */ playing = false; seamless = false; pthread_mutex_lock(&stream_mutex); struct timespec ts = time_helper::compute_interval(5000); Audio_s *audio_state = S_Audio_s::get_instance(); volume = 0; if(validate_stream()) volume = xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME); old_volume = volume; while(!quitting){ xine_request = _XINE_REQUEST_NONE; int ret = pthread_cond_timedwait(&stream_switch, &stream_mutex, &ts); if (!running || quitting){ ts = time_helper::compute_interval(5000); continue; } if (ret != ETIMEDOUT && xine_request == _XINE_REQUEST_NONE) continue; /* we're not done waiting */ /* if (xine_request != _XINE_REQUEST_NONE) fprintf (stderr, "Loop received event request (%d)\n", xine_request); */ switch(xine_request){ case _XINE_REQUEST_PLAY_AT: case _XINE_REQUEST_PLAY:{ retry_track = false; if(!validate_stream()) break; #ifdef XINE_PARAM_EARLY_FINISHED_EVENT if (seamless && xine_check_version(1,1,1) && oldfile.type != "web" && file.type != "web"){ xine_set_param(stream, XINE_PARAM_GAPLESS_SWITCH, 1); } // else{ // xine_close(stream); // } seamless = false; #endif oldfile = file; /* fprintf(stderr, "file.path %s\n", file.path.c_str()); */ std::string _str = file.path; if (file.type == "media-track"){ std::string _path = "cdda:/" + cd_device + "/"; _str = regex_tools::regex_replace(_str, _path.c_str(), "^cdda:/", false, false); /* fprintf(stderr, "%s\n", _str.c_str()); */ } else { vector<string> urls = PlaylistParser::resolve_playlist(_str); if (!urls.empty()) _str = urls[0]; /* TODO: Handle multiple playlist entries here */ } if(!xine_open(stream, _str.c_str())){ #ifdef XINE_PARAM_GAPLESS_SWITCH if (xine_check_version(1,1,1)) xine_set_param(stream, XINE_PARAM_GAPLESS_SWITCH, 0); #endif break; } int len = 0; off_t play_at = 0; const bool has_audio = xine_get_stream_info( stream, XINE_STREAM_INFO_HAS_AUDIO ); const bool audio_handled = xine_get_stream_info( stream, XINE_STREAM_INFO_AUDIO_HANDLED ); if (xine_request == _XINE_REQUEST_PLAY_AT){ xine_get_pos_length(stream, 0, 0, &len); play_at = len > 0 ? static_cast<double>(cur_time*65535)/(len/1000) : 0; } else cur_time = 0; _cur_time = cur_time; total_time = 0; _total_time = 0; if ((has_audio || file.type == "web") && audio_handled && xine_play(stream, play_at, cur_time * 1000)){ playing = true; //gather_info_internal(); audio_state->set_playing(true); buffering_state = 0; } else{ playing = false; audio_state->set_playing(false); xine_close(stream); } audio_state->get_audio()->update_playlist_view(); #ifdef XINE_PARAM_EARLY_FINISHED_EVENT #ifdef XINE_PARAM_GAPLESS_SWITCH if (xine_check_version(1,1,1)){ if (!audio_state->get_audio()->next_helper(false).path.empty()){ xine_set_param(stream, XINE_PARAM_EARLY_FINISHED_EVENT, 1); /* fprintf(stderr, "Not last track\n"); */ #ifdef XINE_PARAM_DELAY_FINISHED_EVENT xine_set_param(stream, XINE_PARAM_DELAY_FINISHED_EVENT, 0); #endif } else { /* If we don't disable XINE_PARAM_DELAY_FINISHED_EVENT for the last track in the playlist, * xine won't play the last couple of seconds of it */ xine_set_param(stream, XINE_PARAM_EARLY_FINISHED_EVENT, 0); /* fprintf(stderr, "Last track\n"); */ } } #endif #endif if (start_paused){ start_paused = false; audio_state->set_pause(true); } else audio_state->set_pause(false); break; } case _XINE_REQUEST_STOP: case _XINE_REQUEST_RELEASE_DEVICE: retry_track = false; seamless = false; if(stream){ xine_close(stream); xine_event_dispose_queue(event_queue); event_queue = NULL; xine_dispose(stream); stream = NULL; } playing = false; audio_state->set_playing(false); if (xine_request == _XINE_REQUEST_RELEASE_DEVICE){ xine_close_audio_driver(xine, ao_port); ao_port = NULL; } break; case _XINE_REQUEST_PAUSE: if(!validate_stream()||!playing) break; if(xine_get_param(stream, XINE_PARAM_SPEED) != XINE_SPEED_PAUSE) { xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); audio_state->set_pause(true); } else { xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); audio_state->set_pause(false); } break; case _XINE_REQUEST_FF:{ if(!playing || !validate_stream()) break; gather_info_internal(); if (_cur_time + 5 > _total_time) break; _cur_time +=5; off_t pos = _total_time > 0 ? static_cast<double>(_cur_time*65535)/_total_time : 0; xine_play(stream, pos, _cur_time*1000); audio_state->set_pause(false); break; } case _XINE_REQUEST_FB:{ if(!playing || !validate_stream()) break; gather_info_internal(); if (static_cast<int>(_cur_time) - 5 < 0) break; _cur_time -=5; off_t pos = _total_time > 0 ? static_cast<double>(_cur_time*65535)/_total_time : 0; xine_play(stream, pos, _cur_time*1000); audio_state->set_pause(false); break; } default: break; } if (ret == ETIMEDOUT && playing) gather_info_internal(); if (playing) ts = time_helper::compute_interval(500); else ts = time_helper::compute_interval(5000); } if(stream){ xine_close(stream); xine_event_dispose_queue(event_queue); event_queue = NULL; xine_dispose(stream); stream = NULL; } playing = false; if (ao_port) xine_close_audio_driver(xine, ao_port); ao_port = NULL; pthread_mutex_unlock(&stream_mutex); /* bye */ }
static double icvGetPropertyAVI_XINE( CvCaptureAVI_XINE* capture, int property_id ) { #ifndef NDEBUG fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... start\n" ); #endif OPENCV_ASSERT ( capture, "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture"); OPENCV_ASSERT ( capture->stream, "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream"); OPENCV_ASSERT ( capture->vo_port, "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port"); OPENCV_ASSERT ( capture->xine, "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->xine"); OPENCV_ASSERT ( capture->bgr_frame, "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->bgr_frame"); // not needed tnx to asserts... // we need a valid capture context and it's stream to seek through // if ( !capture || !capture->stream || !capture->bgr_frame || !capture->xine || !capture->vo_port ) return 0 int pos_t, pos_l, length; xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length ); fprintf( stderr, "ratio on GetProperty(): %i\n", pos_l ); switch ( property_id ) { /// return actual position in msec case CV_CAP_PROP_POS_MSEC: if ( !capture->seekable ) { fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_MSEC:\n" ); fprintf( stderr, " Stream is NOT seekable, so position info may NOT be valid !!\n" ); } return pos_t; /// return actual frame number case CV_CAP_PROP_POS_FRAMES: /// we insist the capture->frame_number to be remain updated !!!! return capture->frame_number; /// return actual position ratio in the range [0..1] depending on /// the total length of the stream and the actual position case CV_CAP_PROP_POS_AVI_RATIO: if ( !capture->seekable ) { fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_AVI_RATIO:\n" ); fprintf( stderr, " Stream is NOT seekable, so ratio info may NOT be valid !!\n" ); } if ( length == 0 ) break; else return pos_l / 65535; /// return width of image source case CV_CAP_PROP_FRAME_WIDTH: return capture->size.width; /// return height of image source case CV_CAP_PROP_FRAME_HEIGHT: return capture->size.height; /// return framerate of stream case CV_CAP_PROP_FPS: if ( !capture->seekable ) { fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_FPS:\n" ); fprintf( stderr, " Stream is NOT seekable, so FPS info may NOT be valid !!\n" ); } return capture->frame_rate; /// return four-character-code (FOURCC) of source's codec case CV_CAP_PROP_FOURCC: return ( double ) xine_get_stream_info( capture->stream, XINE_STREAM_INFO_VIDEO_FOURCC ); } #ifndef NDEBUG fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... failed!\n" ); #endif return 0; }
/* this is a slave controller thread for the xine module - libxine loves * to deadlock, internally stall and otherwise have unpredictable behavior * if we use the main process thread for many things - so a lot will be * farmed off to this slave. its job is to handle opening, closing, file * opening, recoder init etc. and all sorts of things can that often block. * anything this thread needs to return, it will return via the event pipe. */ static void * _em_slave(void *par) { Emotion_Xine_Video *ev; void *buf[2]; int len; ev = (Emotion_Xine_Video *)par; while ((len = read(ev->fd_slave_read, buf, sizeof(buf))) > 0) { if (len == sizeof(buf)) { Emotion_Xine_Event *eev; ev = buf[0]; eev = buf[1]; switch (eev->mtype) { case 0: /* noop */ break; case 1: /* init */ { ev->decoder = xine_new(); xine_init(ev->decoder); xine_register_plugins(ev->decoder, emotion_xine_plugin_info); if (1) { xine_cfg_entry_t cf; if (xine_config_lookup_entry(ev->decoder, "input.dvd_use_readahead", &cf)) { cf.num_value = 1; // 0 or 1 xine_config_update_entry(ev->decoder, &cf); } } DBG("OPEN VIDEO PLUGIN..."); if (!ev->opt_no_video) ev->video = xine_open_video_driver(ev->decoder, "emotion", XINE_VISUAL_TYPE_NONE, ev); DBG("RESULT: xine_open_video_driver() = %p", ev->video); // Let xine autodetect the best audio output driver if (!ev->opt_no_audio) ev->audio = xine_open_audio_driver(ev->decoder, NULL, ev); // ev->audio = xine_open_audio_driver(ev->decoder, "oss", ev); // dont use alsa - alsa has oss emulation. // ev->audio = xine_open_audio_driver(ev->decoder, "alsa", ev); // ev->audio = xine_open_audio_driver(ev->decoder, "arts", ev); // ev->audio = xine_open_audio_driver(ev->decoder, "esd", ev); ev->stream = xine_stream_new(ev->decoder, ev->audio, ev->video); ev->queue = xine_event_new_queue(ev->stream); xine_event_create_listener_thread(ev->queue, _em_event, ev); ev->opening = 0; ev->play_ok = 1; _em_module_event(ev, 1); /* event - open done */ } break; case 3: /* shutdown */ { _em_module_event(ev, 3); DBG("shutdown stop"); xine_stop(ev->stream); // pthread_mutex_lock(&(ev->get_pos_len_mutex)); if (!ev->get_pos_thread_deleted) { DBG("closing get_pos thread, %p", ev); pthread_mutex_lock(&(ev->get_pos_len_mutex)); pthread_cond_broadcast(&(ev->get_pos_len_cond)); pthread_mutex_unlock(&(ev->get_pos_len_mutex)); while (ev->get_poslen); } DBG("dispose %p", ev); xine_dispose(ev->stream); DBG("dispose evq %p", ev); xine_event_dispose_queue(ev->queue); DBG("close video drv %p", ev); if (ev->video) xine_close_video_driver(ev->decoder, ev->video); DBG("wait for vo to go"); while (ev->have_vo); DBG("vo gone"); DBG("close audio drv %p", ev); if (ev->audio) xine_close_audio_driver(ev->decoder, ev->audio); DBG("xine exit %p", ev); xine_exit(ev->decoder); DBG("DONE %p", ev); close(ev->fd_write); close(ev->fd_read); close(ev->fd_ev_write); close(ev->fd_ev_read); close(ev->fd_slave_write); close(ev->fd_slave_read); ev->closing = 0; if (eev->xine_event) free(eev->xine_event); free(eev); free(ev); return NULL; } break; case 2: /* file open */ { int pos_stream = 0; int pos_time = 0; int length_time = 0; uint32_t v; char *file; file = eev->xine_event; DBG("OPEN STREAM %s", file); if (xine_open(ev->stream, file)) { if (xine_get_pos_length(ev->stream, &pos_stream, &pos_time, &length_time)) { if (length_time == 0) { ev->pos = (double)pos_stream / 65535; ev->len = 1.0; ev->no_time = 1; } else { ev->pos = 0.0; ev->len = (double)length_time / 1000.0; } } else { ev->pos = 0.0; ev->len = 1.0; } v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_FRAME_DURATION); if (v > 0) ev->fps = 90000.0 / (double)v; v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_WIDTH); ev->w = v; v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HEIGHT); ev->h = v; v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_RATIO); ev->ratio = (double)v / 10000.0; ev->just_loaded = 1; ev->get_poslen = 0; xine_set_param(ev->stream, XINE_PARAM_AUDIO_VOLUME, ev->volume * 100); } _em_module_event(ev, 2); /* event - open done */ } break; case 11: /* file close */ { DBG("done %p", ev); em_frame_done(ev); DBG("stop %p", ev); xine_stop(ev->stream); DBG("close %p", ev); xine_close(ev->stream); DBG("close done %p", ev); _em_module_event(ev, 11); } break; case 4: /* play */ { double pos; int pos_stream, pos_time, length_time; pos = *((double *)eev->xine_event); if ((xine_get_param(ev->stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE) && (pos == ev->pos) && (!ev->just_loaded)) { xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); } else { if (ev->no_time) xine_play(ev->stream, pos * 65535, 0); else xine_play(ev->stream, 0, pos * 1000); } ev->just_loaded = 0; if (xine_get_pos_length(ev->stream, &pos_stream, &pos_time, &length_time)) { if (length_time == 0) { ev->pos = (double)pos_stream / 65535; ev->len = 1.0; ev->no_time = 1; } else { ev->pos = (double)pos_time / 1000.0; ev->len = (double)length_time / 1000.0; } } _em_module_event(ev, 4); } break; case 5: /* stop */ { xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); _em_module_event(ev, 5); } break; case 6: /* seek */ { double pos; pos = *((double *)eev->xine_event); if (ev->no_time) xine_play(ev->stream, pos * 65535, 0); else xine_play(ev->stream, 0, pos * 1000); if (!ev->play) xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); _em_module_event(ev, 6); } break; case 7: /* eject */ { xine_eject(ev->stream); _em_module_event(ev, 7); } break; case 8: /* spu mute */ { xine_set_param(ev->stream, XINE_PARAM_IGNORE_SPU, ev->spu_mute); _em_module_event(ev, 8); } break; case 9: /* channel */ { xine_set_param(ev->stream, XINE_PARAM_SPU_CHANNEL, ev->spu_channel); _em_module_event(ev, 9); } break; case 10: /* vol */ { xine_set_param(ev->stream, XINE_PARAM_AUDIO_VOLUME, ev->volume * 100); _em_module_event(ev, 10); } break; case 12: /* audio mute */ { xine_set_param(ev->stream, XINE_PARAM_AUDIO_MUTE, ev->audio_mute); } break; case 13: /* audio mute */ { xine_set_param(ev->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, ev->audio_channel); } break; case 14: /* audio mute */ { xine_set_param(ev->stream, XINE_PARAM_VIDEO_CHANNEL, ev->video_channel); } break; default: break; } if (eev->xine_event) free(eev->xine_event); free(eev); } } return NULL; }
static Epsilon_Image * epsilon_generate_thumb (Epsilon * e) { int ret = XINE_THUMB_SUCCESS; Epsilon_Image *img = NULL; unsigned char *buf = NULL; int cnt, attempts = 0, length = -1, pos_perc, pos_time, new_perc, new_time, req_perc = 500, req_time = 500; static int old_length = -1; char cfg[PATH_MAX]; epsilon_xine_param *param; param = calloc (1, sizeof (epsilon_xine_param)); if (!(param->xine = xine_new ())) { return NULL; } snprintf (cfg, PATH_MAX, "%s%s", xine_get_homedir (), ".xine/config"); xine_config_load (param->xine, cfg); xine_init (param->xine); /* opening xine output ports */ if (! (param->vo_port = xine_open_video_driver (param->xine, "none", XINE_VISUAL_TYPE_NONE, (void *) NULL))) { goto done; } param->ao_port = xine_open_audio_driver (param->xine, "none", NULL); /* open a xine stream connected to these ports */ if (! (param->stream = xine_stream_new (param->xine, param->ao_port, param->vo_port))) { goto done; } if (!xine_open (param->stream, e->src)) { ret = XINE_THUMB_FAIL; goto done; } if (XINE_THUMBNAILER_DEBUG) printf("Starting xine thumbnail process..\n"); try_get_chance: new_perc = -1; new_time = req_time; if (!xine_play (param->stream, 0, new_time)) { new_time = -1; new_perc = req_perc; /* 0..65535 */ if (!xine_play (param->stream, new_perc, 0)) { ret = XINE_THUMB_FAIL; if (XINE_THUMBNAILER_DEBUG) printf("Coudln't play video %s..\n", e->src); goto close_stream; } } /* get position */ for (cnt = 0; ((cnt < 50) && (!xine_get_pos_length (param->stream, &pos_perc, &pos_time, &length) || (length == old_length))); cnt++) usleep (1000); if (length < 0) { if (XINE_THUMBNAILER_DEBUG) printf("Video is 0 length!..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } /* wait till position changes */ for (cnt = 0; (cnt < 50) && (!xine_get_pos_length (param->stream, &new_perc, &new_time, &length) || ((new_perc == pos_perc) && (new_time == pos_time))); cnt++) { usleep (1000); } /* get snapshot */ int w, h, ratio, format; old_length = length; /* ask what size a snapshot would be (if we can make one) */ if (!xine_get_current_frame (param->stream, &w, &h, &ratio, &format, NULL)) { attempts++; if (attempts < 10) { if (req_time < 10000) req_time += 1000; if (req_perc < 10000) req_perc += 1000; goto try_get_chance; } else { if (XINE_THUMBNAILER_DEBUG) printf("Exhausted attempts to thumbnail..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } } else if ((w <= 0) || (h <= 0)) { if (XINE_THUMBNAILER_DEBUG) printf("Width/Height of video invalid: %d:%d..\n", w,h); ret = XINE_THUMB_FAIL; goto close_stream; } else { /* know we know the size, get a buffer for the snapshot */ if (!(buf = malloc (w * h * 2))) { if (XINE_THUMBNAILER_DEBUG) printf("Couldn't allocate memory for thumbnail buffer..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } /* make a snapshot! */ if (!xine_get_current_frame (param->stream, &w, &h, &ratio, &format, buf)) { if (XINE_THUMBNAILER_DEBUG) printf("Couldn't retrieve current video frame..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } else if ((w <= 0) || (h <= 0)) { if (XINE_THUMBNAILER_DEBUG) printf("Width/height of video invalid: %d:%d..\n",w,h); ret = XINE_THUMB_FAIL; goto close_stream; } if (format == XINE_IMGFMT_YUY2) { unsigned char *buf2 = malloc (w * h * 2); unsigned char *tmp = buf; i_yuy2_to_yv12 (buf, buf2, w, h); buf = buf2; free (tmp); format = XINE_IMGFMT_YV12; } if (format == XINE_IMGFMT_YV12) { ret = yv12_to_rgb (e->src, w, h, &buf, &img); if (ret != XINE_THUMB_SUCCESS) { if (img) { if (++attempts > 10) goto close_stream; free(img->data); free(img); img = NULL; if (ret == XINE_THUMB_RETRY) { if (buf) { free (buf); buf = NULL; if ((req_perc += (attempts * 1000)) > 65535) req_perc = 1000; if ((req_time += (attempts * 2500)) > length) req_time = 3000; goto try_get_chance; } if (XINE_THUMBNAILER_DEBUG) printf("Exhausted attempts to thumbnail pos 2..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } } else { if (XINE_THUMBNAILER_DEBUG) printf("Couldn't complete yv12_to_rgb..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } } } ret = XINE_THUMB_SUCCESS; close_stream: if (buf) { free (buf); buf = NULL; } xine_close (param->stream); done: if (ret != XINE_THUMB_SUCCESS) { if (img) { free(img->data); free(img); img = NULL; } } if (param->stream) { xine_dispose (param->stream); param->stream = NULL; } if (param->ao_port) { xine_close_audio_driver (param->xine, param->ao_port); param->ao_port = NULL; } if (param->vo_port) { xine_close_video_driver (param->xine, param->vo_port); param->vo_port = NULL; } free (param); return img; } return NULL; }