diff --git a/aegisub/VideoSink.cpp b/aegisub/VideoSink.cpp index 5d093596d..25e19ed5a 100644 --- a/aegisub/VideoSink.cpp +++ b/aegisub/VideoSink.cpp @@ -5,7 +5,7 @@ * */ -#include "config.h" + #ifdef WITH_DIRECTSHOW #include #ifdef __WXDEBUG__ diff --git a/aegisub/audio_player_dsound.cpp b/aegisub/audio_player_dsound.cpp index 409fe1bc6..a9974caa1 100644 --- a/aegisub/audio_player_dsound.cpp +++ b/aegisub/audio_player_dsound.cpp @@ -39,7 +39,6 @@ /////////// // Headers -#include "config.h" #ifdef WITH_DIRECTSOUND #include diff --git a/aegisub/audio_provider_lavc.cpp b/aegisub/audio_provider_lavc.cpp index 742e9e15f..341fc7868 100644 --- a/aegisub/audio_provider_lavc.cpp +++ b/aegisub/audio_provider_lavc.cpp @@ -36,7 +36,6 @@ /////////// // Headers -#include "config.h" #ifdef WITH_FFMPEG #ifdef WIN32 diff --git a/aegisub/auto4_auto3.cpp b/aegisub/auto4_auto3.cpp index fd214e937..b3f4b4423 100644 --- a/aegisub/auto4_auto3.cpp +++ b/aegisub/auto4_auto3.cpp @@ -33,7 +33,7 @@ // Contact: mailto:jiifurusu@gmail.com // -#include "config.h" + #ifdef WITH_AUTOMATION #ifdef WITH_AUTO3 diff --git a/aegisub/auto4_base.cpp b/aegisub/auto4_base.cpp index c4650171a..1fd062247 100644 --- a/aegisub/auto4_base.cpp +++ b/aegisub/auto4_base.cpp @@ -33,7 +33,7 @@ // Contact: mailto:jiifurusu@gmail.com // -#include "config.h" + #ifdef WITH_AUTOMATION #include "auto4_base.h" diff --git a/aegisub/auto4_lua.cpp b/aegisub/auto4_lua.cpp index 0f8ac76ca..836bcc9ea 100644 --- a/aegisub/auto4_lua.cpp +++ b/aegisub/auto4_lua.cpp @@ -33,7 +33,6 @@ // Contact: mailto:jiifurusu@gmail.com // -#include "config.h" #ifdef WITH_AUTOMATION #include "auto4_lua.h" diff --git a/aegisub/auto4_lua_assfile.cpp b/aegisub/auto4_lua_assfile.cpp index 23911d011..4b74c61ab 100644 --- a/aegisub/auto4_lua_assfile.cpp +++ b/aegisub/auto4_lua_assfile.cpp @@ -33,7 +33,6 @@ // Contact: mailto:jiifurusu@gmail.com // -#include "config.h" #ifdef WITH_AUTOMATION #include "auto4_lua.h" diff --git a/aegisub/auto4_lua_dialog.cpp b/aegisub/auto4_lua_dialog.cpp index 288db6d3e..201276b7f 100644 --- a/aegisub/auto4_lua_dialog.cpp +++ b/aegisub/auto4_lua_dialog.cpp @@ -34,7 +34,6 @@ // -#include "config.h" #ifdef WITH_AUTOMATION #include "auto4_lua.h" diff --git a/aegisub/auto4_lua_scriptreader.cpp b/aegisub/auto4_lua_scriptreader.cpp index 5eb3951bf..886f81ffe 100644 --- a/aegisub/auto4_lua_scriptreader.cpp +++ b/aegisub/auto4_lua_scriptreader.cpp @@ -33,7 +33,6 @@ // Contact: mailto:jiifurusu@gmail.com // -#include "config.h" #ifdef WITH_AUTOMATION #include "auto4_lua_scriptreader.h" diff --git a/aegisub/auto4_perl.cpp b/aegisub/auto4_perl.cpp new file mode 100644 index 000000000..5d1e00cdc --- /dev/null +++ b/aegisub/auto4_perl.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#ifdef WITH_PERL + + +#include "auto4_perl.h" + + +namespace Automation4 { + + +/////////////////////////////////// +// Perl -> C++ interface (XSUBS) +// + EXTERN_C void boot_DynaLoader (pTHX_ CV* cv); + + // Copypasted from somewhere + EXTERN_C void xs_perl_main(pTHX) + { + dXSUB_SYS; + + /* DynaLoader is a special case */ + newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); + + // My XSUBS ^^ + xs_perl_script(aTHX); + xs_perl_misc(aTHX); + xs_perl_console(aTHX); + } + + +/////////////////////// +// PerlScriptFactory +// + class PerlScriptFactory : public ScriptFactory { + private: + PerlInterpreter *parser; + + public: + PerlScriptFactory() + { + // Script engine properties + engine_name = _T("Perl"); + filename_pattern = _T("*") _T(PERL_SCRIPT_EXTENSION); + + // Perl interpreter initialization (ONE FOR ALL THE SCRIPTS) + parser = perl_alloc(); + perl_construct(parser); + char *_embedding[] = { "aegisub", "-e", "0" }; + perl_parse(parser, xs_perl_main, + 3, _embedding, + NULL); + // (That was pretty magic o_O) + + // Let's register the perl script factory \o/ + Register(this); + } + + ~PerlScriptFactory() + { + // Perl interpreter deinitialization + perl_destruct(parser); + perl_free(parser); + } + + virtual Script* Produce(const wxString &filename) const + { + if(filename.EndsWith(_T(PERL_SCRIPT_EXTENSION))) { + return new PerlScript(filename); + } + else { + return 0; + } + } + }; + + // The one and only (thank goodness ¬.¬) perl engine!!! + PerlScriptFactory _perl_script_factory; + +}; + + +#endif //WITH_PERL diff --git a/aegisub/auto4_perl.h b/aegisub/auto4_perl.h new file mode 100644 index 000000000..56fd4ac51 --- /dev/null +++ b/aegisub/auto4_perl.h @@ -0,0 +1,180 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#pragma once +#ifndef _AUTO4_PERL_H +#define _AUTO4_PERL_H + + +#include "auto4_base.h" +#include +#include + +#include "ass_file.h" +//#include "ass_dialogue.h" + +#include +#include +#include + +#include "auto4_perldata.inc" // Parl variables manipulation macros + + +// the fucking perl.h redefines _() -.- please disregard warnings during compilation +#define _(s) wxGetTranslation(_T(s)) + + +// String conversions between wxWidgets and Perl +#define wx2pl wxConvUTF8 +#define pl2wx wxConvUTF8 + + +#define PERL_SCRIPT_EXTENSION ".pl" /* TODO maybe: make it multi-extension */ + + +namespace Automation4 { + + +/////////// +// XSUBS +// + void xs_perl_script(pTHX); + void xs_perl_misc(pTHX); + void xs_perl_console(pTHX); + + +/////////////////// +// Script object +// + class PerlFeatureMacro; + class PerlScript : public Script { + private: + static PerlScript *active; // The active script (at any given time) + + AV *inc_saved; + wxString package; // Every script resides in a package named at random + + bool reload; // Automatically reload if source file has changed + time_t mtime; // The mtime of the loaded source file + + void load(); // It doas all the script initialization + void unload(); // It does all the script disposing + + static void activate(PerlScript *script); // Set the active script /* TODO: add @INC hacking */ + static void deactivate(); // Unset the active script + + public: + PerlScript(const wxString &filename); + virtual ~PerlScript(); + + virtual void Reload(); // Reloading of a loaded script + + void Activate() { activate(this); } // Set the script as active + void Deactivate() const { deactivate(); } // Unset the active script + + const wxString& GetPackage() const { return package; } // The perl package containing script code + static PerlScript *GetScript() { return active; } // Query the value of the active script + + /* TODO maybe: change these into tying of scalars */ + void ReadVars(); // Sync the script's vars from perl package to script object + void WriteVars() const; // Sync the script's vars from script object to perl package + + /* TODO: add c++ equivalents */ + static XS(set_info); // Aegisub::Script::set_info() + void AddFeature(Feature *feature); + void DeleteFeature(Feature *feature); + static XS(register_macro); // Aegisub::Script::register_macro() + static XS(register_console); // Aegisub::Script::register_console() /* TODO: move this into PerlConsole class */ + + }; + + +////////////////// +// Macro object +// + class PerlFeatureMacro : public FeatureMacro { + private: + SV *processing_sub; // May be reference or name of sub + SV *validation_sub; // here too + + protected: + PerlScript *script; // The owner script + + public: + PerlFeatureMacro(const wxString &name, const wxString &description, PerlScript *perl_script, SV *proc_sub, SV *val_sub); + virtual ~PerlFeatureMacro(); + + virtual bool Validate(AssFile *subs, const std::vector &selected, int active); + virtual void Process(AssFile *subs, std::vector &selected, int active, wxWindow * const progress_parent); + }; + + +/////////////////////////////////////////////////// +// Conversion between aegisub data and perl data +// + class PerlAss { + private: + + public: + static wxString GetEntryClass(AssEntry *entry); + + static HV *MakeHasshEntry(AssEntry *entry); + static HV *MakeHasshStyle(AssStyle *style); + static HV *MakeHasshDialogue(AssDialogue *diag); + static AV *MakeHasshLines(AV *lines, AssFile *ass); + + static AssEntry *MakeAssEntry(HV *entry); + static AssStyle *MakeAssStyle(HV *style); + static AssDialogue *MakeAssDialogue(HV *diag); + static AssFile *MakeAssLines(AssFile *ass, AV *lines); + }; + + +///////////////////////// +// Misc utility functions +// + class PerlLog { + public: + static XS(log_warning); // Aegisub::warn() + }; + + XS(text_extents); // Aegisub::text_extents() + + +}; + + +#endif diff --git a/aegisub/auto4_perl_ass.cpp b/aegisub/auto4_perl_ass.cpp new file mode 100644 index 000000000..78fa35e3a --- /dev/null +++ b/aegisub/auto4_perl_ass.cpp @@ -0,0 +1,463 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#ifdef WITH_PERL + + +#include "auto4_perl.h" +#include "ass_file.h" +#include "ass_entry.h" +#include "ass_style.h" +#include "ass_dialogue.h" +#include "ass_attachment.h" + + +// For wxString::Trim +#define right true +#define left false + + +#define HASSH_BASIC_INIT(ae, he) \ + HV_TOUCH(he, "raw", 3)\ + HV_STORE(newSVpv(ae->GetEntryData().mb_str(wx2pl), 0));\ + HV_TOUCH(he, "section", 7)\ + HV_STORE(newSVpv(ae->group.mb_str(wx2pl), 0));\ + wxString he ## _class = GetEntryClass(ae);\ + HV_TOUCH(he, "class", 5)\ + HV_STORE(newSVpv(he ## _class.mb_str(wx2pl), 0)) + +#define ASS_BASIC_INIT(he, ae) \ + HV_FETCH(he, "raw", 3)\ + ae->SetEntryData(wxString(SvPV_nolen(HV_VAL), pl2wx));\ + HV_FETCH(he, "section", 7)\ + ae->group = wxString(SvPV_nolen(HV_VAL), pl2wx) + + +namespace Automation4 { + + wxString PerlAss::GetEntryClass(AssEntry *entry) + { + wxString data = entry->GetEntryData(); + + if(entry->GetType() == ENTRY_DIALOGUE) return _T("dialogue"); + + if(entry->GetType() == ENTRY_STYLE) { + return _T("style"); + /* TODO: add stylex recognition */ + } + + if(entry->GetType() == ENTRY_BASE) { + if(entry->group == _T("[Script Info]") && data.Matches(_T("*:*"))) return _T("info"); + + if(data == entry->group) return _T("head"); + + if(data.StartsWith(_T("Format:"))) return _T("format"); + + if(data.IsEmpty()) return _T("clear"); + + if(data.Trim(left).StartsWith(_T(";"))) return _T("comment"); + } + + // Fallback + return _T("unknown"); + } + + + HV *PerlAss::MakeHasshEntry(AssEntry *e) + { + switch((int)e->GetType()) { + case ENTRY_DIALOGUE: + return MakeHasshDialogue(AssEntry::GetAsDialogue(e)); + + case ENTRY_STYLE: + return MakeHasshStyle(AssEntry::GetAsStyle(e)); + + default: + case ENTRY_BASE: + dHV; + HV *entry = newHV(); + HASSH_BASIC_INIT(e, entry); + + if(entry_class == _T("info")) { + // Info + HV_TOUCH(entry, "key", 3) { + wxString _text = e->GetEntryData().BeforeFirst(_T(':')).Strip(wxString::both); + HV_STORE(newSVpv(_text.mb_str(wx2pl), 0)); + } + + HV_TOUCH(entry, "value", 5) { + wxString _text = e->GetEntryData().AfterFirst(_T(':')).Strip(wxString::both); + HV_STORE(newSVpv(_text.mb_str(wx2pl), 0)); + } + } + else if(entry_class == _T("format")) { + // Format °_° + HV_TOUCH(entry, "fields", 6) { + AV *fields_av = newAV(); + HV_STORE(newRV_noinc((SV*)fields_av)); + for(wxString fields_buf = e->GetEntryData().AfterFirst(_T(':')).Trim(left); + !fields_buf.IsEmpty(); + fields_buf = fields_buf.AfterFirst(_T(',')).Trim(left)) { + av_push(fields_av, newSVpv(fields_buf.BeforeFirst(_T(',')).Trim(right).mb_str(wx2pl), 0)); + } + } + } + else if(entry_class == _T("comment")) { + // Comment + HV_TOUCH(entry, "text", 4) { + wxString _text = e->GetEntryData().AfterFirst(_T(';')); + HV_STORE(newSVpv(_text.mb_str(wx2pl), 0)); + } + } + return entry; + } + } + + HV *PerlAss::MakeHasshStyle(AssStyle *s) + { + dHV; + + // Create new empty hash + HV *style = newHV(); + + // Add fields + HASSH_BASIC_INIT(s, style); + + HV_TOUCH(style, "name", 4) + HV_STORE(newSVpv(s->name.mb_str(wx2pl), 0)); + + HV_TOUCH(style, "font", 4) + HV_STORE(newSVpv(s->font.mb_str(wx2pl), 0)); + + HV_FAS(style, "fontsize", 8, nv, s->fontsize); + + HV_TOUCH(style, "color1", 6) + HV_STORE(newSVpv(s->primary.GetASSFormatted(true).mb_str(wx2pl), 0)); + HV_TOUCH(style, "color2", 6) + HV_STORE(newSVpv(s->secondary.GetASSFormatted(true).mb_str(wx2pl), 0)); + HV_TOUCH(style, "color3", 6) + HV_STORE(newSVpv(s->outline.GetASSFormatted(true).mb_str(wx2pl), 0)); + HV_TOUCH(style, "color4", 6) + HV_STORE(newSVpv(s->shadow.GetASSFormatted(true).mb_str(wx2pl), 0)); + + HV_TOUCH(style, "bold", 4) HV_STORE(newSViv(s->bold)); + + HV_FAS(style, "italic", 6, iv, s->italic); + HV_FAS(style, "underline", 9, iv, s->underline); + HV_FAS(style, "strikeout", 9, iv, s->strikeout); + + HV_FAS(style, "scale_x", 7, nv, s->scalex); + HV_FAS(style, "scale_y", 7, nv, s->scaley); + + HV_FAS(style, "spacing", 7, nv, s->spacing); + + HV_FAS(style, "angle", 5, nv, s->angle); + + HV_FAS(style, "borderstyle", 11, iv, s->borderstyle); + + HV_FAS(style, "outline", 7, nv, s->outline_w); + + HV_FAS(style, "shadow", 6, nv, s->shadow_w); + + HV_FAS(style, "align", 5, iv, s->alignment); + + HV_FAS(style, "margin_l", 8, iv, s->Margin[0]); + HV_FAS(style, "margin_r", 8, iv, s->Margin[1]); + HV_FAS(style, "margin_t", 8, iv, s->Margin[2]); + HV_FAS(style, "margin_b", 8, iv, s->Margin[3]); + + HV_FAS(style, "encoding", 8, iv, s->encoding); + HV_FAS(style, "relative_to", 11, iv, s->relativeTo); + + // Return the hassh style + return style; + } + + HV *PerlAss::MakeHasshDialogue(AssDialogue *d) + { + dHV; + + // Create new hash + HV *diag = newHV(); + + // Copy the values from the AssDialogue + HASSH_BASIC_INIT(d, diag); + + HV_FAS(diag, "comment", 7, iv, d->Comment); + + HV_FAS(diag, "layer", 5, iv, d->Layer); + + HV_FAS(diag, "start_time", 10, iv, d->Start.GetMS()); + HV_FAS(diag, "end_time", 8, iv, d->End.GetMS()); + + HV_TOUCH(diag, "style", 5) + HV_STORE(newSVpv(d->Style.mb_str(wx2pl), 0)); + + HV_TOUCH(diag, "actor", 5) + HV_STORE(newSVpv(d->Actor.mb_str(wx2pl), 0)); + + HV_FAS(diag, "margin_l", 8, iv, d->Margin[0]); + HV_FAS(diag, "margin_r", 8, iv, d->Margin[1]); + HV_FAS(diag, "margin_t", 8, iv, d->Margin[2]); + HV_FAS(diag, "margin_b", 8, iv, d->Margin[3]); + + HV_TOUCH(diag, "effect", 6) + HV_STORE(newSVpv(d->Effect.mb_str(wx2pl), 0)); + + HV_TOUCH(diag, "text", 4) + HV_STORE(newSVpv(d->Text.mb_str(wx2pl), 0)); + + // Return the dialogue + return diag; + } + + AV *PerlAss::MakeHasshLines(AV *lines, AssFile *ass) + { + if(!lines) { + lines = newAV(); + } + + dAV; + I32 i = 0; I32 lines_len = av_len(lines); + for(std::list::iterator it = ass->Line.begin(); it != ass->Line.end(); it++) { + if(i <= lines_len && av_exists(lines, i)) + av_delete(lines, i, G_DISCARD); + AV_TOUCH(lines, i++) + AV_STORE(newRV_noinc((SV*)MakeHasshEntry(*it))); + } + for(; i <= lines_len; i++) { + if(av_exists(lines, i)) + av_delete(lines, i, G_DISCARD); + } + + return lines; + } + + + AssEntry *PerlAss::MakeAssEntry(HV *entry) + { + dHV; + + if(!entry) { + // Create an empty line, if NULL + entry = newHV(); + } + + // The fallback class + wxString cl(_T("unknown")); + // Let's get the actual class of the hassh + HV_FETCH(entry, "class", 5) + cl = wxString(SvPV_nolen(HV_VAL), pl2wx); + + // We trust the value of entry{class} + if(cl == _T("dialogue")) { + // It seems to be a dialogue, let's call the specialized function + return MakeAssDialogue(entry); + } + else if(cl == _T("style")) { + // It seems to be a style, let's call the specialized function + return MakeAssStyle(entry); + } + else { + AssEntry *e = new AssEntry(); + + ASS_BASIC_INIT(entry, e); + + // A base entry + if(cl == _T("info")) { + wxString key, value; + HV_FETCH(entry, "key", 3) { + key = wxString(SvPV_nolen(HV_VAL), pl2wx); + HV_FETCH(entry, "value", 5) { + value = wxString(SvPV_nolen(HV_VAL), pl2wx); + e->SetEntryData(key + _T(": ") + value); + } + } + } + // Not necessary, format customization isn't even supported by aegi (atm? °_°) + /*else if(cl == _T("format")) { + HV_FETCH(entry, "fields", 6) { + AV *fields = (AV*)SvRV(HV_VAL); + for(int i = 0; i < av_len(fields); i++) { + SV ** field = av_fetch(fields, i, 0); + if(field) { + wxString field(SvPV_nolen(*field), pl2wx); + } + } + } + }*/ + else if(cl == _T("comment")) { + HV_FETCH(entry, "text", 4) { + e->SetEntryData(_T(";") + wxString(SvPV_nolen(HV_VAL), pl2wx)); + } + } + return e; + } + } + + AssStyle *PerlAss::MakeAssStyle(HV *style) + { + dHV; + + // Create a default style + AssStyle *s = new AssStyle(); + + // Fill it with the values from the hassh + ASS_BASIC_INIT(style, s); + + HV_FETCH(style, "name", 4) + s->name = wxString(SvPV_nolen(HV_VAL), pl2wx); + + HV_FETCH(style, "font", 4) + s->font = wxString(SvPV_nolen(HV_VAL), pl2wx); + + HV_FAA(style, "fontsize", 8, NV, s->fontsize); + + HV_FETCH(style, "color1", 6) + s->primary.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx)); + HV_FETCH(style, "color2", 6) + s->secondary.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx)); + HV_FETCH(style, "color3", 6) + s->outline.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx)); + HV_FETCH(style, "color4", 6) + s->shadow.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx)); + + HV_FAA(style, "bold", 4, IV, s->bold); + + HV_FAA(style, "italic", 6, IV, s->italic); + HV_FAA(style, "underline", 9, IV, s->underline); + HV_FAA(style, "strikeout", 9, IV, s->strikeout); + + HV_FAA(style, "scale_x", 7, NV, s->scalex); + HV_FAA(style, "scale_y", 7, NV, s->scaley); + + HV_FAA(style, "spacing", 7, NV, s->spacing); + + HV_FAA(style, "angle", 5, NV, s->angle); + + HV_FAA(style, "borderstyle", 11, IV, s->borderstyle); + + HV_FAA(style, "outline", 7, NV, s->outline_w); + + HV_FAA(style, "shadow", 6, NV, s->shadow_w); + + HV_FAA(style, "align", 5, IV, s->alignment); + + HV_FAA(style, "margin_l", 8, IV, s->Margin[0]); + HV_FAA(style, "margin_r", 8, IV, s->Margin[1]); + HV_FAA(style, "margin_t", 8, IV, s->Margin[2]); + HV_FAA(style, "margin_b", 8, IV, s->Margin[3]); + + HV_FAA(style, "encoding", 8, IV, s->encoding); + HV_FAA(style, "relative_to", 11, IV, s->relativeTo); + + // Return the style + return s; + } + + AssDialogue *PerlAss::MakeAssDialogue(HV *diag) + { + dHV; + + // Create a default dialogue + AssDialogue *d = new AssDialogue(); + + ASS_BASIC_INIT(diag, d); + + HV_FAA(diag, "comment", 7, IV, d->Comment); + + HV_FAA(diag, "layer", 5, IV, d->Layer); + + HV_FETCH(diag, "start_time", 10) + d->Start.SetMS(SvIV(HV_VAL)); + HV_FETCH(diag, "end_time", 8) + d->End.SetMS(SvIV(HV_VAL)); + + HV_FETCH(diag, "style", 5) + d->Style = wxString(SvPV_nolen(HV_VAL), pl2wx); + + HV_FETCH(diag, "actor", 5) + d->Actor = wxString(SvPV_nolen(HV_VAL), pl2wx); + + HV_FAA(diag, "margin_l", 8, IV, d->Margin[0]); + HV_FAA(diag, "margin_r", 8, IV, d->Margin[1]); + HV_FAA(diag, "margin_t", 8, IV, d->Margin[2]); + HV_FAA(diag, "margin_b", 8, IV, d->Margin[3]); + + HV_FETCH(diag, "effect", 6) + d->Effect = wxString(SvPV_nolen(HV_VAL), pl2wx); + + HV_FETCH(diag, "text", 4) + d->Text = wxString(SvPV_nolen(HV_VAL), pl2wx); + + // Return the dialogue + return d; + } + + AssFile *PerlAss::MakeAssLines(AssFile *ass, AV *lines) + { + if(!ass) { + /* TODO: create new AssFile if NULL */ + return NULL; + } + + dAV; + std::list::iterator it = ass->Line.begin(); + for(I32 i = 0; i <= av_len(lines); i++) { + if(!av_exists(lines, i)) continue; + if(i < ass->Line.size()) { + if(*it) delete *it; + AV_FETCH(lines, i) + *it++ = MakeAssEntry((HV*)SvRV(AV_VAL)); + } + else { + AV_FETCH(lines, i) + ass->Line.push_back(MakeAssEntry((HV*)SvRV(AV_VAL))); + } + } + + for(; it != ass->Line.end();) { + it = ass->Line.erase(it); + } + + return ass; + } + + +}; + + +#endif //WITH_PERL diff --git a/aegisub/auto4_perl_console.cpp b/aegisub/auto4_perl_console.cpp new file mode 100644 index 000000000..95290aa02 --- /dev/null +++ b/aegisub/auto4_perl_console.cpp @@ -0,0 +1,272 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#ifdef WITH_PERL + + +#include "auto4_perl.h" +#include "auto4_perl_console.h" +#include "main.h" +#include "frame_main.h" +#include "subs_grid.h" + + +namespace Automation4 { + + + void xs_perl_console(pTHX) + { + newXS("Aegisub::PerlConsole::echo", PerlConsole::echo, __FILE__); + newXS("Aegisub::PerlConsole::register_console", PerlConsole::register_console, __FILE__); + } + + +//////////////////////////////////// +// PerlConsole::Dialog +// + + inline PerlConsole::Dialog::Dialog() + { + txt_out = NULL; + } + + inline bool PerlConsole::Dialog::Create(wxWindow* parent, wxWindowID id, const wxString& title, + const wxPoint& pos, const wxSize& size, + long style, const wxString& name) + { + wxDialog::Create(parent, id, title, pos, size, style, name); + + // The text controls in the console + txt_out = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxSize(300,200), + wxTE_MULTILINE | wxTE_READONLY | wxTE_CHARWRAP | wxTE_RICH); + + txt_hist = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxDefaultSize, + wxTE_MULTILINE | wxTE_READONLY | wxTE_CHARWRAP | wxTE_RICH); + txt_in = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxDefaultSize, + wxTE_MULTILINE | wxTE_CHARWRAP | wxTE_PROCESS_ENTER); + + // The right panel + wxBoxSizer *rightpanel = new wxBoxSizer(wxVERTICAL); + rightpanel->Add(txt_hist, 1, wxEXPAND); + rightpanel->Add(txt_in, 0, wxEXPAND); + // And the event handler for the input box + Connect(txt_in->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(PerlConsole::Dialog::InputEnter)); + + // The whole dialog + wxBoxSizer *mainpanel = new wxBoxSizer(wxHORIZONTAL); + mainpanel->Add(txt_out, 1, wxEXPAND | wxRIGHT, 2); + mainpanel->Add(rightpanel, 1, wxEXPAND | wxLEFT, 2); + + // Getting it to work + SetSizer(mainpanel); + mainpanel->SetSizeHints(this); + + return true; + } + + inline void PerlConsole::Dialog::InputEnter(wxCommandEvent& evt) + { + if(txt_in->GetInsertionPoint() == txt_in->GetLastPosition() && + txt_in->GetLineLength(txt_in->GetNumberOfLines()-1) == 0) { + // If an empty line have been entered... + /* TODO: implement an actual command history */ + *txt_hist << txt_in->GetValue() << PerlConsole::Evaluate(txt_in->GetValue()) << _T("\n"); + + // Resetting the input box + txt_in->ChangeValue(_T("")); + } + else { + // Just a normal line with text + txt_in->WriteText(_T("\n")); + } + } + + inline void PerlConsole::Dialog::Echo(const wxString &str) + { + if(txt_out) *txt_out << str << _T("\n"); + else PerlIO_printf(PerlIO_stdout(), "%s\n", str.mb_str(wxConvLocal).data()); + } + + +////////////////////// +// PerlConsole +// + PerlConsole *PerlConsole::registered = NULL; + + PerlConsole::PerlConsole(const wxString &name, const wxString &desc, PerlScript *script): + Feature(SCRIPTFEATURE_MACRO, name), + /*FeatureMacro(name, description),*/ + PerlFeatureMacro(name, desc, script, NULL, NULL) + { + parent_window = NULL; + dialog = new Dialog(); + + // Fuck off any previously registered console °_° + if(registered) delete registered; + registered = this; + } + + PerlConsole::~PerlConsole() + { + if(dialog) dialog->Destroy(); + + /* TODO: Free something? */ + + // Delete the registered console + PerlConsole::registered = NULL; + } + + void PerlConsole::Process(AssFile *subs, std::vector &selected, int active, wxWindow * const progress_parent) + { + if(!parent_window) { + // Create the console's dialog if it doesn't already exist + parent_window = progress_parent; + dialog->Create(parent_window, -1, GetName(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER); + } + // Show the console + dialog->Show(true); + // and return, the console will stay visible and permit running other macros + // the console will 'just' emulate the execution of a macro whenever some code will be evaluated + } + + wxString PerlConsole::evaluate(const wxString &str) + { + /* This mimics FrameMain::OnAutomationMacro */ + + // Get a hold of the SubsBox + SubtitlesGrid *sb = wxGetApp().frame->SubsBox; + sb->BeginBatch(); + + // Create the @_ (global <.<) + AV *AT = get_av("_", 1); + av_clear(AT); + // $_[0] + AV *lines = PerlAss::MakeHasshLines(NULL, AssFile::top); + av_push(AT, newRV_noinc((SV*)lines)); + // $_[1] + std::vector selected_lines = sb->GetAbsoluteSelection(); + AV *selected_av = newAV(); + VECTOR_AV(selected_lines, selected_av, int, iv); + av_push(AT, newRV_noinc((SV*)selected_av)); + // $_[2] + int first_sel = sb->GetFirstSelRow(); + av_push(AT, newSViv(first_sel)); + +// Clear all maps from the subs grid before running the macro +// The stuff done by the macro might invalidate some of the iterators held by the grid, which will cause great crashing + sb->Clear(); + + // Here we go + script->WriteVars(); + // Box the code into the right package + wxString code = _T("package ") + script->GetPackage() + _T(";\n"); + // Add the user's code + code << str; + // Evaluate the code + SV *e = eval_pv(code.mb_str(wx2pl), 0); + /* TODO: check for errors */ + script->ReadVars(); + + // Recreate the top assfile from perl hassh + //AssFile::top->FlagAsModified(GetName()); + PerlAss::MakeAssLines(AssFile::top, lines); + av_undef(lines); + // And reset selection vector + selected_lines.clear(); + AV_VECTOR(selected_av, selected_lines, IV); + CHOP_SELECTED(AssFile::top, selected_lines); + av_undef(selected_av); + +// Have the grid update its maps, this properly refreshes it to reflect the changed subs + sb->UpdateMaps(); + sb->SetSelectionFromAbsolute(selected_lines); + sb->CommitChanges(true, false); + sb->EndBatch(); + + // The eval's return + return wxString(SvPV_nolen(e), pl2wx); + } + + XS(PerlConsole::register_console) + { + dXSARGS; + PerlScript *script = PerlScript::GetScript(); + if(script) { + wxString name = _T("Perl console"); + wxString desc = _T("Show the Perl console"); + switch (items) { + case 2: + desc = wxString(SvPV_nolen(ST(1)), pl2wx); + case 1: + name = wxString(SvPV_nolen(ST(0)), pl2wx); + } + + if(!registered) + // If there's no registered console + script->AddFeature(new PerlConsole(name, desc, script)); + } + } + + XS(PerlConsole::echo) + { + dXSARGS; + + // We should get some parameters + if(items == 0) XSRETURN_EMPTY; + + // Join the params in a unique string :S + wxString buffer = wxString(SvPV_nolen(ST(0)), pl2wx); + for(int i = 1; i < items; i++) { + buffer << _T(" ") << wxString(SvPV_nolen(ST(i)), pl2wx); + } + + if(registered) { + // If there's a console echo to it + registered->dialog->Echo(buffer); + } + else { + // Otherwise print on stdout + PerlIO_printf(PerlIO_stdout(), "%s\n", buffer.mb_str(wxConvLocal).data()); + // (through perl io system) + } + + XSRETURN_EMPTY; + } + +}; + + +#endif //WITH_PERL diff --git a/aegisub/auto4_perl_console.h b/aegisub/auto4_perl_console.h new file mode 100644 index 000000000..d8746f9e3 --- /dev/null +++ b/aegisub/auto4_perl_console.h @@ -0,0 +1,91 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#pragma once +#ifndef _AUTO4_PERL_CONSOLE_H +#define _AUTO4_PERL_CONSOLE_H + + +#include "auto4_perl.h" +#include + + +namespace Automation4 { + + class PerlConsole : public PerlFeatureMacro { + private: + static PerlConsole *registered; + + // Nested classes are messy, therefore we use them :) + class Dialog : public wxDialog { + private: + wxTextCtrl *txt_out, *txt_hist, *txt_in; + + public: + Dialog(); + + bool Create(wxWindow* parent, wxWindowID id, const wxString& title, + const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_DIALOG_STYLE, const wxString& name = _T("console_dialog")); + + void InputEnter(wxCommandEvent& evt); + void Echo(const wxString &str); + }; + + Dialog *dialog; + wxWindow *parent_window; + + SV *cout; + wxString evaluate(const wxString &str); + + public: + PerlConsole(const wxString &name, const wxString &desc, PerlScript *script); + virtual ~PerlConsole(); + + static PerlConsole *GetConsole() { return registered; } + + virtual bool Validate(AssFile *subs, const std::vector &selected, int active) { return true; } + virtual void Process(AssFile *subs, std::vector &selected, int active, wxWindow * const progress_parent); + + static wxString Evaluate(const wxString &str) { if(registered) return registered->evaluate(str); } + static XS(register_console); + static XS(echo); + }; + +}; + + +#endif diff --git a/aegisub/auto4_perl_macro.cpp b/aegisub/auto4_perl_macro.cpp new file mode 100644 index 000000000..594af8385 --- /dev/null +++ b/aegisub/auto4_perl_macro.cpp @@ -0,0 +1,187 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#ifdef WITH_PERL + + +#include "auto4_perl.h" +#include "ass_file.h" + + +namespace Automation4 { + + +////////////////////// +// PerlFeatureMacro +// + + PerlFeatureMacro::PerlFeatureMacro(const wxString &name, const wxString &description, PerlScript *own_script, SV *proc_sub, SV *val_sub): + Feature(SCRIPTFEATURE_MACRO, name), + FeatureMacro(name, description) + { + // We know what script we belong to ^_^ + script = own_script; + + // And not surprisingly we have some callbacks too + processing_sub = newSVsv(proc_sub); + validation_sub = newSVsv(val_sub); + } + + PerlFeatureMacro::~PerlFeatureMacro() { + // The macro subroutines get undefined + /* This is crappy and creepy at the same time */ + /* TODO: thoroughly recheck the code */ + CV *cv = Nullcv; + HV *hv = NULL; + GV *gv = NULL; + if(processing_sub) { + cv = sv_2cv(processing_sub, &hv, &gv, 1); + cv_undef(cv); + if(hv) hv_undef(hv); + } + if(validation_sub) { + cv = sv_2cv(validation_sub, &hv, &gv, 1); + cv_undef(cv); + if(hv) hv_undef(hv); + } + }; + + bool PerlFeatureMacro::Validate(AssFile *subs, const std::vector &selected, int active) + { + // If there's no validation subroutine defined simply return true + if(!validation_sub) return true; + // otherwise... + + // Sub lines + AV *lines = PerlAss::MakeHasshLines(NULL, subs); + // Selection array + AV *selected_av = newAV(); + VECTOR_AV(selected, selected_av, int, iv); + + // Sync script's vars with package's + script->Activate(); + + bool ret = false; + int c = 0; + + // Prepare the stack + dSP; + + ENTER; + SAVETMPS; + + // Push the parameters on the stack + PUSHMARK(SP); + XPUSHs(sv_2mortal(newRV_noinc((SV*)lines))); + XPUSHs(sv_2mortal(newRV_noinc((SV*)selected_av))); + XPUSHs(sv_2mortal(newSViv(active))); + PUTBACK; + + // Call back the callback + c = call_sv(validation_sub, G_EVAL | G_SCALAR); + SPAGAIN; + + if(SvTRUE(ERRSV)) { + wxLogVerbose(wxString(SvPV_nolen(ERRSV), pl2wx)); + ret = false; + } + else { + SV *wtf = sv_mortalcopy(POPs); + ret = SvTRUE(wtf); + } + + // Tidy up everything + PUTBACK; + FREETMPS; + LEAVE; + + script->Deactivate(); + + return ret; + } + + void PerlFeatureMacro::Process(AssFile *subs, std::vector &selected, int active, wxWindow * const progress_parent) + { + // Reference to the hassh (lines) + AV *lines = PerlAss::MakeHasshLines(NULL, subs); + // Selection array + AV *selected_av = newAV(); + VECTOR_AV(selected, selected_av, int, iv); + + script->Activate(); + + // Prepare the stack + dSP; + + ENTER; + SAVETMPS; + + // Push the parameters on the stack + PUSHMARK(SP); + XPUSHs(sv_2mortal(newRV_noinc((SV*)lines))); + XPUSHs(sv_2mortal(newRV_noinc((SV*)selected_av))); + XPUSHs(sv_2mortal(newSViv(active))); + PUTBACK; + + // Call back the callback :) + call_sv(processing_sub, G_EVAL | G_VOID); + + if(SvTRUE(ERRSV)) { + // Error + wxLogError(wxString(SvPV_nolen(ERRSV), pl2wx)); + } + else { + // Non-error: recreate the hassh :S + subs->FlagAsModified(GetName()); + PerlAss::MakeAssLines(subs, lines); + // And reset selection vector + selected.clear(); + AV_VECTOR(selected_av, selected, IV); + CHOP_SELECTED(subs, selected); + } + + // Clean everything + FREETMPS; + LEAVE; + + script->Deactivate(); + } + + +}; + + +#endif //WITH_PERL diff --git a/aegisub/auto4_perl_misc.cpp b/aegisub/auto4_perl_misc.cpp new file mode 100644 index 000000000..169209a36 --- /dev/null +++ b/aegisub/auto4_perl_misc.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#ifdef WITH_PERL + + +#include "auto4_perl.h" + + +namespace Automation4 { + + + void xs_perl_misc(pTHX) + { + newXS("Aegisub::warn", PerlLog::log_warning, __FILE__); + newXS("Aegisub::text_extents", text_extents, __FILE__); + } + + +///////////// +// PerlLog +// + + XS(PerlLog::log_warning) + { + dXSARGS; + wxString buffer; + if(items >= 1) { + buffer = wxString(SvPV_nolen(ST(0)), wx2pl); + for(I32 i = 1; i < items; i++) { + buffer << _T(" ") << wxString(SvPV_nolen(ST(i)), wx2pl); + } + } + wxLogWarning(buffer); + } + + +//////////// +// Others +// + + XS(text_extents) + { + /* TODO badly: rewrite this shit */ + dXSARGS; + + // Read the parameters + SV *style; wxString text; + if(items >= 2) { + // Enough of them + style = sv_mortalcopy(ST(0)); + text = wxString(SvPV_nolen(ST(1)), pl2wx); + } + else { + // We needed 2 parameters at least! + XSRETURN_UNDEF; + } + + // Get the AssStyle + AssStyle *s; + if(SvROK(style)) { + // Create one from the hassh + s = PerlAss::MakeAssStyle((HV*)SvRV(style)); + } + else { + // It's the name of the style + wxString sn(SvPV_nolen(style), pl2wx); + // We get it from the AssFile::top + s = AssFile::top->GetStyle(sn); + /* TODO: make it dig from the current hassh's styles */ + } + + // The return parameters + double width, height, descent, extlead; + // The actual calculation + if(!CalculateTextExtents(s, text, width, height, descent, extlead)) { + /* TODO: diagnose error */ + XSRETURN_EMPTY; + } + + // Returns + switch(GIMME_V) { + case G_ARRAY: + // List context + EXTEND(SP, 4); + XST_mNV(0, width); + XST_mNV(1, height); + XST_mNV(2, descent); + XST_mNV(3, extlead); + XSRETURN(4); + break; + case G_SCALAR: + // Scalar context + XSRETURN_NV(width); + } + } + + +}; + + +#endif //WITH_PERL diff --git a/aegisub/auto4_perl_script.cpp b/aegisub/auto4_perl_script.cpp new file mode 100644 index 000000000..c00ee48a0 --- /dev/null +++ b/aegisub/auto4_perl_script.cpp @@ -0,0 +1,353 @@ +// Copyright (c) 2008, Simone Cociancich +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#ifdef WITH_PERL + + +#include "auto4_perl.h" +#include "auto4_perl_console.h" +#include "version.h" +#include "standard_paths.h" + + +namespace Automation4 { + + + void xs_perl_script(pTHX) + { + newXS("Aegisub::Script::set_info", PerlScript::set_info, __FILE__); + newXS("Aegisub::Script::register_macro", PerlScript::register_macro, __FILE__); + } + + +////////////////////// +// PerlScript class +// + PerlScript *PerlScript::active = NULL; + + PerlScript::PerlScript(const wxString &filename): + Script(filename) + { + // Create a package name for the script + package.Printf(_T("Aegisub::Script::p%lx"), this); + + inc_saved = newAV(); + + reload = false; + mtime = 0; + + // Load the code + load(); + } + + PerlScript::~PerlScript() + { + unload(); + } + + void PerlScript::Reload() + { + unload(); + reload = false; + load(); + } + + void PerlScript::load() + { + wxLogTrace("Loading %*s inside %s", 0, GetFilename().c_str(), package.c_str()); + + // Feed some defaults into the script info + name = GetPrettyFilename().BeforeLast(_T('.')); + description = _("Perl script"); + author = wxString(getlogin(), wxConvLibc); + version = GetAegisubShortVersionString(); + + // Get file's mtime + struct stat s; + stat(GetFilename().mb_str(wxConvLibc), &s); + mtime = s.st_mtime; + + // Create the script's package + gv_stashpv(package.mb_str(wx2pl), 1); + // Set this script as active + activate(this); + + // 'Enclose' the script into its package + wxString _script = _T("package ") + package + _T(";\n") + _T("our ($_script_reload, $_script_path, $_script_package);\n") // Internal vars + _T("our ($script_name, $script_description, $script_author, $script_version);\n") // Package info + _T("open SCRIPT, $_script_path;\n") // Open the script file + _T("local @_source =