First commit.
This commit is contained in:
		
							
								
								
									
										270
									
								
								bin/mpresent
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										270
									
								
								bin/mpresent
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,270 @@ | ||||
| #! /opt/openoffice4/program/python | ||||
| # -*- coding: utf-8 -*- | ||||
| # OpenOffice mobile presentation constroller, as Python | ||||
| #   by imacat <imacat@mail.imacat.idv.tw>, 2014-02-28 | ||||
|  | ||||
| # Python imports | ||||
| import os | ||||
| import os.path | ||||
| import sys | ||||
| import ssl | ||||
| import time | ||||
| import random | ||||
| import BaseHTTPServer | ||||
|  | ||||
|  | ||||
| def append_uno_path(): | ||||
|     """ Appends the path of the uno module to the import path.  """ | ||||
|  | ||||
|     is_found_uno = False | ||||
|     for p in sys.path: | ||||
|         if os.path.exists(os.path.join(p, "uno.py")): | ||||
|             return | ||||
|     # For uno.py on MacOS | ||||
|     cand = "/Applications/OpenOffice.app/Contents/MacOS" | ||||
|     if os.path.exists(os.path.join(cand, "uno.py")): | ||||
|         sys.path.append(cand) | ||||
|         return | ||||
|     # Finds uno.py for MS-Windows | ||||
|     cand = sys.executable | ||||
|     while cand != os.path.dirname(cand): | ||||
|         cand = os.path.dirname(cand) | ||||
|         if os.path.exists(os.path.join(cand, "uno.py")): | ||||
|             sys.path.append(cand) | ||||
|             return | ||||
|  | ||||
| append_uno_path() | ||||
| import uno | ||||
| from com.sun.star.beans import PropertyValue | ||||
| from com.sun.star.lang import DisposedException | ||||
| from com.sun.star.connection import NoConnectException | ||||
|  | ||||
|  | ||||
| class PresentationController: | ||||
|     """The OpenOffice mobile presentation controller.""" | ||||
|  | ||||
|     def __init__(self, docfile): | ||||
|         """Initializes the object.""" | ||||
|         self.file = docfile | ||||
|         self.bootstrap_context = None | ||||
|         self.service_manager = None | ||||
|         self.desktop = None | ||||
|         self.doc = None | ||||
|  | ||||
|     def check_valid(self): | ||||
|         """Check the validity of the connection and the opened document.""" | ||||
|         try: | ||||
|             presentation = self.doc.getPresentation() | ||||
|         except (AttributeError, DisposedException): | ||||
|             try: | ||||
|                 self.bootstrap_context.getServiceManager() | ||||
|             except (AttributeError, DisposedException): | ||||
|                 self.connect() | ||||
|             self.open() | ||||
|             presentation = self.doc.getPresentation() | ||||
|         if not presentation.isRunning(): | ||||
|             presentation.start() | ||||
|  | ||||
|     def connect(self): | ||||
|         """Connects to the running OpenOffice process.""" | ||||
|         # Obtains the local context | ||||
|         local_context = uno.getComponentContext() | ||||
|         # Obtains the local service manager | ||||
|         local_service_manager = local_context.getServiceManager() | ||||
|         # Obtains the URL resolver | ||||
|         url_resolver = local_service_manager.createInstanceWithContext( | ||||
|             "com.sun.star.bridge.UnoUrlResolver", local_context) | ||||
|         # Obtains the context | ||||
|         url = ("uno:socket,host=localhost,port=2002;" | ||||
|                "urp;StarOffice.ComponentContext") | ||||
|         try: | ||||
|             self.bootstrap_context = url_resolver.resolve(url) | ||||
|         except NoConnectException: | ||||
|             self.start_oo() | ||||
|             self.bootstrap_context = url_resolver.resolve(url) | ||||
|         # Obtains the service manager | ||||
|         self.service_manager = self.bootstrap_context.getServiceManager() | ||||
|         # Obtains the desktop service | ||||
|         self.desktop = self.service_manager.createInstanceWithContext( | ||||
|             "com.sun.star.frame.Desktop", self.bootstrap_context) | ||||
|  | ||||
|     def start_oo(self): | ||||
|         """Starts the OpenOffice in server listening mode""" | ||||
|         # For MS-Windows, which does not have fork() | ||||
|         if os.name == "nt": | ||||
|             from subprocess import Popen | ||||
|             ooexec = os.path.join(os.path.dirname(uno.__file__), "soffice.exe") | ||||
|             DETACHED_PROCESS = 0x00000008 | ||||
|             Popen([ooexec, "-accept=socket,host=localhost,port=2002;urp;"], | ||||
|                   close_fds=True, creationflags=DETACHED_PROCESS) | ||||
|             time.sleep(2) | ||||
|             return | ||||
|  | ||||
|         # For POSIX systems, including Linux | ||||
|         try: | ||||
|             pid = os.fork() | ||||
|         except OSError: | ||||
|             sys.stderr.write("failed to fork().\n") | ||||
|             sys.exit(1) | ||||
|         if pid != 0: | ||||
|             time.sleep(2) | ||||
|             return | ||||
|         os.setsid() | ||||
|         ooexec = os.path.join(os.path.dirname(uno.__file__), "soffice.bin") | ||||
|         try: | ||||
|             os.execl( | ||||
|                 ooexec, ooexec, | ||||
|                 "-accept=socket,host=localhost,port=2002;urp;") | ||||
|         except OSError: | ||||
|             sys.stderr.write( | ||||
|                 ooexec + ": Failed to run the OpenOffice server.\n") | ||||
|             sys.exit(1) | ||||
|  | ||||
|     def open(self): | ||||
|         """Opens an office document.""" | ||||
|         file_content_provider = self.service_manager.createInstance( | ||||
|             "com.sun.star.ucb.FileContentProvider") | ||||
|         url = file_content_provider.getFileURLFromSystemPath("", self.file) | ||||
|         enum = self.desktop.getComponents().createEnumeration() | ||||
|         while enum.hasMoreElements(): | ||||
|             component = enum.nextElement() | ||||
|             if component.supportsService( | ||||
|                     "com.sun.star.presentation.PresentationDocument"): | ||||
|                 if component.getURL() == url: | ||||
|                     self.doc = component | ||||
|                     return | ||||
|         prop1 = PropertyValue() | ||||
|         prop1.Name = "ReadOnly" | ||||
|         prop1.Value = True | ||||
|         prop2 = PropertyValue() | ||||
|         prop2.Name = "MacroExecutionMode" | ||||
|         # com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE | ||||
|         prop2.Value = 2 | ||||
|         self.doc = self.desktop.loadComponentFromURL( | ||||
|             url, "_default", 0, (prop2,)) | ||||
|         if not self.doc.supportsService( | ||||
|                 "com.sun.star.presentation.PresentationDocument"): | ||||
|             sys.stderr.write(self.file + ": not a presentation document.\n") | ||||
|             sys.exit(1) | ||||
|         return | ||||
|  | ||||
|     def goto_next_slide(self): | ||||
|         """Goes to the next slide.""" | ||||
|         self.doc.getPresentation().getController().gotoNextSlide() | ||||
|         return | ||||
|  | ||||
|     def goto_prev_slide(self): | ||||
|         """Goes to the previous slide.""" | ||||
|         self.doc.getPresentation().getController().gotoPreviousSlide() | ||||
|         return | ||||
|  | ||||
|  | ||||
| class MyHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | ||||
|     """The local HTTP request handler.""" | ||||
|     def do_GET(self): | ||||
|         """Handles the GET requests.""" | ||||
|         oo.check_valid() | ||||
|         html = """<?xml version="1.0" encoding="UTF-8" ?> | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" | ||||
|     "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <meta name="viewport" content="width=device-width, initial-scale=1.5" /> | ||||
| <style type="text/css"> | ||||
| .pocket input { | ||||
|     font-size: 8em; | ||||
| } | ||||
| </style> | ||||
| <title>OpenOffice Presentation Controller</title> | ||||
| </head> | ||||
| <body> | ||||
|  | ||||
| <div class="pocket"> | ||||
| <form action="/next" method="POST"> | ||||
| <input type="submit" value="▲" /> | ||||
| </form> | ||||
| </div> | ||||
|  | ||||
| <div class="pocket"> | ||||
| <form action="/prev" method="POST"> | ||||
| <input type="submit" value="▼" /> | ||||
| </form> | ||||
| </div> | ||||
|  | ||||
| </body>""" | ||||
|         self.send_response(200) | ||||
|         self.send_header("Content-Type", "text/html; charset=UTF-8") | ||||
|         self.send_header("Content-Length", len(html)) | ||||
|         self.end_headers() | ||||
|         self.wfile.write(html) | ||||
|  | ||||
|     def do_POST(self): | ||||
|         """Handles the POST requests.""" | ||||
|         oo.check_valid() | ||||
|         if self.path == "/next": | ||||
|             oo.goto_next_slide() | ||||
|         elif self.path == "/prev": | ||||
|             oo.goto_prev_slide() | ||||
|         html = """<?xml version="1.0" encoding="US-ASCII" ?> | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" | ||||
|     "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII" /> | ||||
| <meta name="viewport" content="width=device-width, initial-scale=1.5" /> | ||||
| <title>303 See Others</title> | ||||
| </head> | ||||
| <body> | ||||
| <h1>303 See Others</h1> | ||||
| <p>Please follow <a href="/">this location</a>.</p> | ||||
| </body> | ||||
| </html>""" | ||||
|         self.send_response(303) | ||||
|         self.send_header("Location", "/") | ||||
|         self.send_header("Content-Type", "text/html; charset=US-ASCII") | ||||
|         self.send_header("Content-Length", len(html)) | ||||
|         self.end_headers() | ||||
|         self.wfile.write(html) | ||||
|  | ||||
|  | ||||
| def run(): | ||||
|     """Runs the local HTTP server and starts the presentation.""" | ||||
|     oo.check_valid() | ||||
|     server_address = ("", 53177) | ||||
|     httpd = BaseHTTPServer.HTTPServer(server_address, MyHTTPRequestHandler) | ||||
|     # TODO: Changed to an option or find the certificates automatically | ||||
|     if usessl is not False: | ||||
|         httpd.socket = ssl.wrap_socket( | ||||
|             httpd.socket, | ||||
|             keyfile=usessl[0], | ||||
|             certfile=usessl[1], | ||||
|             server_side=True) | ||||
|     httpd.serve_forever() | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     if len(sys.argv) != 2: | ||||
|         sys.stderr.write("Please specify the presentation document.\n") | ||||
|         sys.exit(1) | ||||
|     docfile = os.path.abspath(sys.argv[1]) | ||||
|     s = docfile.lower() | ||||
|     if not (s.endswith(".odp") | ||||
|             or s.endswith(".sxi") | ||||
|             or s.endswith(".ppt") | ||||
|             or s.endswith(".pptx")): | ||||
|         sys.stderr.write(docfile + ": not a presentation document.\n") | ||||
|         sys.exit(1) | ||||
|     if not os.path.exists(docfile): | ||||
|         sys.stderr.write(docfile + ": file does not exist.\n") | ||||
|         sys.exit(1) | ||||
|     if not os.path.isfile(docfile): | ||||
|         sys.stderr.write(docfile + ": file does not exist.\n") | ||||
|         sys.exit(1) | ||||
|     mydir = os.path.dirname(os.path.abspath(sys.argv[0])) | ||||
|     keyfile = os.path.join(mydir, "server.key.pem") | ||||
|     crtfile = os.path.join(mydir, "server.crt.pem") | ||||
|     usessl = False | ||||
|     if os.path.isfile(keyfile) and os.path.isfile(crtfile): | ||||
|         usessl = (keyfile, crtfile) | ||||
|     oo = PresentationController(docfile) | ||||
|     run() | ||||
							
								
								
									
										22
									
								
								setup.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								setup.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| import os | ||||
| import sys | ||||
| from setuptools import setup | ||||
|  | ||||
| # For Python shipped with OpenOffice, python is a wrapper | ||||
| # for python.bin that fixes the import and library path.  We should | ||||
| # call python instead of python.bin. """ | ||||
| import os | ||||
| import sys | ||||
| if os.path.basename(sys.executable) == "python.bin": | ||||
|     sys.executable = os.path.join( | ||||
|         os.path.dirname(sys.executable), "python") | ||||
|  | ||||
| setup(name="mpresent", | ||||
|       version="0.1", | ||||
|       description="Office mobile presentation constroller", | ||||
|       url="https://github.com/imacat/mpresent", | ||||
|       author="imacat", | ||||
|       author_email="imacat@mail.imacat.idv.tw", | ||||
|       license="Apache License, Version 2.0", | ||||
|       zip_safe=False, | ||||
|       scripts=["bin/mpresent"]) | ||||
		Reference in New Issue
	
	Block a user