mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
Moved webengine into separate file, added callbacks for websockets and made example for triggering ui on driver change, also added json for game driver (nw)
This commit is contained in:
parent
59837a1e7d
commit
5f184e36d6
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1942,6 +1942,8 @@ src/emu/video/video.mak svneol=native#text/plain
|
|||||||
src/emu/video/vooddefs.h svneol=native#text/plain
|
src/emu/video/vooddefs.h svneol=native#text/plain
|
||||||
src/emu/video/voodoo.c svneol=native#text/plain
|
src/emu/video/voodoo.c svneol=native#text/plain
|
||||||
src/emu/video/voodoo.h svneol=native#text/plain
|
src/emu/video/voodoo.h svneol=native#text/plain
|
||||||
|
src/emu/webengine.c svneol=native#text/plain
|
||||||
|
src/emu/webengine.h svneol=native#text/plain
|
||||||
src/ldplayer/layout/pr8210.lay svneol=native#text/plain
|
src/ldplayer/layout/pr8210.lay svneol=native#text/plain
|
||||||
src/ldplayer/ldplayer.c svneol=native#text/plain
|
src/ldplayer/ldplayer.c svneol=native#text/plain
|
||||||
src/ldplayer/ldplayer.lst svneol=native#text/plain
|
src/ldplayer/ldplayer.lst svneol=native#text/plain
|
||||||
|
@ -131,6 +131,7 @@ EMUOBJS = \
|
|||||||
$(EMUOBJ)/debug/textbuf.o \
|
$(EMUOBJ)/debug/textbuf.o \
|
||||||
$(EMUOBJ)/debugint/debugint.o \
|
$(EMUOBJ)/debugint/debugint.o \
|
||||||
$(EMUOBJ)/profiler.o \
|
$(EMUOBJ)/profiler.o \
|
||||||
|
$(EMUOBJ)/webengine.o \
|
||||||
$(OSDOBJ)/osdepend.o \
|
$(OSDOBJ)/osdepend.o \
|
||||||
$(OSDOBJ)/osdnet.o
|
$(OSDOBJ)/osdnet.o
|
||||||
|
|
||||||
|
@ -84,8 +84,7 @@
|
|||||||
#include "crsshair.h"
|
#include "crsshair.h"
|
||||||
#include "validity.h"
|
#include "validity.h"
|
||||||
#include "debug/debugcon.h"
|
#include "debug/debugcon.h"
|
||||||
#include "web/mongoose.h"
|
#include "webengine.h"
|
||||||
#include "web/json/json.h"
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
@ -132,33 +131,6 @@ int mame_is_valid_machine(running_machine &machine)
|
|||||||
return (&machine == global_machine);
|
return (&machine == global_machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function will be called by mongoose on every new request.
|
|
||||||
static int begin_request_handler(struct mg_connection *conn) {
|
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
|
||||||
if (!strcmp(request_info->uri, "/hello")) {
|
|
||||||
Json::Value data;
|
|
||||||
data["key1"] = "data1";
|
|
||||||
data["key2"] = "data2";
|
|
||||||
data["key3"] = "data3";
|
|
||||||
data["key4"] = "data4";
|
|
||||||
|
|
||||||
Json::FastWriter writer;
|
|
||||||
const char *json = writer.write(data).c_str();
|
|
||||||
// Send HTTP reply to the client
|
|
||||||
mg_printf(conn,
|
|
||||||
"HTTP/1.1 200 OK\r\n"
|
|
||||||
"Content-Type: application/json\r\n"
|
|
||||||
"Content-Length: %d\r\n" // Always set Content-Length
|
|
||||||
"\r\n"
|
|
||||||
"%s",
|
|
||||||
(int)strlen(json), json);
|
|
||||||
|
|
||||||
// Returning non-zero tells mongoose that our function has replied to
|
|
||||||
// the client, and mongoose should not send client any more data.
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
mame_execute - run the core emulation
|
mame_execute - run the core emulation
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
@ -172,27 +144,12 @@ int mame_execute(emu_options &options, osd_interface &osd)
|
|||||||
if (options.verbose())
|
if (options.verbose())
|
||||||
print_verbose = true;
|
print_verbose = true;
|
||||||
|
|
||||||
struct mg_context *ctx = NULL;
|
|
||||||
struct mg_callbacks callbacks;
|
|
||||||
|
|
||||||
// List of options. Last element must be NULL.
|
|
||||||
const char *web_options[] = {
|
|
||||||
"listening_ports", options.http_port(),
|
|
||||||
"document_root", options.http_path(),
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
// Prepare callbacks structure.
|
|
||||||
memset(&callbacks, 0, sizeof(callbacks));
|
|
||||||
callbacks.begin_request = begin_request_handler;
|
|
||||||
|
|
||||||
// Start the web server.
|
|
||||||
if (options.http())
|
|
||||||
ctx = mg_start(&callbacks, NULL, web_options);
|
|
||||||
|
|
||||||
// loop across multiple hard resets
|
// loop across multiple hard resets
|
||||||
bool exit_pending = false;
|
bool exit_pending = false;
|
||||||
int error = MAMERR_NONE;
|
int error = MAMERR_NONE;
|
||||||
|
|
||||||
|
web_engine web(options);
|
||||||
|
|
||||||
while (error == MAMERR_NONE && !exit_pending)
|
while (error == MAMERR_NONE && !exit_pending)
|
||||||
{
|
{
|
||||||
// if no driver, use the internal empty driver
|
// if no driver, use the internal empty driver
|
||||||
@ -231,6 +188,8 @@ int mame_execute(emu_options &options, osd_interface &osd)
|
|||||||
// looooong term: remove this
|
// looooong term: remove this
|
||||||
global_machine = &machine;
|
global_machine = &machine;
|
||||||
|
|
||||||
|
web.set_machine(machine);
|
||||||
|
web.push_message("update_machine");
|
||||||
// run the machine
|
// run the machine
|
||||||
error = machine.run(firstrun);
|
error = machine.run(firstrun);
|
||||||
firstrun = false;
|
firstrun = false;
|
||||||
@ -247,10 +206,6 @@ int mame_execute(emu_options &options, osd_interface &osd)
|
|||||||
// machine will go away when we exit scope
|
// machine will go away when we exit scope
|
||||||
global_machine = NULL;
|
global_machine = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop the server.
|
|
||||||
if (options.http())
|
|
||||||
mg_stop(ctx);
|
|
||||||
// return an error
|
// return an error
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
229
src/emu/webengine.c
Normal file
229
src/emu/webengine.c
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
webengine.c
|
||||||
|
|
||||||
|
Handle MAME internal web server.
|
||||||
|
|
||||||
|
****************************************************************************
|
||||||
|
|
||||||
|
Copyright Miodrag Milanovic
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name 'MAME' nor the names of its contributors may be
|
||||||
|
used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY MIODRAG MILANOVIC ''AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL MIODRAG MILANOVIC BE LIABLE FOR ANY DIRECT,
|
||||||
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "emuopts.h"
|
||||||
|
#include "webengine.h"
|
||||||
|
#include "web/mongoose.h"
|
||||||
|
#include "web/json/json.h"
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// WEB ENGINE
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
void web_engine::websocket_ready_handler(struct mg_connection *conn) {
|
||||||
|
static const char *message = "update_machine";
|
||||||
|
mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, message, strlen(message));
|
||||||
|
m_websockets.append(*global_alloc(simple_list_wrapper<mg_connection>(conn)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arguments:
|
||||||
|
// flags: first byte of websocket frame, see websocket RFC,
|
||||||
|
// http://tools.ietf.org/html/rfc6455, section 5.2
|
||||||
|
// data, data_len: payload data. Mask, if any, is already applied.
|
||||||
|
int web_engine::websocket_data_handler(struct mg_connection *conn, int flags,
|
||||||
|
char *data, size_t data_len)
|
||||||
|
{
|
||||||
|
// just Echo example for now
|
||||||
|
if ((flags & 0x0f) == WEBSOCKET_OPCODE_TEXT)
|
||||||
|
mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
|
||||||
|
|
||||||
|
// Returning zero means stoping websocket conversation.
|
||||||
|
// Close the conversation if client has sent us "exit" string.
|
||||||
|
return memcmp(data, "exit", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will be called by mongoose on every new request.
|
||||||
|
int web_engine::begin_request_handler(struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
|
if (!strncmp(request_info->uri, "/json/",6))
|
||||||
|
{
|
||||||
|
if (!strcmp(request_info->uri, "/json/game"))
|
||||||
|
{
|
||||||
|
Json::Value data;
|
||||||
|
data["name"] = m_machine->system().name;
|
||||||
|
data["description"] = m_machine->system().description;
|
||||||
|
data["year"] = m_machine->system().year;
|
||||||
|
data["manufacturer"] = m_machine->system().manufacturer;
|
||||||
|
data["parent"] = m_machine->system().parent;
|
||||||
|
data["source_file"] = m_machine->system().source_file;
|
||||||
|
data["flags"] = m_machine->system().flags;
|
||||||
|
|
||||||
|
Json::FastWriter writer;
|
||||||
|
const char *json = writer.write(data).c_str();
|
||||||
|
// Send HTTP reply to the client
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: application/json\r\n"
|
||||||
|
"Content-Length: %d\r\n" // Always set Content-Length
|
||||||
|
"\r\n"
|
||||||
|
"%s",
|
||||||
|
(int)strlen(json), json);
|
||||||
|
|
||||||
|
// Returning non-zero tells mongoose that our function has replied to
|
||||||
|
// the client, and mongoose should not send client any more data.
|
||||||
|
mg_close_connection(conn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *web_engine::websocket_keepalive()
|
||||||
|
{
|
||||||
|
while(!m_exiting_core)
|
||||||
|
{
|
||||||
|
osd_ticks_t curtime = osd_ticks();
|
||||||
|
if ((curtime - m_lastupdatetime) > osd_ticks_per_second() * 5)
|
||||||
|
{
|
||||||
|
m_lastupdatetime = curtime;
|
||||||
|
for (simple_list_wrapper<mg_connection> *curitem = m_websockets.first(); curitem != NULL; curitem = curitem->next())
|
||||||
|
{
|
||||||
|
mg_websocket_write(curitem->object(), WEBSOCKET_OPCODE_PING, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
osd_sleep(osd_ticks_per_second()/5);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// static callbacks
|
||||||
|
//-------------------------------------------------
|
||||||
|
static void websocket_ready_handler_static(struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
|
web_engine *engine = downcast<web_engine *>(request_info->user_data);
|
||||||
|
engine->websocket_ready_handler(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int websocket_data_handler_static(struct mg_connection *conn, int flags,
|
||||||
|
char *data, size_t data_len)
|
||||||
|
{
|
||||||
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
|
web_engine *engine = downcast<web_engine *>(request_info->user_data);
|
||||||
|
return engine->websocket_data_handler(conn, flags, data, data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int begin_request_handler_static(struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
|
web_engine *engine = downcast<web_engine *>(request_info->user_data);
|
||||||
|
return engine->begin_request_handler(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *websocket_keepalive_static(void *thread_func_param)
|
||||||
|
{
|
||||||
|
web_engine *engine = downcast<web_engine *>(thread_func_param);
|
||||||
|
return engine->websocket_keepalive();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// web_engine - constructor
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
web_engine::web_engine(emu_options &options)
|
||||||
|
: m_options(options),
|
||||||
|
m_machine(NULL),
|
||||||
|
m_ctx(NULL),
|
||||||
|
m_lastupdatetime(0),
|
||||||
|
m_exiting_core(false)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
|
|
||||||
|
// List of options. Last element must be NULL.
|
||||||
|
const char *web_options[] = {
|
||||||
|
"listening_ports", options.http_port(),
|
||||||
|
"document_root", options.http_path(),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prepare callbacks structure.
|
||||||
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
callbacks.begin_request = begin_request_handler_static;
|
||||||
|
callbacks.websocket_ready = websocket_ready_handler_static;
|
||||||
|
callbacks.websocket_data = websocket_data_handler_static;
|
||||||
|
|
||||||
|
// Start the web server.
|
||||||
|
if (m_options.http()) {
|
||||||
|
m_ctx = mg_start(&callbacks, this, web_options);
|
||||||
|
|
||||||
|
mg_start_thread(websocket_keepalive_static, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// ~web_engine - destructor
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
web_engine::~web_engine()
|
||||||
|
{
|
||||||
|
if (m_options.http())
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// close - close and cleanup of lua engine
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void web_engine::close()
|
||||||
|
{
|
||||||
|
m_exiting_core = 1;
|
||||||
|
osd_sleep(osd_ticks_per_second()/5);
|
||||||
|
for (simple_list_wrapper<mg_connection> *curitem = m_websockets.first(); curitem != NULL; curitem = curitem->next())
|
||||||
|
{
|
||||||
|
mg_websocket_write(curitem->object(), WEBSOCKET_OPCODE_CONNECTION_CLOSE, NULL, 0);
|
||||||
|
}
|
||||||
|
// Stop the server.
|
||||||
|
mg_stop(m_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void web_engine::push_message(const char *message)
|
||||||
|
{
|
||||||
|
for (simple_list_wrapper<mg_connection> *curitem = m_websockets.first(); curitem != NULL; curitem = curitem->next())
|
||||||
|
{
|
||||||
|
mg_websocket_write(curitem->object(), WEBSOCKET_OPCODE_TEXT, message, strlen(message));
|
||||||
|
}
|
||||||
|
}
|
74
src/emu/webengine.h
Normal file
74
src/emu/webengine.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
webengine.h
|
||||||
|
|
||||||
|
Handle MAME internal web server.
|
||||||
|
|
||||||
|
****************************************************************************
|
||||||
|
|
||||||
|
Copyright Miodrag Milanovic
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name 'MAME' nor the names of its contributors may be
|
||||||
|
used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY MIODRAG MILANOVIC ''AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL MIODRAG MILANOVIC BE LIABLE FOR ANY DIRECT,
|
||||||
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __WEB_ENGINE_H__
|
||||||
|
#define __WEB_ENGINE_H__
|
||||||
|
|
||||||
|
struct mg_context; // Handle for the HTTP service itself
|
||||||
|
struct mg_connection; // Handle for the individual connection
|
||||||
|
|
||||||
|
class web_engine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// construction/destruction
|
||||||
|
web_engine(emu_options &options);
|
||||||
|
~web_engine();
|
||||||
|
|
||||||
|
void push_message(const char *message);
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void set_machine(running_machine &machine) { m_machine = &machine; }
|
||||||
|
|
||||||
|
void websocket_ready_handler(struct mg_connection *conn);
|
||||||
|
int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len);
|
||||||
|
int begin_request_handler(struct mg_connection *conn);
|
||||||
|
void *websocket_keepalive();
|
||||||
|
private:
|
||||||
|
// internal state
|
||||||
|
emu_options & m_options;
|
||||||
|
running_machine * m_machine;
|
||||||
|
struct mg_context * m_ctx;
|
||||||
|
osd_ticks_t m_lastupdatetime;
|
||||||
|
bool m_exiting_core;
|
||||||
|
simple_list<simple_list_wrapper<mg_connection> > m_websockets;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __web_engine_H__ */
|
@ -19,6 +19,7 @@
|
|||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#define NO_SSL
|
#define NO_SSL
|
||||||
|
#define USE_WEBSOCKET
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define SETSOCKOPT_CAST const char *
|
#define SETSOCKOPT_CAST const char *
|
||||||
@ -4052,7 +4053,7 @@ static void read_websocket(struct mg_connection *conn) {
|
|||||||
if (header_len > 0) {
|
if (header_len > 0) {
|
||||||
// Allocate space to hold websocket payload
|
// Allocate space to hold websocket payload
|
||||||
data = mem;
|
data = mem;
|
||||||
if (data_len > sizeof(mem) && (data = malloc(data_len)) == NULL) {
|
if (data_len > sizeof(mem) && (data = (char*)malloc(data_len)) == NULL) {
|
||||||
// Allocation failed, exit the loop and then close the connection
|
// Allocation failed, exit the loop and then close the connection
|
||||||
// TODO: notify user about the failure
|
// TODO: notify user about the failure
|
||||||
break;
|
break;
|
||||||
|
@ -11,6 +11,31 @@
|
|||||||
<link href="css/default.ultimate.css" media="screen" rel="stylesheet" type="text/css" />
|
<link href="css/default.ultimate.css" media="screen" rel="stylesheet" type="text/css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<script language="javascript" type="text/javascript">
|
||||||
|
|
||||||
|
var writeToScreen = function(message) {
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.innerHTML = message;
|
||||||
|
document.getElementById('output').appendChild(div);
|
||||||
|
};
|
||||||
|
window.onload = function() {
|
||||||
|
var url = 'ws://localhost:8080/foo';
|
||||||
|
websocket = new WebSocket(url);
|
||||||
|
websocket.onopen = function(ev) {
|
||||||
|
writeToScreen('<span style="color: green;">CONNECTED</span>');
|
||||||
|
};
|
||||||
|
websocket.onclose = function(ev) {
|
||||||
|
writeToScreen('<span style="color: white;">DISCONNECTED</span>');
|
||||||
|
};
|
||||||
|
websocket.onmessage = function(ev) {
|
||||||
|
writeToScreen('<span style="color: blue;">RESPONSE: ' + ev.data +
|
||||||
|
' </span>');
|
||||||
|
};
|
||||||
|
websocket.onerror = function(ev) {
|
||||||
|
writeToScreen('<span style="color: red; ">ERROR: </span> ' + ev.data);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
<div data-role="page">
|
<div data-role="page">
|
||||||
<div data-role="header">
|
<div data-role="header">
|
||||||
<img src="images/logo-mame-small.png"/>
|
<img src="images/logo-mame-small.png"/>
|
||||||
@ -46,6 +71,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li id="n-debugger"><a href="./">Debugger</a></li>
|
<li id="n-debugger"><a href="./">Debugger</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<br/><br/><div id="output"></div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user