Make `draw_armature()` abort in case pose is not up-to-date.
[blender.git] / source / blender / editors / space_sequencer / sequencer_preview.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2003-2009, Antony Riakiotakis
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_sequencer/sequencer_preview.c
27  *  \ingroup spseq
28  */
29
30 #include "DNA_sequence_types.h"
31 #include "DNA_sound_types.h"
32
33 #include "BLI_listbase.h"
34 #include "BLI_threads.h"
35
36 #include "BKE_sound.h"
37 #include "BKE_context.h"
38 #include "BKE_global.h"
39
40 #include "WM_api.h"
41 #include "WM_types.h"
42
43 #include "ED_screen.h"
44
45 #include "MEM_guardedalloc.h"
46
47 #include "sequencer_intern.h"
48
49 typedef struct PreviewJob {
50         ListBase previews;
51         ThreadMutex *mutex;
52         Scene *scene;
53         int total;
54         int processed;
55 } PreviewJob;
56
57 typedef struct PreviewJobAudio {
58         struct PreviewJobAudio *next, *prev;
59         bSound *sound;
60         int lr; /* sample left or right */
61         int startframe;
62         bool waveform; /* reload sound or waveform */
63 } PreviewJobAudio;
64
65 static void free_preview_job(void *data)
66 {
67         PreviewJob *pj = (PreviewJob *)data;
68
69         BLI_mutex_free(pj->mutex);
70         BLI_freelistN(&pj->previews);
71         MEM_freeN(pj);
72 }
73
74 /* only this runs inside thread */
75 static void preview_startjob(void *data, short *stop, short *do_update, float *progress)
76 {
77         PreviewJob *pj = data;
78         PreviewJobAudio *previewjb;
79
80         BLI_mutex_lock(pj->mutex);
81         previewjb = pj->previews.first;
82         BLI_mutex_unlock(pj->mutex);
83
84         while (previewjb) {
85                 PreviewJobAudio *preview_next;
86                 bSound *sound = previewjb->sound;
87
88                 BKE_sound_read_waveform(sound, stop);
89
90                 if (*stop || G.is_break) {
91                         BLI_mutex_lock(pj->mutex);
92                         previewjb = previewjb->next;
93                         BLI_mutex_unlock(pj->mutex);
94                         while (previewjb) {
95                                 sound = previewjb->sound;
96
97                                 /* make sure we cleanup the loading flag! */
98                                 BLI_spin_lock(sound->spinlock);
99                                 sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
100                                 BLI_spin_unlock(sound->spinlock);
101
102                                 BLI_mutex_lock(pj->mutex);
103                                 previewjb = previewjb->next;
104                                 BLI_mutex_unlock(pj->mutex);
105                         }
106
107                         BLI_mutex_lock(pj->mutex);
108                         BLI_freelistN(&pj->previews);
109                         pj->total = 0;
110                         pj->processed = 0;
111                         BLI_mutex_unlock(pj->mutex);
112                         break;
113                 }
114
115                 BLI_mutex_lock(pj->mutex);
116                 preview_next = previewjb->next;
117                 BLI_freelinkN(&pj->previews, previewjb);
118                 previewjb = preview_next;
119                 pj->processed++;
120                 *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0f;
121                 *do_update = true;
122                 BLI_mutex_unlock(pj->mutex);
123         }
124 }
125
126 static void preview_endjob(void *data)
127 {
128         PreviewJob *pj = data;
129
130         WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
131 }
132
133
134 void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
135 {
136         /* first, get the preview job, if it exists */
137         wmJob *wm_job;
138         PreviewJob *pj;
139         ScrArea *sa = CTX_wm_area(C);
140         PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
141         wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Strip Previews",
142                              WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
143
144         pj = WM_jobs_customdata_get(wm_job);
145
146         if (!pj) {
147                 pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");
148
149                 pj->mutex = BLI_mutex_alloc();
150                 pj->scene = CTX_data_scene(C);
151
152                 WM_jobs_customdata_set(wm_job, pj, free_preview_job);
153                 WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
154                 WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
155         }
156
157         /* attempt to lock mutex of job here */
158
159         audiojob->sound = seq->sound;
160
161         BLI_mutex_lock(pj->mutex);
162         BLI_addtail(&pj->previews, audiojob);
163         pj->total++;
164         BLI_mutex_unlock(pj->mutex);
165
166         if (!WM_jobs_is_running(wm_job)) {
167                 G.is_break = false;
168                 WM_jobs_start(CTX_wm_manager(C), wm_job);
169         }
170
171         ED_area_tag_redraw(sa);
172 }