forked from mia/Aegisub
Ruby: scripts run in a separate thread
Originally committed to SVN as r921.
This commit is contained in:
parent
6da6f1bc57
commit
2f52b36910
5 changed files with 102 additions and 43 deletions
|
@ -366,9 +366,7 @@ namespace Automation4 {
|
||||||
|
|
||||||
if (script_finished) {
|
if (script_finished) {
|
||||||
if (!debug_visible) {
|
if (!debug_visible) {
|
||||||
if(IsModal())
|
|
||||||
EndModal(0);
|
EndModal(0);
|
||||||
else Show(false);
|
|
||||||
} else {
|
} else {
|
||||||
cancel_button->Enable(true);
|
cancel_button->Enable(true);
|
||||||
cancel_button->SetLabel(_("Close"));
|
cancel_button->SetLabel(_("Close"));
|
||||||
|
@ -452,10 +450,7 @@ namespace Automation4 {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
cancel_button->Enable(false);
|
cancel_button->Enable(false);
|
||||||
} else {
|
} else {
|
||||||
if(this->IsModal())
|
|
||||||
EndModal(0);
|
EndModal(0);
|
||||||
else
|
|
||||||
Show(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,7 @@ namespace Automation4 {
|
||||||
void OnIdle(wxIdleEvent &evt);
|
void OnIdle(wxIdleEvent &evt);
|
||||||
void OnConfigDialog(ShowConfigDialogEvent &evt);
|
void OnConfigDialog(ShowConfigDialogEvent &evt);
|
||||||
|
|
||||||
|
void DoUpdateDisplay();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
volatile bool cancelled;
|
volatile bool cancelled;
|
||||||
|
@ -241,7 +242,6 @@ namespace Automation4 {
|
||||||
virtual ~ProgressSink();
|
virtual ~ProgressSink();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void DoUpdateDisplay();
|
|
||||||
void SetProgress(float _progress);
|
void SetProgress(float _progress);
|
||||||
void SetTask(const wxString &_task);
|
void SetTask(const wxString &_task);
|
||||||
void SetTitle(const wxString &_title);
|
void SetTitle(const wxString &_title);
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace Automation4 {
|
||||||
RubyScript * RubyScript::inst = NULL; // current Ruby Script
|
RubyScript * RubyScript::inst = NULL; // current Ruby Script
|
||||||
RubyProgressSink* RubyProgressSink::inst = NULL;
|
RubyProgressSink* RubyProgressSink::inst = NULL;
|
||||||
VALUE RubyScript::RubyAegisub;
|
VALUE RubyScript::RubyAegisub;
|
||||||
RubyAssFile *RubyAssFile::raf = NULL;
|
// RubyAssFile *RubyAssFile::raf = NULL;
|
||||||
|
|
||||||
// RubyScriptReader
|
// RubyScriptReader
|
||||||
RubyScriptReader::RubyScriptReader(const wxString &filename)
|
RubyScriptReader::RubyScriptReader(const wxString &filename)
|
||||||
|
@ -137,7 +137,8 @@ namespace Automation4 {
|
||||||
rb_protect(rbLoadWrapper, rb_str_new2(t), &status);
|
rb_protect(rbLoadWrapper, rb_str_new2(t), &status);
|
||||||
if(status > 0) // something bad happened (probably parsing error)
|
if(status > 0) // something bad happened (probably parsing error)
|
||||||
{
|
{
|
||||||
//throw StringValueCStr(ruby_errinfo);
|
VALUE err = rb_errinfo();
|
||||||
|
throw StringValueCStr(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE global_var = rb_gv_get("$script_name");
|
VALUE global_var = rb_gv_get("$script_name");
|
||||||
|
@ -281,11 +282,20 @@ namespace Automation4 {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
RubyProgressSink::inst = NULL;
|
||||||
RubyAssFile *subsobj = new RubyAssFile(subs, true, true);
|
RubyAssFile *subsobj = new RubyAssFile(subs, true, true);
|
||||||
VALUE sel = CreateIntegerArray(selected); // selected items
|
VALUE *argv = ALLOCA_N(VALUE, 3);
|
||||||
RubyObjects::Get()->Register(sel);
|
argv[0] = subsobj->rbAssFile;
|
||||||
VALUE result = rbFunCall(rb_mKernel, rb_to_id(validation_fun), 3, subsobj->rbAssFile, sel, rb_int2inum(active));
|
argv[1] = CreateIntegerArray(selected); // selected items;
|
||||||
RubyObjects::Get()->Unregister(sel);
|
argv[2] = INT2FIX(active);
|
||||||
|
RubyCallArguments arg(rb_mKernel, rb_to_id(validation_fun), 3, argv);
|
||||||
|
VALUE result;
|
||||||
|
RubyThreadedCall call(&arg, &result);
|
||||||
|
wxThread::ExitCode code = call.Wait();
|
||||||
|
if(code)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if(result != Qnil && result != Qfalse)
|
if(result != Qnil && result != Qfalse)
|
||||||
return true;
|
return true;
|
||||||
}catch (const char* e) {
|
}catch (const char* e) {
|
||||||
|
@ -302,26 +312,67 @@ namespace Automation4 {
|
||||||
delete RubyProgressSink::inst;
|
delete RubyProgressSink::inst;
|
||||||
RubyProgressSink::inst = new RubyProgressSink(progress_parent, false);
|
RubyProgressSink::inst = new RubyProgressSink(progress_parent, false);
|
||||||
RubyProgressSink::inst->SetTitle(GetName());
|
RubyProgressSink::inst->SetTitle(GetName());
|
||||||
RubyProgressSink::inst->Show(true);
|
|
||||||
|
|
||||||
// do call
|
// do call
|
||||||
RubyAssFile *subsobj = new RubyAssFile(subs, true, true);
|
RubyAssFile *subsobj = new RubyAssFile(subs, true, true);
|
||||||
VALUE sel = CreateIntegerArray(selected); // selected items
|
VALUE *argv = ALLOCA_N(VALUE, 3);
|
||||||
RubyObjects::Get()->Register(sel);
|
argv[0] = subsobj->rbAssFile;
|
||||||
VALUE result = rbFunCall(rb_mKernel, rb_to_id(macro_fun), 3, subsobj->rbAssFile, sel, rb_int2inum(active));
|
argv[1] = CreateIntegerArray(selected); // selected items;
|
||||||
RubyObjects::Get()->Unregister(sel);
|
argv[2] = INT2FIX(active);
|
||||||
if(result != Qnil && result != Qfalse)
|
RubyCallArguments arg(rb_mKernel, rb_to_id(macro_fun), 3, argv);
|
||||||
|
VALUE result;
|
||||||
|
RubyThreadedCall call(&arg, &result);
|
||||||
|
RubyProgressSink::inst->ShowModal();
|
||||||
|
wxThread::ExitCode code = call.Wait();
|
||||||
|
RubyProgressSink::inst = NULL;
|
||||||
|
if(code)
|
||||||
|
{
|
||||||
|
if(TYPE(result) == T_STRING)
|
||||||
|
throw StringValueCStr(result);
|
||||||
|
else throw "Unknown Error";
|
||||||
|
}
|
||||||
|
else if(result != Qnil && result != Qfalse)
|
||||||
{
|
{
|
||||||
subsobj->RubyUpdateAssFile(result);
|
subsobj->RubyUpdateAssFile(result);
|
||||||
}
|
}
|
||||||
|
delete subsobj;
|
||||||
} catch (const char* e) {
|
} catch (const char* e) {
|
||||||
wxString *err = new wxString(e, wxConvUTF8);
|
wxString *err = new wxString(e, wxConvUTF8);
|
||||||
wxMessageBox(*err, _T("Error running macro"),wxICON_ERROR | wxOK);
|
wxMessageBox(*err, _T("Error running macro"),wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
RubyProgressSink::inst->script_finished = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RubyThreadedCall::RubyThreadedCall(RubyCallArguments *a, VALUE *res)
|
||||||
|
: wxThread(wxTHREAD_JOINABLE)
|
||||||
|
,args(a), result(res)
|
||||||
|
{
|
||||||
|
int prio = Options.AsInt(_T("Automation Thread Priority"));
|
||||||
|
if (prio == 0) prio = 50; // normal
|
||||||
|
else if (prio == 1) prio = 30; // below normal
|
||||||
|
else if (prio == 2) prio = 10; // lowest
|
||||||
|
else prio = 50; // fallback normal
|
||||||
|
Create();
|
||||||
|
SetPriority(prio);
|
||||||
|
Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxThread::ExitCode RubyThreadedCall::Entry()
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
*result = rb_protect(rbCallWrapper, reinterpret_cast<VALUE>(args), &error);
|
||||||
|
if(RubyProgressSink::inst)
|
||||||
|
{
|
||||||
|
RubyProgressSink::inst->script_finished = true;
|
||||||
|
wxWakeUpIdle();
|
||||||
|
}
|
||||||
|
if(error) {
|
||||||
|
*result = rb_errinfo();
|
||||||
|
return (wxThread::ExitCode)1;
|
||||||
|
}
|
||||||
|
return (wxThread::ExitCode)0;
|
||||||
|
}
|
||||||
|
|
||||||
// RubyFeatureFilter
|
// RubyFeatureFilter
|
||||||
RubyFeatureFilter::RubyFeatureFilter(const wxString &_name, const wxString &_description,
|
RubyFeatureFilter::RubyFeatureFilter(const wxString &_name, const wxString &_description,
|
||||||
int merit, VALUE _filter_fun, VALUE _dialog_fun)
|
int merit, VALUE _filter_fun, VALUE _dialog_fun)
|
||||||
|
@ -363,19 +414,32 @@ namespace Automation4 {
|
||||||
delete RubyProgressSink::inst;
|
delete RubyProgressSink::inst;
|
||||||
RubyProgressSink::inst = new RubyProgressSink(export_dialog, false);
|
RubyProgressSink::inst = new RubyProgressSink(export_dialog, false);
|
||||||
RubyProgressSink::inst->SetTitle(GetName());
|
RubyProgressSink::inst->SetTitle(GetName());
|
||||||
RubyProgressSink::inst->Show(true);
|
|
||||||
|
|
||||||
RubyAssFile *subsobj = new RubyAssFile(subs, true/*modify*/, false/*undo*/);
|
RubyAssFile *subsobj = new RubyAssFile(subs, true/*modify*/, false/*undo*/);
|
||||||
VALUE result = rbFunCall(rb_mKernel, rb_to_id(filter_fun), 2, subsobj->rbAssFile, Qnil /* config */);
|
VALUE *argv = ALLOCA_N(VALUE, 2);
|
||||||
if(result != Qnil && result != Qfalse)
|
argv[0] = subsobj->rbAssFile;
|
||||||
|
argv[1] = Qnil; // config
|
||||||
|
RubyCallArguments arg(rb_mKernel, rb_to_id(filter_fun), 2, argv);
|
||||||
|
VALUE result;
|
||||||
|
RubyThreadedCall call(&arg, &result);
|
||||||
|
RubyProgressSink::inst->ShowModal();
|
||||||
|
wxThread::ExitCode code = call.Wait();
|
||||||
|
RubyProgressSink::inst = NULL;
|
||||||
|
if(code)
|
||||||
|
{
|
||||||
|
if(TYPE(result) == T_STRING)
|
||||||
|
throw StringValueCStr(result);
|
||||||
|
else throw "Unknown Error";
|
||||||
|
}
|
||||||
|
else if(result != Qnil && result != Qfalse)
|
||||||
{
|
{
|
||||||
subsobj->RubyUpdateAssFile(result);
|
subsobj->RubyUpdateAssFile(result);
|
||||||
}
|
}
|
||||||
|
delete subsobj;
|
||||||
} catch (const char* e) {
|
} catch (const char* e) {
|
||||||
wxString *err = new wxString(e, wxConvUTF8);
|
wxString *err = new wxString(e, wxConvUTF8);
|
||||||
wxMessageBox(*err, _T("Error running filter"),wxICON_ERROR | wxOK);
|
wxMessageBox(*err, _T("Error running filter"),wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
RubyProgressSink::inst->script_finished = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptConfigDialog* RubyFeatureFilter::GenerateConfigDialog(wxWindow *parent)
|
ScriptConfigDialog* RubyFeatureFilter::GenerateConfigDialog(wxWindow *parent)
|
||||||
|
@ -422,8 +486,6 @@ namespace Automation4 {
|
||||||
{
|
{
|
||||||
float _progr = rb_num2dbl(progress);
|
float _progr = rb_num2dbl(progress);
|
||||||
RubyProgressSink::inst->SetProgress(_progr);
|
RubyProgressSink::inst->SetProgress(_progr);
|
||||||
RubyProgressSink::inst->DoUpdateDisplay();
|
|
||||||
wxSafeYield(RubyProgressSink::inst);
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +493,6 @@ namespace Automation4 {
|
||||||
{
|
{
|
||||||
wxString _t(StringValueCStr(task), wxConvUTF8);
|
wxString _t(StringValueCStr(task), wxConvUTF8);
|
||||||
RubyProgressSink::inst->SetTask(_t);
|
RubyProgressSink::inst->SetTask(_t);
|
||||||
RubyProgressSink::inst->DoUpdateDisplay();
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,8 +500,6 @@ namespace Automation4 {
|
||||||
{
|
{
|
||||||
wxString _t(StringValueCStr(title), wxConvUTF8);
|
wxString _t(StringValueCStr(title), wxConvUTF8);
|
||||||
RubyProgressSink::inst->SetTitle(_t);
|
RubyProgressSink::inst->SetTitle(_t);
|
||||||
//wxSafeYield(RubyProgressSink::inst);
|
|
||||||
RubyProgressSink::inst->DoUpdateDisplay();
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,8 +520,6 @@ namespace Automation4 {
|
||||||
else args[1] = args[0];
|
else args[1] = args[0];
|
||||||
wxString _m(StringValueCStr(args[1]), wxConvUTF8);
|
wxString _m(StringValueCStr(args[1]), wxConvUTF8);
|
||||||
RubyProgressSink::inst->AddDebugOutput(_m);
|
RubyProgressSink::inst->AddDebugOutput(_m);
|
||||||
RubyProgressSink::inst->DoUpdateDisplay();
|
|
||||||
wxSafeYield(RubyProgressSink::inst);
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +621,8 @@ namespace Automation4 {
|
||||||
VALUE result;
|
VALUE result;
|
||||||
result = rb_protect(rbCallWrapper, reinterpret_cast<VALUE>(&arg), &error);
|
result = rb_protect(rbCallWrapper, reinterpret_cast<VALUE>(&arg), &error);
|
||||||
if(error) {
|
if(error) {
|
||||||
//throw StringValueCStr(ruby_errinfo);
|
VALUE err = rb_errinfo();
|
||||||
|
throw StringValueCStr(err);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,12 +76,12 @@ namespace Automation4 {
|
||||||
static int RubyUnparseTagData();
|
static int RubyUnparseTagData();
|
||||||
static int RubySetUndoPoint();
|
static int RubySetUndoPoint();
|
||||||
|
|
||||||
~RubyAssFile();
|
|
||||||
public:
|
public:
|
||||||
void RubyUpdateAssFile(VALUE subtitles);
|
void RubyUpdateAssFile(VALUE subtitles);
|
||||||
static VALUE AssEntryToRuby(AssEntry *e); // makes a Ruby representation of AssEntry
|
static VALUE AssEntryToRuby(AssEntry *e); // makes a Ruby representation of AssEntry
|
||||||
static AssEntry *RubyToAssEntry(VALUE ass_entry); // creates an AssEntry object from a Ruby representation
|
static AssEntry *RubyToAssEntry(VALUE ass_entry); // creates an AssEntry object from a Ruby representation
|
||||||
RubyAssFile(AssFile *_ass, bool _can_modify, bool _can_set_undo);
|
RubyAssFile(AssFile *_ass, bool _can_modify, bool _can_set_undo);
|
||||||
|
~RubyAssFile();
|
||||||
|
|
||||||
static RubyAssFile *raf;
|
static RubyAssFile *raf;
|
||||||
VALUE rbAssFile;
|
VALUE rbAssFile;
|
||||||
|
@ -245,6 +245,17 @@ namespace Automation4 {
|
||||||
RubyCallArguments(VALUE _recv, ID _id, int _n, VALUE *_argv);
|
RubyCallArguments(VALUE _recv, ID _id, int _n, VALUE *_argv);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A single call to a Ruby function, run inside a separate thread.
|
||||||
|
// This object should be created on the stack in the function that does the call.
|
||||||
|
class RubyThreadedCall : public wxThread {
|
||||||
|
private:
|
||||||
|
RubyCallArguments *args;
|
||||||
|
VALUE *result;
|
||||||
|
public:
|
||||||
|
RubyThreadedCall(RubyCallArguments *args, VALUE *result);
|
||||||
|
virtual ExitCode Entry();
|
||||||
|
};
|
||||||
|
|
||||||
VALUE rbCallWrapper(VALUE arg);
|
VALUE rbCallWrapper(VALUE arg);
|
||||||
VALUE rbExecWrapper(VALUE arg);
|
VALUE rbExecWrapper(VALUE arg);
|
||||||
VALUE rbLoadWrapper(VALUE arg);
|
VALUE rbLoadWrapper(VALUE arg);
|
||||||
|
|
|
@ -337,8 +337,8 @@ namespace Automation4 {
|
||||||
// If the first line is dialogue we leave header from the original (styles, info, etc)
|
// If the first line is dialogue we leave header from the original (styles, info, etc)
|
||||||
void RubyAssFile::RubyUpdateAssFile(VALUE subtitles)
|
void RubyAssFile::RubyUpdateAssFile(VALUE subtitles)
|
||||||
{
|
{
|
||||||
RubyObjects::Get()->Register(subtitles);
|
//RubyObjects::Get()->Register(subtitles);
|
||||||
int size = rb_num2long(rb_funcall(subtitles, rb_to_id(rb_str_new2("size")), 0));
|
int size = RARRAY(subtitles)->len;
|
||||||
|
|
||||||
if(size <= 0) return; // empty - leave the original
|
if(size <= 0) return; // empty - leave the original
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ namespace Automation4 {
|
||||||
rb_set_errinfo(Qnil);
|
rb_set_errinfo(Qnil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RubyObjects::Get()->Unregister(subtitles);
|
//RubyObjects::Get()->Unregister(subtitles);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RubyAssFile::RubyParseTagData()
|
int RubyAssFile::RubyParseTagData()
|
||||||
|
@ -401,7 +401,6 @@ namespace Automation4 {
|
||||||
|
|
||||||
RubyAssFile::~RubyAssFile()
|
RubyAssFile::~RubyAssFile()
|
||||||
{
|
{
|
||||||
RubyObjects::Get()->Unregister(rbAssFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RubyAssFile::RubyAssFile(AssFile *_ass, bool _can_modify, bool _can_set_undo)
|
RubyAssFile::RubyAssFile(AssFile *_ass, bool _can_modify, bool _can_set_undo)
|
||||||
|
@ -409,12 +408,8 @@ namespace Automation4 {
|
||||||
, can_modify(_can_modify)
|
, can_modify(_can_modify)
|
||||||
, can_set_undo(_can_set_undo)
|
, can_set_undo(_can_set_undo)
|
||||||
{
|
{
|
||||||
if(RubyAssFile::raf)
|
|
||||||
delete RubyAssFile::raf; // delete previous if there is one
|
|
||||||
RubyAssFile::raf = this; // set pointer to this obj
|
|
||||||
|
|
||||||
rbAssFile = rb_ary_new2(ass->Line.size());
|
rbAssFile = rb_ary_new2(ass->Line.size());
|
||||||
RubyObjects::Get()->Register(rbAssFile);
|
|
||||||
|
|
||||||
std::list<AssEntry*>::iterator entry;
|
std::list<AssEntry*>::iterator entry;
|
||||||
int status;
|
int status;
|
||||||
|
|
Loading…
Reference in a new issue