diff --git a/source/blender/blenkernel/intern/sound.cc b/source/blender/blenkernel/intern/sound.cc index d25fcd806ff..4c796638275 100644 --- a/source/blender/blenkernel/intern/sound.cc +++ b/source/blender/blenkernel/intern/sound.cc @@ -427,6 +427,11 @@ static void sound_device_use_begin() static void sound_device_use_end_after(const std::chrono::milliseconds after_ms) { + BLI_assert(g_state.num_device_users > 0); + if (g_state.num_device_users == 0) { + return; + } + --g_state.num_device_users; if (g_state.num_device_users == 0) { g_state.last_user_disconnect_time_point = std::chrono::steady_clock::now() + after_ms; diff --git a/source/blender/editors/screen/screen_ops.cc b/source/blender/editors/screen/screen_ops.cc index 2fd8cc7a89c..acec6f615b5 100644 --- a/source/blender/editors/screen/screen_ops.cc +++ b/source/blender/editors/screen/screen_ops.cc @@ -6039,15 +6039,46 @@ bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm) return nullptr; } -wmOperatorStatus ED_screen_animation_play(bContext *C, int sync, int mode) +static void stop_playback(bContext *C) { + Main *bmain = CTX_data_main(C); + bScreen *screen = ED_screen_animation_playing(CTX_wm_manager(C)); + wmTimer *wt = screen->animtimer; + ScreenAnimData *sad = static_cast(wt->customdata); + Scene *scene = sad->scene; + + ViewLayer *view_layer = sad->view_layer; + Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer); + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + + /* Only stop sound playback, when playing forward, since there is no sound for reverse + * playback. */ + if ((sad->flag & ANIMPLAY_FLAG_REVERSE) == 0) { + BKE_sound_stop_scene(scene_eval); + } + + ED_screen_animation_timer(C, scene, view_layer, 0, 0, 0); + ED_scene_fps_average_clear(scene); + BKE_callback_exec_id_depsgraph(bmain, &scene->id, depsgraph, BKE_CB_EVT_ANIMATION_PLAYBACK_POST); + + /* Triggers redraw of sequencer preview so that it does not show to fps anymore after stopping + * playback. */ + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SEQUENCER, scene); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SPREADSHEET, scene); + WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM, scene); +} + +static wmOperatorStatus start_playback(bContext *C, int sync, int mode) +{ + Main *bmain = CTX_data_main(C); bScreen *screen = CTX_wm_screen(C); + const bool is_sequencer = CTX_wm_space_seq(C) != nullptr; Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C); if (!scene) { return OPERATOR_CANCELLED; } - Main *bmain = CTX_data_main(C); ViewLayer *view_layer = is_sequencer ? BKE_view_layer_default_render(scene) : CTX_data_view_layer(C); Depsgraph *depsgraph = is_sequencer ? BKE_scene_ensure_depsgraph(bmain, scene, view_layer) : @@ -6057,61 +6088,36 @@ wmOperatorStatus ED_screen_animation_play(bContext *C, int sync, int mode) } Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - if (ED_screen_animation_playing(CTX_wm_manager(C))) { - /* stop playback now */ - ED_screen_animation_timer(C, scene, view_layer, 0, 0, 0); - ED_scene_fps_average_clear(scene); - BKE_sound_stop_scene(scene_eval); + BKE_callback_exec_id_depsgraph(bmain, &scene->id, depsgraph, BKE_CB_EVT_ANIMATION_PLAYBACK_PRE); - if (is_sequencer) { - /* Stop sound for active scene in window. */ - BKE_sound_stop_scene(DEG_get_evaluated_scene(CTX_data_ensure_evaluated_depsgraph(C))); - } - else { - /* Stop sound for sequencer scene. */ - WorkSpace *workspace = CTX_wm_workspace(C); - if (workspace->sequencer_scene) { - Depsgraph *depsgraph = BKE_scene_ensure_depsgraph( - bmain, - workspace->sequencer_scene, - BKE_view_layer_default_render(workspace->sequencer_scene)); - Scene *seq_scene_eval = DEG_get_evaluated_scene(depsgraph); - BKE_sound_stop_scene(seq_scene_eval); - } - } - - BKE_callback_exec_id_depsgraph( - bmain, &scene->id, depsgraph, BKE_CB_EVT_ANIMATION_PLAYBACK_POST); - - /* Triggers redraw of sequencer preview so that it does not show to fps anymore after stopping - * playback. */ - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SEQUENCER, scene); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SPREADSHEET, scene); - WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM, scene); + /* Only play sound when playing forward. Reverse sound playback is not implemented. */ + if (mode == 1) { + BKE_sound_play_scene(scene_eval); } - else { - BKE_callback_exec_id_depsgraph( - bmain, &scene->id, depsgraph, BKE_CB_EVT_ANIMATION_PLAYBACK_PRE); - /* these settings are currently only available from a menu in the TimeLine */ - if (mode == 1) { /* XXX only play audio forwards!? */ - BKE_sound_play_scene(scene_eval); - } + ED_screen_animation_timer(C, scene, view_layer, screen->redraws_flag, sync, mode); + ED_scene_fps_average_clear(scene); - ED_screen_animation_timer(C, scene, view_layer, screen->redraws_flag, sync, mode); - ED_scene_fps_average_clear(scene); + if (screen->animtimer) { + wmTimer *wt = screen->animtimer; + ScreenAnimData *sad = static_cast(wt->customdata); - if (screen->animtimer) { - wmTimer *wt = screen->animtimer; - ScreenAnimData *sad = static_cast(wt->customdata); - - sad->region = CTX_wm_region(C); - } + sad->region = CTX_wm_region(C); } return OPERATOR_FINISHED; } +wmOperatorStatus ED_screen_animation_play(bContext *C, int sync, int mode) +{ + if (ED_screen_animation_playing(CTX_wm_manager(C))) { + stop_playback(C); + return OPERATOR_FINISHED; + } + + return start_playback(C, sync, mode); +} + static wmOperatorStatus screen_animation_play_exec(bContext *C, wmOperator *op) { int mode = RNA_boolean_get(op->ptr, "reverse") ? -1 : 1;