void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset) { #ifdef HAVE_TV_TELETEXT tvi_handle_t* tvh=demuxer->priv; int page_changed; if (demuxer->type != DEMUXER_TYPE_TV || !tvh) return; //Also forcing page update when such ioctl is not supported or call error occured if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_IS_CHANGED,&page_changed)!=TVI_CONTROL_TRUE) page_changed=1; if(!page_changed) return; if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_VBIPAGE,&vo_osd_teletext_page)!=TVI_CONTROL_TRUE) vo_osd_teletext_page=NULL; if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_HALF_PAGE,&vo_osd_teletext_half)!=TVI_CONTROL_TRUE) vo_osd_teletext_half=0; if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_MODE,&vo_osd_teletext_mode)!=TVI_CONTROL_TRUE) vo_osd_teletext_mode=0; if(tvh->functions->control(tvh->priv,TV_VBI_CONTROL_GET_FORMAT,&vo_osd_teletext_format)!=TVI_CONTROL_TRUE) vo_osd_teletext_format=0; vo_osd_changed(OSDTYPE_TELETEXT); tvh->functions->control(tvh->priv,TV_VBI_CONTROL_MARK_UNCHANGED,NULL); #endif }
void step_sub(sub_data *subd, float pts, int movement) { subtitle *subs; int key; if (subd == NULL) return; subs = subd->subtitles; key = (pts+sub_delay) * (subd->sub_uses_time ? 100 : sub_fps); /* Tell the OSD subsystem that the OSD contents will change soon */ vo_osd_changed(OSDTYPE_SUBTITLE); /* If we are moving forward, don't count the next (current) subtitle * if we haven't displayed it yet. Same when moving other direction. */ if (movement > 0 && key < subs[current_sub].start) movement--; if (movement < 0 && key >= subs[current_sub].end) movement++; /* Never move beyond first or last subtitle. */ if (current_sub+movement < 0) movement = 0-current_sub; if (current_sub+movement >= subd->sub_num) movement = subd->sub_num - current_sub - 1; current_sub += movement; sub_delay = subs[current_sub].start / (subd->sub_uses_time ? 100 : sub_fps) - pts; }
void update_teletext(sh_video_t *sh_video, demuxer_t *demuxer, int reset) { int page_changed; if (!demuxer->teletext) return; //Also forcing page update when such ioctl is not supported or call error occured if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_IS_CHANGED,&page_changed)!=VBI_CONTROL_TRUE) page_changed=1; if(!page_changed) return; if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_VBIPAGE,&vo_osd_teletext_page)!=VBI_CONTROL_TRUE) vo_osd_teletext_page=NULL; if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_HALF_PAGE,&vo_osd_teletext_half)!=VBI_CONTROL_TRUE) vo_osd_teletext_half=0; if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_MODE,&vo_osd_teletext_mode)!=VBI_CONTROL_TRUE) vo_osd_teletext_mode=0; if(teletext_control(demuxer->teletext,TV_VBI_CONTROL_GET_FORMAT,&vo_osd_teletext_format)!=VBI_CONTROL_TRUE) vo_osd_teletext_format=0; vo_osd_changed(OSDTYPE_TELETEXT); teletext_control(demuxer->teletext,TV_VBI_CONTROL_MARK_UNCHANGED,NULL); }
/** @brief Resize Direct3D context on window resize. * @return 1 on success, 0 on failure */ static int resize_d3d(void) { D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1}; mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>resize_d3d called.\n"); /* Make sure that backbuffer is large enough to accomodate the new viewport dimensions. Grow it if necessary. */ if (vo_dwidth > priv->cur_backbuf_width || vo_dheight > priv->cur_backbuf_height) { if (!change_d3d_backbuffer(BACKBUFFER_RESET)) return 0; } /* Destroy the OSD textures. They should always match the new dimensions * of the onscreen window, so on each resize we need new OSD dimensions. */ if (priv->d3d_texture_osd) IDirect3DTexture9_Release(priv->d3d_texture_osd); priv->d3d_texture_osd = NULL; if (priv->d3d_texture_system) IDirect3DTexture9_Release(priv->d3d_texture_system); priv->d3d_texture_system = NULL; /* Recreate the OSD. The function will observe that the offscreen plain * surface and the backbuffer are not destroyed and will skip their creation, * effectively recreating only the OSD. */ if (!create_d3d_surfaces()) return 0; if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device, &vp))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Setting viewport failed.\n"); return 0; } calc_fs_rect(); #ifdef CONFIG_FREETYPE // font needs to be adjusted force_load_font = 1; #endif // OSD needs to be drawn fresh for new size vo_osd_changed(OSDTYPE_OSD); return 1; }
static void draw_osd(void) { if (!use_osd) return; if (vo_osd_changed(0)) { int osd_h, osd_w; clearOSD(); osd_w = scaled_osd ? image_width : vo_dwidth; osd_h = scaled_osd ? image_height : vo_dheight; vo_draw_text_ext(osd_w, osd_h, ass_border_x, ass_border_y, ass_border_x, ass_border_y, image_width, image_height, create_osd_texture); } if (vo_doublebuffering) do_render_osd(RENDER_OSD); }
static void resize(int x,int y){ // simple orthogonal projection for 0-image_width;0-image_height float matrix[16] = { 2.0/image_width, 0, 0, 0, 0, -2.0/image_height, 0, 0, 0, 0, 0, 0, -1, 1, 0, 1 }; mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n",x,y); if (WinID >= 0) { int left = 0, top = 0, w = x, h = y; geometry(&left, &top, &w, &h, vo_dwidth, vo_dheight); top = y - h - top; mpglViewport(left, top, w, h); } else mpglViewport( 0, 0, x, y ); mpglMatrixMode(GL_PROJECTION); ass_border_x = ass_border_y = 0; if (aspect_scaling() && use_aspect) { int new_w, new_h; GLdouble scale_x, scale_y; aspect(&new_w, &new_h, A_WINZOOM); panscan_calc_windowed(); new_w += vo_panscan_x; new_h += vo_panscan_y; scale_x = (GLdouble)new_w / (GLdouble)x; scale_y = (GLdouble)new_h / (GLdouble)y; matrix[0] *= scale_x; matrix[12] *= scale_x; matrix[5] *= scale_y; matrix[13] *= scale_y; ass_border_x = (vo_dwidth - new_w) / 2; ass_border_y = (vo_dheight - new_h) / 2; } mpglLoadMatrixf(matrix); mpglMatrixMode(GL_MODELVIEW); mpglLoadIdentity(); if (!scaled_osd) { #ifdef CONFIG_FREETYPE // adjust font size to display size force_load_font = 1; #endif vo_osd_changed(OSDTYPE_OSD); } mpglClear(GL_COLOR_BUFFER_BIT); redraw(); }
static void resize(int x,int y){ mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n",x,y); if (WinID >= 0) { int top = 0, left = 0, w = x, h = y; geometry(&top, &left, &w, &h, vo_screenwidth, vo_screenheight); Viewport(top, left, w, h); } else Viewport( 0, 0, x, y ); MatrixMode(GL_PROJECTION); LoadIdentity(); ass_border_x = ass_border_y = 0; if (aspect_scaling() && use_aspect) { int new_w, new_h; GLdouble scale_x, scale_y; aspect(&new_w, &new_h, A_WINZOOM); panscan_calc_windowed(); new_w += vo_panscan_x; new_h += vo_panscan_y; scale_x = (GLdouble)new_w / (GLdouble)x; scale_y = (GLdouble)new_h / (GLdouble)y; Scaled(scale_x, scale_y, 1); ass_border_x = (vo_dwidth - new_w) / 2; ass_border_y = (vo_dheight - new_h) / 2; } Ortho(0, image_width, image_height, 0, -1,1); MatrixMode(GL_MODELVIEW); LoadIdentity(); if (!scaled_osd) { #ifdef CONFIG_FREETYPE // adjust font size to display size force_load_font = 1; #endif vo_osd_changed(OSDTYPE_OSD); } Clear(GL_COLOR_BUFFER_BIT); redraw(); }
void uiEvent(int ev, float param) { int iparam = (int)param; mixer_t *mixer = mpctx_get_mixer(guiInfo.mpcontext); float aspect; char cmd[40]; switch (ev) { /* user events */ case evExit: mplayer(MPLAYER_EXIT_GUI, EXIT_QUIT, 0); break; case evLoadURL: gtkShow(evLoadURL, NULL); break; case ivSetAudio: if (!mpctx_get_demuxer(guiInfo.mpcontext) || audio_id == iparam) break; mp_property_do("switch_audio", M_PROPERTY_SET, &iparam, guiInfo.mpcontext); break; case ivSetVideo: if (!mpctx_get_demuxer(guiInfo.mpcontext) || video_id == iparam) break; mp_property_do("switch_video", M_PROPERTY_SET, &iparam, guiInfo.mpcontext); break; case ivSetSubtitle: mp_property_do("sub", M_PROPERTY_SET, &iparam, guiInfo.mpcontext); break; #ifdef CONFIG_CDDA case ivSetCDTrack: guiInfo.Track = iparam; case evPlayCD: guiInfo.StreamType = STREAMTYPE_CDDA; goto play; #endif #ifdef CONFIG_VCD case ivSetVCDTrack: guiInfo.Track = iparam; case evPlayVCD: guiInfo.StreamType = STREAMTYPE_VCD; goto play; #endif #ifdef CONFIG_DVDREAD case ivSetDVDSubtitle: dvdsub_id = iparam; uiEvent(ivPlayDVD, 0); break; case ivSetDVDAudio: audio_id = iparam; uiEvent(ivPlayDVD, 0); break; case ivSetDVDChapter: guiInfo.Chapter = iparam; uiEvent(ivPlayDVD, 0); break; case ivSetDVDTitle: guiInfo.Track = iparam; guiInfo.Chapter = 1; guiInfo.Angle = 1; uiEvent(ivPlayDVD, 0); break; case evPlayDVD: guiInfo.Chapter = 1; guiInfo.Angle = 1; case ivPlayDVD: guiInfo.StreamType = STREAMTYPE_DVD; goto play; #endif #ifdef CONFIG_TV case evPlayTV: guiInfo.StreamType = guiTV[gui_tv_digital].StreamType; goto play; #endif case evPlay: case evPlaySwitchToPause: play: if (guiInfo.Playing != GUI_PAUSE) { MediumPrepare(guiInfo.StreamType); switch (guiInfo.StreamType) { case STREAMTYPE_FILE: case STREAMTYPE_STREAM: case STREAMTYPE_PLAYLIST: if (!guiInfo.Track) guiInfo.Track = 1; guiInfo.MediumChanged = GUI_MEDIUM_NEW; guiInfo.PlaylistNext = !guiInfo.Playing; break; case STREAMTYPE_CDDA: case STREAMTYPE_VCD: case STREAMTYPE_DVD: case STREAMTYPE_TV: case STREAMTYPE_DVB: if (!guiInfo.Track) guiInfo.Track = (guiInfo.StreamType == STREAMTYPE_VCD ? 2 : 1); case STREAMTYPE_BINCUE: // track 0 is OK and will auto-select first media data track guiInfo.MediumChanged = GUI_MEDIUM_SAME; break; } } uiPlay(); break; case evPause: case evPauseSwitchToPlay: uiPause(); break; case evStop: guiInfo.Playing = GUI_STOP; uiState(); break; case evLoadPlay: uiLoadPlay = True; // guiInfo.StreamType=STREAMTYPE_FILE; case evLoad: gtkShow(evLoad, NULL); break; case evLoadSubtitle: gtkShow(evLoadSubtitle, NULL); break; case evDropSubtitle: nfree(guiInfo.SubtitleFilename); mplayerLoadSubtitle(NULL); break; case evLoadAudioFile: gtkShow(evLoadAudioFile, NULL); break; case evPlayImage: gtkShow(evPlayImage, NULL); break; case evPrev: uiPrev(); break; case evNext: uiNext(); break; case evPlaylist: gtkShow(evPlaylist, NULL); break; case evSkinBrowser: gtkShow(evSkinBrowser, skinName); break; case evAbout: gtkShow(evAbout, NULL); break; case evPreferences: gtkShow(evPreferences, NULL); break; case evEqualizer: gtkShow(evEqualizer, NULL); break; case evForward10min: uiRelSeek(600); break; case evBackward10min: uiRelSeek(-600); break; case evForward1min: uiRelSeek(60); break; case evBackward1min: uiRelSeek(-60); break; case evForward10sec: uiRelSeek(10); break; case evBackward10sec: uiRelSeek(-10); break; case evSetMoviePosition: guiInfo.Position = param; uiPctSeek(guiInfo.Position); break; case evIncVolume: mplayer_put_key(KEY_VOLUME_UP); break; case evDecVolume: mplayer_put_key(KEY_VOLUME_DOWN); break; case evMute: mixer_mute(mixer); break; case evSetVolume: case ivSetVolume: guiInfo.Volume = param; { float l = guiInfo.Volume * (100.0 - guiInfo.Balance) / 50.0; float r = guiInfo.Volume * guiInfo.Balance / 50.0; mixer_setvolume(mixer, FFMIN(l, guiInfo.Volume), FFMIN(r, guiInfo.Volume)); } if (ev == ivSetVolume) break; if (osd_level) { osd_visible = (GetTimerMS() + 1000) | 1; vo_osd_progbar_type = OSD_VOLUME; vo_osd_progbar_value = guiInfo.Volume * 256.0 / 100.0; vo_osd_changed(OSDTYPE_PROGBAR); } break; case evSetBalance: case ivSetBalance: guiInfo.Balance = param; mixer_setbalance(mixer, (guiInfo.Balance - 50.0) / 50.0); // transform 0..100 to -1..1 uiEvent(ivSetVolume, guiInfo.Volume); if (ev == ivSetBalance) break; if (osd_level) { osd_visible = (GetTimerMS() + 1000) | 1; vo_osd_progbar_type = OSD_BALANCE; vo_osd_progbar_value = guiInfo.Balance * 256.0 / 100.0; vo_osd_changed(OSDTYPE_PROGBAR); } break; case evMenu: /*if (guiApp.menuIsPresent) NOTE TO MYSELF: Uncomment only after mouse * { pointer and cursor keys work * gtkShow( ivHidePopUpMenu,NULL ); with this menu from skin as * uiMenuShow( 0,0 ); they do with normal menus. * } * else*/gtkShow(ivShowPopUpMenu, NULL); break; case evIconify: switch (iparam) { case 0: wsWindowIconify(&guiApp.mainWindow); break; case 1: wsWindowIconify(&guiApp.videoWindow); break; } break; case evHalfSize: if (guiInfo.VideoWindow && guiInfo.Playing) { if (guiApp.videoWindow.isFullScreen) { uiFullScreen(); } wsWindowResize(&guiApp.videoWindow, guiInfo.VideoWidth / 2, guiInfo.VideoHeight / 2); btnSet(evFullScreen, btnReleased); } break; case evDoubleSize: if (guiInfo.VideoWindow && guiInfo.Playing) { if (guiApp.videoWindow.isFullScreen) { uiFullScreen(); } wsWindowResize(&guiApp.videoWindow, guiInfo.VideoWidth * 2, guiInfo.VideoHeight * 2); wsWindowMoveWithin(&guiApp.videoWindow, False, guiApp.video.x, guiApp.video.y); btnSet(evFullScreen, btnReleased); } break; case evNormalSize: if (guiInfo.VideoWindow && guiInfo.Playing) { if (guiApp.videoWindow.isFullScreen) { uiFullScreen(); } wsWindowResize(&guiApp.videoWindow, guiInfo.VideoWidth, guiInfo.VideoHeight); btnSet(evFullScreen, btnReleased); break; } else if (!guiApp.videoWindow.isFullScreen) break; case evFullScreen: if (guiInfo.VideoWindow && (guiInfo.Playing || !iparam)) { uiFullScreen(); if (!guiApp.videoWindow.isFullScreen) wsWindowResize(&guiApp.videoWindow, iparam ? guiInfo.VideoWidth : guiApp.video.width, iparam ? guiInfo.VideoHeight : guiApp.video.height); } if (guiApp.videoWindow.isFullScreen) btnSet(evFullScreen, btnPressed); else btnSet(evFullScreen, btnReleased); break; case evSetAspect: switch (iparam) { case 2: aspect = 16.0f / 9.0f; break; case 3: aspect = 4.0f / 3.0f; break; case 4: aspect = 2.35f; break; case 1: default: aspect = -1; break; } snprintf(cmd, sizeof(cmd), "pausing_keep switch_ratio %f", aspect); mp_input_queue_cmd(mp_input_parse_cmd(cmd)); break; case evSetRotation: switch (iparam) { case 90: guiInfo.Rotation = 1; break; case -90: guiInfo.Rotation = 2; break; case 180: guiInfo.Rotation = 8; break; case 0: default: guiInfo.Rotation = -1; break; } guiInfo.MediumChanged = GUI_MEDIUM_SAME; break; /* timer events */ case ivRedraw: { unsigned int now = GetTimerMS(); if ((now > last_redraw_time) && (now < last_redraw_time + GUI_REDRAW_WAIT) && !uiPlaybarFade && (iparam == 0)) break; last_redraw_time = now; } uiMainRender = True; wsWindowRedraw(&guiApp.mainWindow); wsWindowRedraw(&guiApp.playbarWindow); break; /* system events */ case evNone: mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[actions] uiEvent: evNone\n"); break; default: mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[actions] uiEvent: unknown event %d, param %.2f\n", ev, param); break; } }
/** @brief libvo Callback: Draw OSD/Subtitles, */ static void draw_osd(void) { // we can not render OSD if we lost the device e.g. because it was uncooperative if (!priv->d3d_device) return; if (vo_osd_changed(0)) { D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order to copy MPlayer's frame inside it.*/ /* clear the OSD */ if (FAILED(IDirect3DTexture9_LockRect(priv->d3d_texture_system, 0, &locked_rect, NULL, 0))) { mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture lock failed.\n"); return; } /* clear the whole texture to avoid issues due to interpolation */ memset(locked_rect.pBits, 0, locked_rect.Pitch * priv->osd_texture_height); /* this unlock is used for both slice_draw path and D3DRenderFrame path */ if (FAILED(IDirect3DTexture9_UnlockRect(priv->d3d_texture_system, 0))) { mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture unlock failed.\n"); return; } priv->is_osd_populated = 0; /* required for if subs are in the boarder region */ priv->is_clear_needed = 1; vo_draw_text_ext(priv->osd_width, priv->osd_height, priv->border_x, priv->border_y, priv->border_x, priv->border_y, priv->src_width, priv->src_height, draw_alpha); if (!priv->device_texture_sys) { /* only DMA to the shadow if its required */ if (FAILED(IDirect3DDevice9_UpdateTexture(priv->d3d_device, (IDirect3DBaseTexture9 *)priv->d3d_texture_system, (IDirect3DBaseTexture9 *)priv->d3d_texture_osd))) { mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture transfer failed.\n"); return; } } } /* update OSD */ if (priv->is_osd_populated) { struct_vertex osd_quad_vb[] = { {-1.0f, 1.0f, 0.0f, 0, 0 }, { 1.0f, 1.0f, 0.0f, 1, 0 }, {-1.0f,-1.0f, 0.0f, 0, 1 }, { 1.0f,-1.0f, 0.0f, 1, 1 } }; /* calculate the texture coordinates */ osd_quad_vb[1].tu = osd_quad_vb[3].tu = (float)priv->osd_width / priv->osd_texture_width; osd_quad_vb[2].tv = osd_quad_vb[3].tv = (float)priv->osd_height / priv->osd_texture_height; if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed.\n"); return; } /* turn on alpha test */ IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, TRUE); IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, TRUE); /* need to use a texture here (done here as we may be able to texture from system memory) */ IDirect3DDevice9_SetTexture(priv->d3d_device, 0, (IDirect3DBaseTexture9 *)(priv->device_texture_sys ? priv->d3d_texture_system : priv->d3d_texture_osd)); IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_MY_VERTEX); IDirect3DDevice9_DrawPrimitiveUP(priv->d3d_device, D3DPT_TRIANGLESTRIP, 2, osd_quad_vb, sizeof(struct_vertex)); /* turn off alpha test */ IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, FALSE); IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, FALSE); if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>EndScene failed.\n"); return; } } }
/** * Decode a subtitle packet via libavcodec. * \return < 0 on error, > 0 if further processing is needed */ int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size, double *pts, double *endpts) { AVCodecContext *ctx = sh->context; enum CodecID cid = CODEC_ID_NONE; int new_type = 0; int res; int got_sub; AVSubtitle sub; AVPacket pkt; switch (sh->type) { case 'b': cid = CODEC_ID_DVB_SUBTITLE; break; case 'p': cid = CODEC_ID_HDMV_PGS_SUBTITLE; break; case 'x': cid = CODEC_ID_XSUB; break; } av_init_packet(&pkt); pkt.data = *data; pkt.size = *size; pkt.pts = *pts * 1000; if (*pts != MP_NOPTS_VALUE && *endpts != MP_NOPTS_VALUE) pkt.convergence_duration = (*endpts - *pts) * 1000; if (!ctx) { AVCodec *sub_codec; init_avcodec(); ctx = avcodec_alloc_context3(NULL); sub_codec = avcodec_find_decoder(cid); if (!ctx || !sub_codec || avcodec_open2(ctx, sub_codec, NULL) < 0) { mp_msg(MSGT_SUBREADER, MSGL_FATAL, "Could not open subtitle decoder\n"); av_freep(&ctx); return -1; } sh->context = ctx; } res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt); if (res < 0) return res; if (*pts != MP_NOPTS_VALUE) { if (sub.end_display_time > sub.start_display_time) *endpts = *pts + sub.end_display_time / 1000.0; *pts += sub.start_display_time / 1000.0; } if (got_sub && vo_spudec && sub.num_rects == 0) spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, *pts, *endpts); if (got_sub && sub.num_rects > 0) { switch (sub.rects[0]->type) { case SUBTITLE_BITMAP: if (!vo_spudec) vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, NULL, 0); spudec_set_paletted(vo_spudec, sub.rects[0]->pict.data[0], sub.rects[0]->pict.linesize[0], sub.rects[0]->pict.data[1], sub.rects[0]->x, sub.rects[0]->y, sub.rects[0]->w, sub.rects[0]->h, *pts, *endpts); vo_osd_changed(OSDTYPE_SPU); break; case SUBTITLE_TEXT: *data = strdup(sub.rects[0]->text); *size = strlen(*data); new_type = 't'; break; case SUBTITLE_ASS: *data = strdup(sub.rects[0]->ass); *size = strlen(*data); new_type = 'a'; break; } } if (got_sub) avsubtitle_free(&sub); return new_type; }
static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, int data_len, double pts, double duration) { struct sd_lavc_priv *priv = sh->context; AVCodecContext *ctx = priv->avctx; AVSubtitle sub; AVPacket pkt; clear(priv); av_init_packet(&pkt); pkt.data = data; pkt.size = data_len; pkt.pts = pts * 1000; if (duration >= 0) pkt.convergence_duration = duration * 1000; int got_sub; int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt); if (res < 0 || !got_sub) return; if (pts != MP_NOPTS_VALUE) { if (sub.end_display_time > sub.start_display_time) duration = (sub.end_display_time - sub.start_display_time) / 1000.0; pts += sub.start_display_time / 1000.0; } double endpts = MP_NOPTS_VALUE; if (pts != MP_NOPTS_VALUE && duration >= 0) endpts = pts + duration; if (vo_spudec && sub.num_rects == 0) spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, pts, endpts); if (sub.num_rects > 0) { switch (sub.rects[0]->type) { case SUBTITLE_BITMAP: // Assume resolution heuristics only work for PGS and DVB if (!osd->support_rgba || sh->type != 'p' && sh->type != 'b') { if (!vo_spudec) vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, NULL, 0); old_avsub_to_spudec(sub.rects, sub.num_rects, pts, endpts); vo_osd_changed(OSDTYPE_SPU); break; } priv->inbitmaps = talloc_array(priv, struct sub_bitmap, sub.num_rects); for (int i = 0; i < sub.num_rects; i++) { struct AVSubtitleRect *r = sub.rects[i]; struct sub_bitmap *b = &priv->inbitmaps[i]; uint32_t *outbmp = talloc_size(priv->inbitmaps, r->w * r->h * 4); b->bitmap = outbmp; b->w = r->w; b->h = r->h; b->x = r->x; b->y = r->y; uint8_t *inbmp = r->pict.data[0]; uint32_t *palette = (uint32_t *) r->pict.data[1]; for (int y = 0; y < r->h; y++) { for (int x = 0; x < r->w; x++) *outbmp++ = palette[*inbmp++]; inbmp += r->pict.linesize[0] - r->w; }; } priv->count = sub.num_rects; priv->endpts = endpts; break; default: mp_msg(MSGT_SUBREADER, MSGL_ERR, "sd_lavc: unsupported subtitle " "type from libavcodec\n"); break; } } avsubtitle_free(&sub); }
void find_sub(struct MPContext *mpctx, sub_data* subd,int key){ subtitle *subs; subtitle *new_sub = NULL; int i,j; if ( !subd || subd->sub_num == 0) return; subs = subd->subtitles; if (last_sub_data != subd) { // Sub data changed, reset nosub range. last_sub_data = subd; nosub_range_start = -1; nosub_range_end = -1; } if(vo_sub){ if(key>=vo_sub->start && key<=vo_sub->end) return; // OK! } else { if(key>nosub_range_start && key<nosub_range_end) return; // OK! } // sub changed! /* Tell the OSD subsystem that the OSD contents will change soon */ vo_osd_changed(OSDTYPE_SUBTITLE); if(key<=0){ // no sub here goto update; } // printf("\r---- sub changed ----\n"); // check next sub. if(current_sub>=0 && current_sub+1 < subd->sub_num){ if(key>subs[current_sub].end && key<subs[current_sub+1].start){ // no sub nosub_range_start=subs[current_sub].end; nosub_range_end=subs[current_sub+1].start; goto update; } // next sub? ++current_sub; new_sub=&subs[current_sub]; if(key>=new_sub->start && key<=new_sub->end) goto update; // OK! } // printf("\r---- sub log search... ----\n"); // use logarithmic search: i=0; j = subd->sub_num - 1; // printf("Searching %d in %d..%d\n",key,subs[i].start,subs[j].end); while(j>=i){ current_sub=(i+j+1)/2; new_sub=&subs[current_sub]; if(key<new_sub->start) j=current_sub-1; else if(key>new_sub->end) i=current_sub+1; else goto update; // found! } // if(key>=new_sub->start && key<=new_sub->end) return; // OK! // check where are we... if(key<new_sub->start){ if(current_sub<=0){ // before the first sub nosub_range_start=key-1; // tricky nosub_range_end=new_sub->start; // printf("FIRST... key=%d end=%d \n",key,new_sub->start); new_sub=NULL; goto update; } --current_sub; if(key>subs[current_sub].end && key<subs[current_sub+1].start){ // no sub nosub_range_start=subs[current_sub].end; nosub_range_end=subs[current_sub+1].start; // printf("No sub... 1 \n"); new_sub=NULL; goto update; } printf("HEH???? "); } else { if(key<=new_sub->end) printf("JAJJ! "); else if(current_sub+1 >= subd->sub_num){ // at the end? nosub_range_start=new_sub->end; nosub_range_end=0x7FFFFFFF; // MAXINT // printf("END!?\n"); new_sub=NULL; goto update; } else if(key>subs[current_sub].end && key<subs[current_sub+1].start){ // no sub nosub_range_start=subs[current_sub].end; nosub_range_end=subs[current_sub+1].start; // printf("No sub... 2 \n"); new_sub=NULL; goto update; } } mp_msg(MSGT_FIXME,MSGL_FIXME,"SUB ERROR: %d ? %d --- %d [%d] \n",key,(int)new_sub->start,(int)new_sub->end,current_sub); new_sub=NULL; // no sub here update: set_osd_subtitle(mpctx, new_sub); }
static void display_buffer(subtitle * buf) { vo_sub=buf; vo_osd_changed(OSDTYPE_SUBTITLE); }
void mplEventHandling( int msg,float param ) { int iparam = (int)param; mixer_t *mixer = mpctx_get_mixer(guiIntfStruct.mpcontext); switch( msg ) { // --- user events case evExit: exit_player( "Exit" ); break; case evPlayNetwork: gfree( (void **)&guiIntfStruct.Subtitlename ); gfree( (void **)&guiIntfStruct.AudioFile ); guiIntfStruct.StreamType=STREAMTYPE_STREAM; goto play; case evSetURL: gtkShow( evPlayNetwork,NULL ); break; case evSetAudio: if ( !guiIntfStruct.demuxer || audio_id == iparam ) break; audio_id=iparam; goto play; case evSetVideo: if ( !guiIntfStruct.demuxer || video_id == iparam ) break; video_id=iparam; goto play; case evSetSubtitle: mp_property_do("sub",M_PROPERTY_SET,&iparam,guiIntfStruct.mpcontext); break; #ifdef CONFIG_VCD case evSetVCDTrack: guiIntfStruct.Track=iparam; case evPlayVCD: gtkSet( gtkClearStruct,0,(void *)guiALL ); guiIntfStruct.StreamType=STREAMTYPE_VCD; goto play; #endif #ifdef CONFIG_DVDREAD case evPlayDVD: guiIntfStruct.DVD.current_title=1; guiIntfStruct.DVD.current_chapter=1; guiIntfStruct.DVD.current_angle=1; play_dvd_2: gtkSet( gtkClearStruct,0,(void *)(guiALL - guiDVD) ); guiIntfStruct.StreamType=STREAMTYPE_DVD; goto play; #endif case evPlay: case evPlaySwitchToPause: play: if ( ( msg == evPlaySwitchToPause )&&( guiIntfStruct.Playing == 2 ) ) goto NoPause; if ( gtkSet( gtkGetCurrPlItem,0,NULL ) &&( guiIntfStruct.StreamType == STREAMTYPE_FILE ) ) { plItem * next = gtkSet( gtkGetCurrPlItem,0,NULL ); plLastPlayed=next; mplSetFileName( next->path,next->name,STREAMTYPE_FILE ); } switch ( guiIntfStruct.StreamType ) { case STREAMTYPE_STREAM: case STREAMTYPE_FILE: gtkSet( gtkClearStruct,0,(void *)(guiALL - guiFilenames) ); break; #ifdef CONFIG_VCD case STREAMTYPE_VCD: gtkSet( gtkClearStruct,0,(void *)(guiALL - guiVCD - guiFilenames) ); if ( !cdrom_device ) cdrom_device=gstrdup( DEFAULT_CDROM_DEVICE ); mplSetFileName( NULL,cdrom_device,STREAMTYPE_VCD ); if ( guiIntfStruct.Playing != 2 ) { if ( !guiIntfStruct.Track ) { if ( guiIntfStruct.VCDTracks > 1 ) guiIntfStruct.Track=2; else guiIntfStruct.Track=1; } guiIntfStruct.DiskChanged=1; } break; #endif #ifdef CONFIG_DVDREAD case STREAMTYPE_DVD: gtkSet( gtkClearStruct,0,(void *)(guiALL - guiDVD - guiFilenames) ); if ( !dvd_device ) dvd_device=gstrdup( DEFAULT_DVD_DEVICE ); mplSetFileName( NULL,dvd_device,STREAMTYPE_DVD ); if ( guiIntfStruct.Playing != 2 ) { guiIntfStruct.Title=guiIntfStruct.DVD.current_title; guiIntfStruct.Chapter=guiIntfStruct.DVD.current_chapter; guiIntfStruct.Angle=guiIntfStruct.DVD.current_angle; guiIntfStruct.DiskChanged=1; } break; #endif } guiIntfStruct.NewPlay=1; mplPlay(); break; #ifdef CONFIG_DVDREAD case evSetDVDSubtitle: dvdsub_id=iparam; goto play_dvd_2; break; case evSetDVDAudio: audio_id=iparam; goto play_dvd_2; break; case evSetDVDChapter: guiIntfStruct.DVD.current_chapter=iparam; goto play_dvd_2; break; case evSetDVDTitle: guiIntfStruct.DVD.current_title=iparam; guiIntfStruct.DVD.current_chapter=1; guiIntfStruct.DVD.current_angle=1; goto play_dvd_2; break; #endif case evPause: case evPauseSwitchToPlay: NoPause: mplPause(); break; case evStop: guiIntfStruct.Playing=guiSetStop; mplState(); guiIntfStruct.NoWindow=False; break; case evLoadPlay: mplMainAutoPlay=1; // guiIntfStruct.StreamType=STREAMTYPE_FILE; case evLoad: gtkSet( gtkDelPl,0,NULL ); gtkShow( evLoad,NULL ); break; case evLoadSubtitle: gtkShow( evLoadSubtitle,NULL ); break; case evDropSubtitle: gfree( (void **)&guiIntfStruct.Subtitlename ); guiLoadSubtitle( NULL ); break; case evLoadAudioFile: gtkShow( evLoadAudioFile,NULL ); break; case evPrev: mplPrev(); break; case evNext: mplNext(); break; case evPlayList: gtkShow( evPlayList,NULL ); break; case evSkinBrowser: gtkShow( evSkinBrowser,skinName ); break; case evAbout: gtkShow( evAbout,NULL ); break; case evPreferences: gtkShow( evPreferences,NULL ); break; case evEqualizer: gtkShow( evEqualizer,NULL ); break; case evForward10min: mplRelSeek( 600 ); break; case evBackward10min: mplRelSeek( -600 );break; case evForward1min: mplRelSeek( 60 ); break; case evBackward1min: mplRelSeek( -60 ); break; case evForward10sec: mplRelSeek( 10 ); break; case evBackward10sec: mplRelSeek( -10 ); break; case evSetMoviePosition: mplAbsSeek( param ); break; case evIncVolume: vo_x11_putkey( wsGrayMul ); break; case evDecVolume: vo_x11_putkey( wsGrayDiv ); break; case evMute: mixer_mute( mixer ); break; case evSetVolume: guiIntfStruct.Volume=param; goto set_volume; case evSetBalance: guiIntfStruct.Balance=param; set_volume: { float l = guiIntfStruct.Volume * ( ( 100.0 - guiIntfStruct.Balance ) / 50.0 ); float r = guiIntfStruct.Volume * ( ( guiIntfStruct.Balance ) / 50.0 ); if ( l > guiIntfStruct.Volume ) l=guiIntfStruct.Volume; if ( r > guiIntfStruct.Volume ) r=guiIntfStruct.Volume; // printf( "!!! v: %.2f b: %.2f -> %.2f x %.2f\n",guiIntfStruct.Volume,guiIntfStruct.Balance,l,r ); mixer_setvolume( mixer,l,r ); } if ( osd_level ) { osd_visible=(GetTimerMS() + 1000) | 1; vo_osd_progbar_type=OSD_VOLUME; vo_osd_progbar_value=( ( guiIntfStruct.Volume ) * 256.0 ) / 100.0; vo_osd_changed( OSDTYPE_PROGBAR ); } break; case evIconify: switch ( iparam ) { case 0: wsIconify( appMPlayer.mainWindow ); break; case 1: wsIconify( appMPlayer.subWindow ); break; } break; case evHalfSize: btnSet( evFullScreen,btnReleased ); if ( guiIntfStruct.Playing ) { if ( appMPlayer.subWindow.isFullScreen ) { mplFullScreen(); } wsResizeWindow( &appMPlayer.subWindow, guiIntfStruct.MovieWidth / 2, guiIntfStruct.MovieHeight / 2 ); wsMoveWindow( &appMPlayer.subWindow, 0, ( wsMaxX - guiIntfStruct.MovieWidth/2 )/2 + wsOrgX, ( wsMaxY - guiIntfStruct.MovieHeight/2 )/2 + wsOrgY ); } break; case evDoubleSize: btnSet( evFullScreen,btnReleased ); if ( guiIntfStruct.Playing ) { if ( appMPlayer.subWindow.isFullScreen ) { mplFullScreen(); } wsResizeWindow( &appMPlayer.subWindow, guiIntfStruct.MovieWidth * 2, guiIntfStruct.MovieHeight * 2 ); wsMoveWindow( &appMPlayer.subWindow, 0, ( wsMaxX - guiIntfStruct.MovieWidth*2 )/2 + wsOrgX, ( wsMaxY - guiIntfStruct.MovieHeight*2 )/2 + wsOrgY ); } break; case evNormalSize: btnSet( evFullScreen,btnReleased ); if ( guiIntfStruct.Playing ) { if ( appMPlayer.subWindow.isFullScreen ) { mplFullScreen(); } wsResizeWindow( &appMPlayer.subWindow, guiIntfStruct.MovieWidth, guiIntfStruct.MovieHeight ); wsMoveWindow( &appMPlayer.subWindow, 0, ( wsMaxX - guiIntfStruct.MovieWidth )/2 + wsOrgX, ( wsMaxY - guiIntfStruct.MovieHeight )/2 + wsOrgY ); break; } else if ( !appMPlayer.subWindow.isFullScreen ) break; case evFullScreen: if ( !guiIntfStruct.Playing && !gtkShowVideoWindow ) break; mplFullScreen(); if ( appMPlayer.subWindow.isFullScreen ) btnSet( evFullScreen,btnPressed ); else btnSet( evFullScreen,btnReleased ); break; case evSetAspect: switch ( iparam ) { case 2: movie_aspect=16.0f / 9.0f; break; case 3: movie_aspect=4.0f / 3.0f; break; case 4: movie_aspect=2.35; break; case 1: default: movie_aspect=-1; } wsClearWindow( appMPlayer.subWindow ); #ifdef CONFIG_DVDREAD if ( guiIntfStruct.StreamType == STREAMTYPE_DVD || guiIntfStruct.StreamType == STREAMTYPE_VCD ) goto play_dvd_2; else #endif guiIntfStruct.NewPlay=1; break; // --- timer events case evRedraw: { unsigned now = GetTimerMS(); extern int mplPBFade; if ((now > last_redraw_time) && (now < last_redraw_time + GUI_REDRAW_WAIT) && !mplPBFade) break; last_redraw_time = now; } mplMainRender=1; wsPostRedisplay( &appMPlayer.mainWindow ); wsPostRedisplay( &appMPlayer.barWindow ); break; // --- system events #ifdef MP_DEBUG case evNone: mp_msg( MSGT_GPLAYER,MSGL_STATUS,"[mw] event none received.\n" ); break; default: mp_msg( MSGT_GPLAYER,MSGL_STATUS,"[mw] unknown event received ( %d,%.2f ).\n",msg,param ); break; #endif } }
void update_subtitles(sh_video_t *sh_video, double refpts, demux_stream_t *d_dvdsub, int reset) { double curpts = refpts - sub_delay; unsigned char *packet=NULL; int len; int type = d_dvdsub->sh ? ((sh_sub_t *)d_dvdsub->sh)->type : 'v'; static subtitle subs; if (reset) { sub_clear_text(&subs, MP_NOPTS_VALUE); if (vo_sub) { set_osd_subtitle(NULL); } if (vo_spudec) { spudec_reset(vo_spudec); vo_osd_changed(OSDTYPE_SPU); } #ifdef CONFIG_FFMPEG if (is_av_sub(type)) reset_avsub(d_dvdsub->sh); #endif } // find sub if (subdata) { if (sub_fps==0) sub_fps = sh_video ? sh_video->fps : 25; current_module = "find_sub"; if (refpts > sub_last_pts || refpts < sub_last_pts-1.0) { find_sub(subdata, curpts * (subdata->sub_uses_time ? 100. : sub_fps)); if (vo_sub) vo_sub_last = vo_sub; // FIXME! frame counter... sub_last_pts = refpts; } } // DVD sub: if (vo_config_count && (vobsub_id >= 0 || type == 'v')) { int timestamp; current_module = "spudec"; /* Get a sub packet from the DVD or a vobsub */ while(1) { // Vobsub len = 0; if (vo_vobsub) { if (curpts >= 0) { len = vobsub_get_packet(vo_vobsub, curpts, (void**)&packet, ×tamp); if (len > 0) { mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,refpts,sh_video->timer,timestamp / 90000.0,timestamp); } } } else { // DVD sub len = ds_get_packet_sub(d_dvdsub, (unsigned char**)&packet, NULL, NULL); if (len > 0) { // XXX This is wrong, sh_video->pts can be arbitrarily // much behind demuxing position. Unfortunately using // d_video->pts which would have been the simplest // improvement doesn't work because mpeg specific hacks // in video.c set d_video->pts to 0. float x = d_dvdsub->pts - refpts; if (x > -20 && x < 20) // prevent missing subs on pts reset timestamp = 90000*d_dvdsub->pts; else timestamp = 90000*curpts; mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d " "v_pts=%5.3f s_pts=%5.3f ts=%d \n", len, refpts, d_dvdsub->pts, timestamp); } } if (len<=0 || !packet) break; // create it only here, since with some broken demuxers we might // type = v but no DVD sub and we currently do not change the // "original frame size" ever after init, leading to wrong-sized // PGS subtitles. if (!vo_spudec) vo_spudec = spudec_new(NULL); if (vo_vobsub || timestamp >= 0) spudec_assemble(vo_spudec, packet, len, timestamp); } } else if (is_text_sub(type) || is_av_sub(type) || type == 'd') { int orig_type = type; double endpts; if (type == 'd' && !d_dvdsub->demuxer->teletext) { tt_stream_props tsp = {0}; void *ptr = &tsp; if (teletext_control(NULL, TV_VBI_CONTROL_START, &ptr) == VBI_CONTROL_TRUE) d_dvdsub->demuxer->teletext = ptr; } if (d_dvdsub->non_interleaved) ds_get_next_pts(d_dvdsub); while (1) { double subpts = curpts; type = orig_type; len = ds_get_packet_sub(d_dvdsub, &packet, &subpts, &endpts); if (len < 0) break; if (is_av_sub(type)) { #ifdef CONFIG_FFMPEG type = decode_avsub(d_dvdsub->sh, &packet, &len, &subpts, &endpts); if (type <= 0) #endif continue; } if (type == 'm') { if (len < 2) continue; len = FFMIN(len - 2, AV_RB16(packet)); packet += 2; } if (type == 'd') { if (d_dvdsub->demuxer->teletext) { uint8_t *p = packet; p++; len--; while (len >= 46) { int sublen = p[1]; if (p[0] == 2 || p[0] == 3) teletext_control(d_dvdsub->demuxer->teletext, TV_VBI_CONTROL_DECODE_DVB, p + 2); p += sublen + 2; len -= sublen + 2; } } continue; } #ifdef CONFIG_ASS if (ass_enabled) { sh_sub_t* sh = d_dvdsub->sh; ass_track = sh ? sh->ass_track : NULL; if (!ass_track) continue; if (type == 'a') { // ssa/ass subs with libass if (len > 10 && memcmp(packet, "Dialogue: ", 10) == 0) ass_process_data(ass_track, packet, len); else ass_process_chunk(ass_track, packet, len, (long long)(subpts*1000 + 0.5), (long long)((endpts-subpts)*1000 + 0.5)); } else { // plaintext subs with libass if (subpts != MP_NOPTS_VALUE) { subtitle tmp_subs = {0}; if (endpts == MP_NOPTS_VALUE) endpts = subpts + 3; sub_add_text(&tmp_subs, packet, len, endpts, 0); tmp_subs.start = subpts * 100; tmp_subs.end = endpts * 100; ass_process_subtitle(ass_track, &tmp_subs); sub_clear_text(&tmp_subs, MP_NOPTS_VALUE); } } continue; } #endif if (subpts != MP_NOPTS_VALUE) { if (endpts == MP_NOPTS_VALUE) sub_clear_text(&subs, MP_NOPTS_VALUE); if (type == 'a') { // ssa/ass subs without libass => convert to plaintext int i; unsigned char* p = packet; int skip_commas = 8; if (len > 10 && memcmp(packet, "Dialogue: ", 10) == 0) skip_commas = 9; for (i=0; i < skip_commas && *p != '\0'; p++) if (*p == ',') i++; if (*p == '\0') /* Broken line? */ continue; len -= p - packet; packet = p; } sub_add_text(&subs, packet, len, endpts, 1); set_osd_subtitle(&subs); } if (d_dvdsub->non_interleaved) ds_get_next_pts(d_dvdsub); } if (sub_clear_text(&subs, curpts)) set_osd_subtitle(&subs); } if (vo_spudec) { spudec_heartbeat(vo_spudec, 90000*curpts); if (spudec_changed(vo_spudec)) vo_osd_changed(OSDTYPE_SPU); } current_module=NULL; }
void uiEventHandling( int msg,float param ) { int iparam = (int)param; mixer_t *mixer = mpctx_get_mixer(guiInfo.mpcontext); switch( msg ) { /* user events */ case evExit: mplayer( MPLAYER_EXIT_GUI, EXIT_QUIT, 0 ); break; case evLoadURL: gtkShow( evLoadURL,NULL ); break; case ivSetAudio: if ( !mpctx_get_demuxer(guiInfo.mpcontext) || audio_id == iparam ) break; mp_property_do("switch_audio",M_PROPERTY_SET,&iparam,guiInfo.mpcontext); break; case ivSetVideo: if ( !mpctx_get_demuxer(guiInfo.mpcontext) || video_id == iparam ) break; mp_property_do("switch_video",M_PROPERTY_SET,&iparam,guiInfo.mpcontext); break; case ivSetSubtitle: mp_property_do("sub",M_PROPERTY_SET,&iparam,guiInfo.mpcontext); break; #ifdef CONFIG_CDDA case ivSetCDTrack: guiInfo.Track=iparam; case evPlayCD: guiInfoMediumClear ( CLEAR_ALL ); guiInfo.StreamType=STREAMTYPE_CDDA; goto play; #endif #ifdef CONFIG_VCD case ivSetVCDTrack: guiInfo.Track=iparam; case evPlayVCD: guiInfoMediumClear ( CLEAR_ALL ); guiInfo.StreamType=STREAMTYPE_VCD; goto play; #endif #ifdef CONFIG_DVDREAD case ivSetDVDSubtitle: dvdsub_id=iparam; uiEventHandling( ivPlayDVD, 0 ); break; case ivSetDVDAudio: audio_id=iparam; uiEventHandling( ivPlayDVD, 0 ); break; case ivSetDVDChapter: guiInfo.Chapter=iparam; uiEventHandling( ivPlayDVD, 0 ); break; case ivSetDVDTitle: guiInfo.Track=iparam; guiInfo.Chapter=1; guiInfo.Angle=1; uiEventHandling( ivPlayDVD, 0 ); break; case evPlayDVD: guiInfo.Track=1; guiInfo.Chapter=1; guiInfo.Angle=1; case ivPlayDVD: guiInfoMediumClear( CLEAR_ALL - CLEAR_DVD ); guiInfo.StreamType=STREAMTYPE_DVD; goto play; #endif case evPlay: case evPlaySwitchToPause: play: if ( ( msg == evPlaySwitchToPause )&&( guiInfo.Playing == GUI_PAUSE ) ) goto NoPause; if ( listMgr( PLAYLIST_ITEM_GET_CURR,0 ) &&( guiInfo.StreamType == STREAMTYPE_FILE ) ) { plItem * next = listMgr( PLAYLIST_ITEM_GET_CURR,0 ); uiSetFileName( next->path,next->name,SAME_STREAMTYPE ); } switch ( guiInfo.StreamType ) { case STREAMTYPE_FILE: case STREAMTYPE_STREAM: case STREAMTYPE_PLAYLIST: guiInfoMediumClear( CLEAR_ALL - CLEAR_FILE ); if ( !guiInfo.Track ) guiInfo.Track=1; guiInfo.NewPlay=GUI_FILE_NEW; break; case STREAMTYPE_CDDA: guiInfoMediumClear( CLEAR_ALL - CLEAR_VCD - CLEAR_FILE ); if ( guiInfo.Playing != GUI_PAUSE ) { if ( !guiInfo.Track ) guiInfo.Track=1; guiInfo.NewPlay=GUI_FILE_SAME; } break; case STREAMTYPE_VCD: guiInfoMediumClear( CLEAR_ALL - CLEAR_VCD - CLEAR_FILE ); if ( guiInfo.Playing != GUI_PAUSE ) { if ( !guiInfo.Track ) guiInfo.Track=2; guiInfo.NewPlay=GUI_FILE_SAME; } break; case STREAMTYPE_DVD: guiInfoMediumClear( CLEAR_ALL - CLEAR_DVD - CLEAR_FILE ); if ( guiInfo.Playing != GUI_PAUSE ) { guiInfo.NewPlay=GUI_FILE_SAME; } break; } uiPlay(); break; case evPause: case evPauseSwitchToPlay: NoPause: uiPause(); break; case evStop: guiInfo.Playing=GUI_STOP; uiState(); break; case evLoadPlay: uiMainAutoPlay=1; // guiInfo.StreamType=STREAMTYPE_FILE; case evLoad: listMgr( PLAYLIST_DELETE,0 ); gtkShow( evLoad,NULL ); break; case evLoadSubtitle: gtkShow( evLoadSubtitle,NULL ); break; case evDropSubtitle: nfree( guiInfo.SubtitleFilename ); mplayerLoadSubtitle( NULL ); break; case evLoadAudioFile: gtkShow( evLoadAudioFile,NULL ); break; case evPrev: uiPrev(); break; case evNext: uiNext(); break; case evPlaylist: gtkShow( evPlaylist,NULL ); break; case evSkinBrowser: gtkShow( evSkinBrowser,skinName ); break; case evAbout: gtkShow( evAbout,NULL ); break; case evPreferences: gtkShow( evPreferences,NULL ); break; case evEqualizer: gtkShow( evEqualizer,NULL ); break; case evForward10min: uiRelSeek( 600 ); break; case evBackward10min: uiRelSeek( -600 );break; case evForward1min: uiRelSeek( 60 ); break; case evBackward1min: uiRelSeek( -60 ); break; case evForward10sec: uiRelSeek( 10 ); break; case evBackward10sec: uiRelSeek( -10 ); break; case evSetMoviePosition: uiAbsSeek( param ); break; case evIncVolume: vo_x11_putkey( wsGrayMul ); break; case evDecVolume: vo_x11_putkey( wsGrayDiv ); break; case evMute: mixer_mute( mixer ); break; case evSetVolume: guiInfo.Volume=param; goto set_volume; case evSetBalance: guiInfo.Balance=param; set_volume: { float l = guiInfo.Volume * ( ( 100.0 - guiInfo.Balance ) / 50.0 ); float r = guiInfo.Volume * ( ( guiInfo.Balance ) / 50.0 ); if ( l > guiInfo.Volume ) l=guiInfo.Volume; if ( r > guiInfo.Volume ) r=guiInfo.Volume; // printf( "!!! v: %.2f b: %.2f -> %.2f x %.2f\n",guiInfo.Volume,guiInfo.Balance,l,r ); mixer_setvolume( mixer,l,r ); } if ( osd_level ) { osd_visible=(GetTimerMS() + 1000) | 1; vo_osd_progbar_type=OSD_VOLUME; vo_osd_progbar_value=( ( guiInfo.Volume ) * 256.0 ) / 100.0; vo_osd_changed( OSDTYPE_PROGBAR ); } break; case evMenu: /*if (guiApp.menuIsPresent) NOTE TO MYSELF: Uncomment only after mouse { pointer and cursor keys work gtkShow( ivHidePopUpMenu,NULL ); with this menu from skin as uiShowMenu( 0,0 ); they do with normal menus. } else*/ gtkShow( ivShowPopUpMenu,NULL ); break; case evIconify: switch ( iparam ) { case 0: wsIconify( guiApp.mainWindow ); break; case 1: wsIconify( guiApp.videoWindow ); break; } break; case evHalfSize: if ( guiInfo.VideoWindow && guiInfo.Playing ) { if ( guiApp.videoWindow.isFullScreen ) { uiFullScreen(); } wsResizeWindow( &guiApp.videoWindow, guiInfo.VideoWidth / 2, guiInfo.VideoHeight / 2 ); wsMoveWindow( &guiApp.videoWindow, False, guiApp.video.x, guiApp.video.y ); btnSet( evFullScreen,btnReleased ); } break; case evDoubleSize: if ( guiInfo.VideoWindow && guiInfo.Playing ) { if ( guiApp.videoWindow.isFullScreen ) { uiFullScreen(); } wsResizeWindow( &guiApp.videoWindow, guiInfo.VideoWidth * 2, guiInfo.VideoHeight * 2 ); wsMoveWindowWithin( &guiApp.videoWindow, False, guiApp.video.x, guiApp.video.y ); btnSet( evFullScreen,btnReleased ); } break; case evNormalSize: if ( guiInfo.VideoWindow && guiInfo.Playing ) { if ( guiApp.videoWindow.isFullScreen ) { uiFullScreen(); } wsResizeWindow( &guiApp.videoWindow, guiInfo.VideoWidth, guiInfo.VideoHeight ); wsMoveWindow( &guiApp.videoWindow, False, guiApp.video.x, guiApp.video.y ); btnSet( evFullScreen,btnReleased ); break; } else if ( !guiApp.videoWindow.isFullScreen ) break; case evFullScreen: if ( guiInfo.VideoWindow && guiInfo.Playing ) { uiFullScreen(); if ( !guiApp.videoWindow.isFullScreen ) { wsResizeWindow( &guiApp.videoWindow, guiInfo.VideoWidth, guiInfo.VideoHeight ); wsMoveWindow( &guiApp.videoWindow, False, guiApp.video.x, guiApp.video.y ); } } if ( guiApp.videoWindow.isFullScreen ) btnSet( evFullScreen,btnPressed ); else btnSet( evFullScreen,btnReleased ); break; case evSetAspect: switch ( iparam ) { case 2: movie_aspect=16.0f / 9.0f; break; case 3: movie_aspect=4.0f / 3.0f; break; case 4: movie_aspect=2.35; break; case 1: default: movie_aspect=-1; } wsClearWindow( guiApp.videoWindow ); if ( guiInfo.StreamType == STREAMTYPE_VCD ) uiEventHandling( evPlayVCD, 0 ); else if ( guiInfo.StreamType == STREAMTYPE_DVD ) uiEventHandling( ivPlayDVD, 0 ); else guiInfo.NewPlay=GUI_FILE_NEW; break; /* timer events */ case ivRedraw: { unsigned now = GetTimerMS(); if ((now > last_redraw_time) && (now < last_redraw_time + GUI_REDRAW_WAIT) && !uiPlaybarFade && (iparam == 0)) break; last_redraw_time = now; } uiMainRender=1; wsPostRedisplay( &guiApp.mainWindow ); wsPostRedisplay( &guiApp.playbarWindow ); break; /* system events */ case evNone: mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[main] uiEventHandling: evNone\n" ); break; default: mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[main] uiEventHandling: unknown event %d, param %.2f\n", msg, param ); break; } }
void update_subtitles(sh_video_t *sh_video, demux_stream_t *d_dvdsub, int reset) { unsigned char *packet=NULL; int len; char type = d_dvdsub->sh ? ((sh_sub_t *)d_dvdsub->sh)->type : 'v'; static subtitle subs; if (type == 'a') #ifdef USE_ASS if (!ass_enabled) #endif type = 't'; if (reset) { sub_clear_text(&subs, MP_NOPTS_VALUE); if (vo_sub) { vo_sub = NULL; vo_osd_changed(OSDTYPE_SUBTITLE); } if (vo_spudec) { spudec_reset(vo_spudec); vo_osd_changed(OSDTYPE_SPU); } } // find sub if (subdata) { double pts = sh_video->pts; if (sub_fps==0) sub_fps = sh_video->fps; current_module = "find_sub"; if (pts > sub_last_pts || pts < sub_last_pts-1.0) { find_sub(subdata, (pts+sub_delay) * (subdata->sub_uses_time ? 100. : sub_fps)); if (vo_sub) vo_sub_last = vo_sub; // FIXME! frame counter... sub_last_pts = pts; } } // DVD sub: if (vo_config_count && vo_spudec && type == 'v') { int timestamp; current_module = "spudec"; spudec_heartbeat(vo_spudec, 90000*sh_video->timer); /* Get a sub packet from the DVD or a vobsub and make a timestamp * relative to sh_video->timer */ while(1) { // Vobsub len = 0; if (vo_vobsub) { if (sh_video->pts+sub_delay >= 0) { len = vobsub_get_packet(vo_vobsub, sh_video->pts+sub_delay, (void**)&packet, ×tamp); if (len > 0) { timestamp -= (sh_video->pts + sub_delay - sh_video->timer)*90000; mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,sh_video->pts,sh_video->timer,timestamp / 90000.0,timestamp); } } } else { // DVD sub len = ds_get_packet_sub(d_dvdsub, (unsigned char**)&packet); if (len > 0) { // XXX This is wrong, sh_video->pts can be arbitrarily // much behind demuxing position. Unfortunately using // d_video->pts which would have been the simplest // improvement doesn't work because mpeg specific hacks // in video.c set d_video->pts to 0. float x = d_dvdsub->pts - sh_video->pts; if (x > -20 && x < 20) // prevent missing subs on pts reset timestamp = 90000*(sh_video->timer + d_dvdsub->pts + sub_delay - sh_video->pts); else timestamp = 90000*(sh_video->timer + sub_delay); mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d " "v_pts=%5.3f s_pts=%5.3f ts=%d \n", len, sh_video->pts, d_dvdsub->pts, timestamp); } } if (len<=0 || !packet) break; if (timestamp >= 0) spudec_assemble(vo_spudec, packet, len, timestamp); } if (spudec_changed(vo_spudec)) vo_osd_changed(OSDTYPE_SPU); } else if (dvdsub_id >= 0 && type == 't') { double curpts = sh_video->pts + sub_delay; double endpts; vo_sub = &subs; while (d_dvdsub->first) { double pts = ds_get_next_pts(d_dvdsub); if (pts > curpts) break; endpts = d_dvdsub->first->endpts; len = ds_get_packet_sub(d_dvdsub, &packet); #ifdef USE_ASS if (ass_enabled) { static ass_track_t *global_ass_track = NULL; if (!global_ass_track) global_ass_track = ass_default_track(ass_library); ass_track = global_ass_track; vo_sub = NULL; if (pts != MP_NOPTS_VALUE) { if (endpts == MP_NOPTS_VALUE) endpts = pts + 3; sub_clear_text(&subs, MP_NOPTS_VALUE); sub_add_text(&subs, packet, len, endpts); subs.start = pts * 100; subs.end = endpts * 100; ass_process_subtitle(ass_track, &subs); } } else #endif if (pts != MP_NOPTS_VALUE) { if (endpts == MP_NOPTS_VALUE) sub_clear_text(&subs, MP_NOPTS_VALUE); sub_add_text(&subs, packet, len, endpts); vo_osd_changed(OSDTYPE_SUBTITLE); } } if (sub_clear_text(&subs, curpts)) vo_osd_changed(OSDTYPE_SUBTITLE); } current_module=NULL; }