<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://karaoke.kjams.com/w/index.php?action=history&amp;feed=atom&amp;title=Python%2FCode</id>
	<title>Python/Code - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://karaoke.kjams.com/w/index.php?action=history&amp;feed=atom&amp;title=Python%2FCode"/>
	<link rel="alternate" type="text/html" href="https://karaoke.kjams.com/w/index.php?title=Python/Code&amp;action=history"/>
	<updated>2026-08-20T13:07:56Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://karaoke.kjams.com/w/index.php?title=Python/Code&amp;diff=8788&amp;oldid=prev</id>
		<title>Dave: Created page with &quot;&lt;pre&gt; //	CPython.cpp  #include &quot;kVersion.h&quot;  #if kUsePython 	#if __WIN32__ 		#include &quot;python.h&quot; 	#else 		#include &lt;Python/Python.h&gt; 	#endif #endif  #include &quot;stdafx.h&quot; #inclu...&quot;</title>
		<link rel="alternate" type="text/html" href="https://karaoke.kjams.com/w/index.php?title=Python/Code&amp;diff=8788&amp;oldid=prev"/>
		<updated>2013-08-07T18:50:34Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&amp;lt;pre&amp;gt; //	CPython.cpp  #include &amp;quot;kVersion.h&amp;quot;  #if kUsePython 	#if __WIN32__ 		#include &amp;quot;python.h&amp;quot; 	#else 		#include &amp;lt;Python/Python.h&amp;gt; 	#endif #endif  #include &amp;quot;stdafx.h&amp;quot; #inclu...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
//	CPython.cpp&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;kVersion.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#if kUsePython&lt;br /&gt;
	#if __WIN32__&lt;br /&gt;
		#include &amp;quot;python.h&amp;quot;&lt;br /&gt;
	#else&lt;br /&gt;
		#include &amp;lt;Python/Python.h&amp;gt;&lt;br /&gt;
	#endif&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;stdafx.h&amp;quot;&lt;br /&gt;
#include &amp;quot;CApp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;CPython.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
bool	CPython_UsePython()&lt;br /&gt;
{&lt;br /&gt;
	return kUsePython;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#if kUsePython&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;CTaskMgr.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define	kEmbeddedModuleName		&amp;quot;kjams&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define	kCustomPrint			&amp;quot;custom_print&amp;quot;&lt;br /&gt;
#define	kCustomErr			&amp;quot;custom_err&amp;quot;&lt;br /&gt;
#define	kCommand			&amp;quot;do_command&amp;quot;&lt;br /&gt;
#define	kStringCommand			&amp;quot;do_command_str&amp;quot;&lt;br /&gt;
#define	kDoMenuCommand			&amp;quot;do_menu_command&amp;quot;&lt;br /&gt;
#define	kDoMenuName			&amp;quot;do_menu_name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define	kStartupScriptName		&amp;quot;startup.py&amp;quot;&lt;br /&gt;
#define	kUserAbortStr			&amp;quot;User Abort&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/**********************************************/&lt;br /&gt;
class ScEnsureGIL {&lt;br /&gt;
	PyGILState_STATE	i_state;&lt;br /&gt;
	&lt;br /&gt;
	public:&lt;br /&gt;
	ScEnsureGIL() :&lt;br /&gt;
		i_state(PyGILState_Ensure())&lt;br /&gt;
	{ }&lt;br /&gt;
	&lt;br /&gt;
	~ScEnsureGIL() {&lt;br /&gt;
		PyGILState_Release(i_state);&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class ScReleaseGIL {&lt;br /&gt;
	&lt;br /&gt;
	public:&lt;br /&gt;
	PyThreadState	*i_stateP;&lt;br /&gt;
&lt;br /&gt;
	ScReleaseGIL() :&lt;br /&gt;
		i_stateP(PyEval_SaveThread())&lt;br /&gt;
	{ }&lt;br /&gt;
	&lt;br /&gt;
	~ScReleaseGIL() {&lt;br /&gt;
		PyEval_RestoreThread(i_stateP);&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class ScPyObject {&lt;br /&gt;
	PyObject		*i_objP;&lt;br /&gt;
	&lt;br /&gt;
	public:&lt;br /&gt;
	ScPyObject(PyObject *objP) : i_objP(objP) {}&lt;br /&gt;
	~ScPyObject() {&lt;br /&gt;
		Py_DECREF(i_objP);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	operator PyObject*() {&lt;br /&gt;
		return i_objP;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**********************************************/&lt;br /&gt;
class CPython;&lt;br /&gt;
class CT_RunScript;&lt;br /&gt;
&lt;br /&gt;
typedef std::vector&amp;lt;CT_RunScript *&amp;gt;		ScriptVec;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
	this thread runs in the background, serving as the&lt;br /&gt;
	&amp;quot;main event loop&amp;quot; for all python scripts&lt;br /&gt;
	it runs an &amp;quot;idle&amp;quot; on each script every 1/4 second&lt;br /&gt;
	to look for user-aborted threads, and if found, &lt;br /&gt;
	causes an exception to be thrown within that thread&lt;br /&gt;
*/&lt;br /&gt;
class CPython_RunLoop : public CT_Preemptive {&lt;br /&gt;
	public:&lt;br /&gt;
	CPython					*thiz;&lt;br /&gt;
	CMutex_bool				i_abortB;&lt;br /&gt;
	CMutexT&amp;lt;ScriptVec *&amp;gt;			i_scriptVecP;&lt;br /&gt;
	bool					i_continueB;&lt;br /&gt;
	&lt;br /&gt;
	CPython_RunLoop(CPython *in_thiz);&lt;br /&gt;
	~CPython_RunLoop();&lt;br /&gt;
	&lt;br /&gt;
	virtual	OSStatus		operator()(OSStatus err);&lt;br /&gt;
	void				RunScript(const char *unf8NameZ, const char *utf8ScriptZ);&lt;br /&gt;
	&lt;br /&gt;
	void				AddScript(CT_RunScript *scriptP);&lt;br /&gt;
	void				RemoveScript(CT_RunScript *scriptP);&lt;br /&gt;
	void				IdleScripts();&lt;br /&gt;
	void				AllowPendingCalls();&lt;br /&gt;
	size_t				CountScripts();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
	this is the main Python object the app uses to &lt;br /&gt;
 	communicate with the python runloop above&lt;br /&gt;
*/&lt;br /&gt;
class CPython {&lt;br /&gt;
	friend class CPython_RunLoop;&lt;br /&gt;
	static CPython				*s_pythonP;&lt;br /&gt;
	CMutexT&amp;lt;bool&amp;gt;				i_inittedB;&lt;br /&gt;
	std::string				i_appName;&lt;br /&gt;
	CMutexT&amp;lt;CPython_RunLoop*&amp;gt;		i_runLoopP;&lt;br /&gt;
&lt;br /&gt;
	public:&lt;br /&gt;
	CPython(const char *appNameZ);&lt;br /&gt;
	~CPython();&lt;br /&gt;
	&lt;br /&gt;
	static CPython*		Get(const char *appNameZ = NULL);&lt;br /&gt;
	&lt;br /&gt;
	/****************************************************/	&lt;br /&gt;
	void	Startup();&lt;br /&gt;
	void	Test();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//static&lt;br /&gt;
CPython*		CPython::s_pythonP = NULL;&lt;br /&gt;
&lt;br /&gt;
/*********************************************************************/&lt;br /&gt;
struct ThisRec {&lt;br /&gt;
	CT_RunScript	*i_scriptP;&lt;br /&gt;
	ThisRec(CT_RunScript *scriptP) : i_scriptP(scriptP) {}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
boost::thread_specific_ptr&amp;lt;ThisRec&amp;gt; 	g_threadP;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
	this is a script-running thread&lt;br /&gt;
 	if any &amp;quot;error&amp;quot; statements are &amp;quot;printed&amp;quot;, they are gathered up into&lt;br /&gt;
 	a single string and presented to the user as a dialog&lt;br /&gt;
 */&lt;br /&gt;
class CT_RunScript : public CT_Preemptive {&lt;br /&gt;
	public:&lt;br /&gt;
	SuperString			i_name;&lt;br /&gt;
	SuperString			i_script;&lt;br /&gt;
	CPython_RunLoop			*i_runLoopP;&lt;br /&gt;
	long				i_thread_id;&lt;br /&gt;
&lt;br /&gt;
	class CShowErrorTimer;&lt;br /&gt;
	CMutexT&amp;lt;CShowErrorTimer *&amp;gt;	i_errTimerP;&lt;br /&gt;
	&lt;br /&gt;
	/*****************************&lt;br /&gt;
		this gathers all errors printed out:&lt;br /&gt;
	 	if it gets some error text, it waits a half second.&lt;br /&gt;
	 	if more error prints come in within that time, they are appended&lt;br /&gt;
	 	when the timer expires, all the error messages gathered are &lt;br /&gt;
	 	shown to the user in a dialog&lt;br /&gt;
	*/&lt;br /&gt;
	class CShowErrorTimer : public CT_Timer {&lt;br /&gt;
		friend class CT_RunScript;&lt;br /&gt;
		SuperString				i_errStr;&lt;br /&gt;
		CMutex_bool				i_abortB;&lt;br /&gt;
		CT_RunScript				*i_scriptP;&lt;br /&gt;
		bool					i_doneB;&lt;br /&gt;
		&lt;br /&gt;
		public:	&lt;br /&gt;
		CShowErrorTimer(CT_RunScript *scriptP) :&lt;br /&gt;
			i_doneB(false),&lt;br /&gt;
			i_scriptP(scriptP), &lt;br /&gt;
			CT_Timer(NO_KILL &amp;quot;CShowErrorTimer&amp;quot;, kEventDurationSecond / 2)&lt;br /&gt;
		{&lt;br /&gt;
			call();&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		~CShowErrorTimer() {&lt;br /&gt;
			i_scriptP-&amp;gt;i_errTimerP.Set(NULL);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		virtual	OSStatus	operator()() &lt;br /&gt;
		{&lt;br /&gt;
			CCritical		sc(&amp;amp;i_scriptP-&amp;gt;i_errTimerP);&lt;br /&gt;
&lt;br /&gt;
			if (!i_doneB) {&lt;br /&gt;
				i_doneB = true;&lt;br /&gt;
				if (!i_errStr.Contains(kUserAbortStr)) {&lt;br /&gt;
&lt;br /&gt;
					if (i_errStr.GetIndCharR() == &amp;#039;\r&amp;#039;) {&lt;br /&gt;
						i_errStr.pop_back();&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					i_errStr.Replace(&amp;quot;&amp;lt;string&amp;gt;&amp;quot;, i_scriptP-&amp;gt;i_name);&lt;br /&gt;
					PostAlert(&amp;quot;Python Error:&amp;quot;, i_errStr.utf8Z());&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			return threadTimerTerminate;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		void	append(const char *utf8Z) {&lt;br /&gt;
			&lt;br /&gt;
			if (!i_doneB) {&lt;br /&gt;
				i_errStr.append(utf8Z);&lt;br /&gt;
				prime();	//	tickle the timer&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
	/*****************************/&lt;br /&gt;
	&lt;br /&gt;
	CPW_TaskRec		*i_taskRecP;&lt;br /&gt;
	CPW_ProgData		i_progData;&lt;br /&gt;
		&lt;br /&gt;
	CT_RunScript(&lt;br /&gt;
		CPython_RunLoop		*runLoopP,		&lt;br /&gt;
		const SuperString&amp;amp;	name,&lt;br /&gt;
		const SuperString&amp;amp;	script&lt;br /&gt;
	) : &lt;br /&gt;
		i_runLoopP(runLoopP),&lt;br /&gt;
		i_name(name), &lt;br /&gt;
		i_script(script)&lt;br /&gt;
	{&lt;br /&gt;
		SuperString		verb1(&amp;quot;Python: &amp;quot;);&lt;br /&gt;
&lt;br /&gt;
		verb1.append(name);&lt;br /&gt;
		i_taskRecP = gApp-&amp;gt;NewTask(verb1.ref(), NULL);&lt;br /&gt;
		i_runLoopP-&amp;gt;AddScript(this);&lt;br /&gt;
		call(NO_KILL &amp;quot;CPython::CT_RunScript&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	~CT_RunScript() &lt;br /&gt;
	{&lt;br /&gt;
		CF_ASSERT(i_errTimerP.Get() == NULL);		&lt;br /&gt;
		i_taskRecP-&amp;gt;Delete();&lt;br /&gt;
		i_runLoopP-&amp;gt;RemoveScript(this);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	//	called from CPython_RunLoop thread, NOT from &amp;quot;this&amp;quot; thread&lt;br /&gt;
	void					Idle()&lt;br /&gt;
	{&lt;br /&gt;
		OSStatus		err = noErr;&lt;br /&gt;
		&lt;br /&gt;
		ERR(i_runLoopP-&amp;gt;i_abortB.Get());&lt;br /&gt;
		ERR(i_taskRecP-&amp;gt;MT_UpdateData(&amp;amp;i_progData));&lt;br /&gt;
		&lt;br /&gt;
		//	an error here means the user has aborted the script&lt;br /&gt;
		if (err) {&lt;br /&gt;
			err = noErr;&lt;br /&gt;
			&lt;br /&gt;
			ERR_XTE_START {&lt;br /&gt;
				ScEnsureGIL	sc;&lt;br /&gt;
				ScPyObject	exceptionP(PyString_FromString(kUserAbortStr));&lt;br /&gt;
				int		countI(PyThreadState_SetAsyncExc(i_thread_id, exceptionP));&lt;br /&gt;
				&lt;br /&gt;
				//	during shut down it is reasonable that countI may be 0&lt;br /&gt;
				//	but it should never be greater than 1&lt;br /&gt;
				CF_ASSERT(countI == 0 || countI == 1);&lt;br /&gt;
			} ERR_XTE_END;&lt;br /&gt;
			&lt;br /&gt;
			if (err) {&lt;br /&gt;
				ReportErr(&amp;quot;Python: Exception when attempting to kill thread&amp;quot;, err);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	virtual	OSStatus	operator()(OSStatus err)&lt;br /&gt;
	{&lt;br /&gt;
		SetThis(this);&lt;br /&gt;
		&lt;br /&gt;
		{&lt;br /&gt;
			ScEnsureGIL		sc;&lt;br /&gt;
			&lt;br /&gt;
			//	gather my thread ID so i can be killed later if &lt;br /&gt;
			//	the user hits cancel on my thread&lt;br /&gt;
			i_thread_id = PyThreadState_Get()-&amp;gt;thread_id;&lt;br /&gt;
			ERR(PyRun_SimpleString(i_script.utf8Z()));&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		//	now wait until errors have already been shown, if any&lt;br /&gt;
		while (i_errTimerP.Get()) {&lt;br /&gt;
			IdleDuration(0.1f, kDurationForever_Idle);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return err;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	/***************************/&lt;br /&gt;
	//	extensions to python for use within scripts&lt;br /&gt;
	static CT_RunScript*	GetThis() {&lt;br /&gt;
		CT_RunScript		*thiz		= NULL;&lt;br /&gt;
		ThisRec			*thisRecP	= g_threadP.get();&lt;br /&gt;
		&lt;br /&gt;
		if (thisRecP) {&lt;br /&gt;
			thiz = thisRecP-&amp;gt;i_scriptP;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return thiz;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	static void				SetThis(CT_RunScript *scriptP) {&lt;br /&gt;
		g_threadP.reset(new ThisRec(scriptP));&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	static	PyObject*	emb_print_err(PyObject *self, PyObject *args) {&lt;br /&gt;
		return GetThis()-&amp;gt;print_err(args);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PyObject*	print_err(PyObject *args)&lt;br /&gt;
	{&lt;br /&gt;
		PyObject			*resultObjP	= NULL;&lt;br /&gt;
		const char			*utf8_strZ	= NULL;&lt;br /&gt;
		&lt;br /&gt;
		if (PyArg_ParseTuple(args, &amp;quot;s&amp;quot;, &amp;amp;utf8_strZ)) {&lt;br /&gt;
			CCritical		sc(&amp;amp;i_errTimerP);&lt;br /&gt;
			CShowErrorTimer		*errTimerP(i_errTimerP.Get());&lt;br /&gt;
			&lt;br /&gt;
			if (errTimerP == NULL) {&lt;br /&gt;
				errTimerP = new CShowErrorTimer(this);&lt;br /&gt;
				i_errTimerP.Set(errTimerP);&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			errTimerP-&amp;gt;append(utf8_strZ);&lt;br /&gt;
		&lt;br /&gt;
			resultObjP = Py_None;&lt;br /&gt;
			Py_INCREF(resultObjP);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return resultObjP;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/***************************/&lt;br /&gt;
	static	PyObject*	emb_print(PyObject *self, PyObject *args) {&lt;br /&gt;
		return GetThis()-&amp;gt;print(args);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PyObject*	print(PyObject *args)&lt;br /&gt;
	{&lt;br /&gt;
		PyObject		*resultObjP	= NULL;&lt;br /&gt;
		const char		*utf8_strZ	= NULL;&lt;br /&gt;
		&lt;br /&gt;
		if (PyArg_ParseTuple(args, &amp;quot;s&amp;quot;, &amp;amp;utf8_strZ)) {&lt;br /&gt;
			Log(utf8_strZ, false);&lt;br /&gt;
&lt;br /&gt;
			resultObjP = Py_None;&lt;br /&gt;
			Py_INCREF(resultObjP);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return resultObjP;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/***************************/&lt;br /&gt;
	static	PyObject*	emb_do_command(PyObject *self, PyObject *args) {&lt;br /&gt;
		return GetThis()-&amp;gt;do_command(args);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PyObject*	do_command(PyObject *args)&lt;br /&gt;
	{&lt;br /&gt;
		PyObject		*resultObjP	= NULL;&lt;br /&gt;
		int			commandID	= kScriptCommand_NONE;&lt;br /&gt;
		&lt;br /&gt;
		if (PyArg_ParseTuple(args, &amp;quot;i&amp;quot;, &amp;amp;commandID)) {&lt;br /&gt;
			double			resultF = Scripting_Command((SInt32)commandID);&lt;br /&gt;
&lt;br /&gt;
			resultObjP = PyFloat_FromDouble(resultF);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return resultObjP;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/***************************/&lt;br /&gt;
	static	PyObject*	emb_do_command_str(PyObject *self, PyObject *args) {		&lt;br /&gt;
		return GetThis()-&amp;gt;do_command_str(args);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PyObject*	do_command_str(PyObject *args)&lt;br /&gt;
	{&lt;br /&gt;
		PyObject		*resultObjP	= NULL;&lt;br /&gt;
		int			commandID	= kScriptCommand_NONE;&lt;br /&gt;
		&lt;br /&gt;
		if (PyArg_ParseTuple(args, &amp;quot;i&amp;quot;, &amp;amp;commandID)) {&lt;br /&gt;
			SuperString			resultStr(Scripting_CommandStr((SInt32)commandID), true);&lt;br /&gt;
&lt;br /&gt;
			resultObjP = PyString_FromString(resultStr.utf8Z());&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return resultObjP;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/***************************/&lt;br /&gt;
	static	PyObject*	emb_do_menu_command(PyObject *self, PyObject *args) {&lt;br /&gt;
		return GetThis()-&amp;gt;do_menu_command(args);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PyObject*	do_menu_command(PyObject *args)&lt;br /&gt;
	{&lt;br /&gt;
		PyObject	*resultObjP		= NULL;&lt;br /&gt;
		short		menuI			= 0;&lt;br /&gt;
		short		menu_itemI		= 0;&lt;br /&gt;
		short		sub_menu_itemI	= 0;&lt;br /&gt;
		&lt;br /&gt;
		if (PyArg_ParseTuple(args, &amp;quot;hh|h&amp;quot;, &amp;amp;menuI, &amp;amp;menu_itemI, &amp;amp;sub_menu_itemI)) {&lt;br /&gt;
			SInt16Vec		intVec;&lt;br /&gt;
			&lt;br /&gt;
			intVec.push_back(menuI);&lt;br /&gt;
			intVec.push_back(menu_itemI);&lt;br /&gt;
			&lt;br /&gt;
			if (sub_menu_itemI) {&lt;br /&gt;
				intVec.push_back(sub_menu_itemI);&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			DoMenuCommand(intVec);&lt;br /&gt;
			&lt;br /&gt;
			resultObjP = Py_None;&lt;br /&gt;
			Py_INCREF(resultObjP);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return resultObjP;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/***************************/&lt;br /&gt;
	static	PyObject*	emb_do_menu_name(PyObject *self, PyObject *args) {&lt;br /&gt;
		return GetThis()-&amp;gt;do_menu_name(args);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PyObject*	do_menu_name(PyObject *args)&lt;br /&gt;
	{&lt;br /&gt;
		PyObject		*resultObjP		= NULL;&lt;br /&gt;
		const char		*menuZ			= NULL;&lt;br /&gt;
		const char		*menu_itemZ		= NULL;&lt;br /&gt;
		const char		*sub_menu_itemZ	= NULL;&lt;br /&gt;
		&lt;br /&gt;
		if (PyArg_ParseTuple(args, &amp;quot;ss|s&amp;quot;, &amp;amp;menuZ, &amp;amp;menu_itemZ, &amp;amp;sub_menu_itemZ)) {&lt;br /&gt;
			SStringVec		stringVec;&lt;br /&gt;
			&lt;br /&gt;
			stringVec.push_back(menuZ);&lt;br /&gt;
			stringVec.push_back(menu_itemZ);&lt;br /&gt;
			&lt;br /&gt;
			if (sub_menu_itemZ) {&lt;br /&gt;
				stringVec.push_back(sub_menu_itemZ);&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			DoMenuCommand(stringVec);&lt;br /&gt;
&lt;br /&gt;
			resultObjP = Py_None;&lt;br /&gt;
			Py_INCREF(resultObjP);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return resultObjP;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/*****************************************************/&lt;br /&gt;
&lt;br /&gt;
static const PyMethodDef EmbMethods[] = {&lt;br /&gt;
    {kCustomPrint,		CT_RunScript::emb_print,			METH_VARARGS,	&amp;quot;Calls custom print function.&amp;quot;},&lt;br /&gt;
    {kCustomErr,		CT_RunScript::emb_print_err,			METH_VARARGS,	&amp;quot;Calls custom error function.&amp;quot;},&lt;br /&gt;
    {kCommand,			CT_RunScript::emb_do_command,			METH_VARARGS,	&amp;quot;calls scripting command (float result).&amp;quot;},&lt;br /&gt;
    {kStringCommand,		CT_RunScript::emb_do_command_str,		METH_VARARGS,	&amp;quot;calls scripting command (string result).&amp;quot;},&lt;br /&gt;
    {kDoMenuCommand,		CT_RunScript::emb_do_menu_command,		METH_VARARGS,	&amp;quot;calls menu command by index&amp;quot;},&lt;br /&gt;
    {kDoMenuName,		CT_RunScript::emb_do_menu_name,			METH_VARARGS,	&amp;quot;calls menu command by name&amp;quot;},&lt;br /&gt;
    {NULL, NULL, 0, NULL}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
static const char *s_RedirectPrint = &lt;br /&gt;
	&amp;quot;import &amp;quot; kEmbeddedModuleName &amp;quot;\n&amp;quot;&lt;br /&gt;
	&amp;quot;import sys\n&amp;quot;&lt;br /&gt;
	&amp;quot;\n&amp;quot;&lt;br /&gt;
	&amp;quot;class CustomPrintClass:\n&amp;quot;&lt;br /&gt;
	&amp;quot;	def write(self, stuff):\n&amp;quot;&lt;br /&gt;
	&amp;quot;		&amp;quot; kEmbeddedModuleName &amp;quot;.&amp;quot; kCustomPrint &amp;quot;(stuff)\n&amp;quot;&lt;br /&gt;
	&amp;quot;class CustomErrClass:\n&amp;quot;&lt;br /&gt;
	&amp;quot;	def write(self, stuff):\n&amp;quot;&lt;br /&gt;
	&amp;quot;		&amp;quot; kEmbeddedModuleName &amp;quot;.&amp;quot; kCustomErr &amp;quot;(stuff)\n&amp;quot;&lt;br /&gt;
	&amp;quot;sys.stdout = CustomPrintClass()\n&amp;quot;&lt;br /&gt;
	&amp;quot;sys.stderr = CustomErrClass()\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char *s_PrintTime = &lt;br /&gt;
	&amp;quot;import time\n&amp;quot;&lt;br /&gt;
	&amp;quot;print &amp;#039;Today is&amp;#039;, time.ctime(time.time())\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char *s_AllowPendingCalls = &lt;br /&gt;
	&amp;quot;pass\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
/*****************************************************************&lt;br /&gt;
	on Windows, if you bundle python27.dll with your app, it will launch but &lt;br /&gt;
 	crash on systems that do NOT have python actually installed.&lt;br /&gt;
 	so get around that here, and bail gracefully.  at that point you could&lt;br /&gt;
 	instruct the user to go install ActivePython 2.7 for x86 (32bit) from here:&lt;br /&gt;
 	http://www.activestate.com/activepython/downloads&lt;br /&gt;
*/&lt;br /&gt;
static	bool	PythonExists()&lt;br /&gt;
{&lt;br /&gt;
	bool		existsB = true;&lt;br /&gt;
&lt;br /&gt;
	#if OPT_WINOS&lt;br /&gt;
	{&lt;br /&gt;
		CFileRef	system32(CFileRef::kFolder_SYSTEM);	//	CSIDL_SYSTEMX86&lt;br /&gt;
&lt;br /&gt;
		existsB = system32.Descend(&amp;quot;python27.dll&amp;quot;) == noErr;&lt;br /&gt;
	}&lt;br /&gt;
	#endif&lt;br /&gt;
	&lt;br /&gt;
	return existsB;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CPython_RunLoop::CPython_RunLoop(CPython *in_thiz) : &lt;br /&gt;
	thiz(in_thiz),&lt;br /&gt;
	i_continueB(PythonExists())&lt;br /&gt;
{&lt;br /&gt;
	i_scriptVecP.Set(new ScriptVec());&lt;br /&gt;
	call(NO_KILL &amp;quot;CPython_RunLoop&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CPython_RunLoop::~CPython_RunLoop()&lt;br /&gt;
{&lt;br /&gt;
	CCritical		sc(&amp;amp;i_scriptVecP);&lt;br /&gt;
	ScriptVec		*vecP(i_scriptVecP.Get());&lt;br /&gt;
&lt;br /&gt;
	CF_ASSERT(vecP);&lt;br /&gt;
	CF_ASSERT(vecP-&amp;gt;empty());&lt;br /&gt;
	delete vecP;&lt;br /&gt;
	i_scriptVecP.Set(NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
OSStatus	CPython_RunLoop::operator()(OSStatus err)&lt;br /&gt;
{&lt;br /&gt;
	XTE_START {&lt;br /&gt;
		if (i_continueB) {&lt;br /&gt;
			Log(&amp;quot;Python: about to set program name&amp;quot;);&lt;br /&gt;
			Py_SetProgramName(const_cast&amp;lt;char *&amp;gt;(thiz-&amp;gt;i_appName.c_str()));&lt;br /&gt;
&lt;br /&gt;
			Log(&amp;quot;Python: about to init&amp;quot;);&lt;br /&gt;
			Py_Initialize();&lt;br /&gt;
&lt;br /&gt;
			{&lt;br /&gt;
				Log(&amp;quot;Python: about to create &amp;quot; kEmbeddedModuleName &amp;quot; module&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				PyObject	*myModuleP = Py_InitModule(&lt;br /&gt;
						kEmbeddedModuleName, const_cast&amp;lt;PyMethodDef*&amp;gt;(EmbMethods));&lt;br /&gt;
				ETX(myModuleP == NULL);&lt;br /&gt;
				&lt;br /&gt;
				//	the owner of myModuleP is now the python interpreter&lt;br /&gt;
				//	it will auto-decref during Py_Finalize()&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			//	redirect stdout and stderr to my own logging functions&lt;br /&gt;
			Log(&amp;quot;Python: about to run log redirect script&amp;quot;);&lt;br /&gt;
			ETX(PyRun_SimpleString(s_RedirectPrint));&lt;br /&gt;
			PyEval_InitThreads();&lt;br /&gt;
			thiz-&amp;gt;i_inittedB.Set(true);&lt;br /&gt;
		}&lt;br /&gt;
	} XTE_END;&lt;br /&gt;
&lt;br /&gt;
	LogYesOrNo(&amp;quot;Python Initted&amp;quot;, thiz-&amp;gt;i_inittedB.Get());&lt;br /&gt;
	&lt;br /&gt;
	if (thiz-&amp;gt;i_inittedB.Get()) {&lt;br /&gt;
		bool		abortB = false;&lt;br /&gt;
		bool		doneB = false;&lt;br /&gt;
&lt;br /&gt;
		{&lt;br /&gt;
			ScReleaseGIL		sc;&lt;br /&gt;
		&lt;br /&gt;
			/*&lt;br /&gt;
				run the &amp;quot;loop&amp;quot; that will handle killing of&lt;br /&gt;
				any scripts canceled by the user&lt;br /&gt;
			*/&lt;br /&gt;
			&lt;br /&gt;
			do {&lt;br /&gt;
				//	IdleScripts will kill any scripts that the user has hit cancel on&lt;br /&gt;
				IdleScripts();&lt;br /&gt;
				&lt;br /&gt;
				//	if you want to use Py_AddPendingCall() to send a message to THIS&lt;br /&gt;
				//	thread, then you&amp;#039;d need to uncomment this line:&lt;br /&gt;
				//	AllowPendingCalls();&lt;br /&gt;
&lt;br /&gt;
				if (!abortB) {&lt;br /&gt;
					//	this gets set when quitting the app&lt;br /&gt;
					abortB = i_abortB.Get();&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
				if (abortB) {&lt;br /&gt;
					doneB = CountScripts() == 0;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
				if (!doneB) {&lt;br /&gt;
					IdleDuration(kQuarterSecond);&lt;br /&gt;
				}&lt;br /&gt;
			} while (!doneB);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		Py_Finalize();&lt;br /&gt;
		thiz-&amp;gt;i_inittedB.Set(false);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	thiz-&amp;gt;i_runLoopP.Set(NULL);	&lt;br /&gt;
	return err;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void		CPython_RunLoop::AllowPendingCalls()&lt;br /&gt;
{&lt;br /&gt;
	ScEnsureGIL		sc;&lt;br /&gt;
&lt;br /&gt;
	if (PyRun_SimpleString(s_AllowPendingCalls) != 0) {&lt;br /&gt;
		PostAlert(&amp;quot;Python: s_AllowPendingCalls failed&amp;quot;);&lt;br /&gt;
		i_abortB.Set(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void		CPython_RunLoop::RunScript(const char *unf8NameZ, const char *utf8ScriptZ)&lt;br /&gt;
{&lt;br /&gt;
	new CT_RunScript(this, unf8NameZ, utf8ScriptZ);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void		CPython_RunLoop::AddScript(CT_RunScript *scriptP)&lt;br /&gt;
{&lt;br /&gt;
	CCritical		sc(&amp;amp;i_scriptVecP);	CF_ASSERT(i_scriptVecP.Get());&lt;br /&gt;
	i_scriptVecP.Get()-&amp;gt;push_back(scriptP);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void		CPython_RunLoop::RemoveScript(CT_RunScript *scriptP)&lt;br /&gt;
{&lt;br /&gt;
	CCritical				sc(&amp;amp;i_scriptVecP);	CF_ASSERT(i_scriptVecP.Get());&lt;br /&gt;
	ScriptVec&amp;amp;				scriptVec(*i_scriptVecP.Get());&lt;br /&gt;
	ScriptVec::iterator		it(std::find(scriptVec.begin(), scriptVec.end(), scriptP));&lt;br /&gt;
	&lt;br /&gt;
	CF_ASSERT(it != scriptVec.end());&lt;br /&gt;
	if (it != scriptVec.end()) {&lt;br /&gt;
		scriptVec.erase(it);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void		CPython_RunLoop::IdleScripts()&lt;br /&gt;
{&lt;br /&gt;
	ScriptVec				iter_scriptVec;&lt;br /&gt;
&lt;br /&gt;
	{&lt;br /&gt;
		CCritical		sc(&amp;amp;i_scriptVecP);	CF_ASSERT(i_scriptVecP.Get());&lt;br /&gt;
		ScriptVec&amp;amp;		orig_scriptVec(*i_scriptVecP.Get());&lt;br /&gt;
		&lt;br /&gt;
		//	make a copy to iterate over, cuz during the iterate&lt;br /&gt;
		//	we may actually delete the current script&lt;br /&gt;
		iter_scriptVec = orig_scriptVec;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	BOOST_FOREACH(CT_RunScript *scriptP, iter_scriptVec) {&lt;br /&gt;
		{&lt;br /&gt;
			CCritical		sc(&amp;amp;i_scriptVecP);			CF_ASSERT(i_scriptVecP.Get());&lt;br /&gt;
			ScriptVec&amp;amp;		scriptVec(*i_scriptVecP.Get());&lt;br /&gt;
			ScriptVec::iterator	it(std::find(scriptVec.begin(), scriptVec.end(), scriptP));&lt;br /&gt;
			&lt;br /&gt;
			//	we still have to check to see if this script still exists before calling it&lt;br /&gt;
			if (it != scriptVec.end()) {&lt;br /&gt;
				scriptP-&amp;gt;Idle();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
size_t				CPython_RunLoop::CountScripts()&lt;br /&gt;
{&lt;br /&gt;
	CCritical	sc(&amp;amp;i_scriptVecP);	CF_ASSERT(i_scriptVecP.Get());&lt;br /&gt;
&lt;br /&gt;
	return i_scriptVecP.Get()-&amp;gt;size();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**************************************************************/&lt;br /&gt;
CPython::CPython(const char *appNameZ) :&lt;br /&gt;
	i_appName(appNameZ)&lt;br /&gt;
{&lt;br /&gt;
	i_runLoopP.Set(new CPython_RunLoop(this));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CPython::~CPython()&lt;br /&gt;
{&lt;br /&gt;
	s_pythonP = NULL;&lt;br /&gt;
	&lt;br /&gt;
	{&lt;br /&gt;
		CCritical		sc(&amp;amp;i_runLoopP);&lt;br /&gt;
		CPython_RunLoop		*runLoopP(i_runLoopP.Get());&lt;br /&gt;
		&lt;br /&gt;
		if (runLoopP) {&lt;br /&gt;
			runLoopP-&amp;gt;i_abortB.Set(true);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while (i_runLoopP.Get()) {&lt;br /&gt;
		IdleDuration(0.1f, kDurationForever_Idle);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	static &lt;br /&gt;
CPython*		CPython::Get(const char *appNameZ)&lt;br /&gt;
{&lt;br /&gt;
	if (s_pythonP == NULL) {&lt;br /&gt;
		CF_ASSERT(appNameZ);&lt;br /&gt;
		s_pythonP = new CPython(appNameZ);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	return s_pythonP;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/****************************************************/	&lt;br /&gt;
void	CPython::Startup()&lt;br /&gt;
{&lt;br /&gt;
	if (i_inittedB.Get()) XTE_START {&lt;br /&gt;
		CharVec			charVec;&lt;br /&gt;
		CFileRef		pythonRef(kFolder_KJAMS);&lt;br /&gt;
		&lt;br /&gt;
		ETX(pythonRef.Descend(&amp;quot;Python/&amp;quot; kStartupScriptName));&lt;br /&gt;
		pythonRef.Load(&amp;amp;charVec);&lt;br /&gt;
		charVec.push_back(0);&lt;br /&gt;
		i_runLoopP.Get()-&amp;gt;RunScript(kStartupScriptName, &amp;amp;charVec[0]);&lt;br /&gt;
	} XTE_END;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void	CPython::Test()&lt;br /&gt;
{&lt;br /&gt;
	if (i_inittedB.Get()) {&lt;br /&gt;
		i_runLoopP.Get()-&amp;gt;RunScript(&amp;quot;print_time.py&amp;quot;, s_PrintTime);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
/*****************************************************************/&lt;br /&gt;
&lt;br /&gt;
#endif	//	kUsePython&lt;br /&gt;
&lt;br /&gt;
//	the entire public interface is here&lt;br /&gt;
//	called on startup to init&lt;br /&gt;
OSStatus	CPython_PreAlloc(const char *utf8Z)&lt;br /&gt;
{&lt;br /&gt;
	OSStatus			err = noErr;&lt;br /&gt;
	&lt;br /&gt;
	#if kUsePython&lt;br /&gt;
		if (CPython::Get(utf8Z) == NULL) {&lt;br /&gt;
			ERR(tsmUnsupScriptLanguageErr);&lt;br /&gt;
		}&lt;br /&gt;
	#endif&lt;br /&gt;
	&lt;br /&gt;
	return err;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	called on shutdown&lt;br /&gt;
void	CPython_PostDispose()&lt;br /&gt;
{&lt;br /&gt;
	#if kUsePython&lt;br /&gt;
		CPython		*pyP(CPython::Get());&lt;br /&gt;
	&lt;br /&gt;
		if (pyP) {&lt;br /&gt;
			delete pyP;&lt;br /&gt;
		}&lt;br /&gt;
	#endif&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	very simple unit test&lt;br /&gt;
void	CPython_Test()&lt;br /&gt;
{&lt;br /&gt;
	#if kUsePython&lt;br /&gt;
		CPython		*pyP(CPython::Get());&lt;br /&gt;
	&lt;br /&gt;
		if (pyP) {&lt;br /&gt;
			pyP-&amp;gt;Test();&lt;br /&gt;
		}&lt;br /&gt;
	#endif&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	called when startup is complete&lt;br /&gt;
void	CPython_Startup()&lt;br /&gt;
{&lt;br /&gt;
	#if kUsePython&lt;br /&gt;
		CPython		*pyP(CPython::Get());&lt;br /&gt;
	&lt;br /&gt;
		if (pyP) {&lt;br /&gt;
			pyP-&amp;gt;Startup();&lt;br /&gt;
		}&lt;br /&gt;
	#endif&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dave</name></author>
	</entry>
</feed>