From ae53dc3a60daca65907ef8c86cb8947cb525dcfe Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 29 Aug 2025 16:58:08 +0200 Subject: [PATCH] Sequencer: Avoid storing un-tracked pointers in blend files Currently, sequencer structs contain several pointers to data within other structs. These pointers need to be remapped as the structs are reallocated when reading from blend files. That has worked so far because the pointers are exactly the values from the Blender session that saved the file. With the implementation of #127706, the pointers in the file aren't "real" anymore, and we can't offset them to get the struct that contained the data. I'm working on the pointer stability solution now to address a memfile undo performance regression in 5.0 due to the `AttributeStorage` read/write design. This commit replaces these 4 mid-struct pointers to point to the containing strips instead, and uses some trivial logic to access the fallback root sequence channels and strips. This makes the pointer remapping on file load possible again. This change is backward compatible but not forward compatible. Second try after #144626 Pull Request: https://projects.blender.org/blender/blender/pulls/144878 --- source/blender/blenkernel/intern/scene.cc | 93 ++----------------- source/blender/blenloader/BLO_read_write.hh | 5 - source/blender/blenloader/intern/readfile.cc | 8 -- .../blenloader/intern/versioning_290.cc | 6 +- .../blenloader/intern/versioning_300.cc | 10 -- .../blenloader/intern/versioning_500.cc | 20 ++++ .../space_sequencer/sequencer_clipboard.cc | 8 +- .../space_sequencer/sequencer_preview_draw.cc | 2 +- source/blender/makesdna/DNA_sequence_types.h | 20 ++-- source/blender/sequencer/SEQ_channels.hh | 2 +- source/blender/sequencer/SEQ_sequencer.hh | 7 -- source/blender/sequencer/intern/channels.cc | 5 - source/blender/sequencer/intern/prefetch.cc | 4 +- source/blender/sequencer/intern/render.cc | 5 +- source/blender/sequencer/intern/sequencer.cc | 45 ++++----- 15 files changed, 73 insertions(+), 167 deletions(-) diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index c3b903909a1..39304add25f 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -329,7 +329,6 @@ static void scene_copy_data(Main *bmain, /* Copy sequencer, this is local data! */ if (scene_src->ed) { scene_dst->ed = MEM_callocN(__func__); - scene_dst->ed->seqbasep = &scene_dst->ed->seqbase; scene_dst->ed->cache_flag = scene_src->ed->cache_flag; scene_dst->ed->show_missing_media_flag = scene_src->ed->show_missing_media_flag; scene_dst->ed->proxy_storage = scene_src->ed->proxy_storage; @@ -342,7 +341,6 @@ static void scene_copy_data(Main *bmain, blender::seq::StripDuplicate::All, flag_subdata); BLI_duplicatelist(&scene_dst->ed->channels, &scene_src->ed->channels); - scene_dst->ed->displayed_channels = &scene_dst->ed->channels; } if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { @@ -1353,14 +1351,13 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) } if (sce->ed) { - ListBase *old_seqbasep = &sce->ed->seqbase; - ListBase *old_displayed_channels = &sce->ed->channels; - BLO_read_struct(reader, Editing, &sce->ed); Editing *ed = sce->ed; ed->act_strip = static_cast( BLO_read_get_new_data_address_no_us(reader, ed->act_strip, sizeof(Strip))); + ed->current_meta_strip = static_cast( + BLO_read_get_new_data_address_no_us(reader, ed->current_meta_strip, sizeof(Strip))); ed->prefetch_job = nullptr; ed->runtime.strip_lookup = nullptr; ed->runtime.media_presence = nullptr; @@ -1377,88 +1374,14 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) blender::seq::blend_read(reader, &ed->seqbase); BLO_read_struct_list(reader, SeqTimelineChannel, &ed->channels); - /* link metastack, slight abuse of structs here, - * have to restore pointer to internal part in struct */ - { - const int seqbase_offset_file = BLO_read_struct_member_offset( - reader, "Strip", "ListBase", "seqbase"); - const int channels_offset_file = BLO_read_struct_member_offset( - reader, "Strip", "ListBase", "channels"); - const size_t seqbase_offset_mem = offsetof(Strip, seqbase); - const size_t channels_offset_mem = offsetof(Strip, channels); + /* stack */ + BLO_read_struct_list(reader, MetaStack, &(ed->metastack)); - /* seqbase root pointer */ - if (ed->seqbasep == old_seqbasep || seqbase_offset_file < 0) { - ed->seqbasep = &ed->seqbase; - } - else { - void *seqbase_poin = POINTER_OFFSET(ed->seqbasep, -seqbase_offset_file); + LISTBASE_FOREACH (MetaStack *, ms, &ed->metastack) { + BLO_read_struct(reader, Strip, &ms->parent_strip); - seqbase_poin = BLO_read_get_new_data_address_no_us(reader, seqbase_poin, sizeof(Strip)); - - if (seqbase_poin) { - ed->seqbasep = (ListBase *)POINTER_OFFSET(seqbase_poin, seqbase_offset_mem); - } - else { - ed->seqbasep = &ed->seqbase; - } - } - - /* Active channels root pointer. */ - if (ELEM(ed->displayed_channels, old_displayed_channels, nullptr) || - channels_offset_file < 0) - { - ed->displayed_channels = &ed->channels; - } - else { - void *channels_poin = POINTER_OFFSET(ed->displayed_channels, -channels_offset_file); - channels_poin = BLO_read_get_new_data_address_no_us( - reader, channels_poin, sizeof(SeqTimelineChannel)); - - if (channels_poin) { - ed->displayed_channels = (ListBase *)POINTER_OFFSET(channels_poin, channels_offset_mem); - } - else { - ed->displayed_channels = &ed->channels; - } - } - - /* stack */ - BLO_read_struct_list(reader, MetaStack, &(ed->metastack)); - - LISTBASE_FOREACH (MetaStack *, ms, &ed->metastack) { - BLO_read_struct(reader, Strip, &ms->parent_strip); - - if (ms->oldbasep == old_seqbasep || seqbase_offset_file < 0) { - ms->oldbasep = &ed->seqbase; - } - else { - void *seqbase_poin = POINTER_OFFSET(ms->oldbasep, -seqbase_offset_file); - seqbase_poin = BLO_read_get_new_data_address_no_us(reader, seqbase_poin, sizeof(Strip)); - if (seqbase_poin) { - ms->oldbasep = (ListBase *)POINTER_OFFSET(seqbase_poin, seqbase_offset_mem); - } - else { - ms->oldbasep = &ed->seqbase; - } - } - - if (ELEM(ms->old_channels, old_displayed_channels, nullptr) || channels_offset_file < 0) { - ms->old_channels = &ed->channels; - } - else { - void *channels_poin = POINTER_OFFSET(ms->old_channels, -channels_offset_file); - channels_poin = BLO_read_get_new_data_address_no_us( - reader, channels_poin, sizeof(SeqTimelineChannel)); - - if (channels_poin) { - ms->old_channels = (ListBase *)POINTER_OFFSET(channels_poin, channels_offset_mem); - } - else { - ms->old_channels = &ed->channels; - } - } - } + ms->old_strip = static_cast( + BLO_read_get_new_data_address_no_us(reader, ms->old_strip, sizeof(Strip))); } } diff --git a/source/blender/blenloader/BLO_read_write.hh b/source/blender/blenloader/BLO_read_write.hh index 4fa84c4c129..620fd62b413 100644 --- a/source/blender/blenloader/BLO_read_write.hh +++ b/source/blender/blenloader/BLO_read_write.hh @@ -377,11 +377,6 @@ void BLO_read_glob_list(BlendDataReader *reader, ListBase *list); BlendFileReadReport *BLO_read_data_reports(BlendDataReader *reader); struct Library *BLO_read_data_current_library(BlendDataReader *reader); -int BLO_read_struct_member_offset(const BlendDataReader *reader, - const char *stype, - const char *vartype, - const char *name); - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 5f04c9773f7..3dadba569a7 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -5224,14 +5224,6 @@ int BLO_read_fileversion_get(BlendDataReader *reader) return reader->fd->fileversion; } -int BLO_read_struct_member_offset(const BlendDataReader *reader, - const char *stype, - const char *vartype, - const char *name) -{ - return DNA_struct_member_offset_by_name_with_alias(reader->fd->filesdna, stype, vartype, name); -} - void BLO_read_struct_list_with_size(BlendDataReader *reader, const size_t expected_elem_size, ListBase *list) diff --git a/source/blender/blenloader/intern/versioning_290.cc b/source/blender/blenloader/intern/versioning_290.cc index 941a9402bd6..e921d5f492b 100644 --- a/source/blender/blenloader/intern/versioning_290.cc +++ b/source/blender/blenloader/intern/versioning_290.cc @@ -378,7 +378,8 @@ static void seq_update_meta_disp_range(Scene *scene) blender::seq::time_right_handle_frame_set(scene, ms->parent_strip, ms->disp_range[1]); /* Recalculate effects using meta strip. */ - LISTBASE_FOREACH (Strip *, strip, ms->oldbasep) { + ListBase *old_seqbasep = ms->old_strip ? &ms->old_strip->seqbase : &ed->seqbase; + LISTBASE_FOREACH (Strip *, strip, old_seqbasep) { if (strip->input2) { strip->start = strip->startdisp = max_ii(strip->input1->startdisp, strip->input2->startdisp); @@ -386,9 +387,8 @@ static void seq_update_meta_disp_range(Scene *scene) } } - /* Ensure that active seqbase points to active meta strip seqbase. */ MetaStack *active_ms = blender::seq::meta_stack_active_get(ed); - blender::seq::active_seqbase_set(ed, &active_ms->parent_strip->seqbase); + active_ms->old_strip = ms->parent_strip; } } diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 368b89c204a..6144e5fe00a 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3424,16 +3424,6 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } blender::seq::channels_ensure(&ed->channels); blender::seq::for_each_callback(&scene->ed->seqbase, strip_meta_channels_ensure, nullptr); - - ed->displayed_channels = &ed->channels; - - ListBase *previous_channels = &ed->channels; - LISTBASE_FOREACH (MetaStack *, ms, &ed->metastack) { - ms->old_channels = previous_channels; - previous_channels = &ms->parent_strip->channels; - /* If `MetaStack` exists, active channels must point to last link. */ - ed->displayed_channels = &ms->parent_strip->channels; - } } } diff --git a/source/blender/blenloader/intern/versioning_500.cc b/source/blender/blenloader/intern/versioning_500.cc index f29a380e8ce..976f99c0081 100644 --- a/source/blender/blenloader/intern/versioning_500.cc +++ b/source/blender/blenloader/intern/versioning_500.cc @@ -2126,6 +2126,20 @@ static void remove_in_and_out_node_interface(bNodeTree &node_tree) remove_in_and_out_node_panel_recursive(node_tree.tree_interface.root_panel); } +static void sequencer_remove_listbase_pointers(Scene &scene) +{ + Editing *ed = scene.ed; + if (!ed) { + return; + } + const MetaStack *last_meta_stack = blender::seq::meta_stack_active_get(ed); + if (!last_meta_stack) { + return; + } + ed->current_meta_strip = last_meta_stack->parent_strip; + blender::seq::meta_stack_set(&scene, last_meta_stack->parent_strip); +} + void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain) { using namespace blender; @@ -2882,6 +2896,12 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain) FOREACH_NODETREE_END; } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 68)) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + sequencer_remove_listbase_pointers(*scene); + } + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/editors/space_sequencer/sequencer_clipboard.cc b/source/blender/editors/space_sequencer/sequencer_clipboard.cc index dab4b04ec30..ad1a451b89b 100644 --- a/source/blender/editors/space_sequencer/sequencer_clipboard.cc +++ b/source/blender/editors/space_sequencer/sequencer_clipboard.cc @@ -167,7 +167,6 @@ static bool sequencer_write_copy_paste_file(Main *bmain_src, /* Create an empty sequence editor data to store all copied strips. */ scene_dst->ed = MEM_callocN(__func__); - scene_dst->ed->seqbasep = &scene_dst->ed->seqbase; seq::seqbase_duplicate_recursive(bmain_src, scene_src, scene_dst, @@ -177,7 +176,6 @@ static bool sequencer_write_copy_paste_file(Main *bmain_src, 0); BLI_duplicatelist(&scene_dst->ed->channels, &scene_src->ed->channels); - scene_dst->ed->displayed_channels = &scene_dst->ed->channels; /* Save current frame and active strip. */ scene_dst->r.cfra = scene_src->r.cfra; @@ -499,7 +497,7 @@ wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) BKE_id_delete(bmain_dst, scene_src); Strip *iseq_first = static_cast(nseqbase.first); - BLI_movelisttolist(ed_dst->seqbasep, &nseqbase); + BLI_movelisttolist(ed_dst->current_strips(), &nseqbase); /* Restore "first" pointer as BLI_movelisttolist sets it to nullptr */ nseqbase.first = iseq_first; @@ -517,8 +515,8 @@ wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) * strip. */ seq::transform_translate_strip(scene_dst, istrip, ofs); /* Ensure, that pasted strips don't overlap. */ - if (seq::transform_test_overlap(scene_dst, ed_dst->seqbasep, istrip)) { - seq::transform_seqbase_shuffle(ed_dst->seqbasep, istrip, scene_dst); + if (seq::transform_test_overlap(scene_dst, ed_dst->current_strips(), istrip)) { + seq::transform_seqbase_shuffle(ed_dst->current_strips(), istrip, scene_dst); } } diff --git a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc index 9b5576ec296..2dda4dff5d6 100644 --- a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc +++ b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc @@ -1360,7 +1360,7 @@ static void preview_draw_all_image_overlays(const bContext *C, { ListBase *channels = seq::channels_displayed_get(&editing); VectorSet strips = seq::query_rendered_strips( - scene, channels, editing.seqbasep, timeline_frame, 0); + scene, channels, editing.current_strips(), timeline_frame, 0); Strip *active_seq = seq::select_active_get(scene); for (Strip *strip : strips) { /* TODO(sergey): Avoid having per-strip strip-independent checks. */ diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 599185632ed..108f7fb668c 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -305,8 +305,11 @@ typedef struct Strip { typedef struct MetaStack { struct MetaStack *next, *prev; - ListBase *oldbasep; - ListBase *old_channels; + /** + * The meta-strip that contains `parent_strip`. May be null (that means it is the top-most + * strips). + */ + Strip *old_strip; Strip *parent_strip; /* The startdisp/enddisp when entering the metastrip. */ int disp_range[2]; @@ -336,16 +339,11 @@ typedef struct EditingRuntime { typedef struct Editing { /** - * Pointer to the current list of strips being edited (can be within a meta-strip). - * \note Use #current_strips() to access, rather than using this variable directly. + * The current meta-strip being edited and/or viewed, may be null, in which case the top-most + * strips are used. */ - ListBase *seqbasep; - /** - * Pointer to the current list of channels being displayed (can be within a meta-strip). - * \note Use #current_channels() to access, rather than using this variable directly. - */ - ListBase *displayed_channels; - void *_pad0; + Strip *current_meta_strip; + /** Pointer to the top-most strips. */ ListBase seqbase; ListBase metastack; diff --git a/source/blender/sequencer/SEQ_channels.hh b/source/blender/sequencer/SEQ_channels.hh index cf4aa88ff68..0c50401125b 100644 --- a/source/blender/sequencer/SEQ_channels.hh +++ b/source/blender/sequencer/SEQ_channels.hh @@ -15,8 +15,8 @@ struct Strip; namespace blender::seq { +/** The active displayed channels list, either from the root sequence or from a meta-strip. */ ListBase *channels_displayed_get(const Editing *ed); -void channels_displayed_set(Editing *ed, ListBase *channels); void channels_ensure(ListBase *channels); void channels_duplicate(ListBase *channels_dst, ListBase *channels_src); void channels_free(ListBase *channels); diff --git a/source/blender/sequencer/SEQ_sequencer.hh b/source/blender/sequencer/SEQ_sequencer.hh index a96644364d9..40ca17c29ee 100644 --- a/source/blender/sequencer/SEQ_sequencer.hh +++ b/source/blender/sequencer/SEQ_sequencer.hh @@ -69,13 +69,6 @@ void editing_free(Scene *scene, bool do_id_user); * \return pointer to active seqbase. returns NULL if ed is NULL */ ListBase *active_seqbase_get(const Editing *ed); -/** - * Set seqbase that is being viewed currently. This can be main seqbase or meta strip seqbase - * - * \param ed: sequence editor data - * \param seqbase: ListBase with strips - */ -void active_seqbase_set(Editing *ed, ListBase *seqbase); Strip *strip_alloc(ListBase *lb, int timeline_frame, int channel, int type); void strip_free(Scene *scene, Strip *strip); /** diff --git a/source/blender/sequencer/intern/channels.cc b/source/blender/sequencer/intern/channels.cc index b8314993b2a..8cf0542ecf4 100644 --- a/source/blender/sequencer/intern/channels.cc +++ b/source/blender/sequencer/intern/channels.cc @@ -30,11 +30,6 @@ ListBase *channels_displayed_get(const Editing *ed) return ed ? ed->current_channels() : nullptr; } -void channels_displayed_set(Editing *ed, ListBase *channels) -{ - ed->displayed_channels = channels; -} - void channels_ensure(ListBase *channels) { /* Allocate channels. Channel 0 is never used, but allocated to prevent off by 1 issues. */ diff --git a/source/blender/sequencer/intern/prefetch.cc b/source/blender/sequencer/intern/prefetch.cc index afcf5a76f31..bf5fc95cfaf 100644 --- a/source/blender/sequencer/intern/prefetch.cc +++ b/source/blender/sequencer/intern/prefetch.cc @@ -372,10 +372,10 @@ static void seq_prefetch_update_active_seqbase(PrefetchJob *pfjob) if (ms_orig != nullptr) { Strip *meta_eval = original_strip_get(ms_orig->parent_strip, pfjob->scene_eval); - active_seqbase_set(ed_eval, &meta_eval->seqbase); + ed_eval->current_meta_strip = meta_eval; } else { - active_seqbase_set(ed_eval, &ed_eval->seqbase); + ed_eval->current_meta_strip = nullptr; } } diff --git a/source/blender/sequencer/intern/render.cc b/source/blender/sequencer/intern/render.cc index f4c21137220..1c4b102f071 100644 --- a/source/blender/sequencer/intern/render.cc +++ b/source/blender/sequencer/intern/render.cc @@ -1985,8 +1985,9 @@ ImBuf *render_give_ibuf(const RenderData *context, float timeline_frame, int cha if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) { int count = BLI_listbase_count(&ed->metastack); count = max_ii(count + chanshown, 0); - seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep; - channels = ((MetaStack *)BLI_findlink(&ed->metastack, count))->old_channels; + MetaStack *ms = static_cast(BLI_findlink(&ed->metastack, count)); + seqbasep = &ms->old_strip->seqbase; + channels = &ms->old_strip->channels; chanshown = 0; } else { diff --git a/source/blender/sequencer/intern/sequencer.cc b/source/blender/sequencer/intern/sequencer.cc index 35fb3bc16e3..ff455f10a6a 100644 --- a/source/blender/sequencer/intern/sequencer.cc +++ b/source/blender/sequencer/intern/sequencer.cc @@ -284,11 +284,9 @@ Editing *editing_ensure(Scene *scene) Editing *ed; ed = scene->ed = MEM_callocN("addseq"); - ed->seqbasep = &ed->seqbase; ed->cache_flag = (SEQ_CACHE_PREFETCH_ENABLE | SEQ_CACHE_STORE_FINAL_OUT | SEQ_CACHE_STORE_RAW); ed->show_missing_media_flag = SEQ_EDIT_SHOW_MISSING_MEDIA; - ed->displayed_channels = &ed->channels; - channels_ensure(ed->displayed_channels); + channels_ensure(&ed->channels); } return scene->ed; @@ -427,11 +425,6 @@ ListBase *active_seqbase_get(const Editing *ed) return ed ? ed->current_strips() : nullptr; } -void active_seqbase_set(Editing *ed, ListBase *seqbase) -{ - ed->seqbasep = seqbase; -} - static MetaStack *seq_meta_stack_alloc(const Scene *scene, Strip *strip_meta) { Editing *ed = editing_get(scene); @@ -441,9 +434,7 @@ static MetaStack *seq_meta_stack_alloc(const Scene *scene, Strip *strip_meta) ms->parent_strip = strip_meta; /* Reference to previously displayed timeline data. */ - Strip *higher_level_meta = lookup_meta_by_strip(ed, strip_meta); - ms->oldbasep = higher_level_meta ? &higher_level_meta->seqbase : &ed->seqbase; - ms->old_channels = higher_level_meta ? &higher_level_meta->channels : &ed->channels; + ms->old_strip = lookup_meta_by_strip(ed, strip_meta); ms->disp_range[0] = time_left_handle_frame_get(scene, ms->parent_strip); ms->disp_range[1] = time_right_handle_frame_get(scene, ms->parent_strip); @@ -473,13 +464,10 @@ void meta_stack_set(const Scene *scene, Strip *dst) seq_meta_stack_alloc(scene, meta_parent); } - active_seqbase_set(ed, &dst->seqbase); - channels_displayed_set(ed, &dst->channels); + ed->current_meta_strip = dst; } else { - /* Go to top level, exiting meta strip. */ - active_seqbase_set(ed, &ed->seqbase); - channels_displayed_set(ed, &ed->channels); + ed->current_meta_strip = nullptr; } } @@ -487,8 +475,7 @@ Strip *meta_stack_pop(Editing *ed) { MetaStack *ms = meta_stack_active_get(ed); Strip *meta_parent = ms->parent_strip; - active_seqbase_set(ed, ms->oldbasep); - channels_displayed_set(ed, ms->old_channels); + ed->current_meta_strip = ms->old_strip; BLI_remlink(&ed->metastack, ms); MEM_freeN(ms); return meta_parent; @@ -1159,20 +1146,34 @@ void eval_strips(Depsgraph *depsgraph, Scene *scene, ListBase *seqbase) ListBase *Editing::current_strips() { - return this->seqbasep; + if (this->current_meta_strip) { + return &this->current_meta_strip->seqbase; + } + return &this->seqbase; } + ListBase *Editing::current_strips() const { + if (this->current_meta_strip) { + return &this->current_meta_strip->seqbase; + } /* NOTE: Const correctness is non-existent with ListBase anyway. */ - return this->seqbasep; + return &const_cast(this->seqbase); } ListBase *Editing::current_channels() { - return this->displayed_channels; + if (this->current_meta_strip) { + return &this->current_meta_strip->channels; + } + return &this->channels; } + ListBase *Editing::current_channels() const { + if (this->current_meta_strip) { + return &this->current_meta_strip->channels; + } /* NOTE: Const correctness is non-existent with ListBase anyway. */ - return this->displayed_channels; + return &const_cast(this->channels); }