diff --git a/automation/demos/10-furigana.lua b/automation/demos/10-furigana.lua new file mode 100644 index 000000000..ccf6d4df7 --- /dev/null +++ b/automation/demos/10-furigana.lua @@ -0,0 +1,42 @@ +-- Aegisub Automation demonstration script +-- Original written by Niels Martin Hansen +-- Given into the public domain + +include("karaskel-adv.lua") +karaskel.engage_furigana = true +karaskel.engage_trace = true + +version = 3 +kind = "basic_ass" +name = "Furigana demo" +description = "Demonstrates how to use the Furigana feature in karaskel-adv" + +function do_syllable(meta, styles, config, line, syl) + local result = {n=0} + function result.add() + local l = copy_line(line) + table.insert(result, l) + return l + end + -- Place the main text + local l = result.add() + l.text = string.format("{\\an8\\pos(%d,%d)\\k%d\\kf%d}%s", line.centerleft+syl.center, line.height*1.5, syl.start_time/10, syl.duration, syl.text) + l.layer = 5 + -- Perform the highlights + for i = 0, syl.highlights.n-1 do + local hl = syl.highlights[i] + l = result.add() + l.start_time = l.start_time + hl.start_time/10 + l.end_time = l.start_time + 25 + l.text = string.format("{\\an8\\k10000\\k0\\move(%d,%d,%d,%d)\\t(\\1a&HFF&\\2a&HFF&\\3a&HFF&\\4a&HFF&)}%s", line.centerleft+syl.center, line.height*1.5, line.centerleft+syl.center, line.height*3, syl.text_stripped) + l.layer = 10+i + end + -- Place the furigana + for i = 0, syl.furigana.n-1 do + local furi = syl.furigana[i] + l = result.add() + l.text = string.format("{\\an2\\k%d\\k%d\\bord2\\fscx%.1f\\fs%.1f\\t(%d,%d,\\bord0)\\pos(%d,%d)}%s", furi.start_time/10, furi.duration, syl.furigana.scale, syl.furigana.fontsize, furi.start_time, furi.end_time, line.centerleft+furi.center, line.height*1.5, furi.text) + l.layer = 3 + end + return result +end diff --git a/automation/demos/9-skeleton-advanced.lua b/automation/demos/9-advanced-skeleton.lua similarity index 100% rename from automation/demos/9-skeleton-advanced.lua rename to automation/demos/9-advanced-skeleton.lua diff --git a/automation/demos/readme.txt b/automation/demos/readme.txt index 16f078c2c..6939d8505 100644 --- a/automation/demos/readme.txt +++ b/automation/demos/readme.txt @@ -10,6 +10,10 @@ the more advanced ones, I'd really like a bit of credit where it's due. And remember, it's cheap to use someone else's advanced karaoke effect, especially without any changes at all. It also gives bad karma. Like, *really* bad :) +Apart from just the .lua files, there's also a few .ass files, used for eg. showing +how some special feature is implemented in the ASS itself. It should be obvious +what .lua and .ass files are related. + WARNING! DO NOT ADD YOUR OWN FILES TO THIS DIRECTORY, diff --git a/automation/include/karaskel-adv.lua b/automation/include/karaskel-adv.lua index 279946460..68fcf5e0e 100644 --- a/automation/include/karaskel-adv.lua +++ b/automation/include/karaskel-adv.lua @@ -32,7 +32,8 @@ -- positioning of karaoke. -- It automatically includes and re-setups karaskel.lua, so you should not include that yourself! -include("karaskel.lua") +include("karaskel-base.lua") +karaskel.engage_positioning = true -- The interface here has been greatly simplified, there is only one function to override, do_syllable -- The format for that one has changed. @@ -44,23 +45,26 @@ include("karaskel.lua") -- The return value is different now, though. -- It is required to be in the same format as the do_line function: -- A table with an "n" key, and keys 0..n-1 with line structures. -function default_do_syllable(meta, styles, config, line, syl) - aegisub.output_debug("default_do_syllable") +function karaskel.do_syllable(meta, styles, config, line, syl) + karaskel.trace("default_do_syllable") return {n=0} end -do_syllable = default_do_syllable +do_syllable = karaskel.do_syllable -function adv_do_line(meta, styles, config, line) - aegisub.output_debug("adv_do_line") +function karaskel.do_line(meta, styles, config, line) + karaskel.trace("adv_do_line") + if line.kind ~= "dialogue" then + return {n=1, [1]=line} + end local result = {n=0} for i = 0, line.karaoke.n-1 do - aegisub.output_debug("adv_do_line:2:"..i) + karaskel.trace("adv_do_line:2:"..i) local out = do_syllable(meta, styles, config, line, line.karaoke[i]) for j = 1, out.n do table.insert(result, out[j]) end end - aegisub.output_debug("adv_do_line:3") + karaskel.trace("adv_do_line:3") return result end -do_line = adv_do_line +do_line = karaskel.do_line diff --git a/automation/include/karaskel-base.lua b/automation/include/karaskel-base.lua new file mode 100644 index 000000000..9c095cccd --- /dev/null +++ b/automation/include/karaskel-base.lua @@ -0,0 +1,274 @@ +--[[ + Copyright (c) 2005, Niels Martin Hansen + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Aegisub Group nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ]] + +-- Aegisub Automation include file +-- This file is meant as a support file for the various karaoke skeleton +-- scripts, to avoid including unneeded code + +include("utils.lua") + +-- karaskel +-- This is a gloabl table defining various parameters, controlling what the +-- skeleton will do. Not all parameters are defined in this base. +karaskel = { + -- Does this script need positioning information? + engage_positioning = false, + -- Syllable precalc parameters + precalc_start_progress = 0, -- progress precalc starts at + precalc_end_progress = 50, -- and where it ends at + -- Does this script use furigana information? (has no effect without positioning) + engage_furigana = false, + -- Furigana parameters + furigana_scale = 0.4, -- relative size of furigana + -- Default effect-name for inline effects (read manual) + inline_fx_default = "regular", + -- Set this to the name of the style used for out-of-line effect specifications, if any (read manual on this!) + ool_fx_style = false, + -- Show tracing messages? + engage_trace = false +} + +function karaskel.warning(s) + aegisub.output_debug("WARNING! " .. s) +end + +function karaskel.trace(s) + if karaskel.engage_trace then + aegisub.output_debug(s) + else + -- A little optimisation + karaskel.trace = function() end + end +end + +-- precalc_syllable_data +-- Adds various extra fields to the line and syllable tables +-- See the implementation and/or Aegisub help file for more information +function karaskel.precalc_syllable_data(meta, styles, lines) + karaskel.trace("precalc_syllable_data") + aegisub.set_status("Preparing syllable-data") + for i = 0, lines.n-1 do + karaskel.trace("precalc_syllable_data:2:"..i) + aegisub.report_progress(karaskel.precalc_start_progress + i/lines.n*(karaskel.precalc_end_progress-karaskel.precalc_start_progress)) + local line, style = lines[i] + -- Index number of the line + line.i = i + -- Linked list-style access + line.prev = lines[i-1] + line.next = lines[i+1] + karaskel.trace("precalc_syllable_data:3:") + if line.kind == "dialogue" or line.kind == "comment" then + karaskel.trace("precalc_syllable_data:4:") + local style = styles[line.style] + if not style then + -- ok, so the named style does not exist... well there MUST be at least ONE style + -- pick the first one + style = styles[0] + karaskel.warning(string.format("You have a line using a style named \"%s\", but that style does not exist! Using the first defined style (\"%s\") instead.", line.style, style.name)) + end + if karaskel.engage_furigana then + karaskel.split_furigana_data(line) + line.text_stripped = "" + for k = 0, line.karaoke.n-1 do + line.text_stripped = line.text_stripped .. line.karaoke[k].text + end + end + if karaskel.engage_positioning then + -- Line dimensions + line.width, line.height, line.ascent, line.extlead = aegisub.text_extents(style, line.text_stripped) + karaskel.trace("precalc_syllable_data:5:") + -- Line position + line.centerleft = math.floor((meta.res_x - line.width) / 2) + line.centerright = meta.res_x - line.centerleft + end + -- Line duration, in miliseconds + line.duration = (line.end_time - line.start_time) * 10 + -- Style reference + line.styleref = style + karaskel.trace("precalc_syllable_data:6:") + -- Process the syllables + local curx, curtime = 0, 0 + local inline_fx = karaskel.inline_fx_default + for j = 0, line.karaoke.n-1 do + karaskel.trace("precalc_syllable_data:7::"..j) + local syl = line.karaoke[j] + -- Syllable index + syl.i = j + -- Check for inline-effect + karaskel.trace("testing for inline_fx in: " .. syl.text) + local a, b, new_inline_fx = string.find(syl.text, "{%\\?%-(.*)}") + if new_inline_fx then + karaskel.trace("caught new inline_fx: " .. new_inline_fx) + inline_fx = new_inline_fx + end + syl.inline_fx = inline_fx + -- Do positioning calculations, if applicable + if karaskel.engage_positioning then + -- Syllable dimensions + syl.width, syl.height, syl.ascent, syl.extlead = aegisub.text_extents(style, syl.text_stripped) + karaskel.trace("precalc_syllable_data:8::") + -- Syllable positioning + syl.left = curx + syl.center = math.floor(curx + syl.width/2) + syl.right = curx + syl.width + curx = syl.right + if syl.furigana then + karaskel.calc_furigana_sizes(line, syl) + end + end + -- Start and end times in miliseconds + syl.start_time = curtime + syl.end_time = curtime + syl.duration*10 + curtime = syl.end_time + end + end + end +end + +-- Rebuild the entire karaoke data list, splitting out and adding furigana data +-- This also does joining of syllables with "#" as text +-- (Joining of furigana syllables with # as text seems useless for now, so it's not done.) +function karaskel.split_furigana_data(line) + if line.kind ~= "dialogue" then + karaskel.trace("skipping line, not dialogue") + return + end + karaskel.trace("split_furigana_data:1") + line.furigana = {n=0} + local newkara = {n=0} + local curtime = 0 + for i = 0, line.karaoke.n-1 do + karaskel.trace("split_furigana_data:2:"..i) + local syl = line.karaoke[i] + local a, b, maintext, furitext = string.find(syl.text_stripped, "^(.*)|(.*)$") + if not maintext then + maintext = syl.text_stripped + end + karaskel.trace("split_furigana_data:3:"..i..":"..maintext) + local highlight = { duration = syl.duration, start_time = curtime*10, end_time = curtime*10+syl.duration*10 } + curtime = curtime + syl.duration + if maintext == "#" then + karaskel.trace("split_furigana_data:4:"..i..":a") + -- repeat character + newkara[newkara.n-1].duration = newkara[newkara.n-1].duration + syl.duration + syl = newkara[newkara.n-1] + else + karaskel.trace("split_furigana_data:4:"..i..":b") + syl.furigana = {n=0, text=""} -- essentially a list of syllables in the syllable :o + syl.highlights = {n=0} + syl.text_stripped = maintext + newkara[newkara.n] = syl + newkara.n = newkara.n + 1 + end + karaskel.trace("split_furigana_data:5:"..i) + syl.highlights[syl.highlights.n] = highlight + syl.highlights.n = syl.highlights.n + 1 + if a then + karaskel.trace("split_furigana_data:6:"..i) + local furi = { text = furitext, duration = highlight.duration, start_time = highlight.start_time, end_time = highlight.end_time } + syl.furigana[syl.furigana.n] = furi + syl.furigana.n = syl.furigana.n + 1 + syl.furigana.text = syl.furigana.text .. furitext + end + end + line.karaoke = newkara +end + +function karaskel.calc_furigana_sizes(line, syl) + -- assume the sizes for the main syllable itself has been calculated already + local ls = line.styleref + local style = { -- only copy what's needed for text_extents + fontname = ls.fontname, + fontsize = ls.fontsize * karaskel.furigana_scale, + bold = ls.bold, + italic = ls.italic, + underline = ls.underline, + strikeout = ls.strikeout, + scale_x = ls.scale_x, + scale_y = ls.scale_y, + spacing = ls.spacing, + encoding = ls.encoding + } + syl.furigana.width, syl.furigana.height = aegisub.text_extents(style, syl.furigana.text) + syl.furigana.scale = syl.width / syl.furigana.width * 100 + syl.furigana.fontsize = style.fontsize + if syl.furigana.scale > 100 then + syl.furigana.scale = 100 + else + syl.furigana.width = syl.width + end + style.scale_x = style.scale_x * syl.furigana.scale / 100 + local left = syl.left + (syl.width - syl.furigana.width)/2 + for i = 0, syl.furigana.n-1 do + local f = syl.furigana[i] + f.width, f.height = aegisub.text_extents(style, f.text) + f.left = left + f.center = f.left + f.width/2 + f.right = f.left + f.width + left = f.right + end +end + +-- Everything else is done in the process_lines function +function karaskel.process_lines(meta, styles, lines, config) + karaskel.trace("new skeleton") + karaskel.trace("skel_process_lines") + -- Do a little pre-calculation for each line and syllable + karaskel.precalc_syllable_data(meta, styles, lines) + karaskel.trace("skel_process_lines:2") + -- A var for the new output + local result = {n=0} + local ool_fx = {} + aegisub.set_status("Running main-processing") + -- Now do the usual processing + for i = 0, lines.n-1 do + karaskel.trace("skel_process_lines:3:"..i) + aegisub.report_progress(50+i/lines.n*50) + if (lines[i].kind == "dialogue" or lines[i].kind == "comment") and lines[i].style == karaskel.ool_fx_style then + local fx = {} + fx.head, fx.tail = string.headtail(lines[i]) + fx.line = lines[i] + fx.start_time, fx.end_time = fx.line.start_time, fx.line.end_time + ool_fx[fx.head] = fx + else + -- Get replacement lines + lines[i].ool_fx = ool_fx + repl = do_line(meta, styles, config, lines[i]) + karaskel.trace("skel_process_lines:4:"..i) + -- Append to result table + for j = 1, repl.n do + table.insert(result, repl[j]) + end + ool_fx = {} + end + end + -- Done, return the stuff + return result +end +process_lines = karaskel.process_lines diff --git a/automation/include/karaskel.lua b/automation/include/karaskel.lua index 894c11352..c282237a7 100644 --- a/automation/include/karaskel.lua +++ b/automation/include/karaskel.lua @@ -65,67 +65,59 @@ -- start_time - Start time of the syllable, in miliseconds, relative to the start of the line -- end_time - End time of the syllable, similar to start_time --- Since utils.lua is always useful, include it here -include("utils.lua") - --- This one is used -aegisub.output_warning = aegisub.output_debug --- Set the variable show_debug_output to non-nil non-false before including karaskel.lua, to get debug output -if not show_debug_output then - aegisub.output_debug = function() end -end +include("karaskel-base.lua") -- Return a replacement text for a syllable -function default_do_syllable(meta, styles, config, line, syl) - aegisub.output_debug("default_do_syllable") +function karaskel.do_syllable(meta, styles, config, line, syl) + karaskel.trace("default_do_syllable") return syl.text end -- Decide whether or not to process a line -function default_do_line_decide(meta, styles, config, line) - aegisub.output_debug("default_do_line_decide") +function karaskel.do_line_decide(meta, styles, config, line) + karaskel.trace("default_do_line_decide") return line.kind == "dialogue" end -- Return a text to prefix the line -function default_do_line_start(meta, styles, config, line) - aegisub.output_debug("default_do_line_start") +function karaskel.do_line_start(meta, styles, config, line) + karaskel.trace("default_do_line_start") return "" end -- Return a text to suffix the line -function default_do_line_end(meta, styles, config, line) - aegisub.output_debug("default_do_line_end") +function karaskel.do_line_end(meta, styles, config, line) + karaskel.trace("default_do_line_end") return "" end -- Process an entire line (which has pre-calculated extra data in it already) -- Return a table of replacement lines -function default_do_line(meta, styles, config, line) - aegisub.output_debug("default_do_line") +function karaskel.do_line(meta, styles, config, line) + karaskel.trace("default_do_line") -- Check if the line should be processed at all if not do_line_decide(meta, styles, config, line) then return {n=0} end - aegisub.output_debug("default_do_line:2") + karaskel.trace("default_do_line:2") -- Create a new local var for the line replacement text, set it to line prefix -- This is to make sure the actual line text isn't replaced before the line has been completely processed local newtext = do_line_start(meta, styles, config, line) - aegisub.output_debug("default_do_line:3") + karaskel.trace("default_do_line:3") -- Loop over the syllables for i = 0, line.karaoke.n-1 do - aegisub.output_debug("default_do_line:4:"..i) + karaskel.trace("default_do_line:4:"..i) -- Append the replacement for each syllable onto the line newtext = newtext .. do_syllable(meta, styles, config, line, line.karaoke[i]) end - aegisub.output_debug("default_do_line:5") + karaskel.trace("default_do_line:5") -- Append line suffix newtext = newtext .. do_line_end(meta, styles, config, line) - aegisub.output_debug("default_do_line:6") + karaskel.trace("default_do_line:6") -- Now replace the line text line.text = newtext @@ -135,95 +127,8 @@ function default_do_line(meta, styles, config, line) end -- Now assign all the default functions to the names that are actually called -do_syllable = default_do_syllable -do_line_decide = default_do_line_decide -do_line_start = default_do_line_start -do_line_end = default_do_line_end -do_line = default_do_line - -precalc_start_progress = 0 -precalc_end_progress = 50 -function precalc_syllable_data(meta, styles, lines) - aegisub.output_debug("precalc_syllable_data") - aegisub.set_status("Preparing syllable-data") - for i = 0, lines.n-1 do - aegisub.output_debug("precalc_syllable_data:2:"..i) - aegisub.report_progress(precalc_start_progress + i/lines.n*(precalc_end_progress-precalc_start_progress)) - local line, style = lines[i] - -- Index number of the line - line.i = i - -- Linked list-style access - line.prev = lines[i-1] - line.next = lines[i+1] - aegisub.output_debug("precalc_syllable_data:3:") - if line.kind == "dialogue" or line.kind == "comment" then - aegisub.output_debug("precalc_syllable_data:4:") - local style = styles[line.style] - if not style then - -- ok, so the named style does not exist... well there MUST be at least ONE style - -- pick the first one - style = styles[0] - aegisub.output_warning(string.format("WARNING! You have a line using a style named \"%s\", but that style does not exist! Using the first defined style (\"%s\") instead.", line.style, style.name)) - end - -- Line dimensions - line.width, line.height, line.ascent, line.extlead = aegisub.text_extents(style, line.text_stripped) - aegisub.output_debug("precalc_syllable_data:5:") - -- Line position - line.centerleft = math.floor((meta.res_x - line.width) / 2) - line.centerright = meta.res_x - line.centerleft - -- Line duration, in miliseconds - line.duration = (line.end_time - line.start_time) * 10 - -- Style reference - line.styleref = style - aegisub.output_debug("precalc_syllable_data:6:") - -- Process the syllables - local curx, curtime = 0, 0 - for j = 0, line.karaoke.n-1 do - aegisub.output_debug("precalc_syllable_data:7::"..j) - local syl = line.karaoke[j] - -- Syllable index - syl.i = j - -- Syllable dimensions - syl.width, syl.height, syl.ascent, syl.extlead = aegisub.text_extents(style, syl.text_stripped) - aegisub.output_debug("precalc_syllable_data:8::") - -- Syllable positioning - syl.left = curx - syl.center = math.floor(curx + syl.width/2) - syl.right = curx + syl.width - curx = syl.right - -- Start and end times in miliseconds - syl.start_time = curtime - syl.end_time = curtime + syl.duration*10 - curtime = syl.end_time - end - end - end -end - --- Everything else is done in the process_lines function -function skel_process_lines(meta, styles, lines, config) - aegisub.output_debug("skel_process_lines") - -- Do a little pre-calculation for each line and syllable - precalc_syllable_data(meta, styles, lines) - aegisub.output_debug("skel_process_lines:2") - -- A var for the new output - local result = {n=0} - aegisub.set_status("Running main-processing") - -- Now do the usual processing - for i = 0, lines.n-1 do - aegisub.output_debug("skel_process_lines:3:"..i) - aegisub.report_progress(50+i/lines.n*50) - if do_line_decide(meta, styles, config, lines[i]) then - aegisub.output_debug("skel_process_lines:4:..i") - -- Get replacement lines - repl = do_line(meta, styles, config, lines[i]) - -- Append to result table - for j = 1, repl.n do - table.insert(result, repl[j]) - end - end - end - -- Done, return the stuff - return result -end -process_lines = skel_process_lines +do_syllable = karaskel.do_syllable +do_line_decide = karaskel.do_line_decide +do_line_start = karaskel.do_line_start +do_line_end = karaskel.do_line_end +do_line = karaskel.do_line diff --git a/core/ass_export_filter.cpp b/core/ass_export_filter.cpp index 1e096e75e..20545b1fb 100644 --- a/core/ass_export_filter.cpp +++ b/core/ass_export_filter.cpp @@ -67,7 +67,7 @@ AssExportFilter::~AssExportFilter() { void AssExportFilter::Register (wxString name,int priority) { // Check if it's registered if (RegisterName != _T("")) { - throw _T("Register export filter: filter with name \"") + name + _T("\" is already registered."); + throw wxString::Format(_T("Register export filter: filter with name \"%s\" is already registered."), name); } // Remove pipes from name @@ -78,7 +78,7 @@ void AssExportFilter::Register (wxString name,int priority) { FilterList::iterator end = AssExportFilterChain::GetFilterList()->end(); for (FilterList::iterator cur=begin;cur!=end;cur++) { if ((*cur)->RegisterName == name) { - throw _T("Register export filter: name \"") + name + _T("\" already exists."); + throw wxString::Format(_T("Register export filter: name \"%s\" already exists."), name); } } @@ -103,7 +103,7 @@ void AssExportFilter::Register (wxString name,int priority) { // Unregister void AssExportFilter::Unregister () { // Check if it's registered - if (!IsRegistered()) throw _T("Unregister export filter: name \"") + RegisterName + _T("\" is not registered."); + if (!IsRegistered()) throw wxString::Format(_T("Unregister export filter: name \"%s\" is not registered."), RegisterName); // Unregister RegisterName = _T(""); diff --git a/core/ass_exporter.cpp b/core/ass_exporter.cpp index 64c964fb4..e3198e5b6 100644 --- a/core/ass_exporter.cpp +++ b/core/ass_exporter.cpp @@ -91,7 +91,7 @@ void AssExporter::AddFilter(wxString name) { } // Check - if (!filter) throw _T("Filter not found"); + if (!filter) throw wxString::Format(_T("Filter not found: %s"), name); // Add to list Filters.push_back(filter); @@ -176,5 +176,5 @@ wxString AssExporter::GetDescription(wxString name) { return (*cur)->Description; } } - throw _T("Filter not found."); + throw wxString::Format(_T("Filter not found: %s"), name); } diff --git a/core/audio_karaoke.cpp b/core/audio_karaoke.cpp index 4b6c3e943..7b36fdf78 100644 --- a/core/audio_karaoke.cpp +++ b/core/audio_karaoke.cpp @@ -68,7 +68,15 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent) splitting = false; split_cursor_syl = -1; curSyllable = 0; - diag = NULL; + diag = 0; + workDiag = 0; +} + + +////////////// +// Destructor +AudioKaraoke::~AudioKaraoke() { + delete workDiag; } @@ -81,6 +89,7 @@ bool AudioKaraoke::LoadFromDialogue(AssDialogue *_diag) { } // Set dialogue + delete workDiag; diag = _diag; if (!diag) { Refresh(false); @@ -88,8 +97,10 @@ bool AudioKaraoke::LoadFromDialogue(AssDialogue *_diag) { } // Split + workDiag = new AssDialogue(diag->data, false); + workDiag->ParseASSTags(); must_rebuild = false; - bool hasKar = ParseDialogue(diag); + bool hasKar = ParseDialogue(workDiag); // No karaoke, autosplit if (!hasKar) { @@ -137,12 +148,14 @@ void AudioKaraoke::Commit() { KaraokeSyllable *syl; size_t n = syllables.size(); if (must_rebuild) { + workDiag->ClearBlocks(); for (size_t i=0;itag, syl->length) + syl->contents; } + workDiag->Text = finalText; + workDiag->ParseASSTags(); diag->Text = finalText; - //diag->ParseASSTags(); } else { wxLogDebug(_T("Updating karaoke without rebuild")); for (size_t i = 0; i < n; i++) { @@ -152,7 +165,10 @@ void AudioKaraoke::Commit() { syl->original_tagdata->SetInt(syl->length); } wxLogDebug(_T("Done updating syllables")); - diag->UpdateText(); + workDiag->UpdateText(); + workDiag->ClearBlocks(); + workDiag->ParseASSTags(); + diag->Text = workDiag->Text; } } diff --git a/core/audio_karaoke.h b/core/audio_karaoke.h index e80b382a0..d056acd6a 100644 --- a/core/audio_karaoke.h +++ b/core/audio_karaoke.h @@ -84,6 +84,7 @@ typedef std::vector SylVector; class AudioKaraoke : public wxWindow { private: AssDialogue *diag; + AssDialogue *workDiag; int startClickSyl; bool must_rebuild; @@ -112,6 +113,8 @@ public: SylVector syllables; AudioKaraoke(wxWindow *parent); + virtual ~AudioKaraoke(); + bool LoadFromDialogue(AssDialogue *diag); void Commit(); void SetSyllable(int n); diff --git a/core/audio_provider.cpp b/core/audio_provider.cpp index ccf3cc8ae..38d6e7fb5 100644 --- a/core/audio_provider.cpp +++ b/core/audio_provider.cpp @@ -76,7 +76,7 @@ AudioProvider::AudioProvider(wxString _filename, AudioDisplay *_display) { if (!pa_refcount) { PaError err = Pa_Initialize(); if (err != paNoError) - throw _T("Failed opening PortAudio with error: ") + wxString(Pa_GetErrorText(err),wxConvLocal); + throw wxString::Format(_T("Failed opening PortAudio with error: %s"), wxString(Pa_GetErrorText(err),wxConvLocal)); pa_refcount++; } @@ -144,7 +144,7 @@ void AudioProvider::OpenAVSAudio() { LoadFromClip(script); } catch (AvisynthError &err) { - throw _T("AviSynth error: ") + wxString(err.msg,wxConvLocal); + throw wxString::Format(_T("AviSynth error: %s"), wxString(err.msg,wxConvLocal)); } } diff --git a/core/automation.cpp b/core/automation.cpp index f541cd449..600e02296 100644 --- a/core/automation.cpp +++ b/core/automation.cpp @@ -1320,7 +1320,7 @@ void AutomationScript::process_lines(AssFile *input) switch ((*block)->type) { case BLOCK_BASE: - throw _T("BLOCK_BASE found processing dialogue blocks. This should never happen."); + throw wxString(_T("BLOCK_BASE found processing dialogue blocks. This should never happen.")); case BLOCK_PLAIN: ktext += (*block)->text; diff --git a/core/automation_filter.cpp b/core/automation_filter.cpp index 2f6d5ae87..d46b4c82e 100644 --- a/core/automation_filter.cpp +++ b/core/automation_filter.cpp @@ -147,7 +147,7 @@ AutomationFilterConfigDialog::AutomationFilterConfigDialog(wxWindow *parent, Aut AssAutomationFilter::AssAutomationFilter(AutomationScript *a_script) : script(a_script), dialog(0) { - Register(wxString::Format(_T("Automation: %s"), script->name.c_str()), 100); + Register(wxString::Format(_T("Automation: %s"), script->name.c_str()), 2000); if (script->description.IsEmpty()) { Description = wxString::Format(_T("%s\r\n(This Automation script has not provided a description.)"), script->name.c_str()); } else { diff --git a/core/automation_gui.cpp b/core/automation_gui.cpp index c965c16dd..af2717953 100644 --- a/core/automation_gui.cpp +++ b/core/automation_gui.cpp @@ -177,6 +177,9 @@ void DialogAutomationManager::OnAdd(wxCommandEvent &event) catch (AutomationError &err) { wxMessageBox(wxString::Format(_T("Error loading Automation script '%s':\r\n\r\n%s"), sfnames.c_str(), err.message.c_str()), _T("Error loading Automation script"), wxOK | wxICON_ERROR, this); } + catch (wxString &err) { + wxMessageBox(wxString::Format(_T("Error loading Automation script %s:\r\n\r\n%s"), sfnames.c_str(), err), _T("Error loading Automation script"), wxOK|wxICON_ERROR, this); + } catch (wchar_t *err) { wxMessageBox(wxString::Format(_T("Error loading Automation script %s:\r\n\r\n%s"), sfnames.c_str(), err), _T("Error loading Automation script"), wxOK|wxICON_ERROR, this); } diff --git a/core/avisynth_wrap.cpp b/core/avisynth_wrap.cpp index 26469176a..ffe46955c 100644 --- a/core/avisynth_wrap.cpp +++ b/core/avisynth_wrap.cpp @@ -55,12 +55,12 @@ AviSynthWrapper::AviSynthWrapper() { hLib=LoadLibrary(_T("avisynth.dll")); if (hLib == NULL) - throw _T("Could not load avisynth.dll"); + throw wxString(_T("Could not load avisynth.dll")); FUNC *CreateScriptEnv = (FUNC*)GetProcAddress(hLib, "CreateScriptEnvironment"); if (CreateScriptEnv == NULL) - throw _T("Failed to get function from avisynth.dll"); + throw wxString(_T("Failed to get function from avisynth.dll")); // Require Avisynth 2.5.6+? if (Options.AsBool(_T("Allow Ancient Avisynth"))) @@ -69,8 +69,7 @@ AviSynthWrapper::AviSynthWrapper() { env = CreateScriptEnv(AVISYNTH_INTERFACE_VERSION); if (env == NULL) - throw _T("Failed to create a new avisynth script environment. Avisynth is too old?"); - + throw wxString(_T("Failed to create a new avisynth script environment. Avisynth is too old?")); // Set memory limit int memoryMax = Options.AsInt(_T("Avisynth MemoryMax")); if (memoryMax != 0) diff --git a/core/changelog.txt b/core/changelog.txt index 10660797c..3abc2513e 100644 --- a/core/changelog.txt +++ b/core/changelog.txt @@ -49,6 +49,7 @@ Please visit http://aegisub.net to download latest version - Added reading of keyframe and timecode data from Matroska files (which are still not recommended, due to their dependency on DirectShowSource). (AMZ) - Added forums and bugtracker to Help menu. (AMZ) - Fixed Fonts Collector behavior with font shortcuts. (AMZ) +- Better error reporting when loading Automation scripts (jfs) = 1.09 beta - 2006.01.16 =========================== diff --git a/core/dialog_search_replace.cpp b/core/dialog_search_replace.cpp index 39941b2ca..6df385685 100644 --- a/core/dialog_search_replace.cpp +++ b/core/dialog_search_replace.cpp @@ -515,7 +515,7 @@ wxString *SearchReplaceEngine::GetText(int n,int field) { if (field == 0) return &cur->Text; else if (field == 1) return &cur->Style; else if (field == 2) return &cur->Actor; - else throw _T("Invalid field"); + else throw wxString(_T("Invalid field")); } diff --git a/core/export_framerate.cpp b/core/export_framerate.cpp index 7d3d1baf3..6e01a2a27 100644 --- a/core/export_framerate.cpp +++ b/core/export_framerate.cpp @@ -201,7 +201,7 @@ void AssTransformFramerateFilter::TransformTimeTags (wxString name,int n,AssOver curKarPos = lineData->ko; lineData->ko += parVal/10; } - else throw _T("Unknown karaoke tag!"); + else throw wxString::Format(_T("Unknown karaoke tag! '%s'"), name); curKarPos *= 10; parVal += curKarPos; } diff --git a/core/fonts_collector.cpp b/core/fonts_collector.cpp index 37a44ccd6..ddd5ec362 100644 --- a/core/fonts_collector.cpp +++ b/core/fonts_collector.cpp @@ -211,7 +211,7 @@ wxArrayString FontsCollectorThread::GetFontFiles (wxString face) { n++; } } - if (n==0) throw _T("Font not found"); + if (n==0) throw wxString(_T("Font not found: %s"), face); return files; }