1 |
|
# Orca |
2 |
|
# |
3 |
|
# Copyright 2006 Sun Microsystems Inc. |
4 |
|
# |
5 |
|
# This library is free software; you can redistribute it and/or |
6 |
|
# modify it under the terms of the GNU Library General Public |
7 |
|
# License as published by the Free Software Foundation; either |
8 |
|
# version 2 of the License, or (at your option) any later version. |
9 |
|
# |
10 |
|
# This library is distributed in the hope that it will be useful, |
11 |
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 |
|
# Library General Public License for more details. |
14 |
|
# |
15 |
|
# You should have received a copy of the GNU Library General Public |
16 |
|
# License along with this library; if not, write to the |
17 |
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
|
# Boston, MA 02111-1307, USA. |
19 |
|
|
20 |
|
"""Provides an HTTP server for Orca. This currently serves mainly as |
21 |
|
something that self-voicing applications can use as their speech |
22 |
1 |
service.""" |
23 |
|
|
24 |
1 |
__id__ = "$Id: httpserver.py 2504 2007-06-26 20:30:05Z richb $" |
25 |
1 |
__version__ = "$Revision: 2504 $" |
26 |
1 |
__date__ = "$Date: 2007-06-26 16:30:05 -0400 (Tue, 26 Jun 2007) $" |
27 |
1 |
__copyright__ = "Copyright (c) 2006 Sun Microsystems Inc." |
28 |
1 |
__license__ = "LGPL" |
29 |
|
|
30 |
1 |
import threading |
31 |
1 |
import BaseHTTPServer |
32 |
|
|
33 |
1 |
import debug |
34 |
1 |
import platform |
35 |
1 |
import settings |
36 |
1 |
import speech |
37 |
|
|
38 |
1 |
_httpRequestThread = None |
39 |
|
|
40 |
2 |
class _HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
41 |
|
"""Provides support for communicating with Orca via HTTP. This is |
42 |
|
mainly to support self-voicing applications that want to use Orca |
43 |
|
as a speech service. |
44 |
|
|
45 |
|
The protocol is simple: POST content is 'stop', 'speak:<text>', |
46 |
|
or 'isSpeaking'. |
47 |
|
|
48 |
|
To test this, run: |
49 |
|
|
50 |
|
wget --post-data='speak:hello world' localhost:20433 |
51 |
|
|
52 |
1 |
""" |
53 |
|
|
54 |
1 |
def log_request(self, code=None, size=None): |
55 |
|
"""Override to avoid getting a log message on stdout for |
56 |
|
each GET, POST, etc. request""" |
57 |
0 |
pass |
58 |
|
|
59 |
1 |
def do_GET(self): |
60 |
0 |
self.send_response(200) |
61 |
0 |
self.send_header("Content-type", "text/html") |
62 |
0 |
self.end_headers() |
63 |
0 |
self.wfile.write("<html><body><p>Orca %s</p></body></html>" \ |
64 |
0 |
% platform.version) |
65 |
|
|
66 |
1 |
def do_POST(self): |
67 |
0 |
contentLength = self.headers.getheader('content-length') |
68 |
0 |
if contentLength: |
69 |
0 |
contentLength = int(contentLength) |
70 |
0 |
inputBody = self.rfile.read(contentLength) |
71 |
0 |
debug.println(debug.LEVEL_FINEST, |
72 |
0 |
"httpserver._HTTPRequestHandler received %s" \ |
73 |
0 |
% inputBody) |
74 |
0 |
if inputBody.startswith("speak:"): |
75 |
0 |
speech.speak(inputBody[6:]) |
76 |
0 |
self.send_response(200, 'OK') |
77 |
0 |
elif inputBody == "stop": |
78 |
0 |
speech.stop() |
79 |
0 |
self.send_response(200, 'OK') |
80 |
0 |
elif inputBody == "isSpeaking": |
81 |
0 |
self.send_response(200, 'OK') |
82 |
0 |
self.send_header("Content-type", "text/html") |
83 |
0 |
self.end_headers() |
84 |
0 |
self.wfile.write("%s" % speech.isSpeaking()) |
85 |
|
else: |
86 |
0 |
debug.println(debug.LEVEL_FINEST, |
87 |
0 |
"httpserver._HTTPRequestHandler received no data") |
88 |
|
|
89 |
2 |
class _HTTPRequestThread(threading.Thread): |
90 |
1 |
"""Runs a _HTTPRequestHandler in a separate thread.""" |
91 |
|
|
92 |
1 |
def run(self): |
93 |
|
"""Try to start an HTTP server on settings.httpServerPort. |
94 |
|
If this fails, retry settings.maxHttpServerRetries times, |
95 |
|
each time incrementing the server port number by 1. If we |
96 |
|
are still unable to start a server, just fail gracefully. |
97 |
|
""" |
98 |
|
|
99 |
1 |
portNo = settings.httpServerPort |
100 |
1 |
connected = False |
101 |
1 |
while not connected and \ |
102 |
1 |
(portNo < settings.httpServerPort + settings.maxHttpServerRetries): |
103 |
1 |
try: |
104 |
1 |
httpd = BaseHTTPServer.HTTPServer(('', portNo), |
105 |
1 |
_HTTPRequestHandler) |
106 |
1 |
connected = True |
107 |
0 |
except: |
108 |
0 |
if portNo == settings.httpServerPort: |
109 |
0 |
debug.printException(debug.LEVEL_WARNING) |
110 |
0 |
debug.println(debug.LEVEL_WARNING, |
111 |
0 |
"httpserver._HTTPRequestThread unable to start server on port %d" % portNo) |
112 |
0 |
portNo += 1 |
113 |
|
|
114 |
1 |
if not connected: |
115 |
0 |
debug.println(debug.LEVEL_WARNING, |
116 |
0 |
"httpserver._HTTPRequestThread server startup failed.") |
117 |
|
else: |
118 |
1 |
httpd.serve_forever() |
119 |
|
|
120 |
1 |
def init(): |
121 |
|
"""Creates an HTTP server that listens for speak commands from a |
122 |
|
separate port defined by settings.httpServerPort. We run this |
123 |
|
as a daemon so it will die automatically when orca dies.""" |
124 |
|
|
125 |
|
global _httpRequestThread |
126 |
|
|
127 |
1 |
if settings.httpServerPort and (not _httpRequestThread): |
128 |
1 |
try: |
129 |
1 |
_httpRequestThread = _HTTPRequestThread() |
130 |
1 |
_httpRequestThread.setDaemon(True) |
131 |
1 |
_httpRequestThread.start() |
132 |
0 |
except: |
133 |
0 |
debug.printException(debug.LEVEL_WARNING) |
134 |
|
|
135 |
1 |
def shutdown(): |
136 |
|
"""Stops the HTTP server. [[[WDW - not implemented yet.]]]""" |
137 |
1 |
pass |