# HG changeset patch # User morphbr # Date 1188394930 -3600 # Node ID daa61fffb8118f0a7eef05ccdce546566f1fa2dc # Parent e2baa6947dbfedeab04edb7813d102feccf431ee [svn r838] - Arranged code in a better way diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/data/gmsd --- a/gmyth-stream/server/0.3/data/gmsd Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -#!/bin/sh - -PROGRAM_NAME=GMS -PROGRAM_BIN=/usr/bin/gms.py -PIDFILE=/var/run/gms.pid -LOGFILE=/var/log/gms.log - -test -x $PROGRAM_BIN || exit 0 - -set -e - -. /lib/lsb/init-functions -. /etc/default/rcS - -case $1 in - start) - echo -n "Starting $PROGRAM_NAME: " - if [ -f $PIDFILE ] - then - PID=`cat $PIDFILE` - - if ps ax | grep -q "^$PID" - then - echo "$PROGRAM_NAME already running." - else - rm -f $PIDFILE - $PROGRAM_BIN -d > $LOGFILE - echo "OK" - fi - else - $PROGRAM_BIN -d > $LOGFILE - echo "OK" - fi - ;; - - stop) - echo -n "Stopping $PROGRAM_NAME: " - if [ -f $PIDFILE ] - then - PID=`cat $PIDFILE` - if ps ax | grep -q "^$PID" - then - kill -10 $PID - fi - rm $PIDFILE - else - echo "No $PROGRAM_NAME found running; no killed." - fi - ;; - - restart) - $0 stop - sleep 1 - $0 start - ;; - - *) - log_success_msg "Usage: $0 {stop|start|restart}" - exit 1 - ;; -esac diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/data/server.conf --- a/gmyth-stream/server/0.3/data/server.conf Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -[PATHS] -transcoded=/var/gms-media diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/changelog --- a/gmyth-stream/server/0.3/debian/changelog Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -gms (0.3-indt1) unstable; urgency=low - - * First package - - -- Renato Araujo Oliveira Filho Thu, 16 Aug 2007 14:55:00 -0300 - diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/compat --- a/gmyth-stream/server/0.3/debian/compat Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -5 diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/control --- a/gmyth-stream/server/0.3/debian/control Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -Source: gms -Section: sound -Priority: optional -Maintainer: Renato Araujo Oliveira Filho -Build-Depends: debhelper (>= 5.0.38), python-support (>= 0.5), python-central (>= 0.5) -Standards-Version: 3.7.2 - -Package: gms -Architecture: any -Depends: ${python:Depends}, libgstreamer0.10-0, gstreamer0.10-plugins-base, gstreamer0.10-plugins-good -Recommends: gstreamer0.10-plugins-ugly -Description: Media transcoder deamon - Homepage: http://gmyth.sourceforge.net/ diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/copyright --- a/gmyth-stream/server/0.3/debian/copyright Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -It was downloaded from: http://gmyth.sourceforge.net/wiki/ - -License: - This package is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This package is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this package; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -On Debian systems, the complete text of the GNU General Public License can -be found in `/usr/share/common-licenses/GPL'. diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/gms.install --- a/gmyth-stream/server/0.3/debian/gms.install Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -debian/tmp/usr/share/gms/lib/*.py usr/share/gms/lib -debian/tmp/usr/share/gms/plugins/*.py usr/share/gms/plugins -debian/tmp/usr/share/gms/plugins/transcoders/*.py usr/share/gms/plugins/transcoders -debian/tmp/usr/share/gms/plugins/transcoders/mencoder_lib/*.py usr/share/gms/plugins/transcoders/mencoder_lib -debian/tmp/usr/share/gms/html/* usr/share/gms/html -debian/tmp/usr/bin/* usr/bin -debian/etc/init.d/gmsd etc/init.d -debian/etc/gms/*.conf etc/gms/ diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/gms.postinst --- a/gmyth-stream/server/0.3/debian/gms.postinst Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -#! /bin/sh -# postinst script for gms - -set -e - -case "$1" in - configure) - if ! getent passwd gms >/dev/null; then - adduser --disabled-password --quiet --system \ - --home /var/gms-media \ - --gecos "GMS media dir" --group gms - fi - if ! getent passwd gms | grep -q /var/run/gms; then - usermod -d /var/gms-media gms - fi - update-rc.d gmsd defaults - invoke-rc.d gmsd start - ;; - abort-upgrade|abort-remove|abort-deconfigure) - ;; - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -#DEBHELPER# - -exit 0 diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/gms.postrm --- a/gmyth-stream/server/0.3/debian/gms.postrm Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#!/bin/sh - -set -e - -#DEBHELPER# - -if [ "$1" = "purge" ] ; then - invoke-rc.d --force gms stop - deluser --quiet --system gms > /dev/null || true - delgroup --quiet --system gms > /dev/null || true -fi - -exit 0 diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/debian/rules --- a/gmyth-stream/server/0.3/debian/rules Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -PYVER=2.5 -PYTHON=python$(PYVER) - -PREFIX=debian/tmp - -build: build-stamp - -build-stamp: - touch build-stamp - -clean: - dh_testdir - dh_testroot - rm -f build-stamp - dh_clean - -install: build - dh_testdir - dh_testroot - dh_installdirs - dh_clean -k - - @rm -rf build - @$(PYTHON) setup.py install --prefix=$(PREFIX)/usr --no-compile --install-purelib=$(PREFIX)/usr/share/gms - install -D -o root -g root -m 755 $(PREFIX)/usr/etc/init.d/gmsd debian/$(cdbs_curpkg)/etc/init.d/gmsd - install -D -o root -g root -m 755 $(PREFIX)/usr/etc/gms/server.conf debian/$(cdbs_curpkg)/etc/gms/server.conf - - dh_install - -# Build architecture-independent files here. -binary-indep: build install - dh_testdir - dh_testroot - dh_installchangelogs - dh_installdocs - dh_strip - dh_compress - dh_fixperms - dh_installdeb - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep -.PHONY: clean binary-indep binary install - diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/gms.py --- a/gmyth-stream/server/0.3/gms.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Artur Duque de Souza" -__author_email__ = "artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.3" -__thanks__ = "Gustavo Sverzut Barbieri" -__GMS_DATA_DIR__ = "/usr/share/gms/" - -import sys -import os -import mimetypes -import logging as log - -if os.path.exists (__GMS_DATA_DIR__): - sys.path.append(__GMS_DATA_DIR__) - -from lib.server import serve_forever, load_plugins_transcoders -from lib.utils import config - -mimetypes.init() -log_level = log.INFO -for p in sys.argv[1:]: - if p == "-v" or p == "--verbose": - log_level -= 10 - -log.basicConfig(level=log_level, - format=("### %(asctime)s %(name)-18s \t%(levelname)-8s " - "\t%(message)s"), - datefmt="%Y-%m-%d %H:%M:%S") - -if config.get_transcoded_location () is None: - print "Gms not configured" - exit (0) - -if not os.path.exists(config.get_transcoded_location()): - os.mkdir(config.get_transcoded_location()) - - -if "-d" in sys.argv: - #run with deamon - try: - pid = os.fork() - if pid > 0: - sys.exit(0) - except OSError, e: - print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror) - sys.exit(1) - - os.chdir("/") - os.setsid() - os.umask(0) - - try: - pid = os.fork() - if pid > 0: - fp = open ("/var/run/gms.pid", "w") - fp.write ("%d" % pid) - fp.close () - sys.exit(0) - except OSError, e: - print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror) - sys.exit(1) - -# main deamon -pd = os.path.join(__GMS_DATA_DIR__, "plugins", "transcoders") -if os.path.exists (pd): - load_plugins_transcoders(pd) - -pd = os.path.join("plugins", "transcoders"); -if os.path.exists (pd): - load_plugins_transcoders(pd) - -serve_forever() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/html/index.html --- a/gmyth-stream/server/0.3/html/index.html Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ - - GMyth-Streamer Server - -

Welcome to GMyth-Streamer Server

- - - \ No newline at end of file diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/html/menu.html --- a/gmyth-stream/server/0.3/html/menu.html Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -
  • %(name)s
  • diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/html/shutdown.html --- a/gmyth-stream/server/0.3/html/shutdown.html Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - - GMyth-Streamer Server Exited - -

    GMyth-Streamer is not running anymore

    - - \ No newline at end of file diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/html/status.html --- a/gmyth-stream/server/0.3/html/status.html Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - - GMyth-Streamer Server Status - -

    GMyth-Streamer Status

    - - - - diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/html/stop_all.html --- a/gmyth-stream/server/0.3/html/stop_all.html Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ - - GMyth-Streamer Server Stopped Transcoders - -

    GMyth-Streamer stopped running transcoders

    - - - \ No newline at end of file diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/html/stop_selected.html --- a/gmyth-stream/server/0.3/html/stop_selected.html Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ - - GMyth-Streamer Server Stopped Transcoders - -

    GMyth-Streamer stopped running transcoders:

    - - - - diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/lib/file_handler.py --- a/gmyth-stream/server/0.3/lib/file_handler.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Artur Duque de Souza" -__author_email__ = "artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.1" - -import os -import sys -import pickle -import logging -import lib.utils as utils - -from stat import * - -__all__ = ("FileList", "list_media_files") - - -class TranscodedFile(object): - """This class creates and reads information about transcoded files.""" - opts = {} - log = logging.getLogger("gms.file_handler") - - def __init__(self, filename, args): - if filename == "" or not os.path.exists(filename): - self.opts = args.copy() - - if self.opts["type"][0] != "myth": - self.opts["original_mtime"] = os.path.getmtime( - self.opts["uri"][0]) - - name = os.path.basename(self.opts["uri"][0]) - self.opts["original"] = [name] - output_file = os.path.basename(self.opts["outfile"][0]) - dat_file = output_file + ".dat"; - dat_path = os.path.join (utils.config.get_transcoded_location(), - dat_file); - - output = open(dat_path, "wb") - # dumps data using the highest protocol - pickle.dump(self.opts, output, -1) - output.close() - else: - name = os.path.splitext(os.path.basename(filename))[0] - dat_file = name + ".dat"; - dat_path = os.path.join (utils.config.get_transcoded_location(), - dat_file); - pkl_file = open(dat_path, "rb") - self.opts = pickle.load(pkl_file) - # __init__() - -# TranscodedFile - - -class FileList(list): - """Class to hold file's list - reimplements str and repr.""" - def __str__(self): - ret = "" - if len(self) > 0: - for item in self: - ret = ret + "%s" % item - return ret - # __str__() - - def __repr__(self): - return self.__str__() - # __repr__() - -# FileList - -def list_media_files(directory, file_list): - """Show all the media files with extension defined in the var 'ext' - that are in the directory, appending each one to 'file_list'.""" - ext = ['mpg', 'avi', 'mp4', 'nuv', 'mpeg', 'mov'] - for root, dirs, files in os.walk(directory): - for name in files: - if os.path.splitext(name)[1].strip(".") in ext: - dat_file = os.path.join(sys.path[0],root, - os.path.splitext(name)[0]+".dat") - - if name not in file_list and \ - os.path.exists(dat_file): - file_list.append(name) - - return True -# list_media_files() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/lib/gmsconfig.py --- a/gmyth-stream/server/0.3/lib/gmsconfig.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#!/usr/bin/env - -__author__ = "Renato Araujo Oliveira Filho" -__author_email__ = "renato.filho@indt.org.br" -__license__ = "GPL" -__version__ = "0.3" - - -import os -import ConfigParser - -__all__ = ("GmsConfig") - -class GmsConfig: - config = ConfigParser.ConfigParser() - __CONFIG_FILE__ = "server.conf" - __CONFIG_DIRS__ = [os.path.join (os.path.expanduser("~"), ".gms"), \ - os.path.join ("/", "etc", "gms"), \ - "."] - - def __init__(self): - for path in self.__CONFIG_DIRS__: - file_name = os.path.join (path, self.__CONFIG_FILE__) - if os.path.exists (file_name): - fp = open (file_name, "r") - self.config.readfp (fp) - return - # __init__() - - def get_transcoded_location (self): - try: - return os.path.realpath (self.config.get("PATHS", "transcoded")) - except: - return None - # get_transcoded_location() - - -# GmsConfig diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/lib/log.py --- a/gmyth-stream/server/0.3/lib/log.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Artur Duque de Souza" -__author_email__ = "artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.1" - -import os -import logging - -__all__ = ("Log", "log_structure") - -class log_structure(object): - """Structure to hold log info.""" - - def __init__(self, log=None): - self.log = log - self.history = [] - # __init__() - -# log_structure() - -class Log(object): - """This class implements a log where we can store status of - all transcoders (even from those that are not running any more).""" - - ## key = tid - ## item = ls - logs = {} - - def insert(self, tid, name): - """Insert a given tid on the log structure""" - if not self.logs.has_key(tid): - self.logs[tid] = log_structure(logging.getLogger(name)) - return True - else: - return False - # insert() - - def remove(self, tid=None): - """Cleans up all log stored for a - given tid or for all transcodes.""" - if not tid: - self.logs = {} - else: - del(self.logs[tid]) - - return True - # clean() - - def get_status(self, tid=None, all=False): - """Get the status of all transcoders or - of just one of them if it's given an tid.""" - if not tid: - ret = {} - for tids, logs in self.logs.items(): - if len(logs.history) > 0: - if not all: - ret[tids] = logs.history[-1] - else: - ret[tids] = logs.history - return ret - elif self.logs.has_key(tid) and len(self.logs[tid].history) > 0: - if not all: - return self.logs[tid].history[-1] - else: - return self.logs[tid].history - - return False - # get_status() - - def _update_status(self, tid=None, msg=""): - """Update the status of a given tid. Private method that - is only called inside error/info/debug wrappers""" - if msg != "": - self.logs[tid].history.append(msg) - return True - else: - return False - # update_status() - - def error(self, tid, msg): - """Python's Log.error wrapper""" - if self.logs.has_key(tid): - self.logs[tid].log.error("%s" % msg) - return self._update_status(tid, msg) - else: - return False - # error() - - def info(self, tid, msg): - """Python's Log.info wrapper""" - if self.logs.has_key(tid): - self.logs[tid].log.info("%s" % msg) - self._update_status(tid, msg) - return True - else: - return False - # info() - - def debug(self, tid, msg): - """Python's Log.debug wrapper""" - if self.logs.has_key(tid): - self.logs[tid].log.debug("%s" % msg) - self._update_status(tid, msg) - return True - else: - return False - # debug() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/lib/request_handler.py --- a/gmyth-stream/server/0.3/lib/request_handler.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,470 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.3" - -import os -import cgi -import socket -import logging -import urlparse -import threading -import SocketServer -import BaseHTTPServer -import mimetypes - -import lib.utils as utils -import lib.file_handler as files -import lib.transcoder as transcoder - -from log import Log - -__all__ = ("RequestHandler") - -class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - """Class that implements an HTTP request handler for our server.""" - log = logging.getLogger("gms.request") - def_transcoder = None - transcoders = utils.PluginSet(transcoder.Transcoder) - transcoders_log = Log() - tid_queue = [] - - menu = { - "Log": "/get_log.do", - "Stop": "/stop-transcoder.do", - "Status": "/status.do", - "All Log": "/get_all_log.do", - "Version": "/version.do", - "Shutdown": "/shutdown.do" - } - - @classmethod - def load_plugins_transcoders(cls, directory): - cls.transcoders.load_from_directory(directory) - - if cls.def_transcoder is None and cls.transcoders: - cls.def_transcoder = cls.transcoders[0].name - # load_plugins_transcoders() - - - def do_dispatch(self, body): - self.url = self.path - pieces = urlparse.urlparse(self.path) - self.path = pieces[2] - self.query = cgi.parse_qs(pieces[4]) - - url = { - "/": self.serve_main, - "/shutdown.do": self.serve_shutdown, - "/stop-transcoder.do": self.serve_stop_transcoder, - "/status.do": self.serve_status, - "/version.do": self.serve_version, - "/new_id.do": self.serve_new_id, - "/get_log.do": self.serve_get_log, - "/get_all_log.do": self.serve_get_all_log, - "/stream.do": self.serve_stream, - "/transcode.do": self.serve_transcode, - "/list.do": self.serve_list, - "/get_file_info.do": self.serve_file_info, - } - - try: - url[self.path](body) - except KeyError: - try: - action = self.query.get("action", None) - if action and "stream.do" in action: - self.serve_stream(body) - elif os.path.exists("html/%s" % self.path): - data = open("html/%s" % self.path) - self.wfile.write(data.read()) - else: - self.send_error(404, "File not found") - except Exception, e: - self.log.error(e) - - # do_dispatch() - - - def do_GET(self): - self.do_dispatch(True) - # do_GET() - - - def do_HEAD(self): - self.do_dispatch(False) - # do_HEAD() - - - def _nav_items(self): - ret = "" - for name, url in self.menu.items(): - ret += utils.getHTML("menu", {"name": name, "url": url}) - return ret - # _nav_items() - - - def serve_main(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - if body: - self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()})) - # serve_main() - - - def serve_version(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - if body: - self.wfile.write("Version: %s" % __version__) - # serve_version - - - def serve_shutdown(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - if body: - self.wfile.write(utils.getHTML("shutdown")) - self.server.server_close() - # serve_shutdown() - - - def serve_list(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - - if body: - file_list = [] - files.list_media_files(utils.config.get_transcoded_location(), file_list) - output = files.FileList(map(lambda x, y: x+y, file_list, - ["
    "]*len(file_list))) - self.wfile.write(output) - - # serve_list() - - - def serve_stop_all_transcoders(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - if body: - self.server.stop_transcoders() - self.wfile.write(utils.getHTML("stop_all", - {"menu": self._nav_items()})) - # serve_stop_all_transcoders() - - - def serve_stop_selected_transcoders(self, body, tids=[]): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - opts = "" - if body: - transcoders = self.server.get_transcoders() - - for tid in tids: - for t, r in transcoders: - if t.tid == int(tid): - try: - t.stop() - except Exception, e: - self.log.info("Plugin already stopped") - - opts += utils._create_html_item("%s" % t) - - break - - self.wfile.write(utils.getHTML("stop_selected", - {"menu": self._nav_items(), - "opts": opts})) - # serve_stop_selected_transcoders() - - - def serve_stop_transcoder(self, body): - req = self.query.get("request", None) - tid = self.query.get("tid", None) - if req and "all" in req: - self.serve_stop_all_transcoders(body) - elif tid: - self.serve_stop_selected_transcoders(body, tid[0].split(";")) - else: - self.serve_status(body) - # serve_stop_transcoder() - - - def serve_status(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - stopone = "" - running = "" - stopall = "" - - if body: - tl = self.server.get_transcoders() - if not tl and not self.query.get("tid", None) and \ - not self.query.get("running", None): - running = "

    No running transcoder.

    \n" - - elif not tl and self.query.get("tid", None): - tids = self.query.get("tid") - for tid in tids: - stat = self.transcoders_log.get_status(int(tid)) - self.wfile.write("%s
    " % stat) - return True - - elif self.query.get("running", None): - for transcoder, request in tl: - outf = transcoder.params_first("outfile") - tid = transcoder.tid - self.wfile.write("%s:%s
    " % (tid, outf)) - return True - - elif self.query.get("tid", None): - req_tid = self.query.get("tid") - for transcoder, request in tl: - if str(transcoder.tid) in req_tid: - self.wfile.write("Status:%s:%s %%" % (\ - transcoder.tid, transcoder.status)) - return True - stat = self.transcoders_log.get_status(int(req_tid[0])) - self.wfile.write("%s
    " % stat) - return True - - else: - running = "

    Running transcoders:

    \n" - stopall = utils._create_html_item("" - "[STOP ALL]" % - self.menu["Stop"]) - - for transcoder, request in tl: - stopone += utils._create_html_item("%s;" - "" - " [STOP] ") % ( - transcoder, self.menu["Stop"], transcoder.tid) - - self.wfile.write(utils.getHTML("status", - {"menu": self._nav_items(), - "running": running, - "stopall": stopall, - "stopone": stopone})) - # serve_status() - - - def _get_transcoder(self): - # get transcoder option: mencoder is the default - request_transcoders = self.query.get("transcoder", ["mencoder"]) - - for t in request_transcoders: - transcoder = self.transcoders.get(t) - if transcoder: - return transcoder - - if not transcoder: - return self.transcoders[self.def_transcoder] - # _get_transcoder() - - - def _get_new_id(self, tid): - self.server.last_tid = utils.create_tid(tid) - self.tid_queue.append(self.server.last_tid) - return self.server.last_tid - # _get_new_id() - - - def serve_new_id(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - - if body: - self.wfile.write("%s" % self._get_new_id(self.server.last_tid)) - # serve_new_id() - - def serve_get_log(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - - if body: - if self.query.get("tid", None): - tid = int(self.query.get("tid")[0]) - stat = self.transcoders_log.get_status(tid) - self.wfile.write("Status: %s" % stat) - else: - stat = self.transcoders_log.get_status() - for rtid, status in stat.iteritems(): - self.wfile.write("%s: %s

    " % (rtid, status)) - # serve_get_log() - - def serve_get_all_log(self, body): - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - - if body: - if self.query.get("tid", None): - tid = int(self.query.get("tid")[0]) - stat = self.transcoders_log.get_status(tid, True) - for status in stat: - self.wfile.write("%s

    " % status) - else: - stat = self.transcoders_log.get_status(None, True) - for rtid, history in stat.iteritems(): - for status in history: - self.wfile.write("%s: %s
    " % (rtid, status)) - self.wfile.write("

    ") - # serve_get_all_log() - - - def serve_file_info(self, body): - if body: - - file_dat = self.query.get("file", None) - - if file_dat: - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.send_header('Connection', 'close') - self.end_headers() - - try: - opts = files.TranscodedFile(file_dat[0], self.query).opts - for key in opts.keys(): - self.wfile.write("%s=%s
    " % (key, opts.get(key, "None")[0])) - - except Exception, e: - self.send_error(500, str(e)) - return - # serve_file_info() - - def serve_stream(self, body): - args = self.query.get("file", None) - if not args: - self.send_error(404, "File not found") - return - - filename = args[0]; - if not filename: - self.send_error(404, "File not found") - return - - #Only stream files on .transcode dir - filename = os.path.join (utils.config.get_transcoded_location(), - os.path.basename(filename)) - self.log.error("Stream file: %s" % filename) - if not os.path.exists (filename): - self.send_error(404, "File not found") - return - - size = int(os.path.getsize(filename)) - self.send_response(200) - self.send_header("Content-Type", mimetypes.guess_type(filename)[0]) - self.send_header("Cache-Control","no-cache") - self.send_header("Content-Length", size) - self.end_headers() - - media = open(filename) - data_in = " " - total_read = 0 - - test_tid = int(self.query.get("tid", "0")[0]) - if test_tid == 0 or test_tid not in self.tid_queue: - test_tid = self._get_new_id(self.server.last_tid) - - self.transcoders_log.insert(test_tid, "gms.Stream: %s" % filename) - - try: - file_data = "" - while data_in != "": - data_in = media.read(4096) - file_data += data_in - - #total_read += 4096 - self.wfile.write(file_data) - #status = utils.progress_bar(total_read, size, 50) - #msg_status = "Status:%s:%s%%" % (test_tid, status) - #self.transcoders_log._update_status(test_tid, msg_status) - - self.transcoders_log._update_status(test_tid, "OK: Done") - - except Exception, e: - self.log.error("Stream error: %s" %e) - self.transcoders_log._update_status(test_tid, "Error: %s" % e) - # serve_stream() - - def serve_transcode(self, body): - type = self.query.get("type", None)[0] - if type.upper() == "FILE": - self.send_error(404, "Transcode local files not allowed") - return - - transcoder = self._get_transcoder() - try: - obj = transcoder(self.query) - except Exception, e: - self.send_error(500, str(e)) - return - - self.send_response(200) - self.send_header("Content-Type", obj.get_mimetype()) - self.send_header("Cache-Control","no-cache") - - if (obj.name == "gmencoder"): - self.send_header("Transfer-Encoding", "chunked") - - self.end_headers() - - if body: - test_tid = int(self.query.get("tid", "0")[0]) - if test_tid == 0 or test_tid not in self.tid_queue: - test_tid = self._get_new_id(self.server.last_tid) - - if self.query.get("transcoder", None): - self.transcoders_log.insert(test_tid, "gms.%s" % obj.name) - obj.tid = test_tid - obj.log = self.transcoders_log - - self.server.add_transcoders(self, obj) - if obj.start(self.wfile): - self.transcoders_log.info (test_tid, "OK") - else: - self.transcoders_log.info (test_tid, "Fail") - - self.server.del_transcoders(self, obj) - files.TranscodedFile("", self.query) - - # serve_stream() - - - def log_request(self, code='-', size='-'): - self.log.info('"%s" %s %s', self.requestline, str(code), str(size)) - # log_request() - - - def log_error(self, format, *args): - self.log.error("%s: %s" % (self.address_string(), format % args)) - # log_error() - - - def log_message(self, format, *args): - self.log.info("%s: %s" % (self.address_string(), format % args)) - # log_message() - -# RequestHandler diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/lib/server.py --- a/gmyth-stream/server/0.3/lib/server.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.4" - -import os -import threading -import SocketServer -import BaseHTTPServer -import socket -import urlparse -import cgi -import lib.utils as utils -import logging - -from log import Log -from request_handler import RequestHandler - -__all__ = ("Server", "serve_forever", "load_plugins_transcoders") - -class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): - log = logging.getLogger("gms.server") - last_tid = 0 - run = True - _transcoders = {} - _lock = threading.RLock() - - def serve_forever(self): - self.log.info("GMyth-Streamer serving HTTP on %s:%s" % - self.socket.getsockname()) - try: - while self.run: - self.handle_request() - except KeyboardInterrupt, e: - pass - - self.log.debug("Stopping all remaining transcoders...") - self.stop_transcoders() - self.log.debug("Transcoders stopped!") - # serve_forever() - - - def get_request(self): - skt = self.socket - old = skt.gettimeout() - skt.settimeout(0.5) - while self.run: - try: - r = skt.accept() - skt.settimeout(old) - return r - except socket.timeout, e: - pass - raise socket.error("Not running") - # get_request() - - - def server_close(self): - self.run = False - self.stop_transcoders() - - BaseHTTPServer.HTTPServer.server_close(self) - # server_close() - - - def stop_transcoders(self): - self._lock.acquire() - for transcoder, request in self._transcoders.iteritems(): - self.log.info("Stop transcoder: %s, client=%s" % - (transcoder, request.client_address)) - transcoder.stop() - self._lock.release() - # stop_transcoders() - - - def get_transcoders(self): - self._lock.acquire() - try: - return self._transcoders.items() - finally: - self._lock.release() - # get_transcoders() - - - def add_transcoders(self, request, transcoder): - self._lock.acquire() - try: - self._transcoders[transcoder] = request - finally: - self._lock.release() - # add_transcoders() - - - def del_transcoders(self, request, transcoder): - self._lock.acquire() - try: - del self._transcoders[transcoder] - finally: - self._lock.release() - # del_transcoders() -# Server - - - -def serve_forever(host="0.0.0.0", port=40000): - addr = (host, port) - RequestHandler.protocol_version = "HTTP/1.0" - httpd = Server(addr, RequestHandler) - httpd.serve_forever() -# serve_forever() - - -def load_plugins_transcoders(directory): - RequestHandler.load_plugins_transcoders(directory) -# load_plugins_transcoders() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/lib/transcoder.py --- a/gmyth-stream/server/0.3/lib/transcoder.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.4" - -__all__ = ("Transcoder") - -class Transcoder(object): - """Transcoder's Class: parent class to implement - a plugin for transcoding data.""" - priority = 0 # negative values have higher priorities - name = None # to be used in requests - status = None - log = None - tid = -1 - - def __init__(self, params): - self.params = params - # __init__() - - def params_first(self, key, default=None): - if default is None: - return self.params[key][0] - else: - try: - return self.params[key][0] - except: - return default - # params_first() - - def get_mimetype(self): - return "application/octet-stream" - # get_mimetype() - - def start(self, outfile): - pass - # start() - - def stop(self): - pass - # stop() - - def get_legth (self): - pass - # get_leght () - - def get_progress (self): - pass - # get_progress () - - def __str__(self): - return '%s: %s( params=%s ) - Status: %s%%' % \ - (self.__class__.__name__, self.tid, - self.params, self.status) - # __str__() -# Transcoder diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/lib/utils.py --- a/gmyth-stream/server/0.3/lib/utils.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -#!/usr/bin/env - -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.3" - -import os -import stat -import sys -import logging -import urllib -import gobject -import imp - -import gmsconfig - -log = logging.getLogger("gms.utils") -config = gmsconfig.GmsConfig() - -__all__ = ("which", "load_plugins", "PluginSet", "getHTML", - "progress_bar", "create_tid", "list_media_files") - -def which(app): - """Function to implement which(1) unix command""" - pl = os.environ["PATH"].split(os.pathsep) - for p in pl: - path = os.path.join(p, app) - if os.path.isfile(path): - st = os.stat(path) - if st[stat.ST_MODE] & 0111: - return path - return "" -# which() - - -def _load_module(pathlist, name): - fp, path, desc = imp.find_module(name, pathlist) - try: - module = imp.load_module(name, fp, path, desc) - return module - finally: - if fp: - fp.close() -# _load_module() - - -class PluginSet(object): - def __init__(self, basetype, *items): - self.basetype = basetype - self.map = {} - self.list = [] - - for i in items: - self._add(i) - self._sort() - # __init__() - - - def _add(self, item): - self.map[item.name] = item - self.list.append(item) - # _add() - - - def add(self, item): - self._add() - self._sort() - # add() - - - def __getitem__(self, spec): - if isinstance(spec, basestring): - return self.map[spec] - else: - return self.list[spec] - # __getitem__() - - - def get(self, name, default=None): - return self.map.get(name, default) - # get() - - - def __iter__(self): - return self.list.__iter__() - # __iter__() - - - def __len__(self): - return len(self.list) - # __len__() - - - def _sort(self): - self.list.sort(lambda a, b: cmp(a.priority, b.priority)) - # _sort() - - - def update(self, pluginset): - self.map.update(pluginset.map) - self.list.extend(pluginset.list) - self._sort() - # update() - - - def load_from_directory(self, directory): - for i in load_plugins(directory, self.basetype): - self._add(i) - self._sort() - # load_from_directory() - - - def __str__(self): - lst = [] - for o in self.list: - lst.append('"%s" (%s)' % (o.name, o.__name__)) - - return "%s(basetype=%s, items=[%s])" % \ - (self.__class__.__name__, - self.basetype.__name__, - ", ".join(lst)) - # __str__() -# PluginSet - - -def load_plugins(directory, basetype): - """Function to load plugins from a given directory""" - tn = basetype.__name__ - log.debug("Loading plugins from %s, type=%s" % (directory, tn)) - - - plugins = [] - for d in os.listdir(directory): - if not d.endswith(".py"): - continue - - name = d[0: -3] - if name == "__init__": - continue - - directory.replace(os.path.sep, ".") - mod = _load_module([directory], name) - for sym in dir(mod): - cls = getattr(mod, sym) - if isinstance(cls, type) and issubclass(cls, basetype) and \ - cls != basetype: - plugins.append(cls) - log.info("Loaded %s (%s) from %s" % \ - (cls.__name__, tn, os.path.join(directory, d))) - - return plugins -# load_plugins() - -def getHTML(html_file, params={}): - """This function parses an html file with the given - parameters and returns a formated web-page""" - try: - filename = os.path.join(sys.path[0], "html", html_file + ".html") - html = open(filename).read() % params - return html - except Exception, e: - return "HTML format error. Wrong keys: %s" % e - -# getHTML - -def _create_html_item(opt): - """Create an
  • item using HTML.""" - return "
  • %s
  • \n" % opt -# _create_html_item - -def progress_bar(value, max, barsize): - """Creates and displays a progressbar. By OSantana""" - chars = int(value * barsize / float(max)) - percent = int((value / float(max)) * 100) - sys.stdout.write("#" * chars) - sys.stdout.write(" " * (barsize - chars + 2)) - if value >= max: - sys.stdout.write("done.\n\n") - else: - sys.stdout.write("[%3i%%]\r" % (percent)) - sys.stdout.flush() - return percent -# progress_bar() by osantana - -def create_tid(last_tid): - """Function to generate TIDs (ids for transcoders). - At first it just do +1 on last_tid but can be implemented - to generate more sparse TIDs""" - tid = last_tid + 1 - return tid -# create_id() - diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/plugins/transcoders/gmencoder.py --- a/gmyth-stream/server/0.3/plugins/transcoders/gmencoder.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Renato Filho" -__author_email__ = "renato.filho@indt.org.br" -__license__ = "GPL" -__version__ = "0.2" - -import os -import sys -import shlex -import signal -import subprocess -import time - -import select -import fcntl - -import lib.utils as utils -import lib.server as server -import lib.transcoder as transcoder - -__all__ = ("TranscoderGMencoder",) - -class TranscoderGMencoder(transcoder.Transcoder): - gmencoder_path = utils.which("gmencoder") - name = "gmencoder" - priority = -1 - proc = None - - def __init__(self, params): - self.status = 0 - transcoder.Transcoder.__init__(self, params) - self.opts = [] - self.opts.append (self.gmencoder_path) - self.opts.append ("-d") - self._parser_params () - - # __init__() - - def _insert_param (self, name, value): - if (value != ""): - self.opts.append(name) - self.opts.append(value) - - def _parser_params (self): - self._insert_param("-i", \ - "%s://%s" % (self.params_first("type", "file"), - self.params_first("uri", ""))) - self._insert_param("--video-encode", self.params_first("ve", "ffenc_mpeg1video")) - self._insert_param("--video-opts", "bitrate=300000,pass=512,quantizer=0.01,quant-type=1") - #self._insert_param("--video-fps", self.params_first("fps", "")) - self._insert_param("--video-fps", self.params_first("fps", "10")) - self._insert_param("--video-width", self.params_first("width", "320")) - self._insert_param("--video-height", self.params_first("height", "240")) - self._insert_param("--audio-rate", "32000") - self._insert_param("--audio-encode", self.params_first("ae", "")) - # _parse_params - - def start(self, outfd): - outfile = self.params_first("outfile", "") - - if outfile != "": - path = os.path.join(utils.config.get_transcoded_location(), outfile) - self._insert_param("-o", "file://%s" % path) - else: - self._insert_param ("-o", "fd://%d" % outfd.fileno()) - self.opts.append ("-c") - - cmd = " ".join(self.opts) - self.log.info(self.tid, "GMencoder: %s" % cmd) - - try: - self.proc = subprocess.Popen(self.opts, stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - - if outfile: - outfd.write("OK ") - - except Exception, e: - self.log.error(self.tid, "Error: executing GMencoder: %s" % e) - outfd.write("Error: GMencoder: %s" % e) - return False - - try: - if not outfile: - p = select.poll() - p.register (outfd, select.POLLNVAL | select.POLLERR | select.POLLHUP | select.POLLIN ) - - while (self.proc and self.proc.poll() == None): - r, w, x = select.select([self.proc.stdout], [], [], 1) - if self.proc.stdout in r: - progress = self.proc.stdout.readline() - if (progress.find ("PROGRESS") >= 0): - self.status = progress.split (":")[1] - elif (progress.find ("Erro") >= 0): - return False - - if not outfile: - ret = p.poll(0) - if ret: - print "Lost Connection" - self.stop () - return False - - except Exception, e: - self.log.error(self.tid, "Problems handling data: %s" % e) - return False - - self.status = 100; - - - return True - # start() - - - def stop(self): - if self.proc: - self.log.info(self.tid, "Stopped GMencoder plugin") - try: - os.kill(self.proc.pid, signal.SIGKILL) - self.proc.wait() - except Exception, e: - pass - - self.proc = None - # stop() - - def get_progress(self): - return self.status - - def get_lenght(self): - return -1 - -# TranscoderGMencoder diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/plugins/transcoders/mencoder.py --- a/gmyth-stream/server/0.3/plugins/transcoders/mencoder.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,334 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Artur Duque de Souza" -__author_email__ = "artur.souza@indt.org.br" -__license__ = "GPL" -__version__ = "0.3" - -import os -import time -import fcntl -import shlex -import socket -import struct -import signal -import subprocess - -import lib.utils as utils -import lib.server as server -import plugins.transcoders.mencoder_lib.mythtv as mythtv - -from select import select -import lib.transcoder as transcoder - -__all__ = ("TranscoderMencoder",) - -class TranscoderMencoder(transcoder.Transcoder): - """Transcoder class that implements a transcoder using Mencoder""" - mencoder_path = utils.which("mencoder") - name = "mencoder" - priority = -1 - args = {} - proc = None - gmyth = None - - # only works with avi container - status = 0 - - def _setup_params(self): - params_first = self.params_first - - # general_opts - self.args["local"] = params_first("local", False) - self.args["language"] = params_first("language", False) - self.args["subtitle"] = params_first("subtitle", False) - self.args["format"] = params_first("format", "mpeg1") - self.args["outfile"] = params_first("outfile", "-") - - # input_opt - self.args["type"] = params_first("type", "file") - self.args["input"] = params_first("uri", "-") - - # audio_opts - self.args["acodec"] = params_first("acodec", "mp2") - self.args["abitrate"] = params_first("abitrate", 192) - self.args["volume"] = params_first("volume", 5) - - # video_opts - self.args["mux"] = params_first("mux", "mpeg") - self.args["fps"] = params_first("fps", 25) - self.args["vcodec"] = params_first("vcodec", "mpeg1video") - self.args["vbitrate"] = params_first("vbitrate", 400) - self.args["width"] = params_first("width", 320) - self.args["height"] = params_first("height", 240) - # _setup_params() - - - def _setup_audio(self): - if self.args["acodec"] == "mp3lame": - audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % ( - self.args["abitrate"], self.args["volume"]) - else: - audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % ( - self.args["acodec"], self.args["abitrate"]) - - return audio - # _setup_audio() - - - def _setup_video(self): - video = " -of %s" % self.args["mux"] - video += " -ofps %s" % self.args["fps"] - - vcodec = self.args["vcodec"] - if vcodec == "nuv" or vcodec == "xvid"\ - or vcodec == "qtvideo" or vcodec == "copy": - video += " -ovc %s" % vcodec - else: - video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % ( - vcodec, self.args["vbitrate"]) - - if self.args["mux"] == "mpeg": - video += " -mpegopts format=%s" % self.args["format"] - - video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"]) - return video - # _setup_video() - - - def _arg_append(self, args, options): - for arg in shlex.split(options): - args.append(arg) - # arg_append() - - def _setup_mencoder_opts(self, args): - args.append(self.mencoder_path) - - if self.args["type"] and self.args["type"] == "tv": - self._arg_append(args, self.args["tv"]) - elif self.args["outfile"] == "-" and self.args["type"]: - args.append(self.args["input"]) - else: - args.append("-") - - if self.args["language"]: - self._arg_append(args, "-alang %s" % self.args["language"]) - - if self.args["subtitle"]: - self._arg_append(args, "-slang %s" % self.args["subtitle"]) - self._arg_append(args, "-subfps %s" % self.args["fps"]) - - self._arg_append(args, "-idx") - self._arg_append(args, "-cache 1024") - self._arg_append(args, self._setup_audio()) - self._arg_append(args, self._setup_video()) - - self._arg_append(args, "-really-quiet") - - if self.args["outfile"] != "-": - self.args["outfile"] = ".transcoded/%s" % ( - os.path.basename(self.args["outfile"])) - - self._arg_append(args, "-o %s" % self.args["outfile"]) - self._arg_append(args, "2>%s" % os.devnull) - # _setup_args() - - def _setup_filename(self): - """This function setups the file to encode parsing the uri. - So, type can be: - * file - * dvd - * myth - - If the last one is detected we have to parse the uri to find args. - Then we store all the args inside a dictionary: self.args['gmyth-cat'] - """ - _type = self.args["type"] - - if _type == "file": - if not os.path.exists(self.args["input"]): - raise IOError,\ - "File requested does not exist: %s." % self.args["input"] - else: - self.args["input"] = "file://%s" % self.args["input"] - - elif _type == "dvd": - self.args["input"] = "dvd://%s" % self.args["input"] - - elif _type == "myth": - self.args["gmyth-cat"] = mythtv._setup_mythfilename(self) - - elif _type == "tv": - driver = self.params_first("driver", "v4l2") - norm = self.params_first("norm", "pal-m") - channel = self.params_first("channel", "13") - chanlist = self.params_first("chanlist", "us-bcast") - outfmt = self.params_first("outfmt", "yuy2") - vdev = self.params_first("vdev", "/dev/video0") - adev = self.params_first("adev", "/dev/dsp") - self.args["tv"] = "tv:// -v -tv driver=%s:norm=%s:channel=%s:" \ - "chanlist=%s:width=%s:height=%s:outfmt=%s:" \ - "device=%s:adevice=%s" % (driver, norm, - channel, chanlist, - self.args["width"], - self.args["height"], - outfmt, vdev, adev) - # _setup_filename() - - - def __init__(self, params): - transcoder.Transcoder.__init__(self, params) - self.mencoder_opts = [] - - try: - self._setup_params() - self._setup_filename() - self._setup_mencoder_opts(self.mencoder_opts) - except Exception, e: - if self.log: - self.log.error(self.tid, "Error: %s" % e) - else: - raise - # __init__() - - - def _check_opened_file(self, stdw, _stdin): - loop = True - while loop: - try: - return open(self.args["outfile"]) - except: - os.write(stdw, _stdin.read(1024)) - # _check_opened_file - - - def _start_outfile(self, outfd): - finished = False - - # Configuring stdin - try: - filename = self.args["input"].split("://")[1] - _stdin = open(filename) - size = int(os.path.getsize(filename)) - except Exception, e: - self.log.error(self.tid, "Error: Mencoder stdin"\ - " setup error: %s" % e) - outfd.write("Error: Mencoder stdin setup error: %s" %e) - return False - - self.status = 0 - total_read = 0 - - # Configuring pipes - stdr, stdw = os.pipe() - - if not self._run_mencoder(input=stdr): - return False - - stdout = self._check_opened_file(stdw, _stdin) - outfd.write("OK ") - - try: - while self.proc and self.proc.poll() == None: - if not finished: - data_in = _stdin.read(4096) - if data_in != "": - os.write(stdw, data_in) - total_read += 4096 - d = stdout.read(4096) - self.status = utils.progress_bar(total_read, - size, 50) - else: - finished = True - os.close(stdw) - - else: - d = stdout.read(4096) - - except Exception, e: - self.log.error(self.tid, "Error: %s" % e) - self.stop() - return False - - self.log.info(self.tid, "OK: Done") - return True - # _start_outfile() - - - def _start(self, outfd): - # Play a file on disk or DVD - if not self._run_mencoder(output=subprocess.PIPE): - return False - - try: - while self.proc and self.proc.poll() == None: - d = self.proc.stdout.read(1024) - outfd.write(d) - except Exception, e: - self.log.error(self.tid, "Error: %s" % e) - return False - - self.log.info(self.tid, "OK: Done") - return True - # _start() - - def _run_mencoder(self, input=None, output=None): - try: - self.proc = subprocess.Popen(self.mencoder_opts, stdin=input, - stdout=output, close_fds=True) - except Exception, e: - self.log.error(self.tid, "Error: Mencoder: %s" % e) - return False - - return True - # _run_mencoder() - - def start(self, outfd): - cmd = " ".join(self.mencoder_opts) - self.log.debug(self.tid, "Plugin's tid: %s" % self.tid) - self.log.debug(self.tid, "Mencoder: %s" % cmd) - - ret = False - - if self.args["outfile"] == "-" and \ - self.args["type"] in ["file", "dvd", "tv"]: - ret = self._start(outfd) - - elif self.args["type"] == "myth": - ret = mythtv.start_myth(self, outfd) - - else: - ret = self._start_outfile(outfd) - - self.stop() - - if not ret: - self.log.error(self.tid, "Error: Problems while "\ - "starting streaming.") - - return ret - # start() - - def _aux_stop(self, obj, next=False): - if obj: - try: - os.kill(obj.pid, signal.SIGKILL) - if next: - os.kill(obj.pid+1, signal.SIGKILL) - except OSError, e: - pass - - try: - obj.wait() - except Exception, e: - pass - - obj = None - # _aux_stop - - def stop(self): - self._aux_stop(self.proc, True) - self._aux_stop(self.gmyth) - # stop() - -# TranscoderMencoder diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/plugins/transcoders/mencoder_lib/mythtv.py --- a/gmyth-stream/server/0.3/plugins/transcoders/mencoder_lib/mythtv.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -import os -import subprocess -import fcntl - -import lib.utils as utils -import lib.server as server - -from select import select - -def _setup_mythfilename(self): - # mythtv:mythtv@192.168.3.110:6543/1002_20070426230000.nuv - try: - _mysql = self.args["input"].split("@")[0].split(":") - except IndexError, e: - _mysql = ["mythtv", "mythtv"] - - try: - _args = self.args["input"].split("@")[1].split(":") - except IndexError, e: - _args = self.args["input"].split(":") - - gmyth_dict = {} - gmyth_dict["mysql"] = _mysql - gmyth_dict["backend"] = _args[0] - gmyth_dict["port"] = _args[1].split("/", 1)[0] - - _tmp_file = _args[1].split("/", 1)[1] - - if _tmp_file.find("channel") >= 0: - gmyth_dict["kind"] = "c" - gmyth_dict["cfile"] = _tmp_file.split("=")[1] - else: - gmyth_dict["kind"] = "f" - gmyth_dict["cfile"] = _tmp_file - - self.args["input"] = "-" - return gmyth_dict -# _setup_mythfilename - -def _setup_mythfile(err): - size = err.readline().split("Size:")[1] - flags = fcntl.fcntl (err, fcntl.F_GETFL, 0) | os.O_NONBLOCK - fcntl.fcntl(err, fcntl.F_SETFL, flags) - return size -# _setup_mythfile - -def _setup_gmythcat(self): - gmyth_cat = utils.which("gmyth-cat") - if self.args.has_key("gmyth-cat"): - return [ utils.which("gmyth-cat"), - "-h", self.args["gmyth-cat"]["backend"], - "-p", self.args["gmyth-cat"]["port"], - "-" + self.args["gmyth-cat"]["kind"], - self.args["gmyth-cat"]["cfile"] - ] - else: - self.log.error(self.tid, "Error: URI error") - return [] -# _setup_gmythcat - -def start_myth(self, outfd): - opts = _setup_gmythcat(self) - try: - self.gmyth = subprocess.Popen(opts, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - close_fds=True) - except Exception, e: - self.log.error(self.tid, "Error: gmyth-cat: %s" % e) - return False - - if not self._run_mencoder(input=self.gmyth.stdout, - output=subprocess.PIPE): - return False - - if self.args["gmyth-cat"]["kind"] == "f": - try: - size = _setup_mythfile(self.gmyth.stderr) - self.log.debug(self.tid, "Info: Size of file: %s" % size) - except Exception, e: - self.log.error(self.tid, "Error: Problems getting size of"\ - " file: %s" % e) - outfd.write("Error: Problems getting size of file: %s" % e) - return False - - outfd.write("OK ") - - try: - while self.proc and self.proc.poll() == None: - r, w, x = select([self.gmyth.stderr, self.proc.stdout], - [], [], 0) - if self.proc.stdout in r: - d = self.proc.stdout.read(4096) - outfd.write(d) - - if self.gmyth.stderr in r: - partial = self.gmyth.stderr.readline() - if partial != "": - self.status = utils.progress_bar(int(partial), - int(size), 50) - - except IndexError, e: - pass - except Exception, e: - self.log.error(self.tid, "Error: %s" % e) - return False - - self.log.info(self.tid, "OK: Done") - return True -# _start_myth() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/server.conf --- a/gmyth-stream/server/0.3/server.conf Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -[PATHS] -transcoded=./.transcoded diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/0.3/setup.py --- a/gmyth-stream/server/0.3/setup.py Wed Aug 29 14:29:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -from distutils.core import setup -from glob import glob - -setup(name='gms', - version='0.6', - description='carman rich view package', - long_description='carman rich view (SDL based) package', - url='http://www.indt.org.br', - scripts=['gms.py'], - package_dir={'lib': 'lib', 'plugins' : 'plugins','data' : 'data' }, - packages=['lib','plugins','plugins.transcoders','plugins.transcoders.mencoder_lib'], - data_files = [ - ('share/gms/html', glob("html/*")), - ('etc/init.d', ['data/gmsd']), - ('etc/gms', ['data/server.conf']) - ], - ) diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/data/gmsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/data/gmsd Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,61 @@ +#!/bin/sh + +PROGRAM_NAME=GMS +PROGRAM_BIN=/usr/bin/gms.py +PIDFILE=/var/run/gms.pid +LOGFILE=/var/log/gms.log + +test -x $PROGRAM_BIN || exit 0 + +set -e + +. /lib/lsb/init-functions +. /etc/default/rcS + +case $1 in + start) + echo -n "Starting $PROGRAM_NAME: " + if [ -f $PIDFILE ] + then + PID=`cat $PIDFILE` + + if ps ax | grep -q "^$PID" + then + echo "$PROGRAM_NAME already running." + else + rm -f $PIDFILE + $PROGRAM_BIN -d > $LOGFILE + echo "OK" + fi + else + $PROGRAM_BIN -d > $LOGFILE + echo "OK" + fi + ;; + + stop) + echo -n "Stopping $PROGRAM_NAME: " + if [ -f $PIDFILE ] + then + PID=`cat $PIDFILE` + if ps ax | grep -q "^$PID" + then + kill -10 $PID + fi + rm $PIDFILE + else + echo "No $PROGRAM_NAME found running; no killed." + fi + ;; + + restart) + $0 stop + sleep 1 + $0 start + ;; + + *) + log_success_msg "Usage: $0 {stop|start|restart}" + exit 1 + ;; +esac diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/data/server.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/data/server.conf Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,2 @@ +[PATHS] +transcoded=/var/gms-media diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/changelog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/changelog Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,6 @@ +gms (0.3-indt1) unstable; urgency=low + + * First package + + -- Renato Araujo Oliveira Filho Thu, 16 Aug 2007 14:55:00 -0300 + diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/compat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/compat Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,1 @@ +5 diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/control Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,13 @@ +Source: gms +Section: sound +Priority: optional +Maintainer: Renato Araujo Oliveira Filho +Build-Depends: debhelper (>= 5.0.38), python-support (>= 0.5), python-central (>= 0.5) +Standards-Version: 3.7.2 + +Package: gms +Architecture: any +Depends: ${python:Depends}, libgstreamer0.10-0, gstreamer0.10-plugins-base, gstreamer0.10-plugins-good +Recommends: gstreamer0.10-plugins-ugly +Description: Media transcoder deamon + Homepage: http://gmyth.sourceforge.net/ diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/copyright --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/copyright Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,19 @@ +It was downloaded from: http://gmyth.sourceforge.net/wiki/ + +License: + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General Public License can +be found in `/usr/share/common-licenses/GPL'. diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/gms.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/gms.install Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,8 @@ +debian/tmp/usr/share/gms/lib/*.py usr/share/gms/lib +debian/tmp/usr/share/gms/plugins/*.py usr/share/gms/plugins +debian/tmp/usr/share/gms/plugins/transcoders/*.py usr/share/gms/plugins/transcoders +debian/tmp/usr/share/gms/plugins/transcoders/mencoder_lib/*.py usr/share/gms/plugins/transcoders/mencoder_lib +debian/tmp/usr/share/gms/html/* usr/share/gms/html +debian/tmp/usr/bin/* usr/bin +debian/etc/init.d/gmsd etc/init.d +debian/etc/gms/*.conf etc/gms/ diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/gms.postinst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/gms.postinst Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,29 @@ +#! /bin/sh +# postinst script for gms + +set -e + +case "$1" in + configure) + if ! getent passwd gms >/dev/null; then + adduser --disabled-password --quiet --system \ + --home /var/gms-media \ + --gecos "GMS media dir" --group gms + fi + if ! getent passwd gms | grep -q /var/run/gms; then + usermod -d /var/gms-media gms + fi + update-rc.d gmsd defaults + invoke-rc.d gmsd start + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/gms.postrm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/gms.postrm Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,13 @@ +#!/bin/sh + +set -e + +#DEBHELPER# + +if [ "$1" = "purge" ] ; then + invoke-rc.d --force gms stop + deluser --quiet --system gms > /dev/null || true + delgroup --quiet --system gms > /dev/null || true +fi + +exit 0 diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/debian/rules --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/debian/rules Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,52 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +PYVER=2.5 +PYTHON=python$(PYVER) + +PREFIX=debian/tmp + +build: build-stamp + +build-stamp: + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + dh_clean + +install: build + dh_testdir + dh_testroot + dh_installdirs + dh_clean -k + + @rm -rf build + @$(PYTHON) setup.py install --prefix=$(PREFIX)/usr --no-compile --install-purelib=$(PREFIX)/usr/share/gms + install -D -o root -g root -m 755 $(PREFIX)/usr/etc/init.d/gmsd debian/$(cdbs_curpkg)/etc/init.d/gmsd + install -D -o root -g root -m 755 $(PREFIX)/usr/etc/gms/server.conf debian/$(cdbs_curpkg)/etc/gms/server.conf + + dh_install + +# Build architecture-independent files here. +binary-indep: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep +.PHONY: clean binary-indep binary install + diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/gms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/gms.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +__author__ = "Artur Duque de Souza" +__author_email__ = "artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.3" +__thanks__ = "Gustavo Sverzut Barbieri" +__GMS_DATA_DIR__ = "/usr/share/gms/" + +import sys +import os +import mimetypes +import logging as log + +if os.path.exists (__GMS_DATA_DIR__): + sys.path.append(__GMS_DATA_DIR__) + +from lib.server import serve_forever, load_plugins_transcoders +from lib.utils import config + +mimetypes.init() +log_level = log.INFO +for p in sys.argv[1:]: + if p == "-v" or p == "--verbose": + log_level -= 10 + +log.basicConfig(level=log_level, + format=("### %(asctime)s %(name)-18s \t%(levelname)-8s " + "\t%(message)s"), + datefmt="%Y-%m-%d %H:%M:%S") + +if config.get_transcoded_location () is None: + print "Gms not configured" + exit (0) + +if not os.path.exists(config.get_transcoded_location()): + os.mkdir(config.get_transcoded_location()) + + +if "-d" in sys.argv: + #run with deamon + try: + pid = os.fork() + if pid > 0: + sys.exit(0) + except OSError, e: + print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror) + sys.exit(1) + + os.chdir("/") + os.setsid() + os.umask(0) + + try: + pid = os.fork() + if pid > 0: + fp = open ("/var/run/gms.pid", "w") + fp.write ("%d" % pid) + fp.close () + sys.exit(0) + except OSError, e: + print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror) + sys.exit(1) + +# main deamon +pd = os.path.join(__GMS_DATA_DIR__, "plugins", "transcoders") +if os.path.exists (pd): + load_plugins_transcoders(pd) + +pd = os.path.join("plugins", "transcoders"); +if os.path.exists (pd): + load_plugins_transcoders(pd) + +serve_forever() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/html/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/html/index.html Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,9 @@ + + GMyth-Streamer Server + +

    Welcome to GMyth-Streamer Server

    +
      +%(menu)s +
    + + \ No newline at end of file diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/html/menu.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/html/menu.html Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,1 @@ +
  • %(name)s
  • diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/html/shutdown.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/html/shutdown.html Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,6 @@ + + GMyth-Streamer Server Exited + +

    GMyth-Streamer is not running anymore

    + + \ No newline at end of file diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/html/status.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/html/status.html Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,14 @@ + + GMyth-Streamer Server Status + +

    GMyth-Streamer Status

    +
      + %(running)s + %(stopall)s + %(stopone)s +
    +
      + %(menu)s +
    + + diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/html/stop_all.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/html/stop_all.html Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,9 @@ + + GMyth-Streamer Server Stopped Transcoders + +

    GMyth-Streamer stopped running transcoders

    +
      + %(menu)s +
    + + \ No newline at end of file diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/html/stop_selected.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/html/stop_selected.html Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,12 @@ + + GMyth-Streamer Server Stopped Transcoders + +

    GMyth-Streamer stopped running transcoders:

    +
      + %(opts)s +
    +
      + %(menu)s +
    + + diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/lib/file_handler.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/file_handler.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,86 @@ +#!/usr/bin/env python + +__author__ = "Artur Duque de Souza" +__author_email__ = "artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.1" + +import os +import sys +import pickle +import logging +import lib.utils as utils + +from stat import * + +__all__ = ("FileList", "list_media_files") + + +class TranscodedFile(object): + """This class creates and reads information about transcoded files.""" + opts = {} + log = logging.getLogger("gms.file_handler") + + def __init__(self, filename, args): + if filename == "" or not os.path.exists(filename): + self.opts = args.copy() + + if self.opts["type"][0] != "myth": + self.opts["original_mtime"] = os.path.getmtime( + self.opts["uri"][0]) + + name = os.path.basename(self.opts["uri"][0]) + self.opts["original"] = [name] + output_file = os.path.basename(self.opts["outfile"][0]) + dat_file = output_file + ".dat"; + dat_path = os.path.join (utils.config.get_transcoded_location(), + dat_file); + + output = open(dat_path, "wb") + # dumps data using the highest protocol + pickle.dump(self.opts, output, -1) + output.close() + else: + name = os.path.splitext(os.path.basename(filename))[0] + dat_file = name + ".dat"; + dat_path = os.path.join (utils.config.get_transcoded_location(), + dat_file); + pkl_file = open(dat_path, "rb") + self.opts = pickle.load(pkl_file) + # __init__() + +# TranscodedFile + + +class FileList(list): + """Class to hold file's list - reimplements str and repr.""" + def __str__(self): + ret = "" + if len(self) > 0: + for item in self: + ret = ret + "%s" % item + return ret + # __str__() + + def __repr__(self): + return self.__str__() + # __repr__() + +# FileList + +def list_media_files(directory, file_list): + """Show all the media files with extension defined in the var 'ext' + that are in the directory, appending each one to 'file_list'.""" + ext = ['mpg', 'avi', 'mp4', 'nuv', 'mpeg', 'mov'] + for root, dirs, files in os.walk(directory): + for name in files: + if os.path.splitext(name)[1].strip(".") in ext: + dat_file = os.path.join(sys.path[0],root, + os.path.splitext(name)[0]+".dat") + + if name not in file_list and \ + os.path.exists(dat_file): + file_list.append(name) + + return True +# list_media_files() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/lib/gmsconfig.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/gmsconfig.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,38 @@ +#!/usr/bin/env + +__author__ = "Renato Araujo Oliveira Filho" +__author_email__ = "renato.filho@indt.org.br" +__license__ = "GPL" +__version__ = "0.3" + + +import os +import ConfigParser + +__all__ = ("GmsConfig") + +class GmsConfig: + config = ConfigParser.ConfigParser() + __CONFIG_FILE__ = "server.conf" + __CONFIG_DIRS__ = [os.path.join (os.path.expanduser("~"), ".gms"), \ + os.path.join ("/", "etc", "gms"), \ + "."] + + def __init__(self): + for path in self.__CONFIG_DIRS__: + file_name = os.path.join (path, self.__CONFIG_FILE__) + if os.path.exists (file_name): + fp = open (file_name, "r") + self.config.readfp (fp) + return + # __init__() + + def get_transcoded_location (self): + try: + return os.path.realpath (self.config.get("PATHS", "transcoded")) + except: + return None + # get_transcoded_location() + + +# GmsConfig diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/lib/log.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/log.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +__author__ = "Artur Duque de Souza" +__author_email__ = "artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.1" + +import os +import logging + +__all__ = ("Log", "log_structure") + +class log_structure(object): + """Structure to hold log info.""" + + def __init__(self, log=None): + self.log = log + self.history = [] + # __init__() + +# log_structure() + +class Log(object): + """This class implements a log where we can store status of + all transcoders (even from those that are not running any more).""" + + ## key = tid + ## item = ls + logs = {} + + def insert(self, tid, name): + """Insert a given tid on the log structure""" + if not self.logs.has_key(tid): + self.logs[tid] = log_structure(logging.getLogger(name)) + return True + else: + return False + # insert() + + def remove(self, tid=None): + """Cleans up all log stored for a + given tid or for all transcodes.""" + if not tid: + self.logs = {} + else: + del(self.logs[tid]) + + return True + # clean() + + def get_status(self, tid=None, all=False): + """Get the status of all transcoders or + of just one of them if it's given an tid.""" + if not tid: + ret = {} + for tids, logs in self.logs.items(): + if len(logs.history) > 0: + if not all: + ret[tids] = logs.history[-1] + else: + ret[tids] = logs.history + return ret + elif self.logs.has_key(tid) and len(self.logs[tid].history) > 0: + if not all: + return self.logs[tid].history[-1] + else: + return self.logs[tid].history + + return False + # get_status() + + def _update_status(self, tid=None, msg=""): + """Update the status of a given tid. Private method that + is only called inside error/info/debug wrappers""" + if msg != "": + self.logs[tid].history.append(msg) + return True + else: + return False + # update_status() + + def error(self, tid, msg): + """Python's Log.error wrapper""" + if self.logs.has_key(tid): + self.logs[tid].log.error("%s" % msg) + return self._update_status(tid, msg) + else: + return False + # error() + + def info(self, tid, msg): + """Python's Log.info wrapper""" + if self.logs.has_key(tid): + self.logs[tid].log.info("%s" % msg) + self._update_status(tid, msg) + return True + else: + return False + # info() + + def debug(self, tid, msg): + """Python's Log.debug wrapper""" + if self.logs.has_key(tid): + self.logs[tid].log.debug("%s" % msg) + self._update_status(tid, msg) + return True + else: + return False + # debug() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/lib/request_handler.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/request_handler.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,470 @@ +#!/usr/bin/env python + +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.3" + +import os +import cgi +import socket +import logging +import urlparse +import threading +import SocketServer +import BaseHTTPServer +import mimetypes + +import lib.utils as utils +import lib.file_handler as files +import lib.transcoder as transcoder + +from log import Log + +__all__ = ("RequestHandler") + +class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): + """Class that implements an HTTP request handler for our server.""" + log = logging.getLogger("gms.request") + def_transcoder = None + transcoders = utils.PluginSet(transcoder.Transcoder) + transcoders_log = Log() + tid_queue = [] + + menu = { + "Log": "/get_log.do", + "Stop": "/stop-transcoder.do", + "Status": "/status.do", + "All Log": "/get_all_log.do", + "Version": "/version.do", + "Shutdown": "/shutdown.do" + } + + @classmethod + def load_plugins_transcoders(cls, directory): + cls.transcoders.load_from_directory(directory) + + if cls.def_transcoder is None and cls.transcoders: + cls.def_transcoder = cls.transcoders[0].name + # load_plugins_transcoders() + + + def do_dispatch(self, body): + self.url = self.path + pieces = urlparse.urlparse(self.path) + self.path = pieces[2] + self.query = cgi.parse_qs(pieces[4]) + + url = { + "/": self.serve_main, + "/shutdown.do": self.serve_shutdown, + "/stop-transcoder.do": self.serve_stop_transcoder, + "/status.do": self.serve_status, + "/version.do": self.serve_version, + "/new_id.do": self.serve_new_id, + "/get_log.do": self.serve_get_log, + "/get_all_log.do": self.serve_get_all_log, + "/stream.do": self.serve_stream, + "/transcode.do": self.serve_transcode, + "/list.do": self.serve_list, + "/get_file_info.do": self.serve_file_info, + } + + try: + url[self.path](body) + except KeyError: + try: + action = self.query.get("action", None) + if action and "stream.do" in action: + self.serve_stream(body) + elif os.path.exists("html/%s" % self.path): + data = open("html/%s" % self.path) + self.wfile.write(data.read()) + else: + self.send_error(404, "File not found") + except Exception, e: + self.log.error(e) + + # do_dispatch() + + + def do_GET(self): + self.do_dispatch(True) + # do_GET() + + + def do_HEAD(self): + self.do_dispatch(False) + # do_HEAD() + + + def _nav_items(self): + ret = "" + for name, url in self.menu.items(): + ret += utils.getHTML("menu", {"name": name, "url": url}) + return ret + # _nav_items() + + + def serve_main(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()})) + # serve_main() + + + def serve_version(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.wfile.write("Version: %s" % __version__) + # serve_version + + + def serve_shutdown(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.wfile.write(utils.getHTML("shutdown")) + self.server.server_close() + # serve_shutdown() + + + def serve_list(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + file_list = [] + files.list_media_files(utils.config.get_transcoded_location(), file_list) + output = files.FileList(map(lambda x, y: x+y, file_list, + ["
    "]*len(file_list))) + self.wfile.write(output) + + # serve_list() + + + def serve_stop_all_transcoders(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.server.stop_transcoders() + self.wfile.write(utils.getHTML("stop_all", + {"menu": self._nav_items()})) + # serve_stop_all_transcoders() + + + def serve_stop_selected_transcoders(self, body, tids=[]): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + opts = "" + if body: + transcoders = self.server.get_transcoders() + + for tid in tids: + for t, r in transcoders: + if t.tid == int(tid): + try: + t.stop() + except Exception, e: + self.log.info("Plugin already stopped") + + opts += utils._create_html_item("%s" % t) + + break + + self.wfile.write(utils.getHTML("stop_selected", + {"menu": self._nav_items(), + "opts": opts})) + # serve_stop_selected_transcoders() + + + def serve_stop_transcoder(self, body): + req = self.query.get("request", None) + tid = self.query.get("tid", None) + if req and "all" in req: + self.serve_stop_all_transcoders(body) + elif tid: + self.serve_stop_selected_transcoders(body, tid[0].split(";")) + else: + self.serve_status(body) + # serve_stop_transcoder() + + + def serve_status(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + stopone = "" + running = "" + stopall = "" + + if body: + tl = self.server.get_transcoders() + if not tl and not self.query.get("tid", None) and \ + not self.query.get("running", None): + running = "

    No running transcoder.

    \n" + + elif not tl and self.query.get("tid", None): + tids = self.query.get("tid") + for tid in tids: + stat = self.transcoders_log.get_status(int(tid)) + self.wfile.write("%s
    " % stat) + return True + + elif self.query.get("running", None): + for transcoder, request in tl: + outf = transcoder.params_first("outfile") + tid = transcoder.tid + self.wfile.write("%s:%s
    " % (tid, outf)) + return True + + elif self.query.get("tid", None): + req_tid = self.query.get("tid") + for transcoder, request in tl: + if str(transcoder.tid) in req_tid: + self.wfile.write("Status:%s:%s %%" % (\ + transcoder.tid, transcoder.status)) + return True + stat = self.transcoders_log.get_status(int(req_tid[0])) + self.wfile.write("%s
    " % stat) + return True + + else: + running = "

    Running transcoders:

    \n" + stopall = utils._create_html_item("" + "[STOP ALL]" % + self.menu["Stop"]) + + for transcoder, request in tl: + stopone += utils._create_html_item("%s;" + "" + " [STOP] ") % ( + transcoder, self.menu["Stop"], transcoder.tid) + + self.wfile.write(utils.getHTML("status", + {"menu": self._nav_items(), + "running": running, + "stopall": stopall, + "stopone": stopone})) + # serve_status() + + + def _get_transcoder(self): + # get transcoder option: mencoder is the default + request_transcoders = self.query.get("transcoder", ["mencoder"]) + + for t in request_transcoders: + transcoder = self.transcoders.get(t) + if transcoder: + return transcoder + + if not transcoder: + return self.transcoders[self.def_transcoder] + # _get_transcoder() + + + def _get_new_id(self, tid): + self.server.last_tid = utils.create_tid(tid) + self.tid_queue.append(self.server.last_tid) + return self.server.last_tid + # _get_new_id() + + + def serve_new_id(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + self.wfile.write("%s" % self._get_new_id(self.server.last_tid)) + # serve_new_id() + + def serve_get_log(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + if self.query.get("tid", None): + tid = int(self.query.get("tid")[0]) + stat = self.transcoders_log.get_status(tid) + self.wfile.write("Status: %s" % stat) + else: + stat = self.transcoders_log.get_status() + for rtid, status in stat.iteritems(): + self.wfile.write("%s: %s

    " % (rtid, status)) + # serve_get_log() + + def serve_get_all_log(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + if self.query.get("tid", None): + tid = int(self.query.get("tid")[0]) + stat = self.transcoders_log.get_status(tid, True) + for status in stat: + self.wfile.write("%s

    " % status) + else: + stat = self.transcoders_log.get_status(None, True) + for rtid, history in stat.iteritems(): + for status in history: + self.wfile.write("%s: %s
    " % (rtid, status)) + self.wfile.write("

    ") + # serve_get_all_log() + + + def serve_file_info(self, body): + if body: + + file_dat = self.query.get("file", None) + + if file_dat: + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + try: + opts = files.TranscodedFile(file_dat[0], self.query).opts + for key in opts.keys(): + self.wfile.write("%s=%s
    " % (key, opts.get(key, "None")[0])) + + except Exception, e: + self.send_error(500, str(e)) + return + # serve_file_info() + + def serve_stream(self, body): + args = self.query.get("file", None) + if not args: + self.send_error(404, "File not found") + return + + filename = args[0]; + if not filename: + self.send_error(404, "File not found") + return + + #Only stream files on .transcode dir + filename = os.path.join (utils.config.get_transcoded_location(), + os.path.basename(filename)) + self.log.error("Stream file: %s" % filename) + if not os.path.exists (filename): + self.send_error(404, "File not found") + return + + size = int(os.path.getsize(filename)) + self.send_response(200) + self.send_header("Content-Type", mimetypes.guess_type(filename)[0]) + self.send_header("Cache-Control","no-cache") + self.send_header("Content-Length", size) + self.end_headers() + + media = open(filename) + data_in = " " + total_read = 0 + + test_tid = int(self.query.get("tid", "0")[0]) + if test_tid == 0 or test_tid not in self.tid_queue: + test_tid = self._get_new_id(self.server.last_tid) + + self.transcoders_log.insert(test_tid, "gms.Stream: %s" % filename) + + try: + file_data = "" + while data_in != "": + data_in = media.read(4096) + file_data += data_in + + #total_read += 4096 + self.wfile.write(file_data) + #status = utils.progress_bar(total_read, size, 50) + #msg_status = "Status:%s:%s%%" % (test_tid, status) + #self.transcoders_log._update_status(test_tid, msg_status) + + self.transcoders_log._update_status(test_tid, "OK: Done") + + except Exception, e: + self.log.error("Stream error: %s" %e) + self.transcoders_log._update_status(test_tid, "Error: %s" % e) + # serve_stream() + + def serve_transcode(self, body): + type = self.query.get("type", None)[0] + if type.upper() == "FILE": + self.send_error(404, "Transcode local files not allowed") + return + + transcoder = self._get_transcoder() + try: + obj = transcoder(self.query) + except Exception, e: + self.send_error(500, str(e)) + return + + self.send_response(200) + self.send_header("Content-Type", obj.get_mimetype()) + self.send_header("Cache-Control","no-cache") + + if (obj.name == "gmencoder"): + self.send_header("Transfer-Encoding", "chunked") + + self.end_headers() + + if body: + test_tid = int(self.query.get("tid", "0")[0]) + if test_tid == 0 or test_tid not in self.tid_queue: + test_tid = self._get_new_id(self.server.last_tid) + + if self.query.get("transcoder", None): + self.transcoders_log.insert(test_tid, "gms.%s" % obj.name) + obj.tid = test_tid + obj.log = self.transcoders_log + + self.server.add_transcoders(self, obj) + if obj.start(self.wfile): + self.transcoders_log.info (test_tid, "OK") + else: + self.transcoders_log.info (test_tid, "Fail") + + self.server.del_transcoders(self, obj) + files.TranscodedFile("", self.query) + + # serve_stream() + + + def log_request(self, code='-', size='-'): + self.log.info('"%s" %s %s', self.requestline, str(code), str(size)) + # log_request() + + + def log_error(self, format, *args): + self.log.error("%s: %s" % (self.address_string(), format % args)) + # log_error() + + + def log_message(self, format, *args): + self.log.info("%s: %s" % (self.address_string(), format % args)) + # log_message() + +# RequestHandler diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/lib/server.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/server.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,117 @@ +#!/usr/bin/env python + +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.4" + +import os +import threading +import SocketServer +import BaseHTTPServer +import socket +import urlparse +import cgi +import lib.utils as utils +import logging + +from log import Log +from request_handler import RequestHandler + +__all__ = ("Server", "serve_forever", "load_plugins_transcoders") + +class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): + log = logging.getLogger("gms.server") + last_tid = 0 + run = True + _transcoders = {} + _lock = threading.RLock() + + def serve_forever(self): + self.log.info("GMyth-Streamer serving HTTP on %s:%s" % + self.socket.getsockname()) + try: + while self.run: + self.handle_request() + except KeyboardInterrupt, e: + pass + + self.log.debug("Stopping all remaining transcoders...") + self.stop_transcoders() + self.log.debug("Transcoders stopped!") + # serve_forever() + + + def get_request(self): + skt = self.socket + old = skt.gettimeout() + skt.settimeout(0.5) + while self.run: + try: + r = skt.accept() + skt.settimeout(old) + return r + except socket.timeout, e: + pass + raise socket.error("Not running") + # get_request() + + + def server_close(self): + self.run = False + self.stop_transcoders() + + BaseHTTPServer.HTTPServer.server_close(self) + # server_close() + + + def stop_transcoders(self): + self._lock.acquire() + for transcoder, request in self._transcoders.iteritems(): + self.log.info("Stop transcoder: %s, client=%s" % + (transcoder, request.client_address)) + transcoder.stop() + self._lock.release() + # stop_transcoders() + + + def get_transcoders(self): + self._lock.acquire() + try: + return self._transcoders.items() + finally: + self._lock.release() + # get_transcoders() + + + def add_transcoders(self, request, transcoder): + self._lock.acquire() + try: + self._transcoders[transcoder] = request + finally: + self._lock.release() + # add_transcoders() + + + def del_transcoders(self, request, transcoder): + self._lock.acquire() + try: + del self._transcoders[transcoder] + finally: + self._lock.release() + # del_transcoders() +# Server + + + +def serve_forever(host="0.0.0.0", port=40000): + addr = (host, port) + RequestHandler.protocol_version = "HTTP/1.0" + httpd = Server(addr, RequestHandler) + httpd.serve_forever() +# serve_forever() + + +def load_plugins_transcoders(directory): + RequestHandler.load_plugins_transcoders(directory) +# load_plugins_transcoders() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/lib/transcoder.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/transcoder.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.4" + +__all__ = ("Transcoder") + +class Transcoder(object): + """Transcoder's Class: parent class to implement + a plugin for transcoding data.""" + priority = 0 # negative values have higher priorities + name = None # to be used in requests + status = None + log = None + tid = -1 + + def __init__(self, params): + self.params = params + # __init__() + + def params_first(self, key, default=None): + if default is None: + return self.params[key][0] + else: + try: + return self.params[key][0] + except: + return default + # params_first() + + def get_mimetype(self): + return "application/octet-stream" + # get_mimetype() + + def start(self, outfile): + pass + # start() + + def stop(self): + pass + # stop() + + def get_legth (self): + pass + # get_leght () + + def get_progress (self): + pass + # get_progress () + + def __str__(self): + return '%s: %s( params=%s ) - Status: %s%%' % \ + (self.__class__.__name__, self.tid, + self.params, self.status) + # __str__() +# Transcoder diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/lib/utils.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/utils.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,193 @@ +#!/usr/bin/env + +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.3" + +import os +import stat +import sys +import logging +import urllib +import gobject +import imp + +import gmsconfig + +log = logging.getLogger("gms.utils") +config = gmsconfig.GmsConfig() + +__all__ = ("which", "load_plugins", "PluginSet", "getHTML", + "progress_bar", "create_tid", "list_media_files") + +def which(app): + """Function to implement which(1) unix command""" + pl = os.environ["PATH"].split(os.pathsep) + for p in pl: + path = os.path.join(p, app) + if os.path.isfile(path): + st = os.stat(path) + if st[stat.ST_MODE] & 0111: + return path + return "" +# which() + + +def _load_module(pathlist, name): + fp, path, desc = imp.find_module(name, pathlist) + try: + module = imp.load_module(name, fp, path, desc) + return module + finally: + if fp: + fp.close() +# _load_module() + + +class PluginSet(object): + def __init__(self, basetype, *items): + self.basetype = basetype + self.map = {} + self.list = [] + + for i in items: + self._add(i) + self._sort() + # __init__() + + + def _add(self, item): + self.map[item.name] = item + self.list.append(item) + # _add() + + + def add(self, item): + self._add() + self._sort() + # add() + + + def __getitem__(self, spec): + if isinstance(spec, basestring): + return self.map[spec] + else: + return self.list[spec] + # __getitem__() + + + def get(self, name, default=None): + return self.map.get(name, default) + # get() + + + def __iter__(self): + return self.list.__iter__() + # __iter__() + + + def __len__(self): + return len(self.list) + # __len__() + + + def _sort(self): + self.list.sort(lambda a, b: cmp(a.priority, b.priority)) + # _sort() + + + def update(self, pluginset): + self.map.update(pluginset.map) + self.list.extend(pluginset.list) + self._sort() + # update() + + + def load_from_directory(self, directory): + for i in load_plugins(directory, self.basetype): + self._add(i) + self._sort() + # load_from_directory() + + + def __str__(self): + lst = [] + for o in self.list: + lst.append('"%s" (%s)' % (o.name, o.__name__)) + + return "%s(basetype=%s, items=[%s])" % \ + (self.__class__.__name__, + self.basetype.__name__, + ", ".join(lst)) + # __str__() +# PluginSet + + +def load_plugins(directory, basetype): + """Function to load plugins from a given directory""" + tn = basetype.__name__ + log.debug("Loading plugins from %s, type=%s" % (directory, tn)) + + + plugins = [] + for d in os.listdir(directory): + if not d.endswith(".py"): + continue + + name = d[0: -3] + if name == "__init__": + continue + + directory.replace(os.path.sep, ".") + mod = _load_module([directory], name) + for sym in dir(mod): + cls = getattr(mod, sym) + if isinstance(cls, type) and issubclass(cls, basetype) and \ + cls != basetype: + plugins.append(cls) + log.info("Loaded %s (%s) from %s" % \ + (cls.__name__, tn, os.path.join(directory, d))) + + return plugins +# load_plugins() + +def getHTML(html_file, params={}): + """This function parses an html file with the given + parameters and returns a formated web-page""" + try: + filename = os.path.join(sys.path[0], "html", html_file + ".html") + html = open(filename).read() % params + return html + except Exception, e: + return "HTML format error. Wrong keys: %s" % e + +# getHTML + +def _create_html_item(opt): + """Create an
  • item using HTML.""" + return "
  • %s
  • \n" % opt +# _create_html_item + +def progress_bar(value, max, barsize): + """Creates and displays a progressbar. By OSantana""" + chars = int(value * barsize / float(max)) + percent = int((value / float(max)) * 100) + sys.stdout.write("#" * chars) + sys.stdout.write(" " * (barsize - chars + 2)) + if value >= max: + sys.stdout.write("done.\n\n") + else: + sys.stdout.write("[%3i%%]\r" % (percent)) + sys.stdout.flush() + return percent +# progress_bar() by osantana + +def create_tid(last_tid): + """Function to generate TIDs (ids for transcoders). + At first it just do +1 on last_tid but can be implemented + to generate more sparse TIDs""" + tid = last_tid + 1 + return tid +# create_id() + diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/plugins/transcoders/gmencoder.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/plugins/transcoders/gmencoder.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +__author__ = "Renato Filho" +__author_email__ = "renato.filho@indt.org.br" +__license__ = "GPL" +__version__ = "0.2" + +import os +import sys +import shlex +import signal +import subprocess +import time + +import select +import fcntl + +import lib.utils as utils +import lib.server as server +import lib.transcoder as transcoder + +__all__ = ("TranscoderGMencoder",) + +class TranscoderGMencoder(transcoder.Transcoder): + gmencoder_path = utils.which("gmencoder") + name = "gmencoder" + priority = -1 + proc = None + + def __init__(self, params): + self.status = 0 + transcoder.Transcoder.__init__(self, params) + self.opts = [] + self.opts.append (self.gmencoder_path) + self.opts.append ("-d") + self._parser_params () + + # __init__() + + def _insert_param (self, name, value): + if (value != ""): + self.opts.append(name) + self.opts.append(value) + + def _parser_params (self): + self._insert_param("-i", \ + "%s://%s" % (self.params_first("type", "file"), + self.params_first("uri", ""))) + self._insert_param("--video-encode", self.params_first("ve", "ffenc_mpeg1video")) + self._insert_param("--video-opts", "bitrate=300000,pass=512,quantizer=0.01,quant-type=1") + #self._insert_param("--video-fps", self.params_first("fps", "")) + self._insert_param("--video-fps", self.params_first("fps", "10")) + self._insert_param("--video-width", self.params_first("width", "320")) + self._insert_param("--video-height", self.params_first("height", "240")) + self._insert_param("--audio-rate", "32000") + self._insert_param("--audio-encode", self.params_first("ae", "")) + # _parse_params + + def start(self, outfd): + outfile = self.params_first("outfile", "") + + if outfile != "": + path = os.path.join(utils.config.get_transcoded_location(), outfile) + self._insert_param("-o", "file://%s" % path) + else: + self._insert_param ("-o", "fd://%d" % outfd.fileno()) + self.opts.append ("-c") + + cmd = " ".join(self.opts) + self.log.info(self.tid, "GMencoder: %s" % cmd) + + try: + self.proc = subprocess.Popen(self.opts, stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + + if outfile: + outfd.write("OK ") + + except Exception, e: + self.log.error(self.tid, "Error: executing GMencoder: %s" % e) + outfd.write("Error: GMencoder: %s" % e) + return False + + try: + if not outfile: + p = select.poll() + p.register (outfd, select.POLLNVAL | select.POLLERR | select.POLLHUP | select.POLLIN ) + + while (self.proc and self.proc.poll() == None): + r, w, x = select.select([self.proc.stdout], [], [], 1) + if self.proc.stdout in r: + progress = self.proc.stdout.readline() + if (progress.find ("PROGRESS") >= 0): + self.status = progress.split (":")[1] + elif (progress.find ("Erro") >= 0): + return False + + if not outfile: + ret = p.poll(0) + if ret: + self.log.info(self.tid, "Lost connection") + self.stop () + return False + + except Exception, e: + self.log.error(self.tid, "Problems handling data: %s" % e) + return False + + self.status = 100; + + + return True + # start() + + + def stop(self): + if self.proc: + self.log.info(self.tid, "Stopped GMencoder plugin") + try: + os.kill(self.proc.pid, signal.SIGKILL) + self.proc.wait() + except Exception, e: + pass + + self.proc = None + # stop() + + def get_progress(self): + return self.status + + def get_lenght(self): + return -1 + +# TranscoderGMencoder diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/plugins/transcoders/mencoder.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/plugins/transcoders/mencoder.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,334 @@ +#!/usr/bin/env python + +__author__ = "Artur Duque de Souza" +__author_email__ = "artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.3" + +import os +import time +import fcntl +import shlex +import socket +import struct +import signal +import subprocess + +import lib.utils as utils +import lib.server as server +import plugins.transcoders.mencoder_lib.mythtv as mythtv + +from select import select +import lib.transcoder as transcoder + +__all__ = ("TranscoderMencoder",) + +class TranscoderMencoder(transcoder.Transcoder): + """Transcoder class that implements a transcoder using Mencoder""" + mencoder_path = utils.which("mencoder") + name = "mencoder" + priority = -1 + args = {} + proc = None + gmyth = None + + # only works with avi container + status = 0 + + def _setup_params(self): + params_first = self.params_first + + # general_opts + self.args["local"] = params_first("local", False) + self.args["language"] = params_first("language", False) + self.args["subtitle"] = params_first("subtitle", False) + self.args["format"] = params_first("format", "mpeg1") + self.args["outfile"] = params_first("outfile", "-") + + # input_opt + self.args["type"] = params_first("type", "file") + self.args["input"] = params_first("uri", "-") + + # audio_opts + self.args["acodec"] = params_first("acodec", "mp2") + self.args["abitrate"] = params_first("abitrate", 192) + self.args["volume"] = params_first("volume", 5) + + # video_opts + self.args["mux"] = params_first("mux", "mpeg") + self.args["fps"] = params_first("fps", 25) + self.args["vcodec"] = params_first("vcodec", "mpeg1video") + self.args["vbitrate"] = params_first("vbitrate", 400) + self.args["width"] = params_first("width", 320) + self.args["height"] = params_first("height", 240) + # _setup_params() + + + def _setup_audio(self): + if self.args["acodec"] == "mp3lame": + audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % ( + self.args["abitrate"], self.args["volume"]) + else: + audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % ( + self.args["acodec"], self.args["abitrate"]) + + return audio + # _setup_audio() + + + def _setup_video(self): + video = " -of %s" % self.args["mux"] + video += " -ofps %s" % self.args["fps"] + + vcodec = self.args["vcodec"] + if vcodec == "nuv" or vcodec == "xvid"\ + or vcodec == "qtvideo" or vcodec == "copy": + video += " -ovc %s" % vcodec + else: + video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % ( + vcodec, self.args["vbitrate"]) + + if self.args["mux"] == "mpeg": + video += " -mpegopts format=%s" % self.args["format"] + + video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"]) + return video + # _setup_video() + + + def _arg_append(self, args, options): + for arg in shlex.split(options): + args.append(arg) + # arg_append() + + def _setup_mencoder_opts(self, args): + args.append(self.mencoder_path) + + if self.args["type"] and self.args["type"] == "tv": + self._arg_append(args, self.args["tv"]) + elif self.args["outfile"] == "-" and self.args["type"]: + args.append(self.args["input"]) + else: + args.append("-") + + if self.args["language"]: + self._arg_append(args, "-alang %s" % self.args["language"]) + + if self.args["subtitle"]: + self._arg_append(args, "-slang %s" % self.args["subtitle"]) + self._arg_append(args, "-subfps %s" % self.args["fps"]) + + self._arg_append(args, "-idx") + self._arg_append(args, "-cache 1024") + self._arg_append(args, self._setup_audio()) + self._arg_append(args, self._setup_video()) + + self._arg_append(args, "-really-quiet") + + if self.args["outfile"] != "-": + self.args["outfile"] = ".transcoded/%s" % ( + os.path.basename(self.args["outfile"])) + + self._arg_append(args, "-o %s" % self.args["outfile"]) + self._arg_append(args, "2>%s" % os.devnull) + # _setup_args() + + def _setup_filename(self): + """This function setups the file to encode parsing the uri. + So, type can be: + * file + * dvd + * myth + + If the last one is detected we have to parse the uri to find args. + Then we store all the args inside a dictionary: self.args['gmyth-cat'] + """ + _type = self.args["type"] + + if _type == "file": + if not os.path.exists(self.args["input"]): + raise IOError,\ + "File requested does not exist: %s." % self.args["input"] + else: + self.args["input"] = "file://%s" % self.args["input"] + + elif _type == "dvd": + self.args["input"] = "dvd://%s" % self.args["input"] + + elif _type == "myth": + self.args["gmyth-cat"] = mythtv._setup_mythfilename(self) + + elif _type == "tv": + driver = self.params_first("driver", "v4l2") + norm = self.params_first("norm", "pal-m") + channel = self.params_first("channel", "13") + chanlist = self.params_first("chanlist", "us-bcast") + outfmt = self.params_first("outfmt", "yuy2") + vdev = self.params_first("vdev", "/dev/video0") + adev = self.params_first("adev", "/dev/dsp") + self.args["tv"] = "tv:// -v -tv driver=%s:norm=%s:channel=%s:" \ + "chanlist=%s:width=%s:height=%s:outfmt=%s:" \ + "device=%s:adevice=%s" % (driver, norm, + channel, chanlist, + self.args["width"], + self.args["height"], + outfmt, vdev, adev) + # _setup_filename() + + + def __init__(self, params): + transcoder.Transcoder.__init__(self, params) + self.mencoder_opts = [] + + try: + self._setup_params() + self._setup_filename() + self._setup_mencoder_opts(self.mencoder_opts) + except Exception, e: + if self.log: + self.log.error(self.tid, "Error: %s" % e) + else: + raise + # __init__() + + + def _check_opened_file(self, stdw, _stdin): + loop = True + while loop: + try: + return open(self.args["outfile"]) + except: + os.write(stdw, _stdin.read(1024)) + # _check_opened_file + + + def _start_outfile(self, outfd): + finished = False + + # Configuring stdin + try: + filename = self.args["input"].split("://")[1] + _stdin = open(filename) + size = int(os.path.getsize(filename)) + except Exception, e: + self.log.error(self.tid, "Error: Mencoder stdin"\ + " setup error: %s" % e) + outfd.write("Error: Mencoder stdin setup error: %s" %e) + return False + + self.status = 0 + total_read = 0 + + # Configuring pipes + stdr, stdw = os.pipe() + + if not self._run_mencoder(input=stdr): + return False + + stdout = self._check_opened_file(stdw, _stdin) + outfd.write("OK ") + + try: + while self.proc and self.proc.poll() == None: + if not finished: + data_in = _stdin.read(4096) + if data_in != "": + os.write(stdw, data_in) + total_read += 4096 + d = stdout.read(4096) + self.status = utils.progress_bar(total_read, + size, 50) + else: + finished = True + os.close(stdw) + + else: + d = stdout.read(4096) + + except Exception, e: + self.log.error(self.tid, "Error: %s" % e) + self.stop() + return False + + self.log.info(self.tid, "OK: Done") + return True + # _start_outfile() + + + def _start(self, outfd): + # Play a file on disk or DVD + if not self._run_mencoder(output=subprocess.PIPE): + return False + + try: + while self.proc and self.proc.poll() == None: + d = self.proc.stdout.read(1024) + outfd.write(d) + except Exception, e: + self.log.error(self.tid, "Error: %s" % e) + return False + + self.log.info(self.tid, "OK: Done") + return True + # _start() + + def _run_mencoder(self, input=None, output=None): + try: + self.proc = subprocess.Popen(self.mencoder_opts, stdin=input, + stdout=output, close_fds=True) + except Exception, e: + self.log.error(self.tid, "Error: Mencoder: %s" % e) + return False + + return True + # _run_mencoder() + + def start(self, outfd): + cmd = " ".join(self.mencoder_opts) + self.log.debug(self.tid, "Plugin's tid: %s" % self.tid) + self.log.debug(self.tid, "Mencoder: %s" % cmd) + + ret = False + + if self.args["outfile"] == "-" and \ + self.args["type"] in ["file", "dvd", "tv"]: + ret = self._start(outfd) + + elif self.args["type"] == "myth": + ret = mythtv.start_myth(self, outfd) + + else: + ret = self._start_outfile(outfd) + + self.stop() + + if not ret: + self.log.error(self.tid, "Error: Problems while "\ + "starting streaming.") + + return ret + # start() + + def _aux_stop(self, obj, next=False): + if obj: + try: + os.kill(obj.pid, signal.SIGKILL) + if next: + os.kill(obj.pid+1, signal.SIGKILL) + except OSError, e: + pass + + try: + obj.wait() + except Exception, e: + pass + + obj = None + # _aux_stop + + def stop(self): + self._aux_stop(self.proc, True) + self._aux_stop(self.gmyth) + # stop() + +# TranscoderMencoder diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/plugins/transcoders/mencoder_lib/mythtv.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/plugins/transcoders/mencoder_lib/mythtv.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,109 @@ +import os +import subprocess +import fcntl + +import lib.utils as utils +import lib.server as server + +from select import select + +def _setup_mythfilename(self): + # mythtv:mythtv@192.168.3.110:6543/1002_20070426230000.nuv + try: + _mysql = self.args["input"].split("@")[0].split(":") + except IndexError, e: + _mysql = ["mythtv", "mythtv"] + + try: + _args = self.args["input"].split("@")[1].split(":") + except IndexError, e: + _args = self.args["input"].split(":") + + gmyth_dict = {} + gmyth_dict["mysql"] = _mysql + gmyth_dict["backend"] = _args[0] + gmyth_dict["port"] = _args[1].split("/", 1)[0] + + _tmp_file = _args[1].split("/", 1)[1] + + if _tmp_file.find("channel") >= 0: + gmyth_dict["kind"] = "c" + gmyth_dict["cfile"] = _tmp_file.split("=")[1] + else: + gmyth_dict["kind"] = "f" + gmyth_dict["cfile"] = _tmp_file + + self.args["input"] = "-" + return gmyth_dict +# _setup_mythfilename + +def _setup_mythfile(err): + size = err.readline().split("Size:")[1] + flags = fcntl.fcntl (err, fcntl.F_GETFL, 0) | os.O_NONBLOCK + fcntl.fcntl(err, fcntl.F_SETFL, flags) + return size +# _setup_mythfile + +def _setup_gmythcat(self): + gmyth_cat = utils.which("gmyth-cat") + if self.args.has_key("gmyth-cat"): + return [ utils.which("gmyth-cat"), + "-h", self.args["gmyth-cat"]["backend"], + "-p", self.args["gmyth-cat"]["port"], + "-" + self.args["gmyth-cat"]["kind"], + self.args["gmyth-cat"]["cfile"] + ] + else: + self.log.error(self.tid, "Error: URI error") + return [] +# _setup_gmythcat + +def start_myth(self, outfd): + opts = _setup_gmythcat(self) + try: + self.gmyth = subprocess.Popen(opts, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True) + except Exception, e: + self.log.error(self.tid, "Error: gmyth-cat: %s" % e) + return False + + if not self._run_mencoder(input=self.gmyth.stdout, + output=subprocess.PIPE): + return False + + if self.args["gmyth-cat"]["kind"] == "f": + try: + size = _setup_mythfile(self.gmyth.stderr) + self.log.debug(self.tid, "Info: Size of file: %s" % size) + except Exception, e: + self.log.error(self.tid, "Error: Problems getting size of"\ + " file: %s" % e) + outfd.write("Error: Problems getting size of file: %s" % e) + return False + + outfd.write("OK ") + + try: + while self.proc and self.proc.poll() == None: + r, w, x = select([self.gmyth.stderr, self.proc.stdout], + [], [], 0) + if self.proc.stdout in r: + d = self.proc.stdout.read(4096) + outfd.write(d) + + if self.gmyth.stderr in r: + partial = self.gmyth.stderr.readline() + if partial != "": + self.status = utils.progress_bar(int(partial), + int(size), 50) + + except IndexError, e: + pass + except Exception, e: + self.log.error(self.tid, "Error: %s" % e) + return False + + self.log.info(self.tid, "OK: Done") + return True +# _start_myth() diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/server.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/server.conf Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,2 @@ +[PATHS] +transcoded=./.transcoded diff -r e2baa6947dbf -r daa61fffb811 gmyth-stream/server/setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/setup.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,17 @@ +from distutils.core import setup +from glob import glob + +setup(name='gms', + version='0.6', + description='carman rich view package', + long_description='carman rich view (SDL based) package', + url='http://www.indt.org.br', + scripts=['gms.py'], + package_dir={'lib': 'lib', 'plugins' : 'plugins','data' : 'data' }, + packages=['lib','plugins','plugins.transcoders','plugins.transcoders.mencoder_lib'], + data_files = [ + ('share/gms/html', glob("html/*")), + ('etc/init.d', ['data/gmsd']), + ('etc/gms', ['data/server.conf']) + ], + )