diff options
Diffstat (limited to 'lib/wx/c_src/wxe_driver.c')
-rw-r--r-- | lib/wx/c_src/wxe_driver.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/lib/wx/c_src/wxe_driver.c b/lib/wx/c_src/wxe_driver.c new file mode 100644 index 0000000000..3b951bec57 --- /dev/null +++ b/lib/wx/c_src/wxe_driver.c @@ -0,0 +1,221 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2008-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifdef _WIN32 +#include <windows.h> +#include <io.h> +#else +#include <unistd.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <errno.h> +#include <sys/types.h> +#include <fcntl.h> + +#include "wxe_driver.h" + +#define TEMP_BINARY_SIZE 512 + +static ErlDrvData wxe_driver_start(ErlDrvPort port, char *buff); +static int wxe_driver_load(void); +static void wxe_driver_stop(ErlDrvData handle); +static void wxe_driver_unload(void); +static int wxe_driver_control(ErlDrvData handle, unsigned int command, + char* buf, int count, char** res, int res_size); +static int wxe_driver_call(ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen, unsigned int *flags); + +static void standard_outputv(ErlDrvData drv_data, ErlIOVec *ev); +static void wxe_process_died(ErlDrvData drv_data, ErlDrvMonitor *monitor); + +int wxe_debug; + +wxe_data * wxe_master; +char * erl_wx_privdir; + +/* +** The driver struct +*/ +static ErlDrvEntry wxe_driver_entry = { + wxe_driver_load, /* F_PTR init, called at loading */ + wxe_driver_start, /* L_PTR start, called when port is opened */ + wxe_driver_stop, /* F_PTR stop, called when port is closed */ + NULL, /* F_PTR output, called when erlang has sent */ + NULL, /* F_PTR ready_input, called when input descriptor + ready */ + NULL, /* F_PTR ready_output, called when output + descriptor ready */ + "wxe_driver", /* char *driver_name, the argument to open_port */ + wxe_driver_unload, /* F_PTR finish, called when unloaded */ + NULL, /* void * that is not used (BC) */ + wxe_driver_control, /* F_PTR control, port_control callback */ + NULL, /* F_PTR timeout, reserved */ + standard_outputv, /* F_PTR outputv, reserved */ + NULL, /* async */ + NULL, /* flush */ + wxe_driver_call, /* call */ + NULL, /* Event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, /* Port lock */ + NULL, /* Reserved Handle */ + wxe_process_died, /* Process Exited */ +}; + +DRIVER_INIT(wxe_driver) +{ + return &wxe_driver_entry; +} + +int wxe_driver_load() +{ + if(load_native_gui()) + return 0; + else + return -1; +} + +ErlDrvPort WXE_DRV_PORT = 0; + +static ErlDrvData +wxe_driver_start(ErlDrvPort port, char *buff) +{ + wxe_data *data; + + data = (wxe_data *) malloc(sizeof(wxe_data)); + wxe_debug = 0; + + if (data == NULL) { + fprintf(stderr, " Couldn't alloc mem\r\n"); + return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */ + } else { + set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); + data->driver_data = NULL; + data->bin = NULL; + data->port = port; + if(WXE_DRV_PORT == 0) { + for(; *buff != 32; buff++); + buff++; + erl_wx_privdir = malloc(strlen(buff)); + strcpy(erl_wx_privdir, buff); + + WXE_DRV_PORT = port; + wxe_master = data; + if(!(start_native_gui(data) == 1)) + return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */ + } else { + meta_command(CREATE_PORT,data); + } + return (ErlDrvData) data; + } +} + +static void +wxe_driver_stop(ErlDrvData handle) +{ + wxe_data *sd = ((wxe_data *)handle); + if(sd->port != WXE_DRV_PORT) { + // fprintf(stderr, "%s:%d: STOP \r\n", __FILE__,__LINE__); + meta_command(DELETE_PORT,sd); + free(handle); + } +} + +static void +wxe_driver_unload(void) +{ + // fprintf(stderr, "%s:%d: UNLOAD \r\n", __FILE__,__LINE__); + meta_command(WXE_SHUTDOWN, wxe_master); + stop_native_gui(wxe_master); + unload_native_gui(); + free(wxe_master); + wxe_master = NULL; +} + +static int +wxe_driver_control(ErlDrvData handle, unsigned op, + char* buf, int count, char** res, int res_size) +{ + wxe_data *sd = ((wxe_data *)handle); + push_command(op,buf,count,sd); + return 0; +} + +static int wxe_driver_call(ErlDrvData handle, unsigned int command, + char *buf, int len, char **res, int rlen, unsigned int *flags) +{ + wxe_data *sd = ((wxe_data *)handle); + if(command == WXE_DEBUG_DRIVER) { + if(*buf) + wxe_debug = 1; + else + wxe_debug = 0; + } else { + meta_command(PING_PORT,sd); + } + if (len > rlen) + *res = driver_alloc(len); + memcpy((void *) *res, (void *) buf, len); + return len; +} + + +void wxe_process_died(ErlDrvData handle, ErlDrvMonitor *monitor) +{ + /* Callback is active for the dead process */ + wxe_data *sd = ((wxe_data *)handle); + push_command(WXE_CB_RETURN,NULL,0,sd); + +/* ErlDrvTermData pid; */ +/* pid = driver_get_monitored_process(sd->port, monitor); */ +/* fprintf(stderr, "Process died %d \r\n", (int) pid); */ +} + + +static void +standard_outputv(ErlDrvData drv_data, ErlIOVec* ev) +{ + wxe_data* sd = (wxe_data *) drv_data; + WXEBinRef * binref; + ErlDrvBinary* bin; + + if(ev->vsize == 2) { + binref = driver_alloc(sizeof(WXEBinRef)); + binref->base = ev->iov[1].iov_base; + binref->size = ev->iov[1].iov_len; + binref->from = driver_caller(sd->port); + bin = ev->binv[1]; + driver_binary_inc_refc(bin); /* Otherwise it could get deallocated */ + binref->bin = bin; + binref->next = sd->bin; + sd->bin = binref; + } else { /* Empty binary (becomes NULL) */ + binref = driver_alloc(sizeof(WXEBinRef)); + binref->base = NULL; + binref->size = 0; + binref->from = driver_caller(sd->port); + binref->bin = NULL; + binref->next = sd->bin; + sd->bin = binref; + } +} |