diff --git a/player/core.h b/player/core.h index 4303daa78a..abe1316b41 100644 --- a/player/core.h +++ b/player/core.h @@ -181,6 +181,7 @@ typedef struct MPContext { char *term_osd_subs; char *term_osd_contents; char *last_window_title; + struct voctrl_playback_state vo_playback_state; int add_osd_seek_info; // bitfield of enum mp_osd_seek_info double osd_visible; // for the osd bar only @@ -462,6 +463,7 @@ double get_relative_time(struct MPContext *mpctx); void merge_playlist_files(struct playlist *pl); float mp_get_cache_percent(struct MPContext *mpctx); bool mp_get_cache_idle(struct MPContext *mpctx); +void update_vo_playback_state(struct MPContext *mpctx); void update_window_title(struct MPContext *mpctx, bool force); void error_on_track(struct MPContext *mpctx, struct track *track); int stream_dump(struct MPContext *mpctx, const char *source_filename); diff --git a/player/misc.c b/player/misc.c index add73e5a17..1e67adbe32 100644 --- a/player/misc.c +++ b/player/misc.c @@ -153,6 +153,26 @@ bool mp_get_cache_idle(struct MPContext *mpctx) return idle; } +void update_vo_playback_state(struct MPContext *mpctx) +{ + if (mpctx->video_out) { + struct voctrl_playback_state oldstate = mpctx->vo_playback_state; + struct voctrl_playback_state newstate = { + .paused = mpctx->paused, + .percent_pos = get_percent_pos(mpctx), + }; + + if (oldstate.paused != newstate.paused || + oldstate.percent_pos != newstate.percent_pos) { + vo_control(mpctx->video_out, + VOCTRL_UPDATE_PLAYBACK_STATE, &newstate); + mpctx->vo_playback_state = newstate; + } + } else { + mpctx->vo_playback_state = (struct voctrl_playback_state){ 0 }; + } +} + void update_window_title(struct MPContext *mpctx, bool force) { if (!mpctx->video_out && !mpctx->ao) { diff --git a/player/osd.c b/player/osd.c index 596386ebae..cb49131cc1 100644 --- a/player/osd.c +++ b/player/osd.c @@ -164,6 +164,7 @@ static void print_status(struct MPContext *mpctx) struct MPOpts *opts = mpctx->opts; update_window_title(mpctx, false); + update_vo_playback_state(mpctx); if (!opts->use_terminal) return; diff --git a/video/out/vo.h b/video/out/vo.h index 30948e149b..3a8231a295 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -76,6 +76,7 @@ enum mp_voctrl { VOCTRL_ALL_WORKSPACES, VOCTRL_UPDATE_WINDOW_TITLE, // char* + VOCTRL_UPDATE_PLAYBACK_STATE, // struct voctrl_playback_state* VOCTRL_SET_CURSOR_VISIBILITY, // bool* @@ -130,6 +131,12 @@ struct voctrl_get_equalizer_args { #define VO_NOTAVAIL -2 #define VO_NOTIMPL -3 +// VOCTRL_UPDATE_PLAYBACK_STATE +struct voctrl_playback_state { + bool paused; + int percent_pos; +}; + enum { // VO does handle mp_image_params.rotate in 90 degree steps VO_CAP_ROTATE90 = 1 << 0, diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 37e0057162..6f0bb82ed3 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -105,6 +105,9 @@ struct vo_w32_state { int high_surrogate; ITaskbarList2 *taskbar_list; + ITaskbarList3 *taskbar_list3; + UINT tbtnCreatedMsg; + bool tbtnCreated; // updates on move/resize/displaychange double display_fps; @@ -826,6 +829,11 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, break; } + if (message == w32->tbtnCreatedMsg) { + w32->tbtnCreated = true; + return 0; + } + if (mouse_button) { mouse_button |= mod_state(w32); mp_input_put_key(w32->input_ctx, mouse_button); @@ -1198,6 +1206,20 @@ static void *gui_thread(void *ptr) w32->taskbar_list = NULL; } } + + // ITaskbarList3 has methods for status indication on taskbar buttons, + // however that interface is only available on Win7/2008 R2 or newer + if (SUCCEEDED(CoCreateInstance(&CLSID_TaskbarList, NULL, + CLSCTX_INPROC_SERVER, &IID_ITaskbarList3, + (void**)&w32->taskbar_list3))) + { + if (FAILED(ITaskbarList3_HrInit(w32->taskbar_list3))) { + ITaskbarList3_Release(w32->taskbar_list3); + w32->taskbar_list3 = NULL; + } else { + w32->tbtnCreatedMsg = RegisterWindowMessage(L"TaskbarButtonCreated"); + } + } } else { MP_ERR(w32, "Failed to initialize OLE/COM\n"); } @@ -1235,6 +1257,8 @@ done: } if (w32->taskbar_list) ITaskbarList2_Release(w32->taskbar_list); + if (w32->taskbar_list3) + ITaskbarList3_Release(w32->taskbar_list3); if (ole_ok) OleUninitialize(); SetThreadExecutionState(ES_CONTINUOUS); @@ -1348,6 +1372,19 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) talloc_free(title); return VO_TRUE; } + case VOCTRL_UPDATE_PLAYBACK_STATE: { + struct voctrl_playback_state *pstate = + (struct voctrl_playback_state *)arg; + + if (w32->taskbar_list3 && w32->tbtnCreated) { + ITaskbarList3_SetProgressValue(w32->taskbar_list3, w32->window, + pstate->percent_pos, 100); + ITaskbarList3_SetProgressState(w32->taskbar_list3, w32->window, + pstate->paused ? TBPF_PAUSED : + TBPF_NORMAL); + } + return VO_TRUE; + } case VOCTRL_GET_DISPLAY_FPS: update_display_fps(w32); *(double*) arg = w32->display_fps;