Blender V4.3
sequencer_preview.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#include "DNA_sound_types.h"
11
12#include "BLI_listbase.h"
13#include "BLI_task.h"
14#include "BLI_threads.h"
15
16#include "BKE_context.hh"
17#include "BKE_global.hh"
18#include "BKE_sound.h"
19
20#include "WM_api.hh"
21#include "WM_types.hh"
22
23#include "ED_screen.hh"
24
25#include "MEM_guardedalloc.h"
26
27#include "sequencer_intern.hh"
28
38
43 int lr; /* Sample left or right. */
45 bool waveform; /* Reload sound or waveform. */
46};
47
53
54static void free_preview_job(void *data)
55{
56 PreviewJob *pj = static_cast<PreviewJob *>(data);
57
60 MEM_freeN(pj);
61}
62
64{
65 SpinLock *spinlock = static_cast<SpinLock *>(sound->spinlock);
66 BLI_spin_lock(spinlock);
67 sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
68 BLI_spin_unlock(spinlock);
69}
70
71static void free_read_sound_waveform_task(TaskPool *__restrict task_pool, void *data)
72{
74
75 ReadSoundWaveformTask *task = static_cast<ReadSoundWaveformTask *>(data);
76
77 /* The job audio has already been removed from the list, now we just need to free it. */
78 MEM_freeN(task->preview_job_audio);
79
80 BLI_mutex_lock(task->wm_job->mutex);
81 task->wm_job->processed++;
82 BLI_mutex_unlock(task->wm_job->mutex);
83
84 BLI_condition_notify_one(&task->wm_job->preview_suspend_cond);
85
86 MEM_freeN(task);
87}
88
89static void execute_read_sound_waveform_task(TaskPool *__restrict task_pool, void *task_data)
90{
91 ReadSoundWaveformTask *task = static_cast<ReadSoundWaveformTask *>(task_data);
92
94 clear_sound_waveform_loading_tag(task->preview_job_audio->sound);
95 return;
96 }
97
98 PreviewJobAudio *audio_job = task->preview_job_audio;
99 BKE_sound_read_waveform(audio_job->bmain, audio_job->sound, task->stop);
100}
101
103 PreviewJob *pj,
104 PreviewJobAudio *previewjb,
105 bool *stop)
106{
107 ReadSoundWaveformTask *task = MEM_cnew<ReadSoundWaveformTask>("read sound waveform task");
108 task->wm_job = pj;
109 task->preview_job_audio = previewjb;
110 task->stop = stop;
111
114}
115
116/* Only this runs inside thread. */
117static void preview_startjob(void *data, wmJobWorkerStatus *worker_status)
118{
120 PreviewJob *pj = static_cast<PreviewJob *>(data);
121
122 while (true) {
123 /* Wait until there's either a new audio job to process or one of the previously submitted jobs
124 * is done. */
126
127 while (BLI_listbase_is_empty(&pj->previews) && pj->processed != pj->total) {
128
129 float current_progress = (pj->total > 0) ? float(pj->processed) / float(pj->total) : 1.0f;
130
131 if (current_progress != worker_status->progress) {
132 worker_status->progress = current_progress;
133 worker_status->do_update = true;
134 }
135
137 }
138
139 if (pj->processed == pj->total) {
140 pj->running = false;
142 break;
143 }
144
145 if (worker_status->stop || G.is_break) {
147
148 LISTBASE_FOREACH (PreviewJobAudio *, previewjb, &pj->previews) {
149 clear_sound_waveform_loading_tag(previewjb->sound);
150 }
151
153 pj->processed = 0;
154 pj->total = 0;
155 pj->running = false;
156
158 break;
159 }
160
162 push_preview_job_audio_task(task_pool, pj, previewjb, &worker_status->stop);
163
164 BLI_remlink(&pj->previews, previewjb);
165 }
166
168 }
169
172}
173
174static void preview_endjob(void *data)
175{
176 PreviewJob *pj = static_cast<PreviewJob *>(data);
177
179}
180
182{
183 wmJob *wm_job;
184 PreviewJob *pj;
185 ScrArea *area = CTX_wm_area(C);
186
187 wm_job = WM_jobs_get(CTX_wm_manager(C),
188 CTX_wm_window(C),
190 "Strip Previews",
193
194 /* Get the preview job if it exists. */
195 pj = static_cast<PreviewJob *>(WM_jobs_customdata_get(wm_job));
196
197 if (pj) {
199
200 /* If the job exists but is not running, bail and try again on the next draw call. */
201 if (!pj->running) {
203
204 /* Clear the sound loading tag to that it can be reattempted. */
207 return;
208 }
209 }
210 else { /* There's no existing preview job. */
211 pj = MEM_cnew<PreviewJob>("preview rebuild job");
212
213 pj->mutex = BLI_mutex_alloc();
215 pj->scene = CTX_data_scene(C);
216 pj->running = true;
218
221 WM_jobs_callbacks(wm_job, preview_startjob, nullptr, nullptr, preview_endjob);
222 }
223
224 PreviewJobAudio *audiojob = MEM_cnew<PreviewJobAudio>("preview_audio");
225 audiojob->bmain = CTX_data_main(C);
226 audiojob->sound = seq->sound;
227
228 BLI_addtail(&pj->previews, audiojob);
229 pj->total++;
231
233
234 if (!WM_jobs_is_running(wm_job)) {
235 G.is_break = false;
236 WM_jobs_start(CTX_wm_manager(C), wm_job);
237 }
238
239 ED_area_tag_redraw(area);
240}
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
void BKE_sound_read_waveform(struct Main *bmain, struct bSound *sound, bool *stop)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
@ TASK_PRIORITY_LOW
Definition BLI_task.h:56
bool BLI_task_pool_current_canceled(TaskPool *pool)
Definition task_pool.cc:501
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition task_pool.cc:471
void BLI_task_pool_cancel(TaskPool *pool)
Definition task_pool.cc:486
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition task_pool.cc:394
void BLI_task_pool_free(TaskPool *pool)
Definition task_pool.cc:431
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition task_pool.cc:450
pthread_spinlock_t SpinLock
void BLI_mutex_free(ThreadMutex *mutex)
Definition threads.cc:372
ThreadMutex * BLI_mutex_alloc(void)
Definition threads.cc:365
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
Definition threads.cc:582
pthread_cond_t ThreadCondition
void BLI_condition_notify_one(ThreadCondition *cond)
Definition threads.cc:592
void BLI_condition_init(ThreadCondition *cond)
Definition threads.cc:577
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
void BLI_spin_unlock(SpinLock *spin)
Definition threads.cc:430
void BLI_spin_lock(SpinLock *spin)
Definition threads.cc:405
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
#define UNUSED_VARS(...)
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
Read Guarded memory(de)allocation.
@ WM_JOB_TYPE_SEQ_BUILD_PREVIEW
Definition WM_api.hh:1593
@ WM_JOB_PROGRESS
Definition WM_api.hh:1566
#define ND_SEQUENCER
Definition WM_types.hh:404
#define ND_SPACE_SEQUENCER
Definition WM_types.hh:501
#define NC_SCENE
Definition WM_types.hh:345
TaskPool * task_pool
draw_view in_light_buf[] float
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define G(x, y, z)
static void preview_startjob(void *data, wmJobWorkerStatus *worker_status)
static void clear_sound_waveform_loading_tag(bSound *sound)
static void free_read_sound_waveform_task(TaskPool *__restrict task_pool, void *data)
static void preview_endjob(void *data)
static void execute_read_sound_waveform_task(TaskPool *__restrict task_pool, void *task_data)
static void push_preview_job_audio_task(TaskPool *__restrict task_pool, PreviewJob *pj, PreviewJobAudio *previewjb, bool *stop)
static void free_preview_job(void *data)
void sequencer_preview_add_sound(const bContext *C, const Sequence *seq)
PreviewJobAudio * prev
PreviewJobAudio * next
ThreadCondition preview_suspend_cond
ThreadMutex * mutex
PreviewJobAudio * preview_job_audio
struct bSound * sound
void * spinlock
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
bool WM_jobs_is_running(const wmJob *wm_job)
Definition wm_jobs.cc:317
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:352
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:455
void * WM_jobs_customdata_get(wmJob *wm_job)
Definition wm_jobs.cc:328
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:189
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:364
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:336