static PyObject * MediaControl_pause( PyObject *self, PyObject *args ) { mediacontrol_Exception *exception = NULL; Py_BEGIN_ALLOW_THREADS MC_TRY; mediacontrol_pause( LIBVLC_MC(self), exception ); Py_END_ALLOW_THREADS MC_EXCEPT; Py_INCREF( Py_None ); return Py_None; }
/*pause all objects*/ void mediacontrol_pause(GF_ObjectManager *odm) { u32 i; GF_ObjectManager *ctrl_od; GF_Scene *in_scene; GF_Clock *ck; if (odm->flags & GF_ODM_NO_TIME_CTRL) return; /*otherwise locate all objects sharing the clock*/ ck = gf_odm_get_media_clock(odm); if (!ck) { odm->flags |= GF_ODM_PAUSE_QUEUED; return; } in_scene = odm->parentscene; if (odm->subscene) { assert(odm->subscene->root_od==odm); assert(odm->subscene->is_dynamic_scene || gf_odm_shares_clock(odm, ck) ); /*pause root*/ gf_odm_pause(odm); in_scene = odm->subscene; } i=0; while ((ctrl_od = (GF_ObjectManager*)gf_list_enum(in_scene->resources, &i))) { if (!odm->subscene && !gf_odm_shares_clock(ctrl_od, ck)) continue; if (ctrl_od->addon && (ctrl_od->addon->addon_type==GF_ADDON_TYPE_MAIN)) { gf_clock_pause(ck); gf_scene_select_main_addon(in_scene, ctrl_od, GF_TRUE, gf_clock_time(ck) ); } if (ctrl_od->subscene) { mediacontrol_pause(ctrl_od); } else { gf_odm_pause(ctrl_od); } } }
GF_EXPORT void gf_term_download_update_stats(GF_DownloadSession * sess) { GF_ClientService *serv; const char *szURI; u32 total_size, bytes_done, net_status, bytes_per_sec; if (!sess) return; gf_dm_sess_get_stats(sess, NULL, &szURI, &total_size, &bytes_done, &bytes_per_sec, &net_status); serv = (GF_ClientService *)gf_dm_sess_get_private(sess); switch (net_status) { case GF_NETIO_SETUP: gf_term_on_message(serv, GF_OK, "Connecting"); break; case GF_NETIO_CONNECTED: gf_term_on_message(serv, GF_OK, "Connected"); break; case GF_NETIO_WAIT_FOR_REPLY: gf_term_on_message(serv, GF_OK, "Waiting for reply..."); break; case GF_NETIO_PARSE_REPLY: gf_term_on_message(serv, GF_OK, "Starting download..."); break; case GF_NETIO_DATA_EXCHANGE: /*notify some connection / ...*/ if (total_size) { GF_Event evt; evt.type = GF_EVENT_PROGRESS; evt.progress.progress_type = 1; evt.progress.service = szURI; evt.progress.total = total_size; evt.progress.done = bytes_done; evt.progress.bytes_per_seconds = bytes_per_sec; gf_term_send_event(serv->term, &evt); } GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s received %d / %d\n", szURI, bytes_done, total_size)); gf_term_service_media_event_with_download(serv->owner, GF_EVENT_MEDIA_PROGRESS, bytes_done, total_size, bytes_per_sec); /*JLF fix this*/ if (0&& (serv->download_rebuffer || serv->auto_rebuffer) && serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) { GF_Clock *ck = gf_odm_get_media_clock(serv->owner); Double download_percent, playback_percent, adj_percent; download_percent = 100 * bytes_done; download_percent /= total_size; playback_percent = 100 * serv->owner->current_time; playback_percent /= serv->owner->duration; if (serv->auto_rebuffer) adj_percent = 0.0; else adj_percent = 100.0 * serv->download_rebuffer / serv->owner->duration; if (playback_percent >= download_percent) { if (gf_clock_is_started(ck)) { GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% but downloaded %d %% - Pausing\n", (u32) playback_percent, (u32) download_percent)); if (!serv->is_paused) { serv->is_paused = 1; mediacontrol_pause(serv->owner); } gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_WAITING); gf_term_on_message(serv, GF_OK, "HTTP Buffering ..."); } } else if (playback_percent + adj_percent <= download_percent) { Double time_to_play = 0; Double time_to_download = 0; /*automatic rebuffer: make sure we can finish playback before resuming*/ if (serv->auto_rebuffer) { if (bytes_per_sec) { time_to_download = 1000.0*(total_size - bytes_done); time_to_download /= bytes_per_sec; } time_to_play = (Double) serv->owner->duration; time_to_play -= serv->owner->current_time; } if ((time_to_download<=time_to_play) && !gf_clock_is_started(ck)) { GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% and downloaded %d %% - Resuming\n", (u32) playback_percent, (u32) download_percent)); if (serv->auto_rebuffer) { GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Auto-rebuffer done: should be done downloading in %d ms and remains %d ms to play\n", (u32) time_to_download, (u32) (serv->owner->duration - serv->owner->current_time) )); } gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_PLAYING); if (serv->is_paused) { serv->is_paused = 0; mediacontrol_resume(serv->owner); } gf_term_on_message(serv, GF_OK, "HTTP Resuming playback"); } } } break; case GF_NETIO_DATA_TRANSFERED: gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_LOAD_DONE); if (serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) { GF_Clock *ck = gf_odm_get_media_clock(serv->owner); if (!gf_clock_is_started(ck)) { GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Done retrieving file - resuming playback\n")); if (serv->is_paused) { serv->is_paused = 0; mediacontrol_resume(serv->owner); } } } break; } }
void RenderMediaControl(GF_Node *node, void *rs, Bool is_destroy) { Bool shall_restart, need_restart; GF_MediaObject *prev; GF_ObjectManager *odm; GF_TraverseState *tr_state = (GF_TraverseState *)rs; MediaControlStack *stack =(MediaControlStack *) gf_node_get_private(node); if (is_destroy) { GF_ObjectManager *odm; MediaControlStack *stack = (MediaControlStack *) gf_node_get_private(node); /*reset ODM using this control*/ if (stack->stream) { if (stack->stream->odm) { odm = stack->stream->odm; gf_odm_remove_mediacontrol(odm, stack); } /*also removes the association ck<->MC if the object has been destroyed before the node*/ if (stack->ck) stack->ck->mc = NULL; } gf_list_del(stack->seg); gf_sg_vrml_mf_reset(&stack->url, GF_SG_VRML_MFURL); gf_free(stack); return; } //we need to disable culling otherwise we may never be called back again ... tr_state->disable_cull = 1; /*not changed nothing to do - note we need to register with stream yet for control switching...*/ if (stack->stream && (!stack->changed || !stack->control->enabled)) return; need_restart = (stack->changed==2) ? 1 : 0; shall_restart = (stack->control->mediaStartTime>=0) ? 1 : 0; /*check url target*/ if (stack->stream) { if (MC_URLChanged(&stack->url, &stack->control->url)) { gf_sg_vrml_mf_reset(&stack->url, GF_SG_VRML_MFURL); prev = stack->stream; if (gf_list_find(stack->parent->scene_objects, prev)<0) prev = NULL; stack->stream = gf_scene_get_media_object(stack->parent, &stack->control->url, GF_MEDIA_OBJECT_UNDEF, 0); if (stack->stream) { if (!stack->stream->odm) return; /*MediaControl on inline: if dynamic scene, make sure it is connected before attaching...*/ if (stack->stream->odm->subscene) { if (stack->stream->odm->subscene->is_dynamic_scene && !stack->stream->odm->subscene->dyn_ck) return; } gf_sg_vrml_field_copy(&stack->url, &stack->control->url, GF_SG_VRML_MFURL); /*remove from prev*/ if (prev && prev->odm && (prev != stack->stream)) gf_odm_remove_mediacontrol(prev->odm, stack); /*register with new*/ /*if we assigned the media control to an exiting object - force the state of the object*/ gf_odm_set_mediacontrol((GF_ObjectManager *) stack->stream->odm, stack); while (gf_list_count(stack->seg)) gf_list_rem(stack->seg, 0); gf_odm_init_segments((GF_ObjectManager *) stack->stream->odm, stack->seg, &stack->control->url); stack->current_seg = 0; //do not restart if no mediaStartTime and speed is 1 if ((stack->control->mediaStartTime>0) || gf_list_count(stack->seg) || (stack->control->mediaSpeed != FIX_ONE) ) { shall_restart = need_restart = 1; } else { shall_restart = need_restart = 0; //URL changed, we are by default in PLAY mode. stack->media_speed = 1; } stack->ck = gf_odm_get_media_clock(stack->stream->odm); } /*control has been removed and we were paused, resume*/ else if (stack->paused) { mediacontrol_resume((GF_ObjectManager *) prev->odm, 0); stack->paused = 0; } /*MediaControl has been detached*/ else { if (prev) gf_odm_remove_mediacontrol(prev->odm, stack); return; } } } else { stack->stream = gf_scene_get_media_object(stack->parent, &stack->control->url, GF_MEDIA_OBJECT_UNDEF, 0); if (!stack->stream || !stack->stream->odm) { if (stack->control->url.count) gf_term_invalidate_compositor(stack->parent->root_od->term); stack->stream = NULL; stack->changed = 0; return; } stack->ck = gf_odm_get_media_clock(stack->stream->odm); /*OD not ready yet*/ if (!stack->ck) { stack->stream = NULL; if (stack->control->url.count) { stack->is_init = 0; gf_term_invalidate_compositor(stack->parent->root_od->term); } return; } gf_sg_vrml_field_copy(&stack->url, &stack->control->url, GF_SG_VRML_MFURL); gf_odm_set_mediacontrol((GF_ObjectManager *) stack->stream->odm, stack); while (gf_list_count(stack->seg)) gf_list_rem(stack->seg, 0); gf_odm_init_segments((GF_ObjectManager *) stack->stream->odm, stack->seg, &stack->control->url); stack->current_seg = 0; /*we shouldn't have to restart unless start/stop times have been changed, which is tested below*/ need_restart = 0; } if (!stack->changed || !stack->control->enabled || !stack->stream) return; /*if not previously enabled and now enabled, switch all other controls off and reactivate*/ if (!stack->enabled) { stack->enabled = 1; need_restart = gf_odm_switch_mediacontrol(stack->stream->odm, stack); } stack->changed = 0; if (!stack->control->mediaSpeed) shall_restart = 0; odm = (GF_ObjectManager *)stack->stream->odm; /*check for changes*/ if (!stack->is_init) { /*not linked yet*/ if (!odm) return; stack->media_speed = stack->control->mediaSpeed; stack->enabled = stack->control->enabled; stack->media_start = stack->control->mediaStartTime; stack->media_stop = stack->control->mediaStopTime; stack->is_init = 1; stack->paused = 0; /*the object has already been started, and media start time is not 0, restart*/ if (stack->stream->num_open) { if ( (stack->media_start > 0) || (gf_list_count(stack->seg)>0 ) || (stack->media_speed!=FIX_ONE ) ) { mediacontrol_restart(odm); } else if (stack->media_speed == 0) { mediacontrol_pause(odm); stack->paused = 1; } } return; } if (stack->media_speed != stack->control->mediaSpeed) { /*if no speed pause*/ if (!stack->control->mediaSpeed && !stack->paused) { mediacontrol_pause(odm); stack->paused = 1; } /*else resume if paused*/ else if (stack->control->mediaSpeed && stack->paused) { mediacontrol_resume(odm, 0); stack->paused = 0; need_restart += shall_restart; } /*else set speed*/ else if (stack->media_speed && stack->control->mediaSpeed) { /*don't set speed if we have to restart the media ...*/ if (!shall_restart) MC_SetSpeed(odm, stack->control->mediaSpeed); need_restart += shall_restart; } /*init state was paused*/ else if (!stack->media_speed) { need_restart ++; } stack->media_speed = stack->control->mediaSpeed; } /*check start/stop changes*/ if (stack->media_start != stack->control->mediaStartTime) { stack->media_start = stack->control->mediaStartTime; need_restart += shall_restart; } /*stop change triggers restart no matter what (new range) if playing*/ if (stack->media_stop != stack->control->mediaStopTime) { stack->media_stop = stack->control->mediaStopTime; if (stack->control->mediaSpeed) need_restart = 1; } if (need_restart) { mediacontrol_restart(odm); } /*handle preroll*/ }