And Automation 4 is now in the trunk!

Originally committed to SVN as r647.
This commit is contained in:
Niels Martin Hansen 2006-12-28 22:31:33 +00:00
parent 8617602bb1
commit 5f1d8c414d
26 changed files with 577 additions and 97 deletions

View File

@ -101,7 +101,7 @@ public:
const wxString& GetDescription() const;
virtual void ProcessSubs(AssFile *subs)=0; // Process subtitles - this function must be overriden.
virtual void ProcessSubs(AssFile *subs, wxWindow *export_dialog=0)=0; // Process subtitles - this function must be overriden.
virtual wxWindow *GetConfigDialogWindow(wxWindow *parent); // Draw setup controls - this function may optionally be overridden.
virtual void LoadSettings(bool IsDefault); // Config dialog is done - extract data now.
};

View File

@ -126,14 +126,14 @@ wxArrayString AssExporter::GetAllFilterNames() {
//////////
// Export
void AssExporter::Export(wxString filename, wxString charset) {
void AssExporter::Export(wxString filename, wxString charset, wxWindow *export_dialog) {
// Copy
AssFile *Subs = new AssFile(*OriginalSubs);
// Run filters
for (FilterList::iterator cur=Filters.begin();cur!=Filters.end();cur++) {
(*cur)->LoadSettings(IsDefault);
(*cur)->ProcessSubs(Subs);
(*cur)->ProcessSubs(Subs, export_dialog);
}
/*

View File

@ -74,7 +74,7 @@ public:
void AddAutoFilters();
void DrawSettings(wxWindow *parent,wxSizer *AddTo);
wxSizer *GetSettingsSizer(wxString name);
void Export(wxString file, wxString charset = _T(""));
void Export(wxString file, wxString charset, wxWindow *export_dialog);
AssFile *GetOriginalSubs() { return OriginalSubs; }
wxString GetDescription(wxString name);
};

View File

@ -183,7 +183,7 @@ void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wx
void AssFile::Export(wxString _filename) {
AssExporter exporter(this);
exporter.AddAutoFilters();
exporter.Export(_filename,_T("UTF-8"));
exporter.Export(_filename,_T("UTF-8"), 0);
}

View File

@ -501,7 +501,6 @@ void AssOverrideTag::SetText (wxString text) {
// Set tag name
if (!Name.empty()) {
wxLogDebug(_T("Parsing tag: %s"), Name.c_str());
ParseParameters(text.Mid(Name.length()));
valid = true;
}

View File

@ -768,11 +768,6 @@ namespace Automation4 {
}
}
};
LuaScriptFactory *_script_factory;
LuaScriptFactory _script_factory;
};
void Initialise_Auto4Lua()
{
Automation4::_script_factory = new Automation4::LuaScriptFactory;
}

View File

@ -238,7 +238,4 @@ namespace Automation4 {
};
// More or less dummy-function to make sure auto4_lua.cpp is linked in
void Initialise_Auto4Lua();
#endif

View File

@ -886,7 +886,7 @@ namespace Automation4 {
description = wxString(lua_tostring(L, 1), wxConvUTF8);
lua_pop(L, 1);
}
AssFile::FlagAsModified(description);
AssFile::top->FlagAsModified(); // TODO: make undo system support description of action undone
laf->ass = AssFile::top; // make sure we're still working on the most recent undo point
return 0;

295
core/dialog_automation.cpp Normal file
View File

@ -0,0 +1,295 @@
// Copyright (c) 2006, 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
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:jiifurusu@gmail.com
//
#include "main.h"
#include "dialog_automation.h"
#include "auto4_base.h"
#include "options.h"
#include <wx/filename.h>
#include <wx/filedlg.h>
DialogAutomation::DialogAutomation(wxWindow *parent, Automation4::ScriptManager *_local_manager)
: wxDialog(parent, -1, _("Automation Manager"), wxDefaultPosition, wxDefaultSize)
{
local_manager = _local_manager;
global_manager = wxGetApp().global_scripts;
// create main controls
list = new wxListView(this, Automation_List_Box, wxDefaultPosition, wxSize(600, 175), wxLC_REPORT|wxLC_SINGLE_SEL);
add_button = new wxButton(this, Automation_Add_Script, _("&Add"));
remove_button = new wxButton(this, Automation_Remove_Script, _("&Remove"));
reload_button = new wxButton(this, Automation_Reload_Script, _("Re&load"));
info_button = new wxButton(this, Automation_Show_Info, _("Show &Info"));
reload_autoload_button = new wxButton(this, Automation_Reload_Autoload, _("Re&scan Autoload Dir"));
close_button = new wxButton(this, wxID_CLOSE);
// add headers to list view
list->InsertColumn(0, _T(""), wxLIST_FORMAT_CENTER, 20);
list->InsertColumn(1, _("Name"), wxLIST_FORMAT_LEFT, 140);
list->InsertColumn(2, _("Filename"), wxLIST_FORMAT_LEFT, 90);
list->InsertColumn(3, _("Description"), wxLIST_FORMAT_LEFT, 330);
// button layout
wxSizer *button_box = new wxBoxSizer(wxHORIZONTAL);
button_box->AddStretchSpacer(2);
button_box->Add(add_button, 0);
button_box->Add(remove_button, 0);
button_box->AddSpacer(10);
button_box->Add(reload_button, 0);
button_box->Add(info_button, 0);
button_box->AddSpacer(10);
button_box->Add(reload_autoload_button, 0);
button_box->AddSpacer(10);
button_box->Add(close_button, 0);
button_box->AddStretchSpacer(2);
// main layout
wxSizer *main_box = new wxBoxSizer(wxVERTICAL);
main_box->Add(list, 1, wxEXPAND|wxALL, 5);
main_box->Add(button_box, 0, wxEXPAND|wxALL&~wxTOP, 5);
main_box->SetSizeHints(this);
SetSizer(main_box);
Center();
RebuildList();
UpdateDisplay();
}
void DialogAutomation::RebuildList()
{
script_info.clear();
list->DeleteAllItems();
// fill the list view
const std::vector<Automation4::Script*> &global_scripts = global_manager->GetScripts();
for (std::vector<Automation4::Script*>::const_iterator i = global_scripts.begin(); i != global_scripts.end(); ++i) {
ExtraScriptInfo ei;
ei.script = *i;
ei.is_global = true;
AddScript(ei);
}
const std::vector<Automation4::Script*> &local_scripts = local_manager->GetScripts();
for (std::vector<Automation4::Script*>::const_iterator i = local_scripts.begin(); i != local_scripts.end(); ++i) {
ExtraScriptInfo ei;
ei.script = *i;
ei.is_global = false;
AddScript(ei);
}
}
void DialogAutomation::AddScript(ExtraScriptInfo &ei)
{
script_info.push_back(ei);
wxListItem itm;
if (ei.is_global) {
itm.SetText(_T("G"));
} else {
itm.SetText(_T("L"));
}
itm.SetData((int)script_info.size()-1);
itm.SetId(list->GetItemCount());
int i = list->InsertItem(itm);
list->SetItem(i, 1, ei.script->GetName());
list->SetItem(i, 2, wxFileName(ei.script->GetFilename()).GetFullName());
list->SetItem(i, 3, ei.script->GetDescription());
if (ei.script->GetLoadedState() == false) {
list->SetItemBackgroundColour(i, wxColour(255,128,128));
}
}
void DialogAutomation::UpdateDisplay()
{
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
bool selected = i >= 0;
bool global = true;
if (selected) {
const ExtraScriptInfo &ei = script_info[list->GetItemData(i)];
global = ei.is_global;
}
add_button->Enable(true);
remove_button->Enable(selected && !global);
reload_button->Enable(selected);
info_button->Enable(true);
reload_autoload_button->Enable(true);
close_button->Enable(true);
}
BEGIN_EVENT_TABLE(DialogAutomation, wxDialog)
EVT_BUTTON(Automation_Add_Script,DialogAutomation::OnAdd)
EVT_BUTTON(Automation_Remove_Script,DialogAutomation::OnRemove)
EVT_BUTTON(Automation_Reload_Script,DialogAutomation::OnReload)
EVT_BUTTON(Automation_Show_Info,DialogAutomation::OnInfo)
EVT_BUTTON(Automation_Reload_Autoload,DialogAutomation::OnReloadAutoload)
EVT_BUTTON(wxID_CLOSE,DialogAutomation::OnClose)
EVT_LIST_ITEM_SELECTED(Automation_List_Box,DialogAutomation::OnSelectionChange)
EVT_LIST_ITEM_DESELECTED(Automation_List_Box,DialogAutomation::OnSelectionChange)
END_EVENT_TABLE()
void DialogAutomation::OnAdd(wxCommandEvent &evt)
{
// build filename filter list
wxString fnfilter;
const std::vector<Automation4::ScriptFactory*> &factories = Automation4::ScriptFactory::GetFactories();
for (int i = 0; i < (int)factories.size(); i++) {
const Automation4::ScriptFactory *fact = factories[i];
if (fact->GetEngineName().IsEmpty() || fact->GetFilenamePattern().IsEmpty())
continue;
fnfilter = wxString::Format(_T("%s%s scripts|%s|"), fnfilter.c_str(), fact->GetEngineName().c_str(), fact->GetFilenamePattern().c_str());
}
#ifdef __WINDOWS__
fnfilter += _T("All files|*.*");
#else
fnfilter += _T("All files|*");
#endif
wxString fname = wxFileSelector(_("Add Automation script"), Options.AsText(_T("Last open automation path")), wxEmptyString, wxEmptyString, fnfilter, wxOPEN|wxFILE_MUST_EXIST, this);
if (!fname.IsEmpty()) {
wxFileName fnpath(fname);
Options.SetText(_T("Last open automation path"), fnpath.GetPath());
// TODO: make sure each script is only loaded once. check in both local and global managers!!
// it doesn't break for macros, but will for export filters, and maybe for file formats,
// and makes for confusion in the UI anyhow
try {
ExtraScriptInfo ei;
ei.script = Automation4::ScriptFactory::CreateFromFile(fname);
local_manager->Add(ei.script);
ei.is_global = false;
AddScript(ei);
}
catch (const wchar_t *e) {
wxLogError(e);
}
catch (...) {
wxLogError(_T("Unknown error loading script"));
}
}
}
void DialogAutomation::OnRemove(wxCommandEvent &evt)
{
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (i < 0) return;
const ExtraScriptInfo &ei = script_info[list->GetItemData(i)];
if (ei.is_global) return;
list->DeleteItem(i);
local_manager->Remove(ei.script);
// don't bother doing anything in script_info, it's relatively short-lived, and having any indexes change would break stuff
list->Select(i);
}
void DialogAutomation::OnReload(wxCommandEvent &evt)
{
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (i < 0) return;
const ExtraScriptInfo &ei = script_info[list->GetItemData(i)];
try {
ei.script->Reload();
}
catch (const wchar_t *e) {
wxMessageBox(e, _T("Error reloading Automation script"), wxOK|wxICON_ERROR, this);
}
catch (...) {
wxMessageBox(_T("An unknown error occurred reloading Automation script."), _T("Error reloading Automation script"), wxOK|wxICON_ERROR, this);
}
list->SetItem(i, 1, ei.script->GetName());
list->SetItem(i, 2, wxFileName(ei.script->GetFilename()).GetFullName());
list->SetItem(i, 3, ei.script->GetDescription());
if (ei.script->GetLoadedState() == false) {
list->SetItemBackgroundColour(i, wxColour(255,128,128));
}
}
void DialogAutomation::OnInfo(wxCommandEvent &evt)
{
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
ExtraScriptInfo *ei = 0;
if (i >= 0)
ei = &script_info[list->GetItemData(i)];
wxString info = wxString::Format(
_("Total scripts loaded: %d\nGlobal scripts loaded: %d\nLocal scripts loaded: %d\n\n"),
local_manager->GetScripts().size() + global_manager->GetScripts().size(),
global_manager->GetScripts().size(),
local_manager->GetScripts().size());
info += _("Scripting engines installed:\n");
const std::vector<Automation4::ScriptFactory*> &factories = Automation4::ScriptFactory::GetFactories();
for (std::vector<Automation4::ScriptFactory*>::const_iterator i = factories.begin(); i != factories.end(); ++i) {
info += wxString::Format(_T("- %s (%s)\n"), (*i)->GetEngineName().c_str(), (*i)->GetFilenamePattern().c_str());
}
if (ei) {
info += wxString::Format(_("\nScript info:\nName: %s\nDescription: %s\nAuthor: %s\nVersion: %s\nFull path: %s\nCorrectly initialised: %s"),
ei->script->GetName().c_str(),
ei->script->GetDescription().c_str(),
ei->script->GetAuthor().c_str(),
ei->script->GetVersion().c_str(),
ei->script->GetFilename().c_str(),
ei->script->GetLoadedState() ? _("Yes") : _("No"));
}
wxMessageBox(info, _("Automation Script Info"));
}
void DialogAutomation::OnReloadAutoload(wxCommandEvent &evt)
{
global_manager->Reload();
RebuildList();
UpdateDisplay();
}
void DialogAutomation::OnClose(wxCommandEvent &evt)
{
EndModal(0);
}
void DialogAutomation::OnSelectionChange(wxListEvent &evt)
{
UpdateDisplay();
}

94
core/dialog_automation.h Normal file
View File

@ -0,0 +1,94 @@
// 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
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
#pragma once
#ifndef DIALOG_AUTOMATION_H
#define DIALOG_AUTOMATION_H
#include <wx/dialog.h>
#include <wx/listctrl.h>
#include <wx/button.h>
#include <vector>
namespace Automation4 { class ScriptManager; class Script; };
class DialogAutomation : public wxDialog {
private:
struct ExtraScriptInfo {
Automation4::Script *script;
bool is_global;
};
std::vector<ExtraScriptInfo> script_info;
Automation4::ScriptManager *local_manager;
Automation4::AutoloadScriptManager *global_manager;
wxListView *list;
wxButton *add_button;
wxButton *remove_button;
wxButton *reload_button;
wxButton *info_button;
wxButton *reload_autoload_button;
wxButton *close_button;
void RebuildList();
void AddScript(ExtraScriptInfo &ei);
void UpdateDisplay();
void OnAdd(wxCommandEvent &evt);
void OnRemove(wxCommandEvent &evt);
void OnReload(wxCommandEvent &evt);
void OnInfo(wxCommandEvent &evt);
void OnClose(wxCommandEvent &evt);
void OnReloadAutoload(wxCommandEvent &evt);
void OnSelectionChange(wxListEvent &evt);
public:
DialogAutomation(wxWindow *parent, Automation4::ScriptManager *_local_manager);
DECLARE_EVENT_TABLE()
};
enum {
Automation_List_Box = 1000,
Automation_Add_Script,
Automation_Remove_Script,
Automation_Reload_Script,
Automation_Show_Info,
Automation_Reload_Autoload
};
#endif

View File

@ -182,7 +182,6 @@ END_EVENT_TABLE()
// Process start
void DialogExport::OnProcess(wxCommandEvent &event) {
// Get destination
//wxString filename = wxFileSelector(_("Export subtitles file"),_T(""),_T(""),_T(""),_T("All Supported Types (*.ass,*.ssa,*.srt,*.prs)|*.ass;*.ssa;*.srt;*.prs|Advanced Substation Alpha (*.ass)|*.ass|Substation Alpha (*.ssa)|*.ssa|SubRip (*.srt)|*.srt|Plain-text (*.txt)|*.txt|Pre-Rendered Subtitles (*.prs)|*.prs"),wxSAVE | wxOVERWRITE_PROMPT,this);
wxString filename = wxFileSelector(_("Export subtitles file"),_T(""),_T(""),_T(""),AssFile::GetWildcardList(2),wxSAVE | wxOVERWRITE_PROMPT,this);
if (filename.empty()) return;
@ -195,8 +194,9 @@ void DialogExport::OnProcess(wxCommandEvent &event) {
// Export
try {
wxBusyCursor busy;
Export->GetOriginalSubs()->SetScriptInfo(_T("Export Encoding"), CharsetList->GetStringSelection());
Export->Export(filename, CharsetList->GetStringSelection());
Export->Export(filename, CharsetList->GetStringSelection(), this);
}
catch (const wchar_t *error) {
wxString err(error);

View File

@ -62,7 +62,7 @@ void AssTransformCleanInfoFilter::Init() {
///////////
// Process
void AssTransformCleanInfoFilter::ProcessSubs(AssFile *subs) {
void AssTransformCleanInfoFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog) {
using std::list;
AssEntry *curEntry;
entryIter cur, next = subs->Line.begin();

View File

@ -52,14 +52,7 @@ private:
void Init();
public:
void ProcessSubs(AssFile *subs);
void ProcessSubs(AssFile *subs, wxWindow *export_dialog);
wxWindow *GetConfigDialogWindow(wxWindow *parent);
void LoadSettings(bool IsDefault);
};
///////
// IDs
enum {
Get_Input_From_Video = 2000
};

View File

@ -62,7 +62,7 @@ void AssFixStylesFilter::Init() {
///////////
// Process
void AssFixStylesFilter::ProcessSubs(AssFile *subs) {
void AssFixStylesFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog) {
// Build styles list
wxArrayString styles = subs->GetStyles();
size_t n = styles.Count();

View File

@ -51,5 +51,5 @@ private:
void Init();
public:
void ProcessSubs(AssFile *subs);
void ProcessSubs(AssFile *subs, wxWindow *export_dialog);
};

View File

@ -65,7 +65,7 @@ void AssTransformFramerateFilter::Init() {
///////////
// Process
void AssTransformFramerateFilter::ProcessSubs(AssFile *subs) {
void AssTransformFramerateFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog) {
// Transform frame rate
if (Input->IsLoaded() && Output->IsLoaded()) {
if (Output->GetFrameRateType() == VFR || Output->GetAverage() != Input->GetAverage()) {

View File

@ -68,7 +68,7 @@ private:
void Init();
public:
void ProcessSubs(AssFile *subs);
void ProcessSubs(AssFile *subs, wxWindow *export_dialog);
wxWindow *GetConfigDialogWindow(wxWindow *parent);
void LoadSettings(bool IsDefault);
};

View File

@ -58,7 +58,6 @@
#include "version.h"
#include "dialog_splash.h"
#include "dialog_tip.h"
//#include "automation_filter.h"
#include "audio_box.h"
#include "video_box.h"
#include "drop.h"
@ -66,6 +65,7 @@
#include "utils.h"
#include "text_file_reader.h"
#include "text_file_writer.h"
#include "auto4_base.h"
/////////////////////////
@ -84,12 +84,15 @@ FrameMain::FrameMain (wxArrayString args)
wxPNGHandler *png = new wxPNGHandler;
wxImage::AddHandler(png);
// Storage for subs-file-local scripts
local_scripts = new Automation4::ScriptManager();
// Create menu and tool bars
InitToolbar();
InitMenu();
// Create status bar
CreateStatusBar(2);
CreateStatusBar(2);
// Set icon
SetIcon(wxICON(wxicon));
@ -137,6 +140,7 @@ FrameMain::FrameMain (wxArrayString args)
// FrameMain destructor
FrameMain::~FrameMain () {
DeInitContents();
delete local_scripts;
}
@ -387,6 +391,7 @@ void FrameMain::InitMenu() {
// Create Automation menu
automationMenu = new wxMenu();
AppendBitmapMenuItem (automationMenu,Menu_Tools_Automation, _("&Automation..."),_("Open automation manager"), wxBITMAP(automation_toolbutton));
automationMenu->AppendSeparator();
MenuBar->Append(automationMenu, _("&Automation"));
// Create help menu
@ -596,10 +601,6 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
wxMessageBox(wxString(err), _T("Error"), wxOK | wxICON_ERROR, NULL);
return;
}
// catch (AutomationError &err) {
// wxMessageBox(wxString(_T("Automation exception: ")) + err.message, _T("Error"), wxOK | wxICON_ERROR, NULL);
// return;
// }
catch (...) {
wxMessageBox(_T("Unknown error"), _T("Error"), wxOK | wxICON_ERROR, NULL);
return;
@ -808,15 +809,6 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
long videoAr = 0;
double videoArValue = 0.0;
long videoZoom = 0;
// {
// std::list<AssAutomationFilter*>::const_iterator next = AssAutomationFilter::GetFilterList().begin(), f;
// while (next != AssAutomationFilter::GetFilterList().end()) {
// f = next++;
// AutomationScript *s = (*f)->GetScript();
// delete (*f);
// delete s;
// }
// }
// Get AR
wxString arString = subs->GetScriptInfo(_T("Video Aspect Ratio"));
@ -836,40 +828,15 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
wxString curSubsAudio = DecodeRelativePath(subs->GetScriptInfo(_T("Audio File")),AssFile::top->filename);
wxString AutoScriptString = subs->GetScriptInfo(_T("Automation Scripts"));
// Automation script
/* if (AutoScriptString != _T("")) {
wxStringTokenizer toker(AutoScriptString, _T("|"), wxTOKEN_STRTOK);
wxFileName AssFileName(subs->filename);
while (toker.HasMoreTokens()) {
wxString sfnames;
try {
sfnames = toker.GetNextToken().Trim(false).Trim(true);
wxFileName sfname(sfnames);
sfname.Normalize(wxPATH_NORM_ALL, AssFileName.GetPath());
sfnames = sfname.GetFullPath();
AutomationScriptFile *sfile = AutomationScriptFile::CreateFromFile(sfnames);
if (!sfile) {
wxLogWarning(_T("Automation script referenced in subtitle file not found: %s"), sfname.GetName().c_str());
continue;
}
//AssAutomationFilters are added to a global list when constructed, this is not a leak
new AssAutomationFilter(new AutomationScript(sfile));
}
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 (...) {
wxMessageBox(_T("An unknown error occurred loading an Automation script referenced in the subtitle file."), _T("Error loading Automation script"), wxOK | wxICON_ERROR, this);
continue;
}
}
}*/
// Check if there is anything to change
int autoLoadMode = Options.AsInt(_T("Autoload linked files"));
bool hasToLoad = false;
if (curSubsAudio != audioBox->audioName || curSubsVFR != VFR_Output.GetFilename() || curSubsVideo != videoBox->videoDisplay->videoName || curSubsKeyframes != videoBox->videoDisplay->GetKeyFramesName()) {
if (curSubsAudio != audioBox->audioName ||
curSubsVFR != VFR_Output.GetFilename() ||
curSubsVideo != videoBox->videoDisplay->videoName ||
curSubsKeyframes != videoBox->videoDisplay->GetKeyFramesName() ||
!AutoScriptString.IsEmpty() ||
local_scripts->GetScripts().size() > 0) {
hasToLoad = true;
}
@ -907,6 +874,38 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
if (curSubsAudio == _T("?video")) LoadAudio(_T(""),true);
else LoadAudio(curSubsAudio);
}
// Automation scripts
local_scripts->RemoveAll();
wxStringTokenizer tok(AutoScriptString, _T("|"), wxTOKEN_STRTOK);
wxFileName subsfn(subs->filename);
wxString autobasefn(Options.AsText(_T("Automation Base Path")));
while (tok.HasMoreTokens()) {
wxString sfnames = tok.GetNextToken().Trim(true).Trim(false);
wxString sfnamel = sfnames.Left(1);
sfnames.Remove(0, 1);
wxString basepath;
if (sfnamel == _T("~")) {
basepath = subsfn.GetPath();
} else if (sfnamel == _T("$")) {
basepath = autobasefn;
} else if (sfnamel == _T("/")) {
basepath = _T("");
} else {
wxLogWarning(_T("Automation Script referenced with unknown location specifier character.\nLocation specifier found: %s\nFilename specified: %s"),
sfnamel.c_str(), sfnames.c_str());
continue;
}
wxFileName sfname(sfnames);
sfname.MakeAbsolute(basepath);
if (sfname.FileExists()) {
sfnames = sfname.GetFullPath();
local_scripts->Add(Automation4::ScriptFactory::CreateFromFile(sfnames));
} else {
wxLogWarning(_T("Automation Script referenced could not be found.\nFilename specified: %s%s\nSearched relative to: %s\nResolved filename: %s"),
sfnamel.c_str(), sfnames.c_str(), basepath.c_str(), sfname.GetFullPath().c_str());
}
}
}
// Display
@ -939,21 +938,38 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
subs->SetScriptInfo(_T("VFR File"),MakeRelativePath(VFR_Output.GetFilename(),AssFile::top->filename));
subs->SetScriptInfo(_T("Keyframes File"),MakeRelativePath(videoBox->videoDisplay->GetKeyFramesName(),AssFile::top->filename));
// Create list of Automation scripts
/* wxString scripts;
std::list<AssAutomationFilter*>::const_iterator f = AssAutomationFilter::GetFilterList().begin();
wxFileName AssFileName(subs->filename);
for (;f != AssAutomationFilter::GetFilterList().end(); ++f) {
if (!(*f)->GetScript()->filename.empty()) {
wxFileName fn((*f)->GetScript()->filename);
fn.MakeRelativeTo(AssFileName.GetPath());
scripts += wxString::Format(_T("%s|"), fn.GetFullPath().c_str());
// Store Automation script data
// Algorithm:
// 1. If script filename has Automation Base Path as a prefix, the path is relative to that (ie. "$")
// 2. Otherwise try making it relative to the subs filename
// 3. If step 2 failed, or absolut path is shorter than path relative to subs, use absolute path ("/")
// 4. Otherwise, use path relative to subs ("~")
wxString scripts_string;
wxString autobasefn(Options.AsText(_T("Automation Base Path")));
const std::vector<Automation4::Script*> &scripts = local_scripts->GetScripts();
for (int i = 0; i < scripts.size(); i++) {
Automation4::Script *script = scripts[i];
if (i != 0)
scripts_string += _T("|");
wxString autobase_rel, subsfile_rel;
wxString scriptfn(script->GetFilename());
autobase_rel = MakeRelativePath(scriptfn, autobasefn);
subsfile_rel = MakeRelativePath(scriptfn, AssFile::top->filename);
if (autobase_rel.size() <= scriptfn.size() && autobase_rel.size() <= subsfile_rel.size()) {
scriptfn = _T("$") + autobase_rel;
} else if (subsfile_rel.size() <= scriptfn.size() && subsfile_rel.size() <= autobase_rel.size()) {
scriptfn = _T("~") + subsfile_rel;
} else {
scriptfn = _T("/") + wxFileName(scriptfn).GetFullPath(wxPATH_UNIX);
}
scripts_string += scriptfn;
}
if (!scripts.empty()) {
scripts.RemoveLast();
subs->SetScriptInfo(_T("Automation Scripts"), scripts);
}*/
subs->SetScriptInfo(_T("Automation 4 Scripts"), scripts_string);
}
}

View File

@ -41,6 +41,7 @@
///////////////////
// Include headers
#include <wx/wxprec.h>
#include <vector>
////////////////////
@ -53,6 +54,7 @@ class SubsEditBox;
class AudioBox;
class VideoBox;
class AegisubFileDropTarget;
namespace Automation4 { class FeatureMacro; class ScriptManager; };
////////////////////
@ -96,6 +98,11 @@ private:
wxWindow *PreviousFocus;
Automation4::ScriptManager *local_scripts;
std::vector<Automation4::FeatureMacro*> activeMacroItems;
void AddMacroMenuItems(wxMenu *menu, const std::vector<Automation4::FeatureMacro*> &macros);
void InitToolbar();
void InitContents();
void DeInitContents();
@ -197,7 +204,6 @@ private:
void OnOpenTranslation (wxCommandEvent &event);
void OnOpenSpellCheck (wxCommandEvent &event);
void OnOpenFontsCollector (wxCommandEvent &event);
void OnOpenAutomation (wxCommandEvent &event);
void OnSnapSubsStartToVid (wxCommandEvent &event);
void OnSnapSubsEndToVid (wxCommandEvent &event);
void OnSnapVidToSubsStart (wxCommandEvent &event);
@ -213,6 +219,9 @@ private:
void OnOpenOptions (wxCommandEvent &event);
void OnGridEvent (wxCommandEvent &event);
void OnOpenAutomation (wxCommandEvent &event);
void OnAutomationMacro(wxCommandEvent &event);
void OnNextFrame(wxCommandEvent &event);
void OnPrevFrame(wxCommandEvent &event);
void OnFocusSeek(wxCommandEvent &event);
@ -405,6 +414,7 @@ enum {
Menu_Audio_Recent = 2400,
Menu_Timecodes_Recent = 2500,
Menu_Keyframes_Recent = 2600,
Menu_Automation_Macro = 2700,
};

View File

@ -63,7 +63,6 @@
#include "main.h"
#include "dialog_fonts_collector.h"
#include "dialog_about.h"
//#include "automation_gui.h"
#include "dialog_export.h"
#include "audio_box.h"
#include "dialog_selection.h"
@ -82,6 +81,8 @@
#include "dialog_progress.h"
#include "dialog_options.h"
#include "utils.h"
#include "auto4_base.h"
#include "dialog_automation.h"
////////////////////
@ -121,6 +122,7 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame)
EVT_MENU_RANGE(Menu_Audio_Recent,Menu_Audio_Recent+99, FrameMain::OnOpenRecentAudio)
EVT_MENU_RANGE(Menu_Timecodes_Recent,Menu_Timecodes_Recent+99, FrameMain::OnOpenRecentTimecodes)
EVT_MENU_RANGE(Menu_Keyframes_Recent,Menu_Keyframes_Recent+99, FrameMain::OnOpenRecentKeyframes)
EVT_MENU_RANGE(Menu_Automation_Macro,Menu_Automation_Macro+99, FrameMain::OnAutomationMacro)
EVT_MENU_RANGE(MENU_GRID_START+1,MENU_GRID_END-1,FrameMain::OnGridEvent)
EVT_MENU(Menu_File_Exit, FrameMain::OnExit)
@ -235,6 +237,15 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
//Freeze();
wxMenu *curMenu = event.GetMenu();
// Start by cleaning up in macro menu items
for (int i = 0; i < activeMacroItems.size(); i++) {
wxMenu *p = 0;
wxMenuItem *it = MenuBar->FindItem(Menu_Automation_Macro + i, &p);
if (it)
p->Delete(it);
}
activeMacroItems.clear();
// File menu
if (curMenu == fileMenu) {
// Wipe recent
@ -472,10 +483,33 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
MenuBar->Enable(Menu_Edit_Paste_Over,state);
}
// Automation menu
else if (curMenu == automationMenu) {
AddMacroMenuItems(automationMenu, wxGetApp().global_scripts->GetMacros(Automation4::MACROMENU_ALL));
AddMacroMenuItems(automationMenu, local_scripts->GetMacros(Automation4::MACROMENU_ALL));
}
//Thaw();
}
//////////////////////////////
// Macro menu creation helper
void FrameMain::AddMacroMenuItems(wxMenu *menu, const std::vector<Automation4::FeatureMacro*> &macros) {
if (macros.empty()) {
return;
}
int id = activeMacroItems.size();;
for (std::vector<Automation4::FeatureMacro*>::const_iterator i = macros.begin(); i != macros.end(); ++i) {
wxMenuItem * m = menu->Append(Menu_Automation_Macro + id, (*i)->GetName(), (*i)->GetDescription());
m->Enable((*i)->Validate(SubsBox->ass, SubsBox->GetAbsoluteSelection(), SubsBox->GetFirstSelRow()));
activeMacroItems.push_back(*i);
id++;
}
}
///////////////////////////////
// Open recent subs menu entry
void FrameMain::OnOpenRecentSubs(wxCommandEvent &event) {
@ -919,9 +953,18 @@ void FrameMain::OnOpenOptions (wxCommandEvent &event) {
// Open Automation
void FrameMain::OnOpenAutomation (wxCommandEvent &event) {
videoBox->videoDisplay->Stop();
// DialogAutomationManager *automan = new DialogAutomationManager(this, SubsBox);
// automan->ShowModal();
// delete automan;
DialogAutomation dlg(this, local_scripts);
dlg.ShowModal();
}
///////////////////////////////////////////////////////////
// General handler for all Automation-generated menu items
void FrameMain::OnAutomationMacro (wxCommandEvent &event) {
AssFile *oldtop = AssFile::top;
activeMacroItems[event.GetId()-Menu_Automation_Macro]->Process(SubsBox->ass, SubsBox->GetAbsoluteSelection(), SubsBox->GetFirstSelRow(), this);
// check if modifications were made and put on undo stack
SubsBox->LoadFromAss(AssFile::top, true, true);
}

View File

@ -53,6 +53,7 @@
#include "ass_time.h"
#include "ass_dialogue.h"
#include "subs_grid.h"
#include "auto4_base.h"
///////////////////
@ -100,6 +101,9 @@ bool AegisubApp::OnInit() {
locale.Init(wxLocale::GetSystemLanguage());
#endif
// Load Automation scripts
global_scripts = new Automation4::AutoloadScriptManager(Options.AsText(_T("Automation Autoload Path")));
// Load export filters
AssExportFilterChain::PrepareFilters();

View File

@ -49,6 +49,7 @@
//////////////
// Prototypes
class FrameMain;
namespace Automation4 { class AutoloadScriptManager; }
////////////////////////////////
@ -61,6 +62,7 @@ private:
public:
AegisubLocale locale;
FrameMain *frame;
Automation4::AutoloadScriptManager *global_scripts;
static wxString fullPath;
static wxString folderName;
@ -87,6 +89,8 @@ public:
DECLARE_EVENT_TABLE()
};
DECLARE_APP(AegisubApp)
////////////////
// Stack walker

View File

@ -127,7 +127,10 @@ void OptionsManager::LoadDefaults() {
SetText(_T("Audio Downmixer"),_T("ConvertToMono"));
// Automation
SetText(_T("Automation Include Path"), AegisubApp::folderName + _T("automation/include"));
SetText(_T("Automation Base Path"), AegisubApp::folderName + _T("automation/"));
SetText(_T("Automation Include Path"), AegisubApp::folderName + _T("automation/include/"));
SetText(_T("Automation Autoload Path"), AegisubApp::folderName + _T("automation/autoload/"));
SetInt(_T("Automation Trace Level"), 3);
// Edit box cosmetic
SetBool(_T("Syntax Highlight Enabled"),true);

View File

@ -1390,3 +1390,28 @@ void SubtitlesGrid::SetVideoToSubs(bool start) {
video->JumpToFrame(VFR_Output.GetFrameAtTime(cur->End.GetMS(),false));
}
}
/////////////////////////////////////////////////////////////////////
// Retrieve a list of selected lines in the actual ASS file
// (ie. not as displayed in the grid but as represented in the file)
std::vector<int> SubtitlesGrid::GetAbsoluteSelection() {
std::vector<int> result;
result.reserve(GetNumberSelection());
int nrows = GetRows();
for (int i = 0; i != nrows; ++i) {
if (selMap.at(i)) {
entryIter l = diagMap.at(i);
int n = 0;
for (std::list<AssEntry*>::iterator j = ass->Line.begin(); j != ass->Line.end(); ++j, ++n) {
if (j == l) {
result.push_back(n);
break;
}
}
}
}
return result;
}

View File

@ -128,6 +128,8 @@ public:
void CutLines(wxArrayInt lines);
void PasteLines(int pos,bool over=false);
std::vector<int> GetAbsoluteSelection();
DECLARE_EVENT_TABLE()
};

View File

@ -110,7 +110,7 @@ wxString DecodeRelativePath(wxString _path,wxString reference) {
wxFileName path(_path);
wxFileName refPath(reference);
if (!path.IsAbsolute()) path.MakeAbsolute(refPath.GetPath());
return path.GetFullPath();
return path.GetFullPath(wxPATH_UNIX); // also works on windows
}