diff options
4 files changed, 117 insertions, 1 deletions
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 5291ff4bb3d..6c84eaf2363 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -639,6 +639,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): if not strip.use_autocenter: row.prop(strip, "xpos") row.prop(strip, "ypos") + layout.operator("sequencer.export_subtitles") col = layout.column(align=True) if strip.type == 'SPEED': diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 070b4166705..c16b0b2dc3b 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -35,9 +35,11 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_fileops.h" +#include "BLI_ghash.h" #include "BLI_math.h" +#include "BLI_timecode.h" #include "BLI_utildefines.h" -#include "BLI_ghash.h" #include "BLF_translation.h" @@ -3825,3 +3827,112 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot) FILE_DEFAULTDISPLAY); RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip"); } + +static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + char filepath[FILE_MAX]; + + if (G.main->name[0] == 0) + BLI_strncpy(filepath, "untitled", sizeof(filepath)); + else + BLI_strncpy(filepath, G.main->name, sizeof(filepath)); + + BLI_replace_extension(filepath, sizeof(filepath), ".srt"); + RNA_string_set(op->ptr, "filepath", filepath); + } + + WM_event_add_fileselect(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Sequence *seq = BKE_sequencer_active_get(scene); + Editing *ed = BKE_sequencer_editing_get(scene, false); + int iter = 0; + FILE *file; + char filepath[FILE_MAX]; + + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + BKE_report(op->reports, RPT_ERROR, "No filename given"); + return OPERATOR_CANCELLED; + } + + RNA_string_get(op->ptr, "filepath", filepath); + BLI_ensure_extension(filepath, sizeof(filepath), ".srt"); + + /* Avoid File write exceptions */ + if (!BLI_exists(filepath)) { + BLI_make_existing_file(filepath); + if (!BLI_file_touch(filepath)) { + BKE_report(op->reports, RPT_ERROR, "Can't create subtitle file"); + return OPERATOR_CANCELLED; + } + } + else if (!BLI_file_is_writable(filepath)) { + BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file"); + return OPERATOR_CANCELLED; + } + + /* time to open and write! */ + file = BLI_fopen(filepath, "w"); + + SEQ_BEGIN(ed, seq) + { + if (seq->type == SEQ_TYPE_TEXT) { + TextVars *data = seq->effectdata; + char timecode_str[32]; + double sec; + int frac; + int len; + fprintf(file, "%d\n", iter++); + sec = FRA2TIME(seq->startdisp); + frac = 1000 * (sec - floor(sec)); + sec = floor(sec); + BLI_timecode_string_from_time(timecode_str, sizeof(timecode_str), 1, sec, FPS, USER_TIMECODE_SMPTE_FULL); + len = strlen(timecode_str); + timecode_str[len - 3] = 0; + fprintf(file, "%s,%d", timecode_str, frac); + sec = FRA2TIME(seq->enddisp); + BLI_timecode_string_from_time(timecode_str, sizeof(timecode_str), 1, sec, FPS, USER_TIMECODE_SMPTE_FULL); + len = strlen(timecode_str); + timecode_str[len - 3] = 0; + fprintf(file, " --> %s,%d\n", timecode_str, frac); + fprintf(file, "%s\n\n", data->text); + } + } + SEQ_END + + fclose(file); + + return OPERATOR_FINISHED; +} + +static int sequencer_strip_is_text_poll(bContext *C) +{ + Editing *ed; + Sequence *seq; + return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (seq->type == SEQ_TYPE_TEXT)); +} + +void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Export Subtitles"; + ot->idname = "SEQUENCER_OT_export_subtitles"; + ot->description = "Export .srt file containing text strips"; + + /* api callbacks */ + ot->exec = sequencer_export_subtitles_exec; + ot->invoke = sequencer_export_subtitles_invoke; + ot->poll = sequencer_strip_is_text_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER, FILE_BLENDER, FILE_SAVE, + WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); +} diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index eaac43095e8..3e228fd0b31 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -134,6 +134,8 @@ void SEQUENCER_OT_paste(struct wmOperatorType *ot); void SEQUENCER_OT_rebuild_proxy(struct wmOperatorType *ot); void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot); +void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot); + /* preview specific operators */ void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index dadd187f36c..3d08e0c5ed8 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -77,6 +77,8 @@ void sequencer_operatortypes(void) WM_operatortype_append(SEQUENCER_OT_swap_data); WM_operatortype_append(SEQUENCER_OT_rendersize); + WM_operatortype_append(SEQUENCER_OT_export_subtitles); + WM_operatortype_append(SEQUENCER_OT_copy); WM_operatortype_append(SEQUENCER_OT_paste); |