The Blender Command Port patch makes it possible to start Blender in Python server mode. Clients can connect and send Python commands via the command port to the server.
Closed, ArchivedPublic

Description

The appended patch makes it possible to start Blender in Python server
mode. Clients can connect and send Python commands via the command
port to the server.

- The Command Port allows to edit objects simultaneously using the
Blender GUI and one or more clients connected to Blender via the
command port.
- The patch also includes `blash', a Blender Python shell client.
- `blash' can be used with the emacs python mode - the result is a
formidable Blender Python development environment.
- Clients can be written in any language: lisp, Python, Perl, C,
C++, Java etc.
- The patch was only tested on Debian sid until now but should run
on any platform after a little customisation.

For a screenshot see http://formgames.org/blender/command-port/

Have fun,
Dietrich


* Example - a simple pyramid

The following example shows how the command port can be used to model
a simple pyramid:

- start the Blender server in some xterm

$ blender --geometry 800x600+10+10 --bcp 6789 &

- start blash in another xterm

$ blash --port 6789
This is Blash - the GNU BLender-Again SHell :)
Connection to Blender Server established. (IP address: 127.0.0.1, port: 6789)

- enter blender python commands

from Blender import *

vertexes = [[1, 1, 0], [-1, 1, 0], [-1, -1, 0], [1, -1, 0], [0, 0, 1.27]]
faces = [[3, 2, 1, 0], [0, 1, 4], [1, 2, 4], [2, 3, 4], [3, 0, 4]]

mesh = Mesh.New('mesh')
mesh.verts.extend(vertexes)
mesh.faces.extend(faces)

scene = Scene.GetCurrent()
object = scene.objects.new(mesh, 'object')
Redraw()

bye


* Installation

- make a directory to build Blender

BCP=$HOME/bcp
mkdir -p $BCP
cd $BCP

- download blender 2.44 sources

wget http://download.blender.org/source/blender-2.44.tar.gz
wget http://download.blender.org/source/blender-2.44.tar.gz.md5sum
md5sum -c blender-2.44.tar.gz.md5sum

- download blender command port patch

wget http://formgames.org/blender/command-port/patches/blender-command-port-patch.2007-06-26.txt

- unpack the blender sources

gunzip blender-2.44.tar.gz
tar xvf blender-2.44.tar

- patch them

cd blender-2.44
patch -p0 < ../blender-command-port-patch.2007-06-26.txt

- build blash and blender

scons WITH_COMMAND_PORT=true blash

- the (linux) binaries

$BCP/install/linux2/blender
$BCP/install/linux2/blash

Details

Type
Patch

ideasman this something you are interested in reviewing?

Hi again, Campbell Barton :)

I am very glad that you signed for my command port :)

It took me a while to develop and I initially did it for my own purpose. Only recently, after it became something very helpful for my own work, I decided that I should share my code.

I have to admit that I added plenty of things over the time and that my patch is not implementing one isolated feature as this would be the ideal. Probably the best way to get an impression about how the command port can be used is to build it on top of the blender-2.44.tar.gz tarball by following the instructions I added (or even better those on the page http://formgames.org/blender/command-port/). This way you avoid to mess up your own sources :)

If it doesn't work (I only tested with linux) please let me know!

If you think that something should be done in a different way please let me know also. I will try to adapt things to your ideas.

I hope I do not take too much from your time with my patch.

Thanks again for your help,
Dietrich

From a quick glance, it looks like there is a lot going on in this patch:

- command arg processing refactor
- a debug facility
- the command port
- re-implementation of some standard C functions like isdigit.

It is easier to wade thru patches if they deal with a single topic. Nearly 12,000 lines of code makes for a big patch. Something this large might be better done as an svn branch.

Hi Stephen,

Thanks for your comments!

> From a quick glance, it looks like there is a lot going on in
> this patch:

Sorry ... I initially wrote the command port for myself and didn't intend to publish the code. So some changes and experiments which are not really essential for the command port itself ended up in the code.

> - command arg processing refactor

This is mostly for the arguments used for the command port.
I found the current code irritating and tried to make things simpler. By the way, wouldn't it be better to use something like GNU getopt for the command-line options anyway?

> - a debug facility

Mostly for the command port. This makes the development of new clients simpler as it is possible to debug the messages send by them.

> - the command port

:)

> - re-implementation of some standard C functions like isdigit.

Ups ... I didn't mean to re-implement the standard C functions but just chose the name which came first to my mind. No wonder that this has been something used somewhere else :) I should rename those functions to something different!

> It is easier to wade thru patches if they deal with a single
> topic. Nearly 12,000 lines of code makes for a big patch. Something
> this large might be better done as an svn branch.

right!

So how can I make this an svn branch?
Is there some page where the process is described?

After making it a branch I first could refactor those things which should be different and than move my stuff part by part to the trunk - of course only if people agree that the command port is something useful :)

So how should I proceed?

Thanks, Dietrich

"Sorry ... I initially wrote the command port for myself and didn't
intend to publish the code. So some changes and experiments
which are not really essential for the command port itself ended
up in the code."

If you are still interested in this, it needs to be stripped down to a single feature.

The patch doesn't seem to be as bad as it looks; there were very few conflicts when I applied it and updated to current blender svn. I've attached a diff.

%%%Index: README

  • README (revision 13338)

+++ README (working copy)
@@ -24,7 +24,7 @@
-------------------------------------Links--------------------------------------

Getting Involved:
-http://www.blender.org/docs/get_involved.html
+http://www.blender.org/community/get-involved/

Community:
http://www.blender3d.org/Community/

Index: tools/Blender.py

  • tools/Blender.py (revision 13338)

+++ tools/Blender.py (working copy)
@@ -12,6 +12,8 @@
TODO: clean up and sanitise code - crosscheck with btools and SConstruct
to kill any code duplication

+Contributor(s):
+- Dietrich Bollmann - added command port build code.
"""

import os.path
@@ -163,6 +165,8 @@

    syslibs += Split(lenv['BF_OPENGL_LIB'])
if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross'):
    syslibs += Split(lenv['BF_PTHREADS_LIB'])

+ if lenv['WITH_COMMAND_PORT'] or lenv['WITH_BLASH']: # (dietrich)
+ syslibs += Split(lenv['READLINE_LIB'])

    syslibs += Split(lenv['LLIBS'])

@@ -416,6 +420,8 @@

    print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
# note: libs is a global
add_lib_to_dict(libs, libtype, libname, priority)

+ if lenv['WITH_COMMAND_PORT']: # (dietrich)
+ lenv.Append(CPPDEFINES=['WITH_COMMAND_PORT'])

def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
    print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC

Index: tools/btools.py

  • tools/btools.py (revision 13338)

+++ tools/btools.py (working copy)
@@ -54,7 +54,8 @@

'BF_PROFILE_FLAGS', 'LCGDIR', 'WITH_BF_VERSE', 
'BF_VERSE_INCLUDE',
'VERSE_BUILD_BINARY', 'VERSE_BUILD_DIR', 'VERSE_REGEN_PROTO',
  • 'BF_TWEAK_MODE', 'BF_SPLIT_SRC',

+ 'WITH_COMMAND_PORT', 'WITH_BLASH', 'READLINE_LIB',
+ 'BF_TWEAK_MODE', 'BF_SPLIT_SRC',

'WITHOUT_BF_INSTALL',
'BF_FANCY',
]

@@ -86,7 +87,8 @@
def validate_targets(targs, bc):

valid_list = ['.', 'blender', 'blenderstatic', 'blenderplayer', 'webplugin',
        'blendernogame', 'blenderstaticnogame', 'release',
  • 'everything', 'clean', 'install-bin', 'install', 'nsis']

+ 'everything', 'clean', 'install-bin', 'install', 'nsis',
+ 'blash'] # (dietrich)

oklist = []
for t in targs:
    if t in valid_list:

@@ -296,7 +298,9 @@

        ('CXX', 'C++ compiler to use', ''),

        (BoolOption('BF_BUILDINFO', 'Buildtime in splash if true', 'true')),

+ (BoolOption('WITH_COMMAND_PORT', 'Build Blender with command port if true', 'false')),
+ (BoolOption('WITH_BLASH', 'Build blash - the blender python shell - if true', 'false')),
+ ('READLINE_LIB', 'readline libraries', ''),

(BoolOption('BF_TWEAK_MODE', 'Enable tweak mode if true', 'false')),
(BoolOption('BF_SPLIT_SRC', 'Split src lib into several chunks if true', 'false')),
(BoolOption('WITHOUT_BF_INSTALL', 'dont install if true', 'false')),

Index: source/creator/creator.c

  • source/creator/creator.c (revision 13338)

+++ source/creator/creator.c (working copy)
@@ -25,8 +25,14 @@

    • The Original Code is: all of this file.
  • * Contributor(s): none yet.

+ * Contributor(s):

+ * - Dietrich Bollmann (dietrich), 2007/06/21:
+ * - commandport initialization code,
+ * - debug option (--debug, UTL_debug),
+ * - functions to simplify use of command line options (UTL_parse_options),
+ * - geometry option (--geometry, UTL_parse_options_geometry).
+ *

  • * END GPL/BL DUAL LICENSE BLOCK * */ #include <stdlib.h>

@@ -81,11 +87,19 @@

#include "RE_pipeline.h"

+#include "UTL_debug.h"
+#include "UTL_parse_options.h"
+#include "UTL_parse_options_geometry.h"
+
#include "playanim_ext.h"
#include "mydevice.h"
#include "nla.h"
#include "datatoc.h"

+#ifdef WITH_COMMAND_PORT
+#include "commandport.h" /* the Blender command port (dietrich) */
+#endif
+
/* for passing information between creator and gameengine */
#include "SYS_System.h"

@@ -111,8 +125,15 @@

/* Local Function prototypes */
static void print_help();
+static void print_help_debug(); /* (dietrich) */
static void print_version();

+/* handle command port option (dietrich) */
+#ifdef WITH_COMMAND_PORT
+void handle_commandport_option_delete(int *argc, char argv);
+#endif
+void handle_debug_option_delete(int *argc, char
argv);
+void handle_geometry_option_delete(int *argc, char **argv);

/* defined in ghostwinlay and winlay, we can't include carbon here, conflict with DNA */
#ifdef APPLE
@@ -220,6 +241,9 @@

	printf ("  -W\t\tForce opening without borders\n");
	printf ("  -p <sx> <sy> <w> <h>\tOpen with lower left corner at <sx>, <sy>\n");
	printf ("                      \tand width and height <w>, <h>\n");

+ printf (" --geometry <width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>\n"); /* (dietrich) */
+ printf (" \t--geometry can be used alternatively to the -p option\n");
+ printf (" \tto specify size and position of the Blender window.\n");

	printf ("\nGame Engine specific options:\n");
	printf ("  -g fixedtime\t\tRun on 50 hertz without dropping frames\n");
	printf ("  -g vertexarrays\tUse Vertex Arrays for rendering (usually faster)\n");

@@ -228,7 +252,22 @@

	printf ("  -g linearmipmap\tLinear Texture Mipmapping instead of Nearest (default)\n");

	printf ("\nMisc options:\n");
  • printf (" -d\t\tTurn debugging on\n");

+ printf (" -d | --debug <modA>[:<levelA>],<modB>[:<levelB>],...\n"); /* (dietrich) */
+ printf (" \t\tTurn debugging on for module <modX>.\n");
+ printf (" \t\tSet the debug level if <levelX> is given.\n");
+ printf (" \t\tTo see which debug options can be used, try -hd or --help=debug.\n");
+#ifdef WITH_COMMAND_PORT
+ printf (" \t\tExample:\n");
+ printf (" \t\t blender --debug debug,bcp:2,opt ...\n");
+ printf (" \t\tDebug the debug option itself,\n");
+ printf (" \t\tthe command port at verbosity level 2 (`bcp:2')\n");
+ printf (" \t\tand some command line options (`opt').\n");
+#else
+ printf (" \t\tExample:\n");
+ printf (" \t\t blender --debug debug,opt ...\n");
+ printf (" \t\tDebug the debug option itself\n");
+ printf (" \t\tand some command line options (`opt').\n");
+#endif

	printf ("  -noaudio\tDisable audio on systems that support audio\n");
	printf ("  -h\t\tPrint this help text\n");
	printf ("  -y\t\tDisable script links, use -Y to find out why its -y\n");

@@ -236,25 +275,103 @@
#ifdef WIN32

	printf ("  -R\t\tRegister .blend extension\n");

#endif
+#ifdef WITH_COMMAND_PORT
+ printf (" -c <port number> | --bcp <port number>\tStart the Blender Command Port\n"
+ " \t\tusing port <port number>\n"); /* (dietrich) */
+#endif

	printf ("  -v\t\tPrint Blender version and exit\n");
	printf ("  --\t\tEnds option processing.  Following arguments are \n");
	printf ("    \t\t   passed unchanged.  Access via Python's sys.argv\n");

}

+/**
+ help message for debugging mode
+
+ (dietrich)
+*/
+static void print_help_debug()
+{
+ printf("\n"
+ "* Blender Debug Modes\n"
+ "\n"
+ " Usage:\n"
+ "\n"
+ " blender --debug | -d <modA>[:<levelA>],<modB>[:<levelB>],... [more options]\n"
+ "\n"
+ " Turn on debugging for module <modX>;\n"
+ " if <levelX> is given, set debug level for module <modX> to <levelX>\n"
+ "\n"
+ " Possible Arguments:\n"
+ "\n"
+ " debug -- debug the -d | --debug option itself.\n"
+ " opt -- debug some command line options.\n"
+#ifdef WITH_COMMAND_PORT
+ " bcp -- debug the command port.\n"
+ "\n"
+ " This option has to be used together with `--bcp <port>'.\n"
+ " The following debug verbosity levels are available\n"
+ " for debugging the command port:\n"
+ "\n"
+ " bcp:1 -- print general command port debug messages.\n"
+ " bcp:2 -- print more detailed information about\n"
+ " the evaluation of received commands,\n"
+ " the command packages received from a Blender client and\n"
+ " the result packages sent back to the client\n"
+ " after evaluating the commands.\n"
+ " bcp:3 -- hexdump the received packages before processing them.\n"
+ " bcp:4 -- hexdump the received packages without processing them.\n"
+#endif
+ "\n"
+ );
+}
+
+
double PIL_check_seconds_timer(void);
extern void winlay_get_screensize(int *width_r, int *height_r);

int main(int argc, char **argv)
{

  • int a, i, stax, stay, sizx, sizy;

+ int a, stax, stay, sizx, sizy, i;

	SYS_SystemHandle syshandle;
	Scene *sce;

+ int audio;

+ /* Handle unix and windows style help requests */
+ if (option_is_defined_delete(&argc, argv, "-h", "--help") ||
+ option_is_defined_delete(&argc, argv, "/?", "/help" )
+ ) {
+ print_help();
+ exit(0);
+ }
+
+ /* Handle unix and windows style help requests */
+ if (option_is_defined_delete(&argc, argv, "-hd", "--help=debug")) {
+ print_help_debug();
+ exit(0);
+ }
+
+ /* Handle version request */
+ if (option_is_defined_delete(&argc, argv, "-v", "--version")) {
+ print_version();
+ exit(0);
+ }
+
+ /* Handle debug mode requests */
+ handle_debug_option_delete(&argc, argv);
+
+ /* Handle geometry option */
+ handle_geometry_option_delete(&argc, argv);
+
+#ifdef WITH_COMMAND_PORT
+ /* Handle Blender command port option (dietrich) */
+ handle_commandport_option_delete(&argc, argv);
+#endif
+
#if defined(WIN32) || defined (linux)

  • int audio = 1;

+ audio = 1;
#else

  • int audio = 0;

+ audio = 0;
#endif

@@ -336,28 +453,23 @@

	for(a=1; a<argc; a++) {
  • /* Handle unix and windows style help requests */
  • if ((!strcmp(argv[a], "--help")) || (!strcmp(argv[a], "/?"))){
  • print_help();
  • exit(0);
  • }

+ /* Handle -* switches */
+ if (argv[a][0] == '-') {

  • /* end argument processing after -- */
  • if (!strcmp( argv[a], "--")){
  • a = argc;
  • break;
  • }
  • /* Handle long version request */

+ /* end argument processing after -- */
+ if (!strcmp( argv[a], "--")){
+ a = argc;
+ break;
+ }
+
+ /* Handle long version request */

		if (!strcmp(argv[a], "--version")){
			print_version();
			exit(0);
		}
  • /* Handle -* switches */
  • else if(argv[a][0] == '-') { switch(argv[a][1]) {
  • case 'a': /* -b was not given, play an animation */

+ case 'a': /* -b was not given, play an animation */

				playanim(argc-1, argv+1);
				exit(0);
				break;

@@ -387,12 +499,6 @@

				
				exit(252);
  • case 'h':
  • print_help();
  • exit(0);
  • case 'v':
  • print_version();
  • exit(0); default: break; }

@@ -429,6 +535,12 @@

					a++;
					sizy= atoi(argv[a]);

+ if (debug("opt")) { /* use blender --debug opt ... for debugging (dietrich) */
+ printf("[DEBUG opt] Setting window geometry - "
+ "size <%d, %d>, position: <%d, %d>.\n",
+ sizx, sizy, stax, stay);
+ }
+

					setprefsize(stax, stay, sizx, sizy, 0);
					break;
				case 'd':

@@ -478,6 +590,11 @@

						if (G.f & G_DEBUG) printf("setting audio to: %d\n", audio);
					}
					break;

+ default:
+ printf("\nError: Undefined option: %s\n", argv[a]); /* (dietrich) */
+ printf("Try %s --help for usage information.\n\n", argv[0]);
+ exit(2);
+ break;

				}
			}
		}

@@ -493,7 +610,7 @@

		BIF_init();

	}
  • else {

+ else { /* G.background != 0 */

		BPY_start_python(argc, argv);
		
		// (ton) Commented out. I have no idea whats thisfor... will mail around!

@@ -713,6 +830,13 @@

					printf("\nError: you must specify a path after '- '.\n");
				}
				break;

+
+ default:
+ printf("\nError: Undefined option: %s\n", argv[a]); /* (dietrich) */
+ printf("Try %s --help for usage information.\n\n", argv[0]);
+ exit(2);
+ break;
+

			}
		}
		else {

@@ -784,6 +908,10 @@

		set_scene(sce);
	}

+ /* flush stdout and stderr */
+ fflush(stdout);
+ fflush(stderr);
+

	screenmain();

	return 0;

@@ -812,3 +940,141 @@

	BLI_setInterruptCallBack(blender_test_break);

}
+
+/
+ Init debug mode.
+
+ Parse argv for debug options
+ -d <modules> or
+ -d <modules>:<debug level> or
+ --debug <modules> or
+ --debug <modules>:<debug level>
+ process them
+ and delete them from argv / argc.
+
+ (dietrich)
+*/
+void handle_debug_option_delete(int *argc, char
argv)
+{
+ char* debug_options;
+ int i;
+
+ /* init debug mode */
+ debug_options = get_string_option_delete_allocate(argc, argv, "-d", "--debug");
+
+ if (debug_options != (char*) NULL) {
+
+ G.f |= G_DEBUG; /* std output printf's */
+
+ /* print version */
+ printf ("Blender V %d.%02d\n", G.version/100, G.version%100);
+#ifdef NAN_BUILDINFO
+ printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
+#endif // NAN_BUILDINFO
+
+ MEM_set_memory_debug();
+
+ for (i = 0; i < *argc; i++) {
+ printf("argv[%d] = %s\n", i, argv[i]);
+ }
+
+ /* init the debug mode */
+ init_debug_mode(debug_options);
+
+ /* free memory */
+ free(debug_options);
+ }
+}
+
+/
+ Handle the geometry option.
+
+ Parse argv for command port options
+ -G <width>{xX}<height>][{+-}<xoffset>{+-}<yoffset> or
+ --geometry <width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>
+ delete them from argv / argc and set the Geometry of the Blender window
+ to the given values.
+
+ The values for size and position passed into the function
+ are only changed if the respective values have been specified.
+
+ (dietrich)
+*/
+void handle_geometry_option_delete(int *argc, char
argv)
+{
+ char* geometry;
+ int sizex, sizey, x, y;
+ int debug_level;
+ debug_level = debug("opt"); /* use blender --debug opt ... for debugging */
+
+ /* set defaults */
+
+ /* window default position = lower left corner */
+ x = y = 0;
+
+ /* window default size = maximal size */
+ winlay_get_screensize(&sizex, &sizey);
+
+ /* get the geometry value string */
+ geometry = get_string_option_delete_allocate(argc, argv, "-G", "--geometry");
+
+ if (geometry != (char*) NULL) {
+
+ /* parse the value string,
+ overwrite default values with parsed values and
+ set geometry
+ */
+ if (parse_geometry(geometry, &sizex, &sizey, &x, &y)) {
+
+ if (debug_level) {
+ printf("[DEBUG opt] Setting window geometry - "
+ "size <%d, %d>, position: <%d, %d>.\n",
+ sizex, sizey, x, y);
+ }
+
+ setprefsize(x, y, sizex, sizey, 0);
+
+ } else {
+
+ /* the geometry string is ill-formed -
+ print an error message and exit
+ */
+ printf("\nError: Ill-formed geometry value: %s\n", geometry);
+ printf("\n");
+ printf(" try something like:\n");
+ printf(" --geometry 800x600\n");
+ printf(" --geometry +10+20\n");
+ printf(" --geometry 800x600+10+20\n");
+ printf("\n");
+ exit(2);
+ }
+ }
+}
+
+#ifdef WITH_COMMAND_PORT
+/
+ Handle command port options.
+
+ Parse argv for command port options
+ -c <port number> or
+ --bcp <port number>
+ and delete them from argv / argc.
+ If the options have been given, init the command port.
+
+ (dietrich)
+*/
+void handle_commandport_option_delete(int *argc, char
argv)
+{
+ /* get the port number */
+ unsigned short port;
+ port = (unsigned short) get_int_option_delete(argc, argv, "-c", "--bcp");
+
+ /* do nothing if the bcp option hasn't been found */
+ if (port == 0) return;
+
+ /* init the command port */
+ commandport_init(port);
+}
+#endif
+
+/* fin */

Index: source/creator/SConscript

  • source/creator/SConscript (revision 13338)

+++ source/creator/SConscript (working copy)
@@ -15,6 +15,10 @@

    incs += ' ' + env['BF_QUICKTIME_INC']
    defs.append('WITH_QUICKTIME')

+# command port (dietrich)
+if env['WITH_COMMAND_PORT'] == 1:
+ incs += ' ../blender/commandport/include'
+
if env['WITH_BF_BINRELOC']==1:

incs += ' ../../extern/binreloc/include'
defs.append('WITH_BINRELOC')

Index: source/blender/include/mydevice.h

  • source/blender/include/mydevice.h (revision 13338)

+++ source/blender/include/mydevice.h (working copy)
@@ -35,8 +35,9 @@

    • The Original Code is: all of this file.
  • * Contributor(s): none yet.
  • *

+ * Contributor(s):
+ * - Dietrich Bollmann - added command port queue event definition (COMMAND_PORT_INPUT)
+ *

  • * END GPL/BL DUAL LICENSE BLOCK * */

@@ -207,6 +208,9 @@
#define UI_BUT_EVENT 0x4008
#define AUTOSAVE_FILE 0x4009
#define UNDOPUSH 0x400A
+#ifdef WITH_COMMAND_PORT
+#define COMMAND_PORT_INPUT 0x400B /* (dietrich) */
+#endif

/* REDRAWVIEW3D has to be the first one (lowest number) for buttons! */
#define REDRAWVIEW3D 0x4010

Index: source/blender/include/BIF_mainqueue.h

  • source/blender/include/BIF_mainqueue.h (revision 13338)

+++ source/blender/include/BIF_mainqueue.h (working copy)
@@ -27,7 +27,10 @@

    • The Original Code is: all of this file.
  • * Contributor(s): none yet.

+ * Contributor(s):
+ * - Dietrich Bollmann
+ * - added thread protection (mainqueue_mutex) for main queue.
+ * - added the new parameter 'args' to pass an argument struct pointer

  • * END GPL/BL DUAL LICENSE BLOCK * */

@@ -37,11 +40,26 @@

#define MAXQUEUE 4096

-unsigned short mainqtest (void);
-unsigned short mainqread (short *val, char *ascii);
-void mainqenter (unsigned short event, short val);
-void mainqenter_ext (unsigned short event, short val, char ascii);
-void mainqpushback (unsigned short event, short val, char ascii);
+unsigned short mainqtest (void);
+unsigned short mainqread (short *val, char *ascii);
+unsigned short mainqread_args (short *val, char *ascii
+#ifdef WITH_COMMAND_PORT
+ , void** args
+#endif
+ );
+void mainqenter (unsigned short event, short val);
+void mainqenter_ext (unsigned short event, short val, char ascii);
+void mainqenter_args (unsigned short event, short val, char ascii
+#ifdef WITH_COMMAND_PORT
+ , void* args
+#endif
+ );
+void mainqpushback (unsigned short event, short val, char ascii);
+void mainqpushback_args (unsigned short event, short val, char ascii
+#ifdef WITH_COMMAND_PORT
+ , void* args
+#endif
+ );

#endif /* BIF_MAINQUEUE_H */

Index: source/blender/src/mainqueue.c

  • source/blender/src/mainqueue.c (revision 13338)

+++ source/blender/src/mainqueue.c (working copy)
@@ -25,7 +25,10 @@

    • The Original Code is: all of this file.
  • * Contributor(s): none yet.

+ * Contributor(s):
+ * - Dietrich Bollmann
+ * - added thread protection (mainqueue_mutex) for main queue.
+ * - added the new parameter 'args' to pass an argument struct pointer

  • * END GPL/BL DUAL LICENSE BLOCK *

@@ -35,16 +38,58 @@

#include <stdlib.h>
#include <string.h>
+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+#include <pthread.h>
+#endif
+#include <stdio.h>
+
#include "BIF_mainqueue.h"

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+/
+ Using a mutex to protect the mainqueue against simultaneous access
+ by different threads:
+*/
+pthread_mutex_t mainqueue_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/

+ Locking the mutex
+ protecting the mainqueue against access by multiple threads.
+*/
+void lock_mainqueue_mutex()
+{
+ if ( pthread_mutex_lock( &mainqueue_mutex ) ) {
+ perror( "Error: couldn't lock the mainqueue mutex!" );
+ exit( 1 );
+ }
+}
+
+/**
+ Unlocking the mutex
+ protecting the mainqueue against access by multiple threads.
+*/
+void unlock_mainqueue_mutex()
+{
+ if ( pthread_mutex_unlock( &mainqueue_mutex ) ) {
+ perror( "Error: couldn't unlock the mainqueue mutex!" );
+ exit( 1 );
+ }
+}
+#endif
+
typedef struct {

  • unsigned short event;
  • short val;
  • char ascii;

+ unsigned short event;
+ short val;
+ char ascii;
+#ifdef WITH_COMMAND_PORT
+ void* args;
+#endif
} QEvent;

static QEvent mainqueue[MAXQUEUE];
@@ -52,51 +97,154 @@

unsigned short mainqread(short *val, char *ascii)
{
+ void* dummy;
+ return mainqread_args(val, ascii
+#ifdef WITH_COMMAND_PORT
+ , &dummy
+#endif
+ );
+}
+
+unsigned short mainqread_args(short *val, char *ascii
+#ifdef WITH_COMMAND_PORT
+ , void** args
+#endif
+ )
+{
+ unsigned short event = 0;
+
+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+ lock_mainqueue_mutex();
+ /* begin of critical section */
+#endif
+

	if (nevents) {
		nevents--;
  • *val= mainqueue[nevents].val;
  • *ascii= mainqueue[nevents].ascii;

+ *val = mainqueue[nevents].val;
+ *ascii = mainqueue[nevents].ascii;
+#ifdef WITH_COMMAND_PORT
+ *args = mainqueue[nevents].args;
+#endif

		if((*ascii<32)||(*ascii==127)) *ascii=0;
  • return mainqueue[nevents].event;
  • } else
  • return 0;

+ event = mainqueue[nevents].event;
+ }
+
+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+ /* end of critical section */
+ unlock_mainqueue_mutex();
+#endif
+
+ return event;
}

void mainqenter(unsigned short event, short val)
{

  • mainqenter_ext(event, val, 0);

+ mainqenter_args(event, val, 0
+#ifdef WITH_COMMAND_PORT
+ , NULL
+#endif
+ );
}

void mainqenter_ext(unsigned short event, short val, char ascii)
{
+ mainqenter_args(event, val, ascii
+#ifdef WITH_COMMAND_PORT
+ , NULL
+#endif
+ );
+}
+
+void mainqenter_args(unsigned short event, short val, char ascii
+#ifdef WITH_COMMAND_PORT
+ , void* args
+#endif
+ )
+{

	if (!event)
		return;

+#ifdef WITH_MULTI_THREADING_SUPPORT
+ lock_mainqueue_mutex();
+ /* begin of critical section */
+#endif
+

	if (nevents<MAXQUEUE) {

+

		memmove(mainqueue+1, mainqueue, sizeof(*mainqueue)*nevents);
  • mainqueue[0].event= event;
  • mainqueue[0].val= val;
  • mainqueue[0].ascii= ascii;

+ mainqueue[0].event = event;
+ mainqueue[0].val = val;
+ mainqueue[0].ascii = ascii;
+#ifdef WITH_COMMAND_PORT
+ mainqueue[0].args = args;
+#endif

		
		nevents++;
	}

+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+ /* end of critical section */
+ unlock_mainqueue_mutex();
+#endif
}

void mainqpushback(unsigned short event, short val, char ascii)
{
+ mainqpushback_args(event, val, ascii
+#ifdef WITH_COMMAND_PORT
+ , NULL
+#endif
+ );
+}
+
+void mainqpushback_args(unsigned short event, short val, char ascii
+#ifdef WITH_COMMAND_PORT
+ , void* args
+#endif
+ )
+{
+#ifdef WITH_MULTI_THREADING_SUPPORT
+ lock_mainqueue_mutex();
+ /* begin of critical section */
+#endif
+

	if (nevents<MAXQUEUE) {
  • mainqueue[nevents].event= event;
  • mainqueue[nevents].val= val;
  • mainqueue[nevents].ascii= ascii;

+ mainqueue[nevents].event = event;
+ mainqueue[nevents].val = val;
+ mainqueue[nevents].ascii = ascii;
+#ifdef WITH_COMMAND_PORT
+ mainqueue[nevents].args = args;
+#endif

		nevents++;
	}

+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+ /* end of critical section */
+ unlock_mainqueue_mutex();
+#endif
}

unsigned short mainqtest()
{
+ unsigned short event = 0;
+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+ lock_mainqueue_mutex();
+ /* begin of critical section */
+#endif
+

	if (nevents)
  • return mainqueue[nevents-1].event;
  • else
  • return 0;

+ event = mainqueue[nevents-1].event;
+
+#ifdef WITH_MULTI_THREADING_SUPPORT
+ /* end of critical section */
+ unlock_mainqueue_mutex();
+#endif
+
+ return event;
}
+
+/* fin */

Index: source/blender/src/SConscript

  • source/blender/src/SConscript (revision 13338)

+++ source/blender/src/SConscript (working copy)
@@ -33,6 +33,10 @@
incs += ' ' + env['BF_SDL_INC']
incs += ' ' + env['BF_OPENGL_INC']

+# command port (dietrich)
+if env['WITH_COMMAND_PORT'] == 1:
+ incs += ' ../commandport/include'
+
defs = []

if env['BF_TWEAK_MODE'] == 1:

Index: source/blender/src/editscreen.c

  • source/blender/src/editscreen.c (revision 13338)

+++ source/blender/src/editscreen.c (working copy)
@@ -25,7 +25,8 @@

    • The Original Code is: all of this file.
  • * Contributor(s): none yet.

+ * Contributor(s):
+ * - Dietrich Bollmann - added command port functionality.

  • * END GPL/BL DUAL LICENSE BLOCK *
  • All screen functions that are related to the interface

@@ -111,6 +112,10 @@
#include "mydevice.h"
#include "blendef.h"

+#ifdef WITH_COMMAND_PORT
+#include "commandport.h" /* the Blender command port (dietrich) */
+#endif
+
#include "winlay.h"

/* TIPS:
@@ -141,6 +146,12 @@
/* prototypes -------------------*/
int afterqtest(short win, unsigned short evt);
unsigned short screen_qread(short *val, char *ascii);
+unsigned short screen_qread_args(short *val, char *ascii
+#ifdef WITH_COMMAND_PORT
+ , void** args /* (dietrich) */
+#endif
+ );
+unsigned short filter_event(unsigned short event, short val);
void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii);
static void drawscredge_area(ScrArea *sa);

@@ -947,35 +958,88 @@

	return 0;

}

+/**
+ busy waiting for new events.
+
+ Note: The blocking GHOST event processing is
+ implemented in the same way using busy waiting (polling)
+ on the GHOST event queue. Doing the same on the Blender
+ event queue makes it possible to also react to events
+ inserted into the Blender main event queue by parallel
+ threads - for example the Blender command port thread.
+
+ Added to make the command port work :)
+ (dietrich)
+*/
+static void wait_for_event()
+{
+ while (!mainqtest()) {
+ PIL_sleep_ms(5); /* sleep for 5 milliseconds */
+ winlay_process_events(0); /* if there are events in the GHOST queue,
+ (non-blocking polling of GHOST events)
+ preprocess them and copy them over
+ into the Blender main event queue.
+ */
+ }
+}
+
+/*
+ Original version - not reacting on events inserted into the
+ Blender main event by other threads.
+
static void wait_for_event(void)
{

	while (!mainqtest()) {
		winlay_process_events(1);
	}

}
+*/

-unsigned short screen_qread(short *val, char *ascii)
+unsigned short screen_qread(short* val, char* ascii)
{
+ void* dummy;
+ return screen_qread_args(val, ascii
+#ifdef WITH_COMMAND_PORT
+ , &dummy
+#endif
+ );
+}
+
+unsigned short screen_qread_args(short* val, char* ascii
+#ifdef WITH_COMMAND_PORT
+ , void** args
+#endif
+ )
+{

	unsigned short event;

	wait_for_event();
  • event= mainqread(val, ascii);

+ event = mainqread_args(val, ascii
+#ifdef WITH_COMMAND_PORT
+ , args
+#endif
+ );

+ return filter_event(event, *val);
+}
+
+unsigned short filter_event(unsigned short event, short val)
+{

	if(event==RIGHTSHIFTKEY || event==LEFTSHIFTKEY) {
  • if(*val) G.qual |= LR_SHIFTKEY;

+ if (val) G.qual |= LR_SHIFTKEY;

		else G.qual &= ~LR_SHIFTKEY;
	}
	else if(event==RIGHTALTKEY || event==LEFTALTKEY) {
  • if(*val) G.qual |= LR_ALTKEY;

+ if (val) G.qual |= LR_ALTKEY;

		else G.qual &= ~LR_ALTKEY;
	}
	else if(event==RIGHTCTRLKEY || event==LEFTCTRLKEY) {
  • if(*val) G.qual |= LR_CTRLKEY;

+ if (val) G.qual |= LR_CTRLKEY;

		else G.qual &= ~LR_CTRLKEY;
	}
	else if(event==COMMANDKEY) {		// OSX
  • if(*val) G.qual |= LR_COMMANDKEY;

+ if (val) G.qual |= LR_COMMANDKEY;

		else G.qual &= ~LR_COMMANDKEY;
	}

@@ -1283,19 +1347,38 @@

	int firsttime = 1;
	int onload_script = 0;

+#ifdef WITH_COMMAND_PORT
+ /* Start the command port.
+
+ Note: The command port will be started only if the option
+ -c <port> or --bcp <port>
+ was specified on the command line.
+
+ (dietrich)
+ */
+ commandport_start();
+#endif
+

	window_make_active(mainwin);
	
	while (1) {
		unsigned short event;
		short val, towin;
		char ascii;

+#ifdef WITH_COMMAND_PORT
+ void* args;
+#endif

		flush_extqd_events();
		if (nafterqitems && !qtest()) {
			append_afterqueue();
			event= val= ascii= 0;
		} else {
  • event= screen_qread(&val, &ascii);

+ event= screen_qread_args(&val, &ascii
+#ifdef WITH_COMMAND_PORT
+ , &args
+#endif
+ );

		}
		
		// window_make_active(mainwin); // (only for inputchange, removed, (ton))

@@ -1384,6 +1467,12 @@

			BIF_read_file(ext_load_str);
			sound_initialize_sounds();
		}

+#ifdef WITH_COMMAND_PORT
+ else if (event == COMMAND_PORT_INPUT) {
+ /* handle Blender command port input (dietrich) */
+ commandport_handle_input_allocate(args);
+ }
+#endif

		else if ((event==ONLOAD_SCRIPT) && BPY_has_onload_script()) {
			/* event queued in setup_app_data() in blender.c, where G.f is checked */
			onload_script = 1;

@@ -2133,10 +2222,10 @@
void BIF_wait_for_statechange(void)
{

	if (!statechanged) {
  • /* Safety, don't wait more than 0.1 seconds */

+ /* Safety, don't wait more than 0.1 seconds */

		double stime= PIL_check_seconds_timer();
		while (!statechanged) {
  • winlay_process_events(1);

+ wait_for_event();

			if ((PIL_check_seconds_timer()-stime)>0.1) break;
		}
		statechanged= 0;

Index: source/blender/src/usiblender.c

  • source/blender/src/usiblender.c (revision 13338)

+++ source/blender/src/usiblender.c (working copy)
@@ -25,7 +25,8 @@

    • The Original Code is: all of this file.
  • * Contributor(s): none yet.

+ * Contributor(s):
+ * - Dietrich Bollmann - added cleanup code for debug mode and command port.

  • * END GPL/BL DUAL LICENSE BLOCK * */

@@ -143,6 +144,11 @@
#include "radio.h"
#include "datatoc.h"

+#ifdef WITH_COMMAND_PORT
+#include "UTL_debug.h" /* debug module (dietrich) */
+#include "commandport.h" /* Blender command port (dietrich) */
+#endif
+
#include "SYS_System.h"

#include "PIL_time.h"
@@ -956,7 +962,13 @@
void exit_usiblender(void)
{

	struct TmpFont *tf;
  • tf= G.ttfdata.first;

+
+#ifdef WITH_COMMAND_PORT
+ /* cleanup the command port (dietrich) */
+ commandport_destroy();
+#endif
+
+ tf = G.ttfdata.first;

	while(tf)
	{
		freePackedFile(tf->pf);

@@ -1053,6 +1065,14 @@

		MEM_printmemlist();
	}
	delete_autosave();

+
+ /* free debug module
+ see:
+ - blender/source/blender/include/UTL_debug.h
+ - blender/source/blender/blenkernel/intern/debug.c
+ (dietrich)
+ */
+ cleanup_debug_mode();

	
	printf("\nBlender quit\n");

Index: source/blender/src/buttons_scene.c

  • source/blender/src/buttons_scene.c (revision 13338)

+++ source/blender/src/buttons_scene.c (working copy)
@@ -2428,7 +2428,8 @@

				uiDefButI(block, NUM, B_DIFF, "Count:", 170,85,140,20, &G.scene->r.GIphotoncount, 
						0, 10000000, 10, 10, "Number of photons to shoot");
				if(G.scene->r.GIphotonradius==0.0) G.scene->r.GIphotonradius=1.0;
  • uiDefButF(block, NUMSLI, B_DIFF,"Radius:", 170,60,140,20, &(G.scene->r.GIphotonradius),

+ /* (dietrich) changed NUMSLI to NUM as there was no place to display the value */
+ uiDefButF(block, NUM /*SLI*/, B_DIFF,"Radius:", 170,60,140,20, &(G.scene->r.GIphotonradius),

						0.00001, 100.0 ,0,0, "Radius to search for photons to mix (blur)");
				if(G.scene->r.GImixphotons==0) G.scene->r.GImixphotons=100;
				uiDefButI(block, NUM, B_DIFF, "MixCount:", 170,35,140,20, &G.scene->r.GImixphotons,

Index: source/blender/src/eventdebug.c

  • source/blender/src/eventdebug.c (revision 13338)

+++ source/blender/src/eventdebug.c (working copy)
@@ -190,6 +190,9 @@

	smap(ENDKEY);
	smap(REDRAWNLA);
	smap(ONLOAD_SCRIPT);

+#ifdef WITH_COMMAND_PORT
+ smap(COMMAND_PORT_INPUT); /* (dietrich) */
+#endif

	}
	#undef smap

}

Index: source/blender/SConscript

  • source/blender/SConscript (revision 13338)

+++ source/blender/SConscript (working copy)
@@ -31,3 +31,8 @@

if env['WITH_BF_QUICKTIME'] == 1:

SConscript (['quicktime/SConscript'])

+
+# command port (dietrich)
+if env['WITH_COMMAND_PORT'] == 1:
+ SConscript (['commandport/SConscript'])
+

Index: config/win32-vc-config.py

  • config/win32-vc-config.py (revision 13338)

+++ config/win32-vc-config.py (working copy)
@@ -175,3 +175,15 @@

BF_BUILDDIR = '..\\build\\win32-vc'
BF_INSTALLDIR='..\\install\\win32-vc'
+
+# command port (dietrich)
+WITH_COMMAND_PORT = 'false'
+
+# blash - the blender python shell (relies on the command port) (dietrich)
+WITH_BLASH = 'false'
+
+# libraries needed by 'readline' (dietrich)
+# which libraries are necessary for 'readline'? - in the case of linux:
+# todo: READLINE_LIB = 'readline curses'
+
+# fin.

Index: config/linuxcross-config.py

  • config/linuxcross-config.py (revision 13338)

+++ config/linuxcross-config.py (working copy)
@@ -137,3 +137,14 @@

BF_BUILDDIR = '../build/linuxcross'
BF_INSTALLDIR='../install/linuxcross'
+
+# command port (dietrich)
+WITH_COMMAND_PORT = 'false'
+
+# blash - the blender python shell (relies on the command port) (dietrich)
+WITH_BLASH = 'false'
+
+# libraries needed by 'readline' (dietrich)
+READLINE_LIB = 'readline curses'
+
+# fin.

Index: config/sunos5-config.py

  • config/sunos5-config.py (revision 13338)

+++ config/sunos5-config.py (working copy)
@@ -169,3 +169,15 @@

PLATFORM_LINKFLAGS = ['']
+
+# command port (dietrich)
+WITH_COMMAND_PORT = 'false'
+
+# blash - the blender python shell (relies on the command port) (dietrich)
+WITH_BLASH = 'false'
+
+# libraries needed by 'readline' (dietrich)
+# which libraries are necessary for 'readline'? - in the case of linux:
+READLINE_LIB = 'readline curses'
+
+# fin.

Index: config/openbsd3-config.py

  • config/openbsd3-config.py (revision 13338)

+++ config/openbsd3-config.py (working copy)
@@ -158,3 +158,15 @@

BF_BUILDDIR='../build/openbsd3'
BF_INSTALLDIR='../install/openbsd3'
+
+# command port (dietrich)
+WITH_COMMAND_PORT = 'false'
+
+# blash - the blender python shell (relies on the command port) (dietrich)
+WITH_BLASH = 'false'
+
+# libraries needed by 'readline' (dietrich)
+# which libraries are necessary for 'readline'? - in the case of linux:
+READLINE_LIB = 'readline curses'
+
+# fin.

Index: config/linux2-config.py

  • config/linux2-config.py (revision 13338)

+++ config/linux2-config.py (working copy)
@@ -175,3 +175,12 @@
#Link against pthread
PLATFORM_LINKFLAGS = ['-pthread']

+# command port (dietrich)
+WITH_COMMAND_PORT = 'false'
+
+# blash - the blender python shell (relies on the command port) (dietrich)
+WITH_BLASH = 'false'
+
+# libraries needed by 'readline' (dietrich)
+READLINE_LIB = 'readline curses'
+

Index: config/win32-mingw-config.py

  • config/win32-mingw-config.py (revision 13338)

+++ config/win32-mingw-config.py (working copy)
@@ -158,3 +158,15 @@

BF_BUILDDIR = '..\\build\\win32-mingw'
BF_INSTALLDIR='..\\install\\win32-mingw'
+
+# command port (dietrich)
+WITH_COMMAND_PORT = 'false'
+
+# blash - the blender python shell (relies on the command port) (dietrich)
+WITH_BLASH = 'false'
+
+# libraries needed by 'readline' (dietrich)
+# which libraries are necessary for 'readline'? - in the case of linux:
+# todo: READLINE_LIB = 'readline curses'
+
+# fin.

Index: config/darwin-config.py

  • config/darwin-config.py (revision 13338)

+++ config/darwin-config.py (working copy)
@@ -183,3 +183,15 @@

BF_BUILDDIR='../build/darwin'
BF_INSTALLDIR='../install/darwin'
+
+# command port (dietrich)
+WITH_COMMAND_PORT = 'false'
+
+# blash - the blender python shell (relies on the command port) (dietrich)
+WITH_BLASH = 'false'
+
+# libraries needed by 'readline' (dietrich)
+# which libraries are necessary for 'readline'? - in the case of linux:
+READLINE_LIB = 'readline curses'
+
+# fin.

Index: SConstruct

  • SConstruct (revision 13338)

+++ SConstruct (working copy)
@@ -24,7 +24,9 @@

  1. The Original Code is: all of this file.
  2. Contributor(s): Nathan Letwory.

+# Contributor(s):
+# - Nathan Letwory.
+# - Dietrich Bollmann: added building instructions for the command port and blash (2007/05/01).

  1. * END GPL/BL DUAL LICENSE BLOCK *

@@ -58,9 +60,12 @@

B.possible_types = ['core', 'common', 'blender', 'intern',

'international', 'game', 'game2',
  • 'player', 'player2', 'system']

+ 'player', 'player2', 'system',
+ 'blash']

-B.binarykind = ['blender' , 'blenderplayer']
+B.binarykind = ['blender' , 'blenderplayer',
+ 'blash'] # (dietrich)
+

  1. target and argument validation #

@@ -230,6 +235,10 @@
if 'blendernogame' in B.targets:

    env['WITH_BF_GAMEENGINE'] = False

+# blash - the blender python shell (dietrich)
+if env['WITH_COMMAND_PORT'] and 'blash' in B.targets:
+ env['WITH_BLASH'] = True
+

  1. lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep) B.root_build_dir = env['BF_BUILDDIR']

@@ -310,6 +319,11 @@

    playerlist = B.create_blender_liblist(env, 'player')
    env.BlenderProg(B.root_build_dir, "blenderplayer", dobj + playerlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blenderplayer')

+# blash - the blender python shell (dietrich)
+if env['WITH_COMMAND_PORT'] and env['WITH_BLASH']:
+ blashlist = B.create_blender_liblist(env, 'blash')
+ env.BlenderProg(B.root_build_dir, "blash", dobj + blashlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blash')
+

  1. Now define some targets

@@ -335,6 +349,7 @@

  1. .blender dotblendlist = [] dottargetlist = []

+
for dp, dn, df in os.walk('bin/.blender'):

if 'CVS' in dn:
    dn.remove('CVS')

@@ -432,8 +447,15 @@

    blendernogame = env.Alias('blendernogame', B.program_list)
    Depends(blendernogame,installtarget)

+
+if env['WITH_COMMAND_PORT'] and env['WITH_BLASH']: # (dietrich)
+ blenderplayer = env.Alias('blash', B.program_list)
+ Depends(blenderplayer,installtarget)
+
+
Depends(nsiscmd, allinstall)

+
Default(B.program_list)

if not env['WITHOUT_BF_INSTALL']:

Hi John Connors,

> The patch doesn't seem to be as bad as it looks;

Thank you (...or should I be angry? :)

> there were very few conflicts when I applied it and updated to current blender svn. I've attached a diff.

Does this mean that something of the code ended up in the blender repository?

After getting no further comment I gave up any hope for it a while ago. So, coming back to this place by chance today, I am quite astonished that somebody had looked at it again :)

As the command port (in a slightly newer version) together with blender works for me as it is, I stopped to develop it further and concentrated on the other side: the blender client I was developing it for.

But of course, if you think to integrate it into blender I am happy to use some time (don't have so much in the moment though) to change it into something you can imagine to make part of the official blender release.

Or - as Stephen Swaney puts it (hello Stephen Swaney :) - to "stripp[...] (it) down to a single feature". I just need to know more exactly what kind of feature you want me to strip it down to :)

Thank you! ...and best wishes, Dietrich

Alas, its not part of Blender. I was just verifying the patch still works ok with more recent versions of Blender than 2.44, in spite of it's size.

It's an interesting thing and might be useful for a project of my own. The patch wouldn't get accepted until its more slimmed down and tested on other platforms, I guess.

Hi John Connors,

> Alas, its not part of Blender. I was just verifying the patch still
> works ok with more recent versions of Blender than 2.44, in spite of
> it's size.

...and did it work? Which platform did you use?

> It's an interesting thing and might be useful for a project of my
> own. The patch wouldn't get accepted until its more slimmed down and
> tested on other platforms, I guess.

I only have Linux so I can't do that myself. And other people seem
not to be interested in the command port.

It would be simple to get rid of my debug option - which actually is
very helpful - and my option parsing code - which probably is better
than what blender uses in the moment (I personally would prefer GNU
getopt() though), but as long as I do not know what the blender team
actually thinks and wants I doubt that it makes sense to change the
code.

I do not believe that the patch would be accepted anyway [1] and
therefor continue to use and develop my own private blender branch for
the stuff I need [2].

But who knows, may be some day things change :)

Thanks for your interest!

Dietrich

[1] The reason that I do not believe in the acceptance of the patch is
that I am using threads which seem to be deprecated by the blender
team.

I run the server in its own thread and blender with its main loop in
another because I neither like polling nor the complicated and
confusing way, the blender event loop currently is organised. I
therefor had to make the event queue thread save - and I have the
impression that this is not appreciated by the official developers.

[2] It would be nice if it was possible for people interested in
blender development to work on their own branch. I could start a
command port branch which would make it easy for others to use the
command port and for me to adapt the code to the current state of the
svn. It also would be easier to discuss changes which would be
necessary to bring the patch into the tunk as well as to implement
these changes.

Hi,

Here comes a new version of the command port patch.

I adapted the patch to the current state of the blender repository
(Blender 2.46, revision 15538) and, following the advice of Stephen
Swaney "It is easier to wade thru patches if they
deal with a single topic." (Stephen, 2007/08/17), "stripped [it] down to a single feature."
(Stephen, 2007/12/09).

Hope it gets accepted this time :)

Cheers, Dietrich


Example - a simple pyramid

The following example shows how the command port can be used
to model a simple pyramid:

- start the Blender server in some xterm

$ blender -w -p 10 10 800 600 --command-port 6789 &

and erase the default cube

- start blash in another xterm

$ blash --port 6789
This is Blash - the GNU BLender-Again SHell :)
Connection to Blender Server established. (IP address: 127.0.0.1, port: 6789)

- enter blender python commands

from Blender import *

vertexes = [[1, 1, 0], [-1, 1, 0], [-1, -1, 0], [1, -1, 0], [0, 0, 1.27]]
faces = [[3, 2, 1, 0], [0, 1, 4], [1, 2, 4], [2, 3, 4], [3, 0, 4]]

mesh = Mesh.New('mesh')
mesh.verts.extend(vertexes)
mesh.faces.extend(faces)

scene = Scene.GetCurrent()
object = scene.objects.new(mesh, 'object')
Redraw()

bye


Installation

- make a directory to build Blender

BCP=$HOME/bcp
mkdir -p $BCP
cd $BCP

- download the sources of blender 2.46 revision 15538

svn checkout https://svn.blender.org/svnroot/bf-blender/trunk/blender@15538

- download blender command port patch

wget http://formgames.org/blender/command-port/patches/blender-command-port-patch.2008-07-12.2.46.r15538.txt

- patch the sources

cd blender
patch -p0 < ../blender-command-port-patch.2008-07-12.2.46.r15538.txt

- build blash and blender

scons WITH_COMMAND_PORT=true blash

- the (linux) binaries

$BCP/install/linux2/blender
$BCP/install/linux2/blash

Note: If you want to try the patch with a newer state of the blender
sources you might update your copy with svn update and rebuild. If you
are lucky the patch still works...

For more information see the blender command port page
at http://formgames.org/blender/command-port/

A review gave following considerations;

It's basically a good idea, but the patch is gigantic, changing a lot of internals, which is unknown if that's going to be maintained. For an option that not many people will use too problematic. My reason to close this one for now.

The good news is that a similar functionality (commandline python editing) is on the wishlist in Blender itself. After that, an external console should be easy.

Ton Roosendaal (ton) closed this task as "Archived".Sep 18 2008, 7:49 PM

A review gave following considerations;

It's basically a good idea, but the patch is gigantic, changing a lot of internals, which is unknown if that's going to be maintained. For an option that not many people will use too problematic. My reason to close this one for now.

The good news is that a similar functionality (commandline python editing) is on the wishlist in Blender itself. After that, an external console should be easy.

...here:

- http://lists.blender.org/pipermail/bf-committers/2008-September/thread.html#21758
- http://lists.blender.org/pipermail/bf-committers/2008-September/thread.html#21783

...hey Ton - this is not to offend you or to protest against / revert your decision!!! We all love you and I am doing
this just for "hyper linking" things. If I can, I will close it immediatly after again ... we will see ...

...and than, some nice guy wrote ( http://lists.blender.org/pipermail/bf-committers/2008-September/021761.html ):

On Fri, 2008-09-19 at 09:56 +0200, Ton Roosendaal wrote:
> Hi,
>
> You can reply in the tracker if you have questions.

...snip...

> Further I'm also human and can make mistakes! Maybe your patch is
> great, but then try to find people in the active developer/user
> community to review and use it?
>
> -Ton-

Actually there have been such people. See here for example:

- http://lists.blender.org/pipermail/bf-committers/2008-April/020758.html
- http://lists.blender.org/pipermail/bf-committers/2008-July/021401.html

(and you have been one of them a long time ago replying to some messages from Martin DeMello - which I do not find
anymore).

Best wishes, Dietrich :)


By the way - as I am already collecting thing related -
All started with the following message a long time ago:

| Subject: [Bf-committers] listener object
| ---
| I'd like to add a "listener" object to blender, to allow a script to
| be triggered by an external program writing to a socket. (Not
| necessarily proposing this be added to blender proper, but it would be
| very useful for my own copy.) Is this an intrinsically dangerous idea?
| (i.e. could it cause instability or crashes in blender?) If not, how
| would I go about doing it? (i.e., where in the code should I be
| looking to add something like this?)
|
| martin

...which was received very positively by Ton - and probably has been lost in some corner of the internet :(

---
PS:

By fault I submitted this also as a "new patch" here: https://projects.blender.org/tracker/index.php?func=detail&aid=17664&group_id=9&atid=127 :( ... sorry!

Hi,

I put the command port patch on launchpad for easy upgrade.

Here is the link:

https://code.launchpad.net/~diresu/blender/blender-command-port

If some day later you feel like using it - please feel free to get it from there :)

Thanks for your hard work on developing blender!

With best wishes,

Dietrich

i'm testing this on win32 now, had to put a lot of stuff from gnuwin32 to satisfy posix dependencies, and commented out stuff that uses readline.

compiles now, failed to open a socket for some reason, i hope that works with the previous revision (which seemed to me be just changes in Bleneder, not in command port) like Dietrich says on the Bazaar page, will try that next. as there's no changes in commandport this same patch should apply.

note: this is not a proper patch to make command port crossplatform, but just a hack to get to test it on win, and does serve to point out the problem points so that a proper crossplat version can be made.

i was surprised to see how much low level string handling and socket stuff there is in this patch (or a plugin..) in c - would it be possible to do the networking in python instead, and just modify the core of blender so that it can call the networking in the mainloop? would ease crossplatformness. or how do you think this sort of stuff should be made in 2.5?

Hi Toni,

Thank you very much for the efforts you put into the command port code!

> Date: 2009-09-11 09:02
> Sender: Toni Alatalo
>
> i'm testing this on win32 now, had to put a lot of stuff from
> gnuwin32 to satisfy posix dependencies, and commented out stuff
> that uses readline.

For porting blash to Windows this looks like a good strategy: Getting
rid of everything not essential, making the code work on windows and
later reintegrate step by step those things which are useful for the
command port functionality.

On the long term though the possibility to edit the command line of
the command port shell client (blash) is a very useful feature to
have and it would be painful to use blash without it.

That said, I have to admit that I use blash never directly but from
emacs together with a variant of the emacs python mode and therefore
personally don't rely on this feature... I also use the command port
from a common lisp client which speaks the "command port protocol"
itself and doesn't rely on blash at all.

There is a readline library for windows: "Readline for Windows"
http://gnuwin32.sourceforge.net/packages/readline.htm . I never
tried it though as I don't own a windows machine.

> compiles now, failed to open a socket for some reason, i hope
> that works with the previous revision (which seemed to me be
> just changes in Bleneder, not in command port) like Dietrich
> says on the Bazaar page, will try that next. as there's no changes
> in commandport this same patch should apply.

As you observed, beyond the correction of merge conflicts and
bug-fixes, there have been more or less no changes concerning the
command port code during most of the updates on launchpad.

The only two reasons for this branch to exist are

- the possibility to easily update the code to the newest state off
the blender main repository using the automatic launchpad import
branch. By the way: using git or some other distributed version
control system at the place of svn would be a great help for all
developers not being part of the main developer group!

- to publish the newest code for other users of the command port
branch.

So there probably is no need to check the previous revision.

To make the socket code work on Windows it is probably easier to first
port the socket modules independent from the rest of the command port
code - or, as you proposed later, to switch to some other socket
library / inter-process communication system.

> note: this is not a proper patch to make command port crossplatform,
> but just a hack to get to test it on win, and does serve to point
> out the problem points so that a proper crossplat version can
> be made.

I worked for a while on a port for blender 2.5. But than I god too
busy (better too poor) to continue. And as the command port works
fine for me and the blender team seemed to not be interested in this
functionality anyway I postponed further development. If you really
plan to write a crossplat version, I can try to find some time to
continue the port to the 2.5 code base.

The new code adds another event queue to the queues already existing
in blender 2.5. The queue is thread safe and therefor can be written
to by the blender server thread which runs independent from the main
blender thread in its own loop.

> i was surprised to see how much low level string handling and
> socket stuff there is in this patch (or a plugin..) in c - would
> it be possible to do the networking in python instead, and just
> modify the core of blender so that it can call the networking
> in the mainloop? would ease crossplatformness. or how do you
> think this sort of stuff should be made in 2.5?

It would be possible - and a very good idea indeed :)

When I started to work on the patch, I had the impression that the
blender team would prefer a pure C version which doesn't make use of
yet another bunch of libraries. It probably would have been a better
idea to get into touch with the blender developers as fast as
possible at the place of confronting them with the finished patch...

If I would start from scratch again I would use C++ (my C code tries
to use C in an object oriented style), D-Bus (at the place of my own
socket code. D-Bus might still be a good option as it is supported on
Linux, Microsoft Windows and Apple Mac OS X, see for example
http://en.wikipedia.org/wiki/D-Bus ) and some simple XML scheme at the
place of the "command port protocoll" I am using now (see
http://formgames.org/blender/command-port/#bcp-protocol ).

Cheers, Dietrich

> [...] i hope that works with the previous revision (which seemed to me be just changes in Bleneder, not in command port) like Dietrich says on the Bazaar page [...]

The problems I had with the revision 198 of the command port branch on launchpad probably where caused by a bug in my Debian system and not by the blender code...

See the following thread on bf-committers:

- [Bf-committers] Blender GUI not working anymore on Debian sid.
http://lists.blender.org/pipermail/bf-committers/2009-August/thread.html#24276
http://lists.blender.org/pipermail/bf-committers/2009-September/thread.html#24436

The revision on launchpad probably was not "broken" :)

Regards, Dietrich

By the way, I updated the command port blender branch to 2.49b. See https://code.launchpad.net/~diresu/blender ./blender-command-port

Hi,

I ported the command port to Blender 2.5.

The command port works - but for the moment it is not usable as Blender 2.5's Python API only works when executing Python commands from the Blender GUI. The same commands do not work when executing them from a script via the -P <script> option or when sending them to Blender via the command port.

See the bug report here: https://projects.blender.org/tracker/index.php?func=detail&aid=20371&group_id=9&atid=498

The 2.5 blender command port branch can be found on launchpad: https://code.launchpad.net/~diresu/blender/blender-command-port-002

Cheers, Dietrich

Since a while already, the command port works again...

See: https://code.launchpad.net/~diresu/blender/blender-command-port-002

Here an example how the new version can be used (from the launchpad page):

EXAMPLE:

# starting the server:
blender -p 10 10 800 600 --command-port 6789

> found bundled python: /home/dietrich/blendev/bazaar/blender/working/branches/blender-command-port/install/linux2/.blender/python
> Starting the Blender command port - listening on port 6789.

# starting the python client shell
blash --port 6789

> This is Blash - the GNU BLender-Again SHell :)
> Connection to Blender Server established. (IP address: 127.0.0.1, port: 6789)

import bpy

# adding a monkey
bpy.ops.mesh.primitive_monkey_add(layer = [True]+[False]*19)
bpy.ops.wm.redraw()

# adding another monkey
bpy.ops.mesh.primitive_monkey_add(view_align = False, enter_editmode = False, location = (0, 0, 0), rotation = (0, 0, 0), layer = [True]+[False]*19)
bpy.ops.wm.redraw()

# adding a cube
bpy.ops.mesh.primitive_cube_add(layer = [True]+[False]*19)
bpy.ops.wm.redraw()

# adding a pyramid
vertices = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 0, 0, 1.27]
faces = [0, 3, 2, 1, 0, 1, 4, 0, 1, 2, 4, 0, 2, 3, 4, 0, 3, 0, 4, 0]
mesh = bpy.data.meshes.new("Pyramid")
mesh.add_geometry(int(len(vertices) / 3), 0, int(len(faces) / 4))
mesh.verts.foreach_set("co", vertices)
mesh.faces.foreach_set("verts_raw", faces)
mesh.update()
pyramid = bpy.data.objects.new("Pyramid", mesh)
bpy.context.scene.objects.link(pyramid)
bpy.ops.wm.redraw()

# quitting the python client shell
quit

NOTE:

  - The operator bpy.ops.wm.redraw() redraws the blender window.
    It currently only exist in the blender 2.5 command port branch.

Update: The Blender Python API changed - here is the new testcode (again from the launchpad page https://code.launchpad.net/~diresu/blender/blender-command-port-002 ):

EXAMPLE:

# starting the server:
blender -p 10 10 800 600 --command-port 6789

> found bundled python: /home/dietrich/blendev/bazaar/blender/working/branches/blender-command-port/install/linux2/.blender/python
> Starting the Blender command port - listening on port 6789.

# starting the python client shell
blash --port 6789

> This is Blash - the GNU BLender-Again SHell :)
> Connection to Blender Server established. (IP address: 127.0.0.1, port: 6789)

import bpy

# adding a monkey
bpy.ops.mesh.primitive_monkey_add()
bpy.ops.wm.redraw()

# adding another monkey
bpy.ops.mesh.primitive_monkey_add(view_align = False, enter_editmode = False, location = (0, 0, 0), rotation = (0, 0, 0))
bpy.ops.wm.redraw()

# adding a cube
bpy.ops.mesh.primitive_cube_add()
bpy.ops.wm.redraw()

# adding a pyramid
vertices = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 0, 0, 1.27]
faces = [0, 3, 2, 1, 0, 1, 4, 0, 1, 2, 4, 0, 2, 3, 4, 0, 3, 0, 4, 0]
mesh = bpy.data.meshes.new("Pyramid")
mesh.vertices.add(len(vertices) // 3)
mesh.faces.add(len(faces) // 4)
mesh.vertices.foreach_set("co", vertices)
mesh.faces.foreach_set("vertices_raw", faces)
mesh.update()
pyramid = bpy.data.objects.new("Pyramid", mesh)
bpy.context.scene.objects.link(pyramid)
bpy.ops.wm.redraw()

# quitting the python client shell
quit

NOTES:

  - The operator bpy.ops.wm.redraw() redraws the blender window.
    It currently only exist in the blender 2.5 command port branch.