1.1 --- a/gmyth-stream/server/0.3/data/gmsd Wed Aug 29 14:29:24 2007 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,61 +0,0 @@
1.4 -#!/bin/sh
1.5 -
1.6 -PROGRAM_NAME=GMS
1.7 -PROGRAM_BIN=/usr/bin/gms.py
1.8 -PIDFILE=/var/run/gms.pid
1.9 -LOGFILE=/var/log/gms.log
1.10 -
1.11 -test -x $PROGRAM_BIN || exit 0
1.12 -
1.13 -set -e
1.14 -
1.15 -. /lib/lsb/init-functions
1.16 -. /etc/default/rcS
1.17 -
1.18 -case $1 in
1.19 - start)
1.20 - echo -n "Starting $PROGRAM_NAME: "
1.21 - if [ -f $PIDFILE ]
1.22 - then
1.23 - PID=`cat $PIDFILE`
1.24 -
1.25 - if ps ax | grep -q "^$PID"
1.26 - then
1.27 - echo "$PROGRAM_NAME already running."
1.28 - else
1.29 - rm -f $PIDFILE
1.30 - $PROGRAM_BIN -d > $LOGFILE
1.31 - echo "OK"
1.32 - fi
1.33 - else
1.34 - $PROGRAM_BIN -d > $LOGFILE
1.35 - echo "OK"
1.36 - fi
1.37 - ;;
1.38 -
1.39 - stop)
1.40 - echo -n "Stopping $PROGRAM_NAME: "
1.41 - if [ -f $PIDFILE ]
1.42 - then
1.43 - PID=`cat $PIDFILE`
1.44 - if ps ax | grep -q "^$PID"
1.45 - then
1.46 - kill -10 $PID
1.47 - fi
1.48 - rm $PIDFILE
1.49 - else
1.50 - echo "No $PROGRAM_NAME found running; no killed."
1.51 - fi
1.52 - ;;
1.53 -
1.54 - restart)
1.55 - $0 stop
1.56 - sleep 1
1.57 - $0 start
1.58 - ;;
1.59 -
1.60 - *)
1.61 - log_success_msg "Usage: $0 {stop|start|restart}"
1.62 - exit 1
1.63 - ;;
1.64 -esac
2.1 --- a/gmyth-stream/server/0.3/data/server.conf Wed Aug 29 14:29:24 2007 +0100
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,2 +0,0 @@
2.4 -[PATHS]
2.5 -transcoded=/var/gms-media
3.1 --- a/gmyth-stream/server/0.3/debian/changelog Wed Aug 29 14:29:24 2007 +0100
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,6 +0,0 @@
3.4 -gms (0.3-indt1) unstable; urgency=low
3.5 -
3.6 - * First package
3.7 -
3.8 - -- Renato Araujo Oliveira Filho <renato.filho@indt.org> Thu, 16 Aug 2007 14:55:00 -0300
3.9 -
4.1 --- a/gmyth-stream/server/0.3/debian/compat Wed Aug 29 14:29:24 2007 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,1 +0,0 @@
4.4 -5
5.1 --- a/gmyth-stream/server/0.3/debian/control Wed Aug 29 14:29:24 2007 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,13 +0,0 @@
5.4 -Source: gms
5.5 -Section: sound
5.6 -Priority: optional
5.7 -Maintainer: Renato Araujo Oliveira Filho <renato.filho@indt.org>
5.8 -Build-Depends: debhelper (>= 5.0.38), python-support (>= 0.5), python-central (>= 0.5)
5.9 -Standards-Version: 3.7.2
5.10 -
5.11 -Package: gms
5.12 -Architecture: any
5.13 -Depends: ${python:Depends}, libgstreamer0.10-0, gstreamer0.10-plugins-base, gstreamer0.10-plugins-good
5.14 -Recommends: gstreamer0.10-plugins-ugly
5.15 -Description: Media transcoder deamon
5.16 - Homepage: http://gmyth.sourceforge.net/
6.1 --- a/gmyth-stream/server/0.3/debian/copyright Wed Aug 29 14:29:24 2007 +0100
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,19 +0,0 @@
6.4 -It was downloaded from: http://gmyth.sourceforge.net/wiki/
6.5 -
6.6 -License:
6.7 - This package is free software; you can redistribute it and/or modify
6.8 - it under the terms of the GNU General Public License as published by
6.9 - the Free Software Foundation; either version 2 of the License, or
6.10 - (at your option) any later version.
6.11 -
6.12 - This package is distributed in the hope that it will be useful,
6.13 - but WITHOUT ANY WARRANTY; without even the implied warranty of
6.14 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.15 - GNU General Public License for more details.
6.16 -
6.17 - You should have received a copy of the GNU General Public License
6.18 - along with this package; if not, write to the Free Software
6.19 - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6.20 -
6.21 -On Debian systems, the complete text of the GNU General Public License can
6.22 -be found in `/usr/share/common-licenses/GPL'.
7.1 --- a/gmyth-stream/server/0.3/debian/gms.install Wed Aug 29 14:29:24 2007 +0100
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,8 +0,0 @@
7.4 -debian/tmp/usr/share/gms/lib/*.py usr/share/gms/lib
7.5 -debian/tmp/usr/share/gms/plugins/*.py usr/share/gms/plugins
7.6 -debian/tmp/usr/share/gms/plugins/transcoders/*.py usr/share/gms/plugins/transcoders
7.7 -debian/tmp/usr/share/gms/plugins/transcoders/mencoder_lib/*.py usr/share/gms/plugins/transcoders/mencoder_lib
7.8 -debian/tmp/usr/share/gms/html/* usr/share/gms/html
7.9 -debian/tmp/usr/bin/* usr/bin
7.10 -debian/etc/init.d/gmsd etc/init.d
7.11 -debian/etc/gms/*.conf etc/gms/
8.1 --- a/gmyth-stream/server/0.3/debian/gms.postinst Wed Aug 29 14:29:24 2007 +0100
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,29 +0,0 @@
8.4 -#! /bin/sh
8.5 -# postinst script for gms
8.6 -
8.7 -set -e
8.8 -
8.9 -case "$1" in
8.10 - configure)
8.11 - if ! getent passwd gms >/dev/null; then
8.12 - adduser --disabled-password --quiet --system \
8.13 - --home /var/gms-media \
8.14 - --gecos "GMS media dir" --group gms
8.15 - fi
8.16 - if ! getent passwd gms | grep -q /var/run/gms; then
8.17 - usermod -d /var/gms-media gms
8.18 - fi
8.19 - update-rc.d gmsd defaults
8.20 - invoke-rc.d gmsd start
8.21 - ;;
8.22 - abort-upgrade|abort-remove|abort-deconfigure)
8.23 - ;;
8.24 - *)
8.25 - echo "postinst called with unknown argument \`$1'" >&2
8.26 - exit 1
8.27 - ;;
8.28 -esac
8.29 -
8.30 -#DEBHELPER#
8.31 -
8.32 -exit 0
9.1 --- a/gmyth-stream/server/0.3/debian/gms.postrm Wed Aug 29 14:29:24 2007 +0100
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,13 +0,0 @@
9.4 -#!/bin/sh
9.5 -
9.6 -set -e
9.7 -
9.8 -#DEBHELPER#
9.9 -
9.10 -if [ "$1" = "purge" ] ; then
9.11 - invoke-rc.d --force gms stop
9.12 - deluser --quiet --system gms > /dev/null || true
9.13 - delgroup --quiet --system gms > /dev/null || true
9.14 -fi
9.15 -
9.16 -exit 0
10.1 --- a/gmyth-stream/server/0.3/debian/rules Wed Aug 29 14:29:24 2007 +0100
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,52 +0,0 @@
10.4 -#!/usr/bin/make -f
10.5 -# -*- makefile -*-
10.6 -
10.7 -# Uncomment this to turn on verbose mode.
10.8 -#export DH_VERBOSE=1
10.9 -
10.10 -PYVER=2.5
10.11 -PYTHON=python$(PYVER)
10.12 -
10.13 -PREFIX=debian/tmp
10.14 -
10.15 -build: build-stamp
10.16 -
10.17 -build-stamp:
10.18 - touch build-stamp
10.19 -
10.20 -clean:
10.21 - dh_testdir
10.22 - dh_testroot
10.23 - rm -f build-stamp
10.24 - dh_clean
10.25 -
10.26 -install: build
10.27 - dh_testdir
10.28 - dh_testroot
10.29 - dh_installdirs
10.30 - dh_clean -k
10.31 -
10.32 - @rm -rf build
10.33 - @$(PYTHON) setup.py install --prefix=$(PREFIX)/usr --no-compile --install-purelib=$(PREFIX)/usr/share/gms
10.34 - install -D -o root -g root -m 755 $(PREFIX)/usr/etc/init.d/gmsd debian/$(cdbs_curpkg)/etc/init.d/gmsd
10.35 - install -D -o root -g root -m 755 $(PREFIX)/usr/etc/gms/server.conf debian/$(cdbs_curpkg)/etc/gms/server.conf
10.36 -
10.37 - dh_install
10.38 -
10.39 -# Build architecture-independent files here.
10.40 -binary-indep: build install
10.41 - dh_testdir
10.42 - dh_testroot
10.43 - dh_installchangelogs
10.44 - dh_installdocs
10.45 - dh_strip
10.46 - dh_compress
10.47 - dh_fixperms
10.48 - dh_installdeb
10.49 - dh_gencontrol
10.50 - dh_md5sums
10.51 - dh_builddeb
10.52 -
10.53 -binary: binary-indep
10.54 -.PHONY: clean binary-indep binary install
10.55 -
11.1 --- a/gmyth-stream/server/0.3/gms.py Wed Aug 29 14:29:24 2007 +0100
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,74 +0,0 @@
11.4 -#!/usr/bin/env python
11.5 -
11.6 -__author__ = "Artur Duque de Souza"
11.7 -__author_email__ = "artur.souza@indt.org.br"
11.8 -__license__ = "GPL"
11.9 -__version__ = "0.3"
11.10 -__thanks__ = "Gustavo Sverzut Barbieri"
11.11 -__GMS_DATA_DIR__ = "/usr/share/gms/"
11.12 -
11.13 -import sys
11.14 -import os
11.15 -import mimetypes
11.16 -import logging as log
11.17 -
11.18 -if os.path.exists (__GMS_DATA_DIR__):
11.19 - sys.path.append(__GMS_DATA_DIR__)
11.20 -
11.21 -from lib.server import serve_forever, load_plugins_transcoders
11.22 -from lib.utils import config
11.23 -
11.24 -mimetypes.init()
11.25 -log_level = log.INFO
11.26 -for p in sys.argv[1:]:
11.27 - if p == "-v" or p == "--verbose":
11.28 - log_level -= 10
11.29 -
11.30 -log.basicConfig(level=log_level,
11.31 - format=("### %(asctime)s %(name)-18s \t%(levelname)-8s "
11.32 - "\t%(message)s"),
11.33 - datefmt="%Y-%m-%d %H:%M:%S")
11.34 -
11.35 -if config.get_transcoded_location () is None:
11.36 - print "Gms not configured"
11.37 - exit (0)
11.38 -
11.39 -if not os.path.exists(config.get_transcoded_location()):
11.40 - os.mkdir(config.get_transcoded_location())
11.41 -
11.42 -
11.43 -if "-d" in sys.argv:
11.44 - #run with deamon
11.45 - try:
11.46 - pid = os.fork()
11.47 - if pid > 0:
11.48 - sys.exit(0)
11.49 - except OSError, e:
11.50 - print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror)
11.51 - sys.exit(1)
11.52 -
11.53 - os.chdir("/")
11.54 - os.setsid()
11.55 - os.umask(0)
11.56 -
11.57 - try:
11.58 - pid = os.fork()
11.59 - if pid > 0:
11.60 - fp = open ("/var/run/gms.pid", "w")
11.61 - fp.write ("%d" % pid)
11.62 - fp.close ()
11.63 - sys.exit(0)
11.64 - except OSError, e:
11.65 - print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror)
11.66 - sys.exit(1)
11.67 -
11.68 -# main deamon
11.69 -pd = os.path.join(__GMS_DATA_DIR__, "plugins", "transcoders")
11.70 -if os.path.exists (pd):
11.71 - load_plugins_transcoders(pd)
11.72 -
11.73 -pd = os.path.join("plugins", "transcoders");
11.74 -if os.path.exists (pd):
11.75 - load_plugins_transcoders(pd)
11.76 -
11.77 -serve_forever()
12.1 --- a/gmyth-stream/server/0.3/html/index.html Wed Aug 29 14:29:24 2007 +0100
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,9 +0,0 @@
12.4 -<html>
12.5 - <head><title>GMyth-Streamer Server</title></head>
12.6 - <body>
12.7 -<h1>Welcome to GMyth-Streamer Server</h1>
12.8 -<ul>
12.9 -%(menu)s
12.10 -</ul>
12.11 - </body>
12.12 -</html>
12.13 \ No newline at end of file
13.1 --- a/gmyth-stream/server/0.3/html/menu.html Wed Aug 29 14:29:24 2007 +0100
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,1 +0,0 @@
13.4 -<li><a href="%(url)s">%(name)s</a></li>
14.1 --- a/gmyth-stream/server/0.3/html/shutdown.html Wed Aug 29 14:29:24 2007 +0100
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,6 +0,0 @@
14.4 -<html>
14.5 - <head><title>GMyth-Streamer Server Exited</title></head>
14.6 - <body>
14.7 - <h1>GMyth-Streamer is not running anymore</h1>
14.8 - </body>
14.9 -</html>
14.10 \ No newline at end of file
15.1 --- a/gmyth-stream/server/0.3/html/status.html Wed Aug 29 14:29:24 2007 +0100
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,14 +0,0 @@
15.4 -<html>
15.5 - <head><title>GMyth-Streamer Server Status</title></head>
15.6 - <body>
15.7 - <h1>GMyth-Streamer Status</h1>
15.8 - <ul>
15.9 - %(running)s
15.10 - %(stopall)s
15.11 - %(stopone)s
15.12 - </ul>
15.13 - <ul>
15.14 - %(menu)s
15.15 - </ul>
15.16 - </body>
15.17 -</html>
16.1 --- a/gmyth-stream/server/0.3/html/stop_all.html Wed Aug 29 14:29:24 2007 +0100
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,9 +0,0 @@
16.4 -<html>
16.5 - <head><title>GMyth-Streamer Server Stopped Transcoders</title></head>
16.6 - <body>
16.7 - <h1>GMyth-Streamer stopped running transcoders</h1>
16.8 - <ul>
16.9 - %(menu)s
16.10 - </ul>
16.11 - </body>
16.12 -</html>
16.13 \ No newline at end of file
17.1 --- a/gmyth-stream/server/0.3/html/stop_selected.html Wed Aug 29 14:29:24 2007 +0100
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,12 +0,0 @@
17.4 -<html>
17.5 - <head><title>GMyth-Streamer Server Stopped Transcoders</title></head>
17.6 - <body>
17.7 - <h1>GMyth-Streamer stopped running transcoders:</h1>
17.8 - <ul>
17.9 - %(opts)s
17.10 - </ul>
17.11 - <ul>
17.12 - %(menu)s
17.13 - </ul>
17.14 - </body>
17.15 -</html>
18.1 --- a/gmyth-stream/server/0.3/lib/file_handler.py Wed Aug 29 14:29:24 2007 +0100
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,86 +0,0 @@
18.4 -#!/usr/bin/env python
18.5 -
18.6 -__author__ = "Artur Duque de Souza"
18.7 -__author_email__ = "artur.souza@indt.org.br"
18.8 -__license__ = "GPL"
18.9 -__version__ = "0.1"
18.10 -
18.11 -import os
18.12 -import sys
18.13 -import pickle
18.14 -import logging
18.15 -import lib.utils as utils
18.16 -
18.17 -from stat import *
18.18 -
18.19 -__all__ = ("FileList", "list_media_files")
18.20 -
18.21 -
18.22 -class TranscodedFile(object):
18.23 - """This class creates and reads information about transcoded files."""
18.24 - opts = {}
18.25 - log = logging.getLogger("gms.file_handler")
18.26 -
18.27 - def __init__(self, filename, args):
18.28 - if filename == "" or not os.path.exists(filename):
18.29 - self.opts = args.copy()
18.30 -
18.31 - if self.opts["type"][0] != "myth":
18.32 - self.opts["original_mtime"] = os.path.getmtime(
18.33 - self.opts["uri"][0])
18.34 -
18.35 - name = os.path.basename(self.opts["uri"][0])
18.36 - self.opts["original"] = [name]
18.37 - output_file = os.path.basename(self.opts["outfile"][0])
18.38 - dat_file = output_file + ".dat";
18.39 - dat_path = os.path.join (utils.config.get_transcoded_location(),
18.40 - dat_file);
18.41 -
18.42 - output = open(dat_path, "wb")
18.43 - # dumps data using the highest protocol
18.44 - pickle.dump(self.opts, output, -1)
18.45 - output.close()
18.46 - else:
18.47 - name = os.path.splitext(os.path.basename(filename))[0]
18.48 - dat_file = name + ".dat";
18.49 - dat_path = os.path.join (utils.config.get_transcoded_location(),
18.50 - dat_file);
18.51 - pkl_file = open(dat_path, "rb")
18.52 - self.opts = pickle.load(pkl_file)
18.53 - # __init__()
18.54 -
18.55 -# TranscodedFile
18.56 -
18.57 -
18.58 -class FileList(list):
18.59 - """Class to hold file's list - reimplements str and repr."""
18.60 - def __str__(self):
18.61 - ret = ""
18.62 - if len(self) > 0:
18.63 - for item in self:
18.64 - ret = ret + "%s" % item
18.65 - return ret
18.66 - # __str__()
18.67 -
18.68 - def __repr__(self):
18.69 - return self.__str__()
18.70 - # __repr__()
18.71 -
18.72 -# FileList
18.73 -
18.74 -def list_media_files(directory, file_list):
18.75 - """Show all the media files with extension defined in the var 'ext'
18.76 - that are in the directory, appending each one to 'file_list'."""
18.77 - ext = ['mpg', 'avi', 'mp4', 'nuv', 'mpeg', 'mov']
18.78 - for root, dirs, files in os.walk(directory):
18.79 - for name in files:
18.80 - if os.path.splitext(name)[1].strip(".") in ext:
18.81 - dat_file = os.path.join(sys.path[0],root,
18.82 - os.path.splitext(name)[0]+".dat")
18.83 -
18.84 - if name not in file_list and \
18.85 - os.path.exists(dat_file):
18.86 - file_list.append(name)
18.87 -
18.88 - return True
18.89 -# list_media_files()
19.1 --- a/gmyth-stream/server/0.3/lib/gmsconfig.py Wed Aug 29 14:29:24 2007 +0100
19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
19.3 @@ -1,38 +0,0 @@
19.4 -#!/usr/bin/env
19.5 -
19.6 -__author__ = "Renato Araujo Oliveira Filho"
19.7 -__author_email__ = "renato.filho@indt.org.br"
19.8 -__license__ = "GPL"
19.9 -__version__ = "0.3"
19.10 -
19.11 -
19.12 -import os
19.13 -import ConfigParser
19.14 -
19.15 -__all__ = ("GmsConfig")
19.16 -
19.17 -class GmsConfig:
19.18 - config = ConfigParser.ConfigParser()
19.19 - __CONFIG_FILE__ = "server.conf"
19.20 - __CONFIG_DIRS__ = [os.path.join (os.path.expanduser("~"), ".gms"), \
19.21 - os.path.join ("/", "etc", "gms"), \
19.22 - "."]
19.23 -
19.24 - def __init__(self):
19.25 - for path in self.__CONFIG_DIRS__:
19.26 - file_name = os.path.join (path, self.__CONFIG_FILE__)
19.27 - if os.path.exists (file_name):
19.28 - fp = open (file_name, "r")
19.29 - self.config.readfp (fp)
19.30 - return
19.31 - # __init__()
19.32 -
19.33 - def get_transcoded_location (self):
19.34 - try:
19.35 - return os.path.realpath (self.config.get("PATHS", "transcoded"))
19.36 - except:
19.37 - return None
19.38 - # get_transcoded_location()
19.39 -
19.40 -
19.41 -# GmsConfig
20.1 --- a/gmyth-stream/server/0.3/lib/log.py Wed Aug 29 14:29:24 2007 +0100
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,109 +0,0 @@
20.4 -#!/usr/bin/env python
20.5 -
20.6 -__author__ = "Artur Duque de Souza"
20.7 -__author_email__ = "artur.souza@indt.org.br"
20.8 -__license__ = "GPL"
20.9 -__version__ = "0.1"
20.10 -
20.11 -import os
20.12 -import logging
20.13 -
20.14 -__all__ = ("Log", "log_structure")
20.15 -
20.16 -class log_structure(object):
20.17 - """Structure to hold log info."""
20.18 -
20.19 - def __init__(self, log=None):
20.20 - self.log = log
20.21 - self.history = []
20.22 - # __init__()
20.23 -
20.24 -# log_structure()
20.25 -
20.26 -class Log(object):
20.27 - """This class implements a log where we can store status of
20.28 - all transcoders (even from those that are not running any more)."""
20.29 -
20.30 - ## key = tid
20.31 - ## item = ls
20.32 - logs = {}
20.33 -
20.34 - def insert(self, tid, name):
20.35 - """Insert a given tid on the log structure"""
20.36 - if not self.logs.has_key(tid):
20.37 - self.logs[tid] = log_structure(logging.getLogger(name))
20.38 - return True
20.39 - else:
20.40 - return False
20.41 - # insert()
20.42 -
20.43 - def remove(self, tid=None):
20.44 - """Cleans up all log stored for a
20.45 - given tid or for all transcodes."""
20.46 - if not tid:
20.47 - self.logs = {}
20.48 - else:
20.49 - del(self.logs[tid])
20.50 -
20.51 - return True
20.52 - # clean()
20.53 -
20.54 - def get_status(self, tid=None, all=False):
20.55 - """Get the status of all transcoders or
20.56 - of just one of them if it's given an tid."""
20.57 - if not tid:
20.58 - ret = {}
20.59 - for tids, logs in self.logs.items():
20.60 - if len(logs.history) > 0:
20.61 - if not all:
20.62 - ret[tids] = logs.history[-1]
20.63 - else:
20.64 - ret[tids] = logs.history
20.65 - return ret
20.66 - elif self.logs.has_key(tid) and len(self.logs[tid].history) > 0:
20.67 - if not all:
20.68 - return self.logs[tid].history[-1]
20.69 - else:
20.70 - return self.logs[tid].history
20.71 -
20.72 - return False
20.73 - # get_status()
20.74 -
20.75 - def _update_status(self, tid=None, msg=""):
20.76 - """Update the status of a given tid. Private method that
20.77 - is only called inside error/info/debug wrappers"""
20.78 - if msg != "":
20.79 - self.logs[tid].history.append(msg)
20.80 - return True
20.81 - else:
20.82 - return False
20.83 - # update_status()
20.84 -
20.85 - def error(self, tid, msg):
20.86 - """Python's Log.error wrapper"""
20.87 - if self.logs.has_key(tid):
20.88 - self.logs[tid].log.error("%s" % msg)
20.89 - return self._update_status(tid, msg)
20.90 - else:
20.91 - return False
20.92 - # error()
20.93 -
20.94 - def info(self, tid, msg):
20.95 - """Python's Log.info wrapper"""
20.96 - if self.logs.has_key(tid):
20.97 - self.logs[tid].log.info("%s" % msg)
20.98 - self._update_status(tid, msg)
20.99 - return True
20.100 - else:
20.101 - return False
20.102 - # info()
20.103 -
20.104 - def debug(self, tid, msg):
20.105 - """Python's Log.debug wrapper"""
20.106 - if self.logs.has_key(tid):
20.107 - self.logs[tid].log.debug("%s" % msg)
20.108 - self._update_status(tid, msg)
20.109 - return True
20.110 - else:
20.111 - return False
20.112 - # debug()
21.1 --- a/gmyth-stream/server/0.3/lib/request_handler.py Wed Aug 29 14:29:24 2007 +0100
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,470 +0,0 @@
21.4 -#!/usr/bin/env python
21.5 -
21.6 -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
21.7 -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
21.8 -__license__ = "GPL"
21.9 -__version__ = "0.3"
21.10 -
21.11 -import os
21.12 -import cgi
21.13 -import socket
21.14 -import logging
21.15 -import urlparse
21.16 -import threading
21.17 -import SocketServer
21.18 -import BaseHTTPServer
21.19 -import mimetypes
21.20 -
21.21 -import lib.utils as utils
21.22 -import lib.file_handler as files
21.23 -import lib.transcoder as transcoder
21.24 -
21.25 -from log import Log
21.26 -
21.27 -__all__ = ("RequestHandler")
21.28 -
21.29 -class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
21.30 - """Class that implements an HTTP request handler for our server."""
21.31 - log = logging.getLogger("gms.request")
21.32 - def_transcoder = None
21.33 - transcoders = utils.PluginSet(transcoder.Transcoder)
21.34 - transcoders_log = Log()
21.35 - tid_queue = []
21.36 -
21.37 - menu = {
21.38 - "Log": "/get_log.do",
21.39 - "Stop": "/stop-transcoder.do",
21.40 - "Status": "/status.do",
21.41 - "All Log": "/get_all_log.do",
21.42 - "Version": "/version.do",
21.43 - "Shutdown": "/shutdown.do"
21.44 - }
21.45 -
21.46 - @classmethod
21.47 - def load_plugins_transcoders(cls, directory):
21.48 - cls.transcoders.load_from_directory(directory)
21.49 -
21.50 - if cls.def_transcoder is None and cls.transcoders:
21.51 - cls.def_transcoder = cls.transcoders[0].name
21.52 - # load_plugins_transcoders()
21.53 -
21.54 -
21.55 - def do_dispatch(self, body):
21.56 - self.url = self.path
21.57 - pieces = urlparse.urlparse(self.path)
21.58 - self.path = pieces[2]
21.59 - self.query = cgi.parse_qs(pieces[4])
21.60 -
21.61 - url = {
21.62 - "/": self.serve_main,
21.63 - "/shutdown.do": self.serve_shutdown,
21.64 - "/stop-transcoder.do": self.serve_stop_transcoder,
21.65 - "/status.do": self.serve_status,
21.66 - "/version.do": self.serve_version,
21.67 - "/new_id.do": self.serve_new_id,
21.68 - "/get_log.do": self.serve_get_log,
21.69 - "/get_all_log.do": self.serve_get_all_log,
21.70 - "/stream.do": self.serve_stream,
21.71 - "/transcode.do": self.serve_transcode,
21.72 - "/list.do": self.serve_list,
21.73 - "/get_file_info.do": self.serve_file_info,
21.74 - }
21.75 -
21.76 - try:
21.77 - url[self.path](body)
21.78 - except KeyError:
21.79 - try:
21.80 - action = self.query.get("action", None)
21.81 - if action and "stream.do" in action:
21.82 - self.serve_stream(body)
21.83 - elif os.path.exists("html/%s" % self.path):
21.84 - data = open("html/%s" % self.path)
21.85 - self.wfile.write(data.read())
21.86 - else:
21.87 - self.send_error(404, "File not found")
21.88 - except Exception, e:
21.89 - self.log.error(e)
21.90 -
21.91 - # do_dispatch()
21.92 -
21.93 -
21.94 - def do_GET(self):
21.95 - self.do_dispatch(True)
21.96 - # do_GET()
21.97 -
21.98 -
21.99 - def do_HEAD(self):
21.100 - self.do_dispatch(False)
21.101 - # do_HEAD()
21.102 -
21.103 -
21.104 - def _nav_items(self):
21.105 - ret = ""
21.106 - for name, url in self.menu.items():
21.107 - ret += utils.getHTML("menu", {"name": name, "url": url})
21.108 - return ret
21.109 - # _nav_items()
21.110 -
21.111 -
21.112 - def serve_main(self, body):
21.113 - self.send_response(200)
21.114 - self.send_header("Content-Type", "text/html")
21.115 - self.send_header('Connection', 'close')
21.116 - self.end_headers()
21.117 - if body:
21.118 - self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()}))
21.119 - # serve_main()
21.120 -
21.121 -
21.122 - def serve_version(self, body):
21.123 - self.send_response(200)
21.124 - self.send_header("Content-Type", "text/html")
21.125 - self.send_header('Connection', 'close')
21.126 - self.end_headers()
21.127 - if body:
21.128 - self.wfile.write("Version: %s" % __version__)
21.129 - # serve_version
21.130 -
21.131 -
21.132 - def serve_shutdown(self, body):
21.133 - self.send_response(200)
21.134 - self.send_header("Content-Type", "text/html")
21.135 - self.send_header('Connection', 'close')
21.136 - self.end_headers()
21.137 - if body:
21.138 - self.wfile.write(utils.getHTML("shutdown"))
21.139 - self.server.server_close()
21.140 - # serve_shutdown()
21.141 -
21.142 -
21.143 - def serve_list(self, body):
21.144 - self.send_response(200)
21.145 - self.send_header("Content-Type", "text/html")
21.146 - self.send_header('Connection', 'close')
21.147 - self.end_headers()
21.148 -
21.149 - if body:
21.150 - file_list = []
21.151 - files.list_media_files(utils.config.get_transcoded_location(), file_list)
21.152 - output = files.FileList(map(lambda x, y: x+y, file_list,
21.153 - ["<br>"]*len(file_list)))
21.154 - self.wfile.write(output)
21.155 -
21.156 - # serve_list()
21.157 -
21.158 -
21.159 - def serve_stop_all_transcoders(self, body):
21.160 - self.send_response(200)
21.161 - self.send_header("Content-Type", "text/html")
21.162 - self.send_header('Connection', 'close')
21.163 - self.end_headers()
21.164 - if body:
21.165 - self.server.stop_transcoders()
21.166 - self.wfile.write(utils.getHTML("stop_all",
21.167 - {"menu": self._nav_items()}))
21.168 - # serve_stop_all_transcoders()
21.169 -
21.170 -
21.171 - def serve_stop_selected_transcoders(self, body, tids=[]):
21.172 - self.send_response(200)
21.173 - self.send_header("Content-Type", "text/html")
21.174 - self.send_header('Connection', 'close')
21.175 - self.end_headers()
21.176 - opts = ""
21.177 - if body:
21.178 - transcoders = self.server.get_transcoders()
21.179 -
21.180 - for tid in tids:
21.181 - for t, r in transcoders:
21.182 - if t.tid == int(tid):
21.183 - try:
21.184 - t.stop()
21.185 - except Exception, e:
21.186 - self.log.info("Plugin already stopped")
21.187 -
21.188 - opts += utils._create_html_item("%s" % t)
21.189 -
21.190 - break
21.191 -
21.192 - self.wfile.write(utils.getHTML("stop_selected",
21.193 - {"menu": self._nav_items(),
21.194 - "opts": opts}))
21.195 - # serve_stop_selected_transcoders()
21.196 -
21.197 -
21.198 - def serve_stop_transcoder(self, body):
21.199 - req = self.query.get("request", None)
21.200 - tid = self.query.get("tid", None)
21.201 - if req and "all" in req:
21.202 - self.serve_stop_all_transcoders(body)
21.203 - elif tid:
21.204 - self.serve_stop_selected_transcoders(body, tid[0].split(";"))
21.205 - else:
21.206 - self.serve_status(body)
21.207 - # serve_stop_transcoder()
21.208 -
21.209 -
21.210 - def serve_status(self, body):
21.211 - self.send_response(200)
21.212 - self.send_header("Content-Type", "text/html")
21.213 - self.send_header('Connection', 'close')
21.214 - self.end_headers()
21.215 - stopone = ""
21.216 - running = ""
21.217 - stopall = ""
21.218 -
21.219 - if body:
21.220 - tl = self.server.get_transcoders()
21.221 - if not tl and not self.query.get("tid", None) and \
21.222 - not self.query.get("running", None):
21.223 - running = "<p>No running transcoder.</p>\n"
21.224 -
21.225 - elif not tl and self.query.get("tid", None):
21.226 - tids = self.query.get("tid")
21.227 - for tid in tids:
21.228 - stat = self.transcoders_log.get_status(int(tid))
21.229 - self.wfile.write("%s<br>" % stat)
21.230 - return True
21.231 -
21.232 - elif self.query.get("running", None):
21.233 - for transcoder, request in tl:
21.234 - outf = transcoder.params_first("outfile")
21.235 - tid = transcoder.tid
21.236 - self.wfile.write("%s:%s<br>" % (tid, outf))
21.237 - return True
21.238 -
21.239 - elif self.query.get("tid", None):
21.240 - req_tid = self.query.get("tid")
21.241 - for transcoder, request in tl:
21.242 - if str(transcoder.tid) in req_tid:
21.243 - self.wfile.write("Status:%s:%s %%" % (\
21.244 - transcoder.tid, transcoder.status))
21.245 - return True
21.246 - stat = self.transcoders_log.get_status(int(req_tid[0]))
21.247 - self.wfile.write("%s<br>" % stat)
21.248 - return True
21.249 -
21.250 - else:
21.251 - running = "<p>Running transcoders:</p>\n"
21.252 - stopall = utils._create_html_item("<a href='%s?request=all'>"
21.253 - "[STOP ALL]</a>" %
21.254 - self.menu["Stop"])
21.255 -
21.256 - for transcoder, request in tl:
21.257 - stopone += utils._create_html_item("%s;"
21.258 - "<a href='%s?tid=%s'>"
21.259 - " [STOP] </a>") % (
21.260 - transcoder, self.menu["Stop"], transcoder.tid)
21.261 -
21.262 - self.wfile.write(utils.getHTML("status",
21.263 - {"menu": self._nav_items(),
21.264 - "running": running,
21.265 - "stopall": stopall,
21.266 - "stopone": stopone}))
21.267 - # serve_status()
21.268 -
21.269 -
21.270 - def _get_transcoder(self):
21.271 - # get transcoder option: mencoder is the default
21.272 - request_transcoders = self.query.get("transcoder", ["mencoder"])
21.273 -
21.274 - for t in request_transcoders:
21.275 - transcoder = self.transcoders.get(t)
21.276 - if transcoder:
21.277 - return transcoder
21.278 -
21.279 - if not transcoder:
21.280 - return self.transcoders[self.def_transcoder]
21.281 - # _get_transcoder()
21.282 -
21.283 -
21.284 - def _get_new_id(self, tid):
21.285 - self.server.last_tid = utils.create_tid(tid)
21.286 - self.tid_queue.append(self.server.last_tid)
21.287 - return self.server.last_tid
21.288 - # _get_new_id()
21.289 -
21.290 -
21.291 - def serve_new_id(self, body):
21.292 - self.send_response(200)
21.293 - self.send_header("Content-Type", "text/html")
21.294 - self.send_header('Connection', 'close')
21.295 - self.end_headers()
21.296 -
21.297 - if body:
21.298 - self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
21.299 - # serve_new_id()
21.300 -
21.301 - def serve_get_log(self, body):
21.302 - self.send_response(200)
21.303 - self.send_header("Content-Type", "text/html")
21.304 - self.send_header('Connection', 'close')
21.305 - self.end_headers()
21.306 -
21.307 - if body:
21.308 - if self.query.get("tid", None):
21.309 - tid = int(self.query.get("tid")[0])
21.310 - stat = self.transcoders_log.get_status(tid)
21.311 - self.wfile.write("Status: %s" % stat)
21.312 - else:
21.313 - stat = self.transcoders_log.get_status()
21.314 - for rtid, status in stat.iteritems():
21.315 - self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
21.316 - # serve_get_log()
21.317 -
21.318 - def serve_get_all_log(self, body):
21.319 - self.send_response(200)
21.320 - self.send_header("Content-Type", "text/html")
21.321 - self.send_header('Connection', 'close')
21.322 - self.end_headers()
21.323 -
21.324 - if body:
21.325 - if self.query.get("tid", None):
21.326 - tid = int(self.query.get("tid")[0])
21.327 - stat = self.transcoders_log.get_status(tid, True)
21.328 - for status in stat:
21.329 - self.wfile.write("%s<br><br>" % status)
21.330 - else:
21.331 - stat = self.transcoders_log.get_status(None, True)
21.332 - for rtid, history in stat.iteritems():
21.333 - for status in history:
21.334 - self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
21.335 - self.wfile.write("<br><br>")
21.336 - # serve_get_all_log()
21.337 -
21.338 -
21.339 - def serve_file_info(self, body):
21.340 - if body:
21.341 -
21.342 - file_dat = self.query.get("file", None)
21.343 -
21.344 - if file_dat:
21.345 - self.send_response(200)
21.346 - self.send_header("Content-Type", "text/html")
21.347 - self.send_header('Connection', 'close')
21.348 - self.end_headers()
21.349 -
21.350 - try:
21.351 - opts = files.TranscodedFile(file_dat[0], self.query).opts
21.352 - for key in opts.keys():
21.353 - self.wfile.write("%s=%s<br>" % (key, opts.get(key, "None")[0]))
21.354 -
21.355 - except Exception, e:
21.356 - self.send_error(500, str(e))
21.357 - return
21.358 - # serve_file_info()
21.359 -
21.360 - def serve_stream(self, body):
21.361 - args = self.query.get("file", None)
21.362 - if not args:
21.363 - self.send_error(404, "File not found")
21.364 - return
21.365 -
21.366 - filename = args[0];
21.367 - if not filename:
21.368 - self.send_error(404, "File not found")
21.369 - return
21.370 -
21.371 - #Only stream files on .transcode dir
21.372 - filename = os.path.join (utils.config.get_transcoded_location(),
21.373 - os.path.basename(filename))
21.374 - self.log.error("Stream file: %s" % filename)
21.375 - if not os.path.exists (filename):
21.376 - self.send_error(404, "File not found")
21.377 - return
21.378 -
21.379 - size = int(os.path.getsize(filename))
21.380 - self.send_response(200)
21.381 - self.send_header("Content-Type", mimetypes.guess_type(filename)[0])
21.382 - self.send_header("Cache-Control","no-cache")
21.383 - self.send_header("Content-Length", size)
21.384 - self.end_headers()
21.385 -
21.386 - media = open(filename)
21.387 - data_in = " "
21.388 - total_read = 0
21.389 -
21.390 - test_tid = int(self.query.get("tid", "0")[0])
21.391 - if test_tid == 0 or test_tid not in self.tid_queue:
21.392 - test_tid = self._get_new_id(self.server.last_tid)
21.393 -
21.394 - self.transcoders_log.insert(test_tid, "gms.Stream: %s" % filename)
21.395 -
21.396 - try:
21.397 - file_data = ""
21.398 - while data_in != "":
21.399 - data_in = media.read(4096)
21.400 - file_data += data_in
21.401 -
21.402 - #total_read += 4096
21.403 - self.wfile.write(file_data)
21.404 - #status = utils.progress_bar(total_read, size, 50)
21.405 - #msg_status = "Status:%s:%s%%" % (test_tid, status)
21.406 - #self.transcoders_log._update_status(test_tid, msg_status)
21.407 -
21.408 - self.transcoders_log._update_status(test_tid, "OK: Done")
21.409 -
21.410 - except Exception, e:
21.411 - self.log.error("Stream error: %s" %e)
21.412 - self.transcoders_log._update_status(test_tid, "Error: %s" % e)
21.413 - # serve_stream()
21.414 -
21.415 - def serve_transcode(self, body):
21.416 - type = self.query.get("type", None)[0]
21.417 - if type.upper() == "FILE":
21.418 - self.send_error(404, "Transcode local files not allowed")
21.419 - return
21.420 -
21.421 - transcoder = self._get_transcoder()
21.422 - try:
21.423 - obj = transcoder(self.query)
21.424 - except Exception, e:
21.425 - self.send_error(500, str(e))
21.426 - return
21.427 -
21.428 - self.send_response(200)
21.429 - self.send_header("Content-Type", obj.get_mimetype())
21.430 - self.send_header("Cache-Control","no-cache")
21.431 -
21.432 - if (obj.name == "gmencoder"):
21.433 - self.send_header("Transfer-Encoding", "chunked")
21.434 -
21.435 - self.end_headers()
21.436 -
21.437 - if body:
21.438 - test_tid = int(self.query.get("tid", "0")[0])
21.439 - if test_tid == 0 or test_tid not in self.tid_queue:
21.440 - test_tid = self._get_new_id(self.server.last_tid)
21.441 -
21.442 - if self.query.get("transcoder", None):
21.443 - self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
21.444 - obj.tid = test_tid
21.445 - obj.log = self.transcoders_log
21.446 -
21.447 - self.server.add_transcoders(self, obj)
21.448 - if obj.start(self.wfile):
21.449 - self.transcoders_log.info (test_tid, "OK")
21.450 - else:
21.451 - self.transcoders_log.info (test_tid, "Fail")
21.452 -
21.453 - self.server.del_transcoders(self, obj)
21.454 - files.TranscodedFile("", self.query)
21.455 -
21.456 - # serve_stream()
21.457 -
21.458 -
21.459 - def log_request(self, code='-', size='-'):
21.460 - self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
21.461 - # log_request()
21.462 -
21.463 -
21.464 - def log_error(self, format, *args):
21.465 - self.log.error("%s: %s" % (self.address_string(), format % args))
21.466 - # log_error()
21.467 -
21.468 -
21.469 - def log_message(self, format, *args):
21.470 - self.log.info("%s: %s" % (self.address_string(), format % args))
21.471 - # log_message()
21.472 -
21.473 -# RequestHandler
22.1 --- a/gmyth-stream/server/0.3/lib/server.py Wed Aug 29 14:29:24 2007 +0100
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,117 +0,0 @@
22.4 -#!/usr/bin/env python
22.5 -
22.6 -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
22.7 -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
22.8 -__license__ = "GPL"
22.9 -__version__ = "0.4"
22.10 -
22.11 -import os
22.12 -import threading
22.13 -import SocketServer
22.14 -import BaseHTTPServer
22.15 -import socket
22.16 -import urlparse
22.17 -import cgi
22.18 -import lib.utils as utils
22.19 -import logging
22.20 -
22.21 -from log import Log
22.22 -from request_handler import RequestHandler
22.23 -
22.24 -__all__ = ("Server", "serve_forever", "load_plugins_transcoders")
22.25 -
22.26 -class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
22.27 - log = logging.getLogger("gms.server")
22.28 - last_tid = 0
22.29 - run = True
22.30 - _transcoders = {}
22.31 - _lock = threading.RLock()
22.32 -
22.33 - def serve_forever(self):
22.34 - self.log.info("GMyth-Streamer serving HTTP on %s:%s" %
22.35 - self.socket.getsockname())
22.36 - try:
22.37 - while self.run:
22.38 - self.handle_request()
22.39 - except KeyboardInterrupt, e:
22.40 - pass
22.41 -
22.42 - self.log.debug("Stopping all remaining transcoders...")
22.43 - self.stop_transcoders()
22.44 - self.log.debug("Transcoders stopped!")
22.45 - # serve_forever()
22.46 -
22.47 -
22.48 - def get_request(self):
22.49 - skt = self.socket
22.50 - old = skt.gettimeout()
22.51 - skt.settimeout(0.5)
22.52 - while self.run:
22.53 - try:
22.54 - r = skt.accept()
22.55 - skt.settimeout(old)
22.56 - return r
22.57 - except socket.timeout, e:
22.58 - pass
22.59 - raise socket.error("Not running")
22.60 - # get_request()
22.61 -
22.62 -
22.63 - def server_close(self):
22.64 - self.run = False
22.65 - self.stop_transcoders()
22.66 -
22.67 - BaseHTTPServer.HTTPServer.server_close(self)
22.68 - # server_close()
22.69 -
22.70 -
22.71 - def stop_transcoders(self):
22.72 - self._lock.acquire()
22.73 - for transcoder, request in self._transcoders.iteritems():
22.74 - self.log.info("Stop transcoder: %s, client=%s" %
22.75 - (transcoder, request.client_address))
22.76 - transcoder.stop()
22.77 - self._lock.release()
22.78 - # stop_transcoders()
22.79 -
22.80 -
22.81 - def get_transcoders(self):
22.82 - self._lock.acquire()
22.83 - try:
22.84 - return self._transcoders.items()
22.85 - finally:
22.86 - self._lock.release()
22.87 - # get_transcoders()
22.88 -
22.89 -
22.90 - def add_transcoders(self, request, transcoder):
22.91 - self._lock.acquire()
22.92 - try:
22.93 - self._transcoders[transcoder] = request
22.94 - finally:
22.95 - self._lock.release()
22.96 - # add_transcoders()
22.97 -
22.98 -
22.99 - def del_transcoders(self, request, transcoder):
22.100 - self._lock.acquire()
22.101 - try:
22.102 - del self._transcoders[transcoder]
22.103 - finally:
22.104 - self._lock.release()
22.105 - # del_transcoders()
22.106 -# Server
22.107 -
22.108 -
22.109 -
22.110 -def serve_forever(host="0.0.0.0", port=40000):
22.111 - addr = (host, port)
22.112 - RequestHandler.protocol_version = "HTTP/1.0"
22.113 - httpd = Server(addr, RequestHandler)
22.114 - httpd.serve_forever()
22.115 -# serve_forever()
22.116 -
22.117 -
22.118 -def load_plugins_transcoders(directory):
22.119 - RequestHandler.load_plugins_transcoders(directory)
22.120 -# load_plugins_transcoders()
23.1 --- a/gmyth-stream/server/0.3/lib/transcoder.py Wed Aug 29 14:29:24 2007 +0100
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,58 +0,0 @@
23.4 -#!/usr/bin/env python
23.5 -
23.6 -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
23.7 -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
23.8 -__license__ = "GPL"
23.9 -__version__ = "0.4"
23.10 -
23.11 -__all__ = ("Transcoder")
23.12 -
23.13 -class Transcoder(object):
23.14 - """Transcoder's Class: parent class to implement
23.15 - a plugin for transcoding data."""
23.16 - priority = 0 # negative values have higher priorities
23.17 - name = None # to be used in requests
23.18 - status = None
23.19 - log = None
23.20 - tid = -1
23.21 -
23.22 - def __init__(self, params):
23.23 - self.params = params
23.24 - # __init__()
23.25 -
23.26 - def params_first(self, key, default=None):
23.27 - if default is None:
23.28 - return self.params[key][0]
23.29 - else:
23.30 - try:
23.31 - return self.params[key][0]
23.32 - except:
23.33 - return default
23.34 - # params_first()
23.35 -
23.36 - def get_mimetype(self):
23.37 - return "application/octet-stream"
23.38 - # get_mimetype()
23.39 -
23.40 - def start(self, outfile):
23.41 - pass
23.42 - # start()
23.43 -
23.44 - def stop(self):
23.45 - pass
23.46 - # stop()
23.47 -
23.48 - def get_legth (self):
23.49 - pass
23.50 - # get_leght ()
23.51 -
23.52 - def get_progress (self):
23.53 - pass
23.54 - # get_progress ()
23.55 -
23.56 - def __str__(self):
23.57 - return '%s: %s( params=%s ) - Status: %s%%' % \
23.58 - (self.__class__.__name__, self.tid,
23.59 - self.params, self.status)
23.60 - # __str__()
23.61 -# Transcoder
24.1 --- a/gmyth-stream/server/0.3/lib/utils.py Wed Aug 29 14:29:24 2007 +0100
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,193 +0,0 @@
24.4 -#!/usr/bin/env
24.5 -
24.6 -__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
24.7 -__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
24.8 -__license__ = "GPL"
24.9 -__version__ = "0.3"
24.10 -
24.11 -import os
24.12 -import stat
24.13 -import sys
24.14 -import logging
24.15 -import urllib
24.16 -import gobject
24.17 -import imp
24.18 -
24.19 -import gmsconfig
24.20 -
24.21 -log = logging.getLogger("gms.utils")
24.22 -config = gmsconfig.GmsConfig()
24.23 -
24.24 -__all__ = ("which", "load_plugins", "PluginSet", "getHTML",
24.25 - "progress_bar", "create_tid", "list_media_files")
24.26 -
24.27 -def which(app):
24.28 - """Function to implement which(1) unix command"""
24.29 - pl = os.environ["PATH"].split(os.pathsep)
24.30 - for p in pl:
24.31 - path = os.path.join(p, app)
24.32 - if os.path.isfile(path):
24.33 - st = os.stat(path)
24.34 - if st[stat.ST_MODE] & 0111:
24.35 - return path
24.36 - return ""
24.37 -# which()
24.38 -
24.39 -
24.40 -def _load_module(pathlist, name):
24.41 - fp, path, desc = imp.find_module(name, pathlist)
24.42 - try:
24.43 - module = imp.load_module(name, fp, path, desc)
24.44 - return module
24.45 - finally:
24.46 - if fp:
24.47 - fp.close()
24.48 -# _load_module()
24.49 -
24.50 -
24.51 -class PluginSet(object):
24.52 - def __init__(self, basetype, *items):
24.53 - self.basetype = basetype
24.54 - self.map = {}
24.55 - self.list = []
24.56 -
24.57 - for i in items:
24.58 - self._add(i)
24.59 - self._sort()
24.60 - # __init__()
24.61 -
24.62 -
24.63 - def _add(self, item):
24.64 - self.map[item.name] = item
24.65 - self.list.append(item)
24.66 - # _add()
24.67 -
24.68 -
24.69 - def add(self, item):
24.70 - self._add()
24.71 - self._sort()
24.72 - # add()
24.73 -
24.74 -
24.75 - def __getitem__(self, spec):
24.76 - if isinstance(spec, basestring):
24.77 - return self.map[spec]
24.78 - else:
24.79 - return self.list[spec]
24.80 - # __getitem__()
24.81 -
24.82 -
24.83 - def get(self, name, default=None):
24.84 - return self.map.get(name, default)
24.85 - # get()
24.86 -
24.87 -
24.88 - def __iter__(self):
24.89 - return self.list.__iter__()
24.90 - # __iter__()
24.91 -
24.92 -
24.93 - def __len__(self):
24.94 - return len(self.list)
24.95 - # __len__()
24.96 -
24.97 -
24.98 - def _sort(self):
24.99 - self.list.sort(lambda a, b: cmp(a.priority, b.priority))
24.100 - # _sort()
24.101 -
24.102 -
24.103 - def update(self, pluginset):
24.104 - self.map.update(pluginset.map)
24.105 - self.list.extend(pluginset.list)
24.106 - self._sort()
24.107 - # update()
24.108 -
24.109 -
24.110 - def load_from_directory(self, directory):
24.111 - for i in load_plugins(directory, self.basetype):
24.112 - self._add(i)
24.113 - self._sort()
24.114 - # load_from_directory()
24.115 -
24.116 -
24.117 - def __str__(self):
24.118 - lst = []
24.119 - for o in self.list:
24.120 - lst.append('"%s" (%s)' % (o.name, o.__name__))
24.121 -
24.122 - return "%s(basetype=%s, items=[%s])" % \
24.123 - (self.__class__.__name__,
24.124 - self.basetype.__name__,
24.125 - ", ".join(lst))
24.126 - # __str__()
24.127 -# PluginSet
24.128 -
24.129 -
24.130 -def load_plugins(directory, basetype):
24.131 - """Function to load plugins from a given directory"""
24.132 - tn = basetype.__name__
24.133 - log.debug("Loading plugins from %s, type=%s" % (directory, tn))
24.134 -
24.135 -
24.136 - plugins = []
24.137 - for d in os.listdir(directory):
24.138 - if not d.endswith(".py"):
24.139 - continue
24.140 -
24.141 - name = d[0: -3]
24.142 - if name == "__init__":
24.143 - continue
24.144 -
24.145 - directory.replace(os.path.sep, ".")
24.146 - mod = _load_module([directory], name)
24.147 - for sym in dir(mod):
24.148 - cls = getattr(mod, sym)
24.149 - if isinstance(cls, type) and issubclass(cls, basetype) and \
24.150 - cls != basetype:
24.151 - plugins.append(cls)
24.152 - log.info("Loaded %s (%s) from %s" % \
24.153 - (cls.__name__, tn, os.path.join(directory, d)))
24.154 -
24.155 - return plugins
24.156 -# load_plugins()
24.157 -
24.158 -def getHTML(html_file, params={}):
24.159 - """This function parses an html file with the given
24.160 - parameters and returns a formated web-page"""
24.161 - try:
24.162 - filename = os.path.join(sys.path[0], "html", html_file + ".html")
24.163 - html = open(filename).read() % params
24.164 - return html
24.165 - except Exception, e:
24.166 - return "HTML format error. Wrong keys: %s" % e
24.167 -
24.168 -# getHTML
24.169 -
24.170 -def _create_html_item(opt):
24.171 - """Create an <li> item using HTML."""
24.172 - return "<li>%s</li>\n" % opt
24.173 -# _create_html_item
24.174 -
24.175 -def progress_bar(value, max, barsize):
24.176 - """Creates and displays a progressbar. By OSantana"""
24.177 - chars = int(value * barsize / float(max))
24.178 - percent = int((value / float(max)) * 100)
24.179 - sys.stdout.write("#" * chars)
24.180 - sys.stdout.write(" " * (barsize - chars + 2))
24.181 - if value >= max:
24.182 - sys.stdout.write("done.\n\n")
24.183 - else:
24.184 - sys.stdout.write("[%3i%%]\r" % (percent))
24.185 - sys.stdout.flush()
24.186 - return percent
24.187 -# progress_bar() by osantana
24.188 -
24.189 -def create_tid(last_tid):
24.190 - """Function to generate TIDs (ids for transcoders).
24.191 - At first it just do +1 on last_tid but can be implemented
24.192 - to generate more sparse TIDs"""
24.193 - tid = last_tid + 1
24.194 - return tid
24.195 -# create_id()
24.196 -
25.1 --- a/gmyth-stream/server/0.3/plugins/transcoders/gmencoder.py Wed Aug 29 14:29:24 2007 +0100
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,134 +0,0 @@
25.4 -#!/usr/bin/env python
25.5 -
25.6 -__author__ = "Renato Filho"
25.7 -__author_email__ = "renato.filho@indt.org.br"
25.8 -__license__ = "GPL"
25.9 -__version__ = "0.2"
25.10 -
25.11 -import os
25.12 -import sys
25.13 -import shlex
25.14 -import signal
25.15 -import subprocess
25.16 -import time
25.17 -
25.18 -import select
25.19 -import fcntl
25.20 -
25.21 -import lib.utils as utils
25.22 -import lib.server as server
25.23 -import lib.transcoder as transcoder
25.24 -
25.25 -__all__ = ("TranscoderGMencoder",)
25.26 -
25.27 -class TranscoderGMencoder(transcoder.Transcoder):
25.28 - gmencoder_path = utils.which("gmencoder")
25.29 - name = "gmencoder"
25.30 - priority = -1
25.31 - proc = None
25.32 -
25.33 - def __init__(self, params):
25.34 - self.status = 0
25.35 - transcoder.Transcoder.__init__(self, params)
25.36 - self.opts = []
25.37 - self.opts.append (self.gmencoder_path)
25.38 - self.opts.append ("-d")
25.39 - self._parser_params ()
25.40 -
25.41 - # __init__()
25.42 -
25.43 - def _insert_param (self, name, value):
25.44 - if (value != ""):
25.45 - self.opts.append(name)
25.46 - self.opts.append(value)
25.47 -
25.48 - def _parser_params (self):
25.49 - self._insert_param("-i", \
25.50 - "%s://%s" % (self.params_first("type", "file"),
25.51 - self.params_first("uri", "")))
25.52 - self._insert_param("--video-encode", self.params_first("ve", "ffenc_mpeg1video"))
25.53 - self._insert_param("--video-opts", "bitrate=300000,pass=512,quantizer=0.01,quant-type=1")
25.54 - #self._insert_param("--video-fps", self.params_first("fps", ""))
25.55 - self._insert_param("--video-fps", self.params_first("fps", "10"))
25.56 - self._insert_param("--video-width", self.params_first("width", "320"))
25.57 - self._insert_param("--video-height", self.params_first("height", "240"))
25.58 - self._insert_param("--audio-rate", "32000")
25.59 - self._insert_param("--audio-encode", self.params_first("ae", ""))
25.60 - # _parse_params
25.61 -
25.62 - def start(self, outfd):
25.63 - outfile = self.params_first("outfile", "")
25.64 -
25.65 - if outfile != "":
25.66 - path = os.path.join(utils.config.get_transcoded_location(), outfile)
25.67 - self._insert_param("-o", "file://%s" % path)
25.68 - else:
25.69 - self._insert_param ("-o", "fd://%d" % outfd.fileno())
25.70 - self.opts.append ("-c")
25.71 -
25.72 - cmd = " ".join(self.opts)
25.73 - self.log.info(self.tid, "GMencoder: %s" % cmd)
25.74 -
25.75 - try:
25.76 - self.proc = subprocess.Popen(self.opts, stdin=subprocess.PIPE,
25.77 - stdout=subprocess.PIPE)
25.78 -
25.79 - if outfile:
25.80 - outfd.write("OK ")
25.81 -
25.82 - except Exception, e:
25.83 - self.log.error(self.tid, "Error: executing GMencoder: %s" % e)
25.84 - outfd.write("Error: GMencoder: %s" % e)
25.85 - return False
25.86 -
25.87 - try:
25.88 - if not outfile:
25.89 - p = select.poll()
25.90 - p.register (outfd, select.POLLNVAL | select.POLLERR | select.POLLHUP | select.POLLIN )
25.91 -
25.92 - while (self.proc and self.proc.poll() == None):
25.93 - r, w, x = select.select([self.proc.stdout], [], [], 1)
25.94 - if self.proc.stdout in r:
25.95 - progress = self.proc.stdout.readline()
25.96 - if (progress.find ("PROGRESS") >= 0):
25.97 - self.status = progress.split (":")[1]
25.98 - elif (progress.find ("Erro") >= 0):
25.99 - return False
25.100 -
25.101 - if not outfile:
25.102 - ret = p.poll(0)
25.103 - if ret:
25.104 - print "Lost Connection"
25.105 - self.stop ()
25.106 - return False
25.107 -
25.108 - except Exception, e:
25.109 - self.log.error(self.tid, "Problems handling data: %s" % e)
25.110 - return False
25.111 -
25.112 - self.status = 100;
25.113 -
25.114 -
25.115 - return True
25.116 - # start()
25.117 -
25.118 -
25.119 - def stop(self):
25.120 - if self.proc:
25.121 - self.log.info(self.tid, "Stopped GMencoder plugin")
25.122 - try:
25.123 - os.kill(self.proc.pid, signal.SIGKILL)
25.124 - self.proc.wait()
25.125 - except Exception, e:
25.126 - pass
25.127 -
25.128 - self.proc = None
25.129 - # stop()
25.130 -
25.131 - def get_progress(self):
25.132 - return self.status
25.133 -
25.134 - def get_lenght(self):
25.135 - return -1
25.136 -
25.137 -# TranscoderGMencoder
26.1 --- a/gmyth-stream/server/0.3/plugins/transcoders/mencoder.py Wed Aug 29 14:29:24 2007 +0100
26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
26.3 @@ -1,334 +0,0 @@
26.4 -#!/usr/bin/env python
26.5 -
26.6 -__author__ = "Artur Duque de Souza"
26.7 -__author_email__ = "artur.souza@indt.org.br"
26.8 -__license__ = "GPL"
26.9 -__version__ = "0.3"
26.10 -
26.11 -import os
26.12 -import time
26.13 -import fcntl
26.14 -import shlex
26.15 -import socket
26.16 -import struct
26.17 -import signal
26.18 -import subprocess
26.19 -
26.20 -import lib.utils as utils
26.21 -import lib.server as server
26.22 -import plugins.transcoders.mencoder_lib.mythtv as mythtv
26.23 -
26.24 -from select import select
26.25 -import lib.transcoder as transcoder
26.26 -
26.27 -__all__ = ("TranscoderMencoder",)
26.28 -
26.29 -class TranscoderMencoder(transcoder.Transcoder):
26.30 - """Transcoder class that implements a transcoder using Mencoder"""
26.31 - mencoder_path = utils.which("mencoder")
26.32 - name = "mencoder"
26.33 - priority = -1
26.34 - args = {}
26.35 - proc = None
26.36 - gmyth = None
26.37 -
26.38 - # only works with avi container
26.39 - status = 0
26.40 -
26.41 - def _setup_params(self):
26.42 - params_first = self.params_first
26.43 -
26.44 - # general_opts
26.45 - self.args["local"] = params_first("local", False)
26.46 - self.args["language"] = params_first("language", False)
26.47 - self.args["subtitle"] = params_first("subtitle", False)
26.48 - self.args["format"] = params_first("format", "mpeg1")
26.49 - self.args["outfile"] = params_first("outfile", "-")
26.50 -
26.51 - # input_opt
26.52 - self.args["type"] = params_first("type", "file")
26.53 - self.args["input"] = params_first("uri", "-")
26.54 -
26.55 - # audio_opts
26.56 - self.args["acodec"] = params_first("acodec", "mp2")
26.57 - self.args["abitrate"] = params_first("abitrate", 192)
26.58 - self.args["volume"] = params_first("volume", 5)
26.59 -
26.60 - # video_opts
26.61 - self.args["mux"] = params_first("mux", "mpeg")
26.62 - self.args["fps"] = params_first("fps", 25)
26.63 - self.args["vcodec"] = params_first("vcodec", "mpeg1video")
26.64 - self.args["vbitrate"] = params_first("vbitrate", 400)
26.65 - self.args["width"] = params_first("width", 320)
26.66 - self.args["height"] = params_first("height", 240)
26.67 - # _setup_params()
26.68 -
26.69 -
26.70 - def _setup_audio(self):
26.71 - if self.args["acodec"] == "mp3lame":
26.72 - audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
26.73 - self.args["abitrate"], self.args["volume"])
26.74 - else:
26.75 - audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
26.76 - self.args["acodec"], self.args["abitrate"])
26.77 -
26.78 - return audio
26.79 - # _setup_audio()
26.80 -
26.81 -
26.82 - def _setup_video(self):
26.83 - video = " -of %s" % self.args["mux"]
26.84 - video += " -ofps %s" % self.args["fps"]
26.85 -
26.86 - vcodec = self.args["vcodec"]
26.87 - if vcodec == "nuv" or vcodec == "xvid"\
26.88 - or vcodec == "qtvideo" or vcodec == "copy":
26.89 - video += " -ovc %s" % vcodec
26.90 - else:
26.91 - video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
26.92 - vcodec, self.args["vbitrate"])
26.93 -
26.94 - if self.args["mux"] == "mpeg":
26.95 - video += " -mpegopts format=%s" % self.args["format"]
26.96 -
26.97 - video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
26.98 - return video
26.99 - # _setup_video()
26.100 -
26.101 -
26.102 - def _arg_append(self, args, options):
26.103 - for arg in shlex.split(options):
26.104 - args.append(arg)
26.105 - # arg_append()
26.106 -
26.107 - def _setup_mencoder_opts(self, args):
26.108 - args.append(self.mencoder_path)
26.109 -
26.110 - if self.args["type"] and self.args["type"] == "tv":
26.111 - self._arg_append(args, self.args["tv"])
26.112 - elif self.args["outfile"] == "-" and self.args["type"]:
26.113 - args.append(self.args["input"])
26.114 - else:
26.115 - args.append("-")
26.116 -
26.117 - if self.args["language"]:
26.118 - self._arg_append(args, "-alang %s" % self.args["language"])
26.119 -
26.120 - if self.args["subtitle"]:
26.121 - self._arg_append(args, "-slang %s" % self.args["subtitle"])
26.122 - self._arg_append(args, "-subfps %s" % self.args["fps"])
26.123 -
26.124 - self._arg_append(args, "-idx")
26.125 - self._arg_append(args, "-cache 1024")
26.126 - self._arg_append(args, self._setup_audio())
26.127 - self._arg_append(args, self._setup_video())
26.128 -
26.129 - self._arg_append(args, "-really-quiet")
26.130 -
26.131 - if self.args["outfile"] != "-":
26.132 - self.args["outfile"] = ".transcoded/%s" % (
26.133 - os.path.basename(self.args["outfile"]))
26.134 -
26.135 - self._arg_append(args, "-o %s" % self.args["outfile"])
26.136 - self._arg_append(args, "2>%s" % os.devnull)
26.137 - # _setup_args()
26.138 -
26.139 - def _setup_filename(self):
26.140 - """This function setups the file to encode parsing the uri.
26.141 - So, type can be:
26.142 - * file
26.143 - * dvd
26.144 - * myth
26.145 -
26.146 - If the last one is detected we have to parse the uri to find args.
26.147 - Then we store all the args inside a dictionary: self.args['gmyth-cat']
26.148 - """
26.149 - _type = self.args["type"]
26.150 -
26.151 - if _type == "file":
26.152 - if not os.path.exists(self.args["input"]):
26.153 - raise IOError,\
26.154 - "File requested does not exist: %s." % self.args["input"]
26.155 - else:
26.156 - self.args["input"] = "file://%s" % self.args["input"]
26.157 -
26.158 - elif _type == "dvd":
26.159 - self.args["input"] = "dvd://%s" % self.args["input"]
26.160 -
26.161 - elif _type == "myth":
26.162 - self.args["gmyth-cat"] = mythtv._setup_mythfilename(self)
26.163 -
26.164 - elif _type == "tv":
26.165 - driver = self.params_first("driver", "v4l2")
26.166 - norm = self.params_first("norm", "pal-m")
26.167 - channel = self.params_first("channel", "13")
26.168 - chanlist = self.params_first("chanlist", "us-bcast")
26.169 - outfmt = self.params_first("outfmt", "yuy2")
26.170 - vdev = self.params_first("vdev", "/dev/video0")
26.171 - adev = self.params_first("adev", "/dev/dsp")
26.172 - self.args["tv"] = "tv:// -v -tv driver=%s:norm=%s:channel=%s:" \
26.173 - "chanlist=%s:width=%s:height=%s:outfmt=%s:" \
26.174 - "device=%s:adevice=%s" % (driver, norm,
26.175 - channel, chanlist,
26.176 - self.args["width"],
26.177 - self.args["height"],
26.178 - outfmt, vdev, adev)
26.179 - # _setup_filename()
26.180 -
26.181 -
26.182 - def __init__(self, params):
26.183 - transcoder.Transcoder.__init__(self, params)
26.184 - self.mencoder_opts = []
26.185 -
26.186 - try:
26.187 - self._setup_params()
26.188 - self._setup_filename()
26.189 - self._setup_mencoder_opts(self.mencoder_opts)
26.190 - except Exception, e:
26.191 - if self.log:
26.192 - self.log.error(self.tid, "Error: %s" % e)
26.193 - else:
26.194 - raise
26.195 - # __init__()
26.196 -
26.197 -
26.198 - def _check_opened_file(self, stdw, _stdin):
26.199 - loop = True
26.200 - while loop:
26.201 - try:
26.202 - return open(self.args["outfile"])
26.203 - except:
26.204 - os.write(stdw, _stdin.read(1024))
26.205 - # _check_opened_file
26.206 -
26.207 -
26.208 - def _start_outfile(self, outfd):
26.209 - finished = False
26.210 -
26.211 - # Configuring stdin
26.212 - try:
26.213 - filename = self.args["input"].split("://")[1]
26.214 - _stdin = open(filename)
26.215 - size = int(os.path.getsize(filename))
26.216 - except Exception, e:
26.217 - self.log.error(self.tid, "Error: Mencoder stdin"\
26.218 - " setup error: %s" % e)
26.219 - outfd.write("Error: Mencoder stdin setup error: %s" %e)
26.220 - return False
26.221 -
26.222 - self.status = 0
26.223 - total_read = 0
26.224 -
26.225 - # Configuring pipes
26.226 - stdr, stdw = os.pipe()
26.227 -
26.228 - if not self._run_mencoder(input=stdr):
26.229 - return False
26.230 -
26.231 - stdout = self._check_opened_file(stdw, _stdin)
26.232 - outfd.write("OK ")
26.233 -
26.234 - try:
26.235 - while self.proc and self.proc.poll() == None:
26.236 - if not finished:
26.237 - data_in = _stdin.read(4096)
26.238 - if data_in != "":
26.239 - os.write(stdw, data_in)
26.240 - total_read += 4096
26.241 - d = stdout.read(4096)
26.242 - self.status = utils.progress_bar(total_read,
26.243 - size, 50)
26.244 - else:
26.245 - finished = True
26.246 - os.close(stdw)
26.247 -
26.248 - else:
26.249 - d = stdout.read(4096)
26.250 -
26.251 - except Exception, e:
26.252 - self.log.error(self.tid, "Error: %s" % e)
26.253 - self.stop()
26.254 - return False
26.255 -
26.256 - self.log.info(self.tid, "OK: Done")
26.257 - return True
26.258 - # _start_outfile()
26.259 -
26.260 -
26.261 - def _start(self, outfd):
26.262 - # Play a file on disk or DVD
26.263 - if not self._run_mencoder(output=subprocess.PIPE):
26.264 - return False
26.265 -
26.266 - try:
26.267 - while self.proc and self.proc.poll() == None:
26.268 - d = self.proc.stdout.read(1024)
26.269 - outfd.write(d)
26.270 - except Exception, e:
26.271 - self.log.error(self.tid, "Error: %s" % e)
26.272 - return False
26.273 -
26.274 - self.log.info(self.tid, "OK: Done")
26.275 - return True
26.276 - # _start()
26.277 -
26.278 - def _run_mencoder(self, input=None, output=None):
26.279 - try:
26.280 - self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
26.281 - stdout=output, close_fds=True)
26.282 - except Exception, e:
26.283 - self.log.error(self.tid, "Error: Mencoder: %s" % e)
26.284 - return False
26.285 -
26.286 - return True
26.287 - # _run_mencoder()
26.288 -
26.289 - def start(self, outfd):
26.290 - cmd = " ".join(self.mencoder_opts)
26.291 - self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
26.292 - self.log.debug(self.tid, "Mencoder: %s" % cmd)
26.293 -
26.294 - ret = False
26.295 -
26.296 - if self.args["outfile"] == "-" and \
26.297 - self.args["type"] in ["file", "dvd", "tv"]:
26.298 - ret = self._start(outfd)
26.299 -
26.300 - elif self.args["type"] == "myth":
26.301 - ret = mythtv.start_myth(self, outfd)
26.302 -
26.303 - else:
26.304 - ret = self._start_outfile(outfd)
26.305 -
26.306 - self.stop()
26.307 -
26.308 - if not ret:
26.309 - self.log.error(self.tid, "Error: Problems while "\
26.310 - "starting streaming.")
26.311 -
26.312 - return ret
26.313 - # start()
26.314 -
26.315 - def _aux_stop(self, obj, next=False):
26.316 - if obj:
26.317 - try:
26.318 - os.kill(obj.pid, signal.SIGKILL)
26.319 - if next:
26.320 - os.kill(obj.pid+1, signal.SIGKILL)
26.321 - except OSError, e:
26.322 - pass
26.323 -
26.324 - try:
26.325 - obj.wait()
26.326 - except Exception, e:
26.327 - pass
26.328 -
26.329 - obj = None
26.330 - # _aux_stop
26.331 -
26.332 - def stop(self):
26.333 - self._aux_stop(self.proc, True)
26.334 - self._aux_stop(self.gmyth)
26.335 - # stop()
26.336 -
26.337 -# TranscoderMencoder
27.1 --- a/gmyth-stream/server/0.3/plugins/transcoders/mencoder_lib/mythtv.py Wed Aug 29 14:29:24 2007 +0100
27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
27.3 @@ -1,109 +0,0 @@
27.4 -import os
27.5 -import subprocess
27.6 -import fcntl
27.7 -
27.8 -import lib.utils as utils
27.9 -import lib.server as server
27.10 -
27.11 -from select import select
27.12 -
27.13 -def _setup_mythfilename(self):
27.14 - # mythtv:mythtv@192.168.3.110:6543/1002_20070426230000.nuv
27.15 - try:
27.16 - _mysql = self.args["input"].split("@")[0].split(":")
27.17 - except IndexError, e:
27.18 - _mysql = ["mythtv", "mythtv"]
27.19 -
27.20 - try:
27.21 - _args = self.args["input"].split("@")[1].split(":")
27.22 - except IndexError, e:
27.23 - _args = self.args["input"].split(":")
27.24 -
27.25 - gmyth_dict = {}
27.26 - gmyth_dict["mysql"] = _mysql
27.27 - gmyth_dict["backend"] = _args[0]
27.28 - gmyth_dict["port"] = _args[1].split("/", 1)[0]
27.29 -
27.30 - _tmp_file = _args[1].split("/", 1)[1]
27.31 -
27.32 - if _tmp_file.find("channel") >= 0:
27.33 - gmyth_dict["kind"] = "c"
27.34 - gmyth_dict["cfile"] = _tmp_file.split("=")[1]
27.35 - else:
27.36 - gmyth_dict["kind"] = "f"
27.37 - gmyth_dict["cfile"] = _tmp_file
27.38 -
27.39 - self.args["input"] = "-"
27.40 - return gmyth_dict
27.41 -# _setup_mythfilename
27.42 -
27.43 -def _setup_mythfile(err):
27.44 - size = err.readline().split("Size:")[1]
27.45 - flags = fcntl.fcntl (err, fcntl.F_GETFL, 0) | os.O_NONBLOCK
27.46 - fcntl.fcntl(err, fcntl.F_SETFL, flags)
27.47 - return size
27.48 -# _setup_mythfile
27.49 -
27.50 -def _setup_gmythcat(self):
27.51 - gmyth_cat = utils.which("gmyth-cat")
27.52 - if self.args.has_key("gmyth-cat"):
27.53 - return [ utils.which("gmyth-cat"),
27.54 - "-h", self.args["gmyth-cat"]["backend"],
27.55 - "-p", self.args["gmyth-cat"]["port"],
27.56 - "-" + self.args["gmyth-cat"]["kind"],
27.57 - self.args["gmyth-cat"]["cfile"]
27.58 - ]
27.59 - else:
27.60 - self.log.error(self.tid, "Error: URI error")
27.61 - return []
27.62 -# _setup_gmythcat
27.63 -
27.64 -def start_myth(self, outfd):
27.65 - opts = _setup_gmythcat(self)
27.66 - try:
27.67 - self.gmyth = subprocess.Popen(opts, stdout=subprocess.PIPE,
27.68 - stderr=subprocess.PIPE,
27.69 - close_fds=True)
27.70 - except Exception, e:
27.71 - self.log.error(self.tid, "Error: gmyth-cat: %s" % e)
27.72 - return False
27.73 -
27.74 - if not self._run_mencoder(input=self.gmyth.stdout,
27.75 - output=subprocess.PIPE):
27.76 - return False
27.77 -
27.78 - if self.args["gmyth-cat"]["kind"] == "f":
27.79 - try:
27.80 - size = _setup_mythfile(self.gmyth.stderr)
27.81 - self.log.debug(self.tid, "Info: Size of file: %s" % size)
27.82 - except Exception, e:
27.83 - self.log.error(self.tid, "Error: Problems getting size of"\
27.84 - " file: %s" % e)
27.85 - outfd.write("Error: Problems getting size of file: %s" % e)
27.86 - return False
27.87 -
27.88 - outfd.write("OK ")
27.89 -
27.90 - try:
27.91 - while self.proc and self.proc.poll() == None:
27.92 - r, w, x = select([self.gmyth.stderr, self.proc.stdout],
27.93 - [], [], 0)
27.94 - if self.proc.stdout in r:
27.95 - d = self.proc.stdout.read(4096)
27.96 - outfd.write(d)
27.97 -
27.98 - if self.gmyth.stderr in r:
27.99 - partial = self.gmyth.stderr.readline()
27.100 - if partial != "":
27.101 - self.status = utils.progress_bar(int(partial),
27.102 - int(size), 50)
27.103 -
27.104 - except IndexError, e:
27.105 - pass
27.106 - except Exception, e:
27.107 - self.log.error(self.tid, "Error: %s" % e)
27.108 - return False
27.109 -
27.110 - self.log.info(self.tid, "OK: Done")
27.111 - return True
27.112 -# _start_myth()
28.1 --- a/gmyth-stream/server/0.3/server.conf Wed Aug 29 14:29:24 2007 +0100
28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
28.3 @@ -1,2 +0,0 @@
28.4 -[PATHS]
28.5 -transcoded=./.transcoded
29.1 --- a/gmyth-stream/server/0.3/setup.py Wed Aug 29 14:29:24 2007 +0100
29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
29.3 @@ -1,17 +0,0 @@
29.4 -from distutils.core import setup
29.5 -from glob import glob
29.6 -
29.7 -setup(name='gms',
29.8 - version='0.6',
29.9 - description='carman rich view package',
29.10 - long_description='carman rich view (SDL based) package',
29.11 - url='http://www.indt.org.br',
29.12 - scripts=['gms.py'],
29.13 - package_dir={'lib': 'lib', 'plugins' : 'plugins','data' : 'data' },
29.14 - packages=['lib','plugins','plugins.transcoders','plugins.transcoders.mencoder_lib'],
29.15 - data_files = [
29.16 - ('share/gms/html', glob("html/*")),
29.17 - ('etc/init.d', ['data/gmsd']),
29.18 - ('etc/gms', ['data/server.conf'])
29.19 - ],
29.20 - )
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/gmyth-stream/server/data/gmsd Wed Aug 29 14:42:10 2007 +0100
30.3 @@ -0,0 +1,61 @@
30.4 +#!/bin/sh
30.5 +
30.6 +PROGRAM_NAME=GMS
30.7 +PROGRAM_BIN=/usr/bin/gms.py
30.8 +PIDFILE=/var/run/gms.pid
30.9 +LOGFILE=/var/log/gms.log
30.10 +
30.11 +test -x $PROGRAM_BIN || exit 0
30.12 +
30.13 +set -e
30.14 +
30.15 +. /lib/lsb/init-functions
30.16 +. /etc/default/rcS
30.17 +
30.18 +case $1 in
30.19 + start)
30.20 + echo -n "Starting $PROGRAM_NAME: "
30.21 + if [ -f $PIDFILE ]
30.22 + then
30.23 + PID=`cat $PIDFILE`
30.24 +
30.25 + if ps ax | grep -q "^$PID"
30.26 + then
30.27 + echo "$PROGRAM_NAME already running."
30.28 + else
30.29 + rm -f $PIDFILE
30.30 + $PROGRAM_BIN -d > $LOGFILE
30.31 + echo "OK"
30.32 + fi
30.33 + else
30.34 + $PROGRAM_BIN -d > $LOGFILE
30.35 + echo "OK"
30.36 + fi
30.37 + ;;
30.38 +
30.39 + stop)
30.40 + echo -n "Stopping $PROGRAM_NAME: "
30.41 + if [ -f $PIDFILE ]
30.42 + then
30.43 + PID=`cat $PIDFILE`
30.44 + if ps ax | grep -q "^$PID"
30.45 + then
30.46 + kill -10 $PID
30.47 + fi
30.48 + rm $PIDFILE
30.49 + else
30.50 + echo "No $PROGRAM_NAME found running; no killed."
30.51 + fi
30.52 + ;;
30.53 +
30.54 + restart)
30.55 + $0 stop
30.56 + sleep 1
30.57 + $0 start
30.58 + ;;
30.59 +
30.60 + *)
30.61 + log_success_msg "Usage: $0 {stop|start|restart}"
30.62 + exit 1
30.63 + ;;
30.64 +esac
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/gmyth-stream/server/data/server.conf Wed Aug 29 14:42:10 2007 +0100
31.3 @@ -0,0 +1,2 @@
31.4 +[PATHS]
31.5 +transcoded=/var/gms-media
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/gmyth-stream/server/debian/changelog Wed Aug 29 14:42:10 2007 +0100
32.3 @@ -0,0 +1,6 @@
32.4 +gms (0.3-indt1) unstable; urgency=low
32.5 +
32.6 + * First package
32.7 +
32.8 + -- Renato Araujo Oliveira Filho <renato.filho@indt.org> Thu, 16 Aug 2007 14:55:00 -0300
32.9 +
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/gmyth-stream/server/debian/compat Wed Aug 29 14:42:10 2007 +0100
33.3 @@ -0,0 +1,1 @@
33.4 +5
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/gmyth-stream/server/debian/control Wed Aug 29 14:42:10 2007 +0100
34.3 @@ -0,0 +1,13 @@
34.4 +Source: gms
34.5 +Section: sound
34.6 +Priority: optional
34.7 +Maintainer: Renato Araujo Oliveira Filho <renato.filho@indt.org>
34.8 +Build-Depends: debhelper (>= 5.0.38), python-support (>= 0.5), python-central (>= 0.5)
34.9 +Standards-Version: 3.7.2
34.10 +
34.11 +Package: gms
34.12 +Architecture: any
34.13 +Depends: ${python:Depends}, libgstreamer0.10-0, gstreamer0.10-plugins-base, gstreamer0.10-plugins-good
34.14 +Recommends: gstreamer0.10-plugins-ugly
34.15 +Description: Media transcoder deamon
34.16 + Homepage: http://gmyth.sourceforge.net/
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/gmyth-stream/server/debian/copyright Wed Aug 29 14:42:10 2007 +0100
35.3 @@ -0,0 +1,19 @@
35.4 +It was downloaded from: http://gmyth.sourceforge.net/wiki/
35.5 +
35.6 +License:
35.7 + This package is free software; you can redistribute it and/or modify
35.8 + it under the terms of the GNU General Public License as published by
35.9 + the Free Software Foundation; either version 2 of the License, or
35.10 + (at your option) any later version.
35.11 +
35.12 + This package is distributed in the hope that it will be useful,
35.13 + but WITHOUT ANY WARRANTY; without even the implied warranty of
35.14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35.15 + GNU General Public License for more details.
35.16 +
35.17 + You should have received a copy of the GNU General Public License
35.18 + along with this package; if not, write to the Free Software
35.19 + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35.20 +
35.21 +On Debian systems, the complete text of the GNU General Public License can
35.22 +be found in `/usr/share/common-licenses/GPL'.
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/gmyth-stream/server/debian/gms.install Wed Aug 29 14:42:10 2007 +0100
36.3 @@ -0,0 +1,8 @@
36.4 +debian/tmp/usr/share/gms/lib/*.py usr/share/gms/lib
36.5 +debian/tmp/usr/share/gms/plugins/*.py usr/share/gms/plugins
36.6 +debian/tmp/usr/share/gms/plugins/transcoders/*.py usr/share/gms/plugins/transcoders
36.7 +debian/tmp/usr/share/gms/plugins/transcoders/mencoder_lib/*.py usr/share/gms/plugins/transcoders/mencoder_lib
36.8 +debian/tmp/usr/share/gms/html/* usr/share/gms/html
36.9 +debian/tmp/usr/bin/* usr/bin
36.10 +debian/etc/init.d/gmsd etc/init.d
36.11 +debian/etc/gms/*.conf etc/gms/
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/gmyth-stream/server/debian/gms.postinst Wed Aug 29 14:42:10 2007 +0100
37.3 @@ -0,0 +1,29 @@
37.4 +#! /bin/sh
37.5 +# postinst script for gms
37.6 +
37.7 +set -e
37.8 +
37.9 +case "$1" in
37.10 + configure)
37.11 + if ! getent passwd gms >/dev/null; then
37.12 + adduser --disabled-password --quiet --system \
37.13 + --home /var/gms-media \
37.14 + --gecos "GMS media dir" --group gms
37.15 + fi
37.16 + if ! getent passwd gms | grep -q /var/run/gms; then
37.17 + usermod -d /var/gms-media gms
37.18 + fi
37.19 + update-rc.d gmsd defaults
37.20 + invoke-rc.d gmsd start
37.21 + ;;
37.22 + abort-upgrade|abort-remove|abort-deconfigure)
37.23 + ;;
37.24 + *)
37.25 + echo "postinst called with unknown argument \`$1'" >&2
37.26 + exit 1
37.27 + ;;
37.28 +esac
37.29 +
37.30 +#DEBHELPER#
37.31 +
37.32 +exit 0
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/gmyth-stream/server/debian/gms.postrm Wed Aug 29 14:42:10 2007 +0100
38.3 @@ -0,0 +1,13 @@
38.4 +#!/bin/sh
38.5 +
38.6 +set -e
38.7 +
38.8 +#DEBHELPER#
38.9 +
38.10 +if [ "$1" = "purge" ] ; then
38.11 + invoke-rc.d --force gms stop
38.12 + deluser --quiet --system gms > /dev/null || true
38.13 + delgroup --quiet --system gms > /dev/null || true
38.14 +fi
38.15 +
38.16 +exit 0
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/gmyth-stream/server/debian/rules Wed Aug 29 14:42:10 2007 +0100
39.3 @@ -0,0 +1,52 @@
39.4 +#!/usr/bin/make -f
39.5 +# -*- makefile -*-
39.6 +
39.7 +# Uncomment this to turn on verbose mode.
39.8 +#export DH_VERBOSE=1
39.9 +
39.10 +PYVER=2.5
39.11 +PYTHON=python$(PYVER)
39.12 +
39.13 +PREFIX=debian/tmp
39.14 +
39.15 +build: build-stamp
39.16 +
39.17 +build-stamp:
39.18 + touch build-stamp
39.19 +
39.20 +clean:
39.21 + dh_testdir
39.22 + dh_testroot
39.23 + rm -f build-stamp
39.24 + dh_clean
39.25 +
39.26 +install: build
39.27 + dh_testdir
39.28 + dh_testroot
39.29 + dh_installdirs
39.30 + dh_clean -k
39.31 +
39.32 + @rm -rf build
39.33 + @$(PYTHON) setup.py install --prefix=$(PREFIX)/usr --no-compile --install-purelib=$(PREFIX)/usr/share/gms
39.34 + install -D -o root -g root -m 755 $(PREFIX)/usr/etc/init.d/gmsd debian/$(cdbs_curpkg)/etc/init.d/gmsd
39.35 + install -D -o root -g root -m 755 $(PREFIX)/usr/etc/gms/server.conf debian/$(cdbs_curpkg)/etc/gms/server.conf
39.36 +
39.37 + dh_install
39.38 +
39.39 +# Build architecture-independent files here.
39.40 +binary-indep: build install
39.41 + dh_testdir
39.42 + dh_testroot
39.43 + dh_installchangelogs
39.44 + dh_installdocs
39.45 + dh_strip
39.46 + dh_compress
39.47 + dh_fixperms
39.48 + dh_installdeb
39.49 + dh_gencontrol
39.50 + dh_md5sums
39.51 + dh_builddeb
39.52 +
39.53 +binary: binary-indep
39.54 +.PHONY: clean binary-indep binary install
39.55 +
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/gmyth-stream/server/gms.py Wed Aug 29 14:42:10 2007 +0100
40.3 @@ -0,0 +1,74 @@
40.4 +#!/usr/bin/env python
40.5 +
40.6 +__author__ = "Artur Duque de Souza"
40.7 +__author_email__ = "artur.souza@indt.org.br"
40.8 +__license__ = "GPL"
40.9 +__version__ = "0.3"
40.10 +__thanks__ = "Gustavo Sverzut Barbieri"
40.11 +__GMS_DATA_DIR__ = "/usr/share/gms/"
40.12 +
40.13 +import sys
40.14 +import os
40.15 +import mimetypes
40.16 +import logging as log
40.17 +
40.18 +if os.path.exists (__GMS_DATA_DIR__):
40.19 + sys.path.append(__GMS_DATA_DIR__)
40.20 +
40.21 +from lib.server import serve_forever, load_plugins_transcoders
40.22 +from lib.utils import config
40.23 +
40.24 +mimetypes.init()
40.25 +log_level = log.INFO
40.26 +for p in sys.argv[1:]:
40.27 + if p == "-v" or p == "--verbose":
40.28 + log_level -= 10
40.29 +
40.30 +log.basicConfig(level=log_level,
40.31 + format=("### %(asctime)s %(name)-18s \t%(levelname)-8s "
40.32 + "\t%(message)s"),
40.33 + datefmt="%Y-%m-%d %H:%M:%S")
40.34 +
40.35 +if config.get_transcoded_location () is None:
40.36 + print "Gms not configured"
40.37 + exit (0)
40.38 +
40.39 +if not os.path.exists(config.get_transcoded_location()):
40.40 + os.mkdir(config.get_transcoded_location())
40.41 +
40.42 +
40.43 +if "-d" in sys.argv:
40.44 + #run with deamon
40.45 + try:
40.46 + pid = os.fork()
40.47 + if pid > 0:
40.48 + sys.exit(0)
40.49 + except OSError, e:
40.50 + print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror)
40.51 + sys.exit(1)
40.52 +
40.53 + os.chdir("/")
40.54 + os.setsid()
40.55 + os.umask(0)
40.56 +
40.57 + try:
40.58 + pid = os.fork()
40.59 + if pid > 0:
40.60 + fp = open ("/var/run/gms.pid", "w")
40.61 + fp.write ("%d" % pid)
40.62 + fp.close ()
40.63 + sys.exit(0)
40.64 + except OSError, e:
40.65 + print >>sys.stderr, "Fail to start deamon: %d (%s)" % (e.errno, e.strerror)
40.66 + sys.exit(1)
40.67 +
40.68 +# main deamon
40.69 +pd = os.path.join(__GMS_DATA_DIR__, "plugins", "transcoders")
40.70 +if os.path.exists (pd):
40.71 + load_plugins_transcoders(pd)
40.72 +
40.73 +pd = os.path.join("plugins", "transcoders");
40.74 +if os.path.exists (pd):
40.75 + load_plugins_transcoders(pd)
40.76 +
40.77 +serve_forever()
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/gmyth-stream/server/html/index.html Wed Aug 29 14:42:10 2007 +0100
41.3 @@ -0,0 +1,9 @@
41.4 +<html>
41.5 + <head><title>GMyth-Streamer Server</title></head>
41.6 + <body>
41.7 +<h1>Welcome to GMyth-Streamer Server</h1>
41.8 +<ul>
41.9 +%(menu)s
41.10 +</ul>
41.11 + </body>
41.12 +</html>
41.13 \ No newline at end of file
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/gmyth-stream/server/html/menu.html Wed Aug 29 14:42:10 2007 +0100
42.3 @@ -0,0 +1,1 @@
42.4 +<li><a href="%(url)s">%(name)s</a></li>
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/gmyth-stream/server/html/shutdown.html Wed Aug 29 14:42:10 2007 +0100
43.3 @@ -0,0 +1,6 @@
43.4 +<html>
43.5 + <head><title>GMyth-Streamer Server Exited</title></head>
43.6 + <body>
43.7 + <h1>GMyth-Streamer is not running anymore</h1>
43.8 + </body>
43.9 +</html>
43.10 \ No newline at end of file
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/gmyth-stream/server/html/status.html Wed Aug 29 14:42:10 2007 +0100
44.3 @@ -0,0 +1,14 @@
44.4 +<html>
44.5 + <head><title>GMyth-Streamer Server Status</title></head>
44.6 + <body>
44.7 + <h1>GMyth-Streamer Status</h1>
44.8 + <ul>
44.9 + %(running)s
44.10 + %(stopall)s
44.11 + %(stopone)s
44.12 + </ul>
44.13 + <ul>
44.14 + %(menu)s
44.15 + </ul>
44.16 + </body>
44.17 +</html>
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/gmyth-stream/server/html/stop_all.html Wed Aug 29 14:42:10 2007 +0100
45.3 @@ -0,0 +1,9 @@
45.4 +<html>
45.5 + <head><title>GMyth-Streamer Server Stopped Transcoders</title></head>
45.6 + <body>
45.7 + <h1>GMyth-Streamer stopped running transcoders</h1>
45.8 + <ul>
45.9 + %(menu)s
45.10 + </ul>
45.11 + </body>
45.12 +</html>
45.13 \ No newline at end of file
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/gmyth-stream/server/html/stop_selected.html Wed Aug 29 14:42:10 2007 +0100
46.3 @@ -0,0 +1,12 @@
46.4 +<html>
46.5 + <head><title>GMyth-Streamer Server Stopped Transcoders</title></head>
46.6 + <body>
46.7 + <h1>GMyth-Streamer stopped running transcoders:</h1>
46.8 + <ul>
46.9 + %(opts)s
46.10 + </ul>
46.11 + <ul>
46.12 + %(menu)s
46.13 + </ul>
46.14 + </body>
46.15 +</html>
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/gmyth-stream/server/lib/file_handler.py Wed Aug 29 14:42:10 2007 +0100
47.3 @@ -0,0 +1,86 @@
47.4 +#!/usr/bin/env python
47.5 +
47.6 +__author__ = "Artur Duque de Souza"
47.7 +__author_email__ = "artur.souza@indt.org.br"
47.8 +__license__ = "GPL"
47.9 +__version__ = "0.1"
47.10 +
47.11 +import os
47.12 +import sys
47.13 +import pickle
47.14 +import logging
47.15 +import lib.utils as utils
47.16 +
47.17 +from stat import *
47.18 +
47.19 +__all__ = ("FileList", "list_media_files")
47.20 +
47.21 +
47.22 +class TranscodedFile(object):
47.23 + """This class creates and reads information about transcoded files."""
47.24 + opts = {}
47.25 + log = logging.getLogger("gms.file_handler")
47.26 +
47.27 + def __init__(self, filename, args):
47.28 + if filename == "" or not os.path.exists(filename):
47.29 + self.opts = args.copy()
47.30 +
47.31 + if self.opts["type"][0] != "myth":
47.32 + self.opts["original_mtime"] = os.path.getmtime(
47.33 + self.opts["uri"][0])
47.34 +
47.35 + name = os.path.basename(self.opts["uri"][0])
47.36 + self.opts["original"] = [name]
47.37 + output_file = os.path.basename(self.opts["outfile"][0])
47.38 + dat_file = output_file + ".dat";
47.39 + dat_path = os.path.join (utils.config.get_transcoded_location(),
47.40 + dat_file);
47.41 +
47.42 + output = open(dat_path, "wb")
47.43 + # dumps data using the highest protocol
47.44 + pickle.dump(self.opts, output, -1)
47.45 + output.close()
47.46 + else:
47.47 + name = os.path.splitext(os.path.basename(filename))[0]
47.48 + dat_file = name + ".dat";
47.49 + dat_path = os.path.join (utils.config.get_transcoded_location(),
47.50 + dat_file);
47.51 + pkl_file = open(dat_path, "rb")
47.52 + self.opts = pickle.load(pkl_file)
47.53 + # __init__()
47.54 +
47.55 +# TranscodedFile
47.56 +
47.57 +
47.58 +class FileList(list):
47.59 + """Class to hold file's list - reimplements str and repr."""
47.60 + def __str__(self):
47.61 + ret = ""
47.62 + if len(self) > 0:
47.63 + for item in self:
47.64 + ret = ret + "%s" % item
47.65 + return ret
47.66 + # __str__()
47.67 +
47.68 + def __repr__(self):
47.69 + return self.__str__()
47.70 + # __repr__()
47.71 +
47.72 +# FileList
47.73 +
47.74 +def list_media_files(directory, file_list):
47.75 + """Show all the media files with extension defined in the var 'ext'
47.76 + that are in the directory, appending each one to 'file_list'."""
47.77 + ext = ['mpg', 'avi', 'mp4', 'nuv', 'mpeg', 'mov']
47.78 + for root, dirs, files in os.walk(directory):
47.79 + for name in files:
47.80 + if os.path.splitext(name)[1].strip(".") in ext:
47.81 + dat_file = os.path.join(sys.path[0],root,
47.82 + os.path.splitext(name)[0]+".dat")
47.83 +
47.84 + if name not in file_list and \
47.85 + os.path.exists(dat_file):
47.86 + file_list.append(name)
47.87 +
47.88 + return True
47.89 +# list_media_files()
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/gmyth-stream/server/lib/gmsconfig.py Wed Aug 29 14:42:10 2007 +0100
48.3 @@ -0,0 +1,38 @@
48.4 +#!/usr/bin/env
48.5 +
48.6 +__author__ = "Renato Araujo Oliveira Filho"
48.7 +__author_email__ = "renato.filho@indt.org.br"
48.8 +__license__ = "GPL"
48.9 +__version__ = "0.3"
48.10 +
48.11 +
48.12 +import os
48.13 +import ConfigParser
48.14 +
48.15 +__all__ = ("GmsConfig")
48.16 +
48.17 +class GmsConfig:
48.18 + config = ConfigParser.ConfigParser()
48.19 + __CONFIG_FILE__ = "server.conf"
48.20 + __CONFIG_DIRS__ = [os.path.join (os.path.expanduser("~"), ".gms"), \
48.21 + os.path.join ("/", "etc", "gms"), \
48.22 + "."]
48.23 +
48.24 + def __init__(self):
48.25 + for path in self.__CONFIG_DIRS__:
48.26 + file_name = os.path.join (path, self.__CONFIG_FILE__)
48.27 + if os.path.exists (file_name):
48.28 + fp = open (file_name, "r")
48.29 + self.config.readfp (fp)
48.30 + return
48.31 + # __init__()
48.32 +
48.33 + def get_transcoded_location (self):
48.34 + try:
48.35 + return os.path.realpath (self.config.get("PATHS", "transcoded"))
48.36 + except:
48.37 + return None
48.38 + # get_transcoded_location()
48.39 +
48.40 +
48.41 +# GmsConfig
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/gmyth-stream/server/lib/log.py Wed Aug 29 14:42:10 2007 +0100
49.3 @@ -0,0 +1,109 @@
49.4 +#!/usr/bin/env python
49.5 +
49.6 +__author__ = "Artur Duque de Souza"
49.7 +__author_email__ = "artur.souza@indt.org.br"
49.8 +__license__ = "GPL"
49.9 +__version__ = "0.1"
49.10 +
49.11 +import os
49.12 +import logging
49.13 +
49.14 +__all__ = ("Log", "log_structure")
49.15 +
49.16 +class log_structure(object):
49.17 + """Structure to hold log info."""
49.18 +
49.19 + def __init__(self, log=None):
49.20 + self.log = log
49.21 + self.history = []
49.22 + # __init__()
49.23 +
49.24 +# log_structure()
49.25 +
49.26 +class Log(object):
49.27 + """This class implements a log where we can store status of
49.28 + all transcoders (even from those that are not running any more)."""
49.29 +
49.30 + ## key = tid
49.31 + ## item = ls
49.32 + logs = {}
49.33 +
49.34 + def insert(self, tid, name):
49.35 + """Insert a given tid on the log structure"""
49.36 + if not self.logs.has_key(tid):
49.37 + self.logs[tid] = log_structure(logging.getLogger(name))
49.38 + return True
49.39 + else:
49.40 + return False
49.41 + # insert()
49.42 +
49.43 + def remove(self, tid=None):
49.44 + """Cleans up all log stored for a
49.45 + given tid or for all transcodes."""
49.46 + if not tid:
49.47 + self.logs = {}
49.48 + else:
49.49 + del(self.logs[tid])
49.50 +
49.51 + return True
49.52 + # clean()
49.53 +
49.54 + def get_status(self, tid=None, all=False):
49.55 + """Get the status of all transcoders or
49.56 + of just one of them if it's given an tid."""
49.57 + if not tid:
49.58 + ret = {}
49.59 + for tids, logs in self.logs.items():
49.60 + if len(logs.history) > 0:
49.61 + if not all:
49.62 + ret[tids] = logs.history[-1]
49.63 + else:
49.64 + ret[tids] = logs.history
49.65 + return ret
49.66 + elif self.logs.has_key(tid) and len(self.logs[tid].history) > 0:
49.67 + if not all:
49.68 + return self.logs[tid].history[-1]
49.69 + else:
49.70 + return self.logs[tid].history
49.71 +
49.72 + return False
49.73 + # get_status()
49.74 +
49.75 + def _update_status(self, tid=None, msg=""):
49.76 + """Update the status of a given tid. Private method that
49.77 + is only called inside error/info/debug wrappers"""
49.78 + if msg != "":
49.79 + self.logs[tid].history.append(msg)
49.80 + return True
49.81 + else:
49.82 + return False
49.83 + # update_status()
49.84 +
49.85 + def error(self, tid, msg):
49.86 + """Python's Log.error wrapper"""
49.87 + if self.logs.has_key(tid):
49.88 + self.logs[tid].log.error("%s" % msg)
49.89 + return self._update_status(tid, msg)
49.90 + else:
49.91 + return False
49.92 + # error()
49.93 +
49.94 + def info(self, tid, msg):
49.95 + """Python's Log.info wrapper"""
49.96 + if self.logs.has_key(tid):
49.97 + self.logs[tid].log.info("%s" % msg)
49.98 + self._update_status(tid, msg)
49.99 + return True
49.100 + else:
49.101 + return False
49.102 + # info()
49.103 +
49.104 + def debug(self, tid, msg):
49.105 + """Python's Log.debug wrapper"""
49.106 + if self.logs.has_key(tid):
49.107 + self.logs[tid].log.debug("%s" % msg)
49.108 + self._update_status(tid, msg)
49.109 + return True
49.110 + else:
49.111 + return False
49.112 + # debug()
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/gmyth-stream/server/lib/request_handler.py Wed Aug 29 14:42:10 2007 +0100
50.3 @@ -0,0 +1,470 @@
50.4 +#!/usr/bin/env python
50.5 +
50.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
50.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
50.8 +__license__ = "GPL"
50.9 +__version__ = "0.3"
50.10 +
50.11 +import os
50.12 +import cgi
50.13 +import socket
50.14 +import logging
50.15 +import urlparse
50.16 +import threading
50.17 +import SocketServer
50.18 +import BaseHTTPServer
50.19 +import mimetypes
50.20 +
50.21 +import lib.utils as utils
50.22 +import lib.file_handler as files
50.23 +import lib.transcoder as transcoder
50.24 +
50.25 +from log import Log
50.26 +
50.27 +__all__ = ("RequestHandler")
50.28 +
50.29 +class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
50.30 + """Class that implements an HTTP request handler for our server."""
50.31 + log = logging.getLogger("gms.request")
50.32 + def_transcoder = None
50.33 + transcoders = utils.PluginSet(transcoder.Transcoder)
50.34 + transcoders_log = Log()
50.35 + tid_queue = []
50.36 +
50.37 + menu = {
50.38 + "Log": "/get_log.do",
50.39 + "Stop": "/stop-transcoder.do",
50.40 + "Status": "/status.do",
50.41 + "All Log": "/get_all_log.do",
50.42 + "Version": "/version.do",
50.43 + "Shutdown": "/shutdown.do"
50.44 + }
50.45 +
50.46 + @classmethod
50.47 + def load_plugins_transcoders(cls, directory):
50.48 + cls.transcoders.load_from_directory(directory)
50.49 +
50.50 + if cls.def_transcoder is None and cls.transcoders:
50.51 + cls.def_transcoder = cls.transcoders[0].name
50.52 + # load_plugins_transcoders()
50.53 +
50.54 +
50.55 + def do_dispatch(self, body):
50.56 + self.url = self.path
50.57 + pieces = urlparse.urlparse(self.path)
50.58 + self.path = pieces[2]
50.59 + self.query = cgi.parse_qs(pieces[4])
50.60 +
50.61 + url = {
50.62 + "/": self.serve_main,
50.63 + "/shutdown.do": self.serve_shutdown,
50.64 + "/stop-transcoder.do": self.serve_stop_transcoder,
50.65 + "/status.do": self.serve_status,
50.66 + "/version.do": self.serve_version,
50.67 + "/new_id.do": self.serve_new_id,
50.68 + "/get_log.do": self.serve_get_log,
50.69 + "/get_all_log.do": self.serve_get_all_log,
50.70 + "/stream.do": self.serve_stream,
50.71 + "/transcode.do": self.serve_transcode,
50.72 + "/list.do": self.serve_list,
50.73 + "/get_file_info.do": self.serve_file_info,
50.74 + }
50.75 +
50.76 + try:
50.77 + url[self.path](body)
50.78 + except KeyError:
50.79 + try:
50.80 + action = self.query.get("action", None)
50.81 + if action and "stream.do" in action:
50.82 + self.serve_stream(body)
50.83 + elif os.path.exists("html/%s" % self.path):
50.84 + data = open("html/%s" % self.path)
50.85 + self.wfile.write(data.read())
50.86 + else:
50.87 + self.send_error(404, "File not found")
50.88 + except Exception, e:
50.89 + self.log.error(e)
50.90 +
50.91 + # do_dispatch()
50.92 +
50.93 +
50.94 + def do_GET(self):
50.95 + self.do_dispatch(True)
50.96 + # do_GET()
50.97 +
50.98 +
50.99 + def do_HEAD(self):
50.100 + self.do_dispatch(False)
50.101 + # do_HEAD()
50.102 +
50.103 +
50.104 + def _nav_items(self):
50.105 + ret = ""
50.106 + for name, url in self.menu.items():
50.107 + ret += utils.getHTML("menu", {"name": name, "url": url})
50.108 + return ret
50.109 + # _nav_items()
50.110 +
50.111 +
50.112 + def serve_main(self, body):
50.113 + self.send_response(200)
50.114 + self.send_header("Content-Type", "text/html")
50.115 + self.send_header('Connection', 'close')
50.116 + self.end_headers()
50.117 + if body:
50.118 + self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()}))
50.119 + # serve_main()
50.120 +
50.121 +
50.122 + def serve_version(self, body):
50.123 + self.send_response(200)
50.124 + self.send_header("Content-Type", "text/html")
50.125 + self.send_header('Connection', 'close')
50.126 + self.end_headers()
50.127 + if body:
50.128 + self.wfile.write("Version: %s" % __version__)
50.129 + # serve_version
50.130 +
50.131 +
50.132 + def serve_shutdown(self, body):
50.133 + self.send_response(200)
50.134 + self.send_header("Content-Type", "text/html")
50.135 + self.send_header('Connection', 'close')
50.136 + self.end_headers()
50.137 + if body:
50.138 + self.wfile.write(utils.getHTML("shutdown"))
50.139 + self.server.server_close()
50.140 + # serve_shutdown()
50.141 +
50.142 +
50.143 + def serve_list(self, body):
50.144 + self.send_response(200)
50.145 + self.send_header("Content-Type", "text/html")
50.146 + self.send_header('Connection', 'close')
50.147 + self.end_headers()
50.148 +
50.149 + if body:
50.150 + file_list = []
50.151 + files.list_media_files(utils.config.get_transcoded_location(), file_list)
50.152 + output = files.FileList(map(lambda x, y: x+y, file_list,
50.153 + ["<br>"]*len(file_list)))
50.154 + self.wfile.write(output)
50.155 +
50.156 + # serve_list()
50.157 +
50.158 +
50.159 + def serve_stop_all_transcoders(self, body):
50.160 + self.send_response(200)
50.161 + self.send_header("Content-Type", "text/html")
50.162 + self.send_header('Connection', 'close')
50.163 + self.end_headers()
50.164 + if body:
50.165 + self.server.stop_transcoders()
50.166 + self.wfile.write(utils.getHTML("stop_all",
50.167 + {"menu": self._nav_items()}))
50.168 + # serve_stop_all_transcoders()
50.169 +
50.170 +
50.171 + def serve_stop_selected_transcoders(self, body, tids=[]):
50.172 + self.send_response(200)
50.173 + self.send_header("Content-Type", "text/html")
50.174 + self.send_header('Connection', 'close')
50.175 + self.end_headers()
50.176 + opts = ""
50.177 + if body:
50.178 + transcoders = self.server.get_transcoders()
50.179 +
50.180 + for tid in tids:
50.181 + for t, r in transcoders:
50.182 + if t.tid == int(tid):
50.183 + try:
50.184 + t.stop()
50.185 + except Exception, e:
50.186 + self.log.info("Plugin already stopped")
50.187 +
50.188 + opts += utils._create_html_item("%s" % t)
50.189 +
50.190 + break
50.191 +
50.192 + self.wfile.write(utils.getHTML("stop_selected",
50.193 + {"menu": self._nav_items(),
50.194 + "opts": opts}))
50.195 + # serve_stop_selected_transcoders()
50.196 +
50.197 +
50.198 + def serve_stop_transcoder(self, body):
50.199 + req = self.query.get("request", None)
50.200 + tid = self.query.get("tid", None)
50.201 + if req and "all" in req:
50.202 + self.serve_stop_all_transcoders(body)
50.203 + elif tid:
50.204 + self.serve_stop_selected_transcoders(body, tid[0].split(";"))
50.205 + else:
50.206 + self.serve_status(body)
50.207 + # serve_stop_transcoder()
50.208 +
50.209 +
50.210 + def serve_status(self, body):
50.211 + self.send_response(200)
50.212 + self.send_header("Content-Type", "text/html")
50.213 + self.send_header('Connection', 'close')
50.214 + self.end_headers()
50.215 + stopone = ""
50.216 + running = ""
50.217 + stopall = ""
50.218 +
50.219 + if body:
50.220 + tl = self.server.get_transcoders()
50.221 + if not tl and not self.query.get("tid", None) and \
50.222 + not self.query.get("running", None):
50.223 + running = "<p>No running transcoder.</p>\n"
50.224 +
50.225 + elif not tl and self.query.get("tid", None):
50.226 + tids = self.query.get("tid")
50.227 + for tid in tids:
50.228 + stat = self.transcoders_log.get_status(int(tid))
50.229 + self.wfile.write("%s<br>" % stat)
50.230 + return True
50.231 +
50.232 + elif self.query.get("running", None):
50.233 + for transcoder, request in tl:
50.234 + outf = transcoder.params_first("outfile")
50.235 + tid = transcoder.tid
50.236 + self.wfile.write("%s:%s<br>" % (tid, outf))
50.237 + return True
50.238 +
50.239 + elif self.query.get("tid", None):
50.240 + req_tid = self.query.get("tid")
50.241 + for transcoder, request in tl:
50.242 + if str(transcoder.tid) in req_tid:
50.243 + self.wfile.write("Status:%s:%s %%" % (\
50.244 + transcoder.tid, transcoder.status))
50.245 + return True
50.246 + stat = self.transcoders_log.get_status(int(req_tid[0]))
50.247 + self.wfile.write("%s<br>" % stat)
50.248 + return True
50.249 +
50.250 + else:
50.251 + running = "<p>Running transcoders:</p>\n"
50.252 + stopall = utils._create_html_item("<a href='%s?request=all'>"
50.253 + "[STOP ALL]</a>" %
50.254 + self.menu["Stop"])
50.255 +
50.256 + for transcoder, request in tl:
50.257 + stopone += utils._create_html_item("%s;"
50.258 + "<a href='%s?tid=%s'>"
50.259 + " [STOP] </a>") % (
50.260 + transcoder, self.menu["Stop"], transcoder.tid)
50.261 +
50.262 + self.wfile.write(utils.getHTML("status",
50.263 + {"menu": self._nav_items(),
50.264 + "running": running,
50.265 + "stopall": stopall,
50.266 + "stopone": stopone}))
50.267 + # serve_status()
50.268 +
50.269 +
50.270 + def _get_transcoder(self):
50.271 + # get transcoder option: mencoder is the default
50.272 + request_transcoders = self.query.get("transcoder", ["mencoder"])
50.273 +
50.274 + for t in request_transcoders:
50.275 + transcoder = self.transcoders.get(t)
50.276 + if transcoder:
50.277 + return transcoder
50.278 +
50.279 + if not transcoder:
50.280 + return self.transcoders[self.def_transcoder]
50.281 + # _get_transcoder()
50.282 +
50.283 +
50.284 + def _get_new_id(self, tid):
50.285 + self.server.last_tid = utils.create_tid(tid)
50.286 + self.tid_queue.append(self.server.last_tid)
50.287 + return self.server.last_tid
50.288 + # _get_new_id()
50.289 +
50.290 +
50.291 + def serve_new_id(self, body):
50.292 + self.send_response(200)
50.293 + self.send_header("Content-Type", "text/html")
50.294 + self.send_header('Connection', 'close')
50.295 + self.end_headers()
50.296 +
50.297 + if body:
50.298 + self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
50.299 + # serve_new_id()
50.300 +
50.301 + def serve_get_log(self, body):
50.302 + self.send_response(200)
50.303 + self.send_header("Content-Type", "text/html")
50.304 + self.send_header('Connection', 'close')
50.305 + self.end_headers()
50.306 +
50.307 + if body:
50.308 + if self.query.get("tid", None):
50.309 + tid = int(self.query.get("tid")[0])
50.310 + stat = self.transcoders_log.get_status(tid)
50.311 + self.wfile.write("Status: %s" % stat)
50.312 + else:
50.313 + stat = self.transcoders_log.get_status()
50.314 + for rtid, status in stat.iteritems():
50.315 + self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
50.316 + # serve_get_log()
50.317 +
50.318 + def serve_get_all_log(self, body):
50.319 + self.send_response(200)
50.320 + self.send_header("Content-Type", "text/html")
50.321 + self.send_header('Connection', 'close')
50.322 + self.end_headers()
50.323 +
50.324 + if body:
50.325 + if self.query.get("tid", None):
50.326 + tid = int(self.query.get("tid")[0])
50.327 + stat = self.transcoders_log.get_status(tid, True)
50.328 + for status in stat:
50.329 + self.wfile.write("%s<br><br>" % status)
50.330 + else:
50.331 + stat = self.transcoders_log.get_status(None, True)
50.332 + for rtid, history in stat.iteritems():
50.333 + for status in history:
50.334 + self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
50.335 + self.wfile.write("<br><br>")
50.336 + # serve_get_all_log()
50.337 +
50.338 +
50.339 + def serve_file_info(self, body):
50.340 + if body:
50.341 +
50.342 + file_dat = self.query.get("file", None)
50.343 +
50.344 + if file_dat:
50.345 + self.send_response(200)
50.346 + self.send_header("Content-Type", "text/html")
50.347 + self.send_header('Connection', 'close')
50.348 + self.end_headers()
50.349 +
50.350 + try:
50.351 + opts = files.TranscodedFile(file_dat[0], self.query).opts
50.352 + for key in opts.keys():
50.353 + self.wfile.write("%s=%s<br>" % (key, opts.get(key, "None")[0]))
50.354 +
50.355 + except Exception, e:
50.356 + self.send_error(500, str(e))
50.357 + return
50.358 + # serve_file_info()
50.359 +
50.360 + def serve_stream(self, body):
50.361 + args = self.query.get("file", None)
50.362 + if not args:
50.363 + self.send_error(404, "File not found")
50.364 + return
50.365 +
50.366 + filename = args[0];
50.367 + if not filename:
50.368 + self.send_error(404, "File not found")
50.369 + return
50.370 +
50.371 + #Only stream files on .transcode dir
50.372 + filename = os.path.join (utils.config.get_transcoded_location(),
50.373 + os.path.basename(filename))
50.374 + self.log.error("Stream file: %s" % filename)
50.375 + if not os.path.exists (filename):
50.376 + self.send_error(404, "File not found")
50.377 + return
50.378 +
50.379 + size = int(os.path.getsize(filename))
50.380 + self.send_response(200)
50.381 + self.send_header("Content-Type", mimetypes.guess_type(filename)[0])
50.382 + self.send_header("Cache-Control","no-cache")
50.383 + self.send_header("Content-Length", size)
50.384 + self.end_headers()
50.385 +
50.386 + media = open(filename)
50.387 + data_in = " "
50.388 + total_read = 0
50.389 +
50.390 + test_tid = int(self.query.get("tid", "0")[0])
50.391 + if test_tid == 0 or test_tid not in self.tid_queue:
50.392 + test_tid = self._get_new_id(self.server.last_tid)
50.393 +
50.394 + self.transcoders_log.insert(test_tid, "gms.Stream: %s" % filename)
50.395 +
50.396 + try:
50.397 + file_data = ""
50.398 + while data_in != "":
50.399 + data_in = media.read(4096)
50.400 + file_data += data_in
50.401 +
50.402 + #total_read += 4096
50.403 + self.wfile.write(file_data)
50.404 + #status = utils.progress_bar(total_read, size, 50)
50.405 + #msg_status = "Status:%s:%s%%" % (test_tid, status)
50.406 + #self.transcoders_log._update_status(test_tid, msg_status)
50.407 +
50.408 + self.transcoders_log._update_status(test_tid, "OK: Done")
50.409 +
50.410 + except Exception, e:
50.411 + self.log.error("Stream error: %s" %e)
50.412 + self.transcoders_log._update_status(test_tid, "Error: %s" % e)
50.413 + # serve_stream()
50.414 +
50.415 + def serve_transcode(self, body):
50.416 + type = self.query.get("type", None)[0]
50.417 + if type.upper() == "FILE":
50.418 + self.send_error(404, "Transcode local files not allowed")
50.419 + return
50.420 +
50.421 + transcoder = self._get_transcoder()
50.422 + try:
50.423 + obj = transcoder(self.query)
50.424 + except Exception, e:
50.425 + self.send_error(500, str(e))
50.426 + return
50.427 +
50.428 + self.send_response(200)
50.429 + self.send_header("Content-Type", obj.get_mimetype())
50.430 + self.send_header("Cache-Control","no-cache")
50.431 +
50.432 + if (obj.name == "gmencoder"):
50.433 + self.send_header("Transfer-Encoding", "chunked")
50.434 +
50.435 + self.end_headers()
50.436 +
50.437 + if body:
50.438 + test_tid = int(self.query.get("tid", "0")[0])
50.439 + if test_tid == 0 or test_tid not in self.tid_queue:
50.440 + test_tid = self._get_new_id(self.server.last_tid)
50.441 +
50.442 + if self.query.get("transcoder", None):
50.443 + self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
50.444 + obj.tid = test_tid
50.445 + obj.log = self.transcoders_log
50.446 +
50.447 + self.server.add_transcoders(self, obj)
50.448 + if obj.start(self.wfile):
50.449 + self.transcoders_log.info (test_tid, "OK")
50.450 + else:
50.451 + self.transcoders_log.info (test_tid, "Fail")
50.452 +
50.453 + self.server.del_transcoders(self, obj)
50.454 + files.TranscodedFile("", self.query)
50.455 +
50.456 + # serve_stream()
50.457 +
50.458 +
50.459 + def log_request(self, code='-', size='-'):
50.460 + self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
50.461 + # log_request()
50.462 +
50.463 +
50.464 + def log_error(self, format, *args):
50.465 + self.log.error("%s: %s" % (self.address_string(), format % args))
50.466 + # log_error()
50.467 +
50.468 +
50.469 + def log_message(self, format, *args):
50.470 + self.log.info("%s: %s" % (self.address_string(), format % args))
50.471 + # log_message()
50.472 +
50.473 +# RequestHandler
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/gmyth-stream/server/lib/server.py Wed Aug 29 14:42:10 2007 +0100
51.3 @@ -0,0 +1,117 @@
51.4 +#!/usr/bin/env python
51.5 +
51.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
51.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
51.8 +__license__ = "GPL"
51.9 +__version__ = "0.4"
51.10 +
51.11 +import os
51.12 +import threading
51.13 +import SocketServer
51.14 +import BaseHTTPServer
51.15 +import socket
51.16 +import urlparse
51.17 +import cgi
51.18 +import lib.utils as utils
51.19 +import logging
51.20 +
51.21 +from log import Log
51.22 +from request_handler import RequestHandler
51.23 +
51.24 +__all__ = ("Server", "serve_forever", "load_plugins_transcoders")
51.25 +
51.26 +class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
51.27 + log = logging.getLogger("gms.server")
51.28 + last_tid = 0
51.29 + run = True
51.30 + _transcoders = {}
51.31 + _lock = threading.RLock()
51.32 +
51.33 + def serve_forever(self):
51.34 + self.log.info("GMyth-Streamer serving HTTP on %s:%s" %
51.35 + self.socket.getsockname())
51.36 + try:
51.37 + while self.run:
51.38 + self.handle_request()
51.39 + except KeyboardInterrupt, e:
51.40 + pass
51.41 +
51.42 + self.log.debug("Stopping all remaining transcoders...")
51.43 + self.stop_transcoders()
51.44 + self.log.debug("Transcoders stopped!")
51.45 + # serve_forever()
51.46 +
51.47 +
51.48 + def get_request(self):
51.49 + skt = self.socket
51.50 + old = skt.gettimeout()
51.51 + skt.settimeout(0.5)
51.52 + while self.run:
51.53 + try:
51.54 + r = skt.accept()
51.55 + skt.settimeout(old)
51.56 + return r
51.57 + except socket.timeout, e:
51.58 + pass
51.59 + raise socket.error("Not running")
51.60 + # get_request()
51.61 +
51.62 +
51.63 + def server_close(self):
51.64 + self.run = False
51.65 + self.stop_transcoders()
51.66 +
51.67 + BaseHTTPServer.HTTPServer.server_close(self)
51.68 + # server_close()
51.69 +
51.70 +
51.71 + def stop_transcoders(self):
51.72 + self._lock.acquire()
51.73 + for transcoder, request in self._transcoders.iteritems():
51.74 + self.log.info("Stop transcoder: %s, client=%s" %
51.75 + (transcoder, request.client_address))
51.76 + transcoder.stop()
51.77 + self._lock.release()
51.78 + # stop_transcoders()
51.79 +
51.80 +
51.81 + def get_transcoders(self):
51.82 + self._lock.acquire()
51.83 + try:
51.84 + return self._transcoders.items()
51.85 + finally:
51.86 + self._lock.release()
51.87 + # get_transcoders()
51.88 +
51.89 +
51.90 + def add_transcoders(self, request, transcoder):
51.91 + self._lock.acquire()
51.92 + try:
51.93 + self._transcoders[transcoder] = request
51.94 + finally:
51.95 + self._lock.release()
51.96 + # add_transcoders()
51.97 +
51.98 +
51.99 + def del_transcoders(self, request, transcoder):
51.100 + self._lock.acquire()
51.101 + try:
51.102 + del self._transcoders[transcoder]
51.103 + finally:
51.104 + self._lock.release()
51.105 + # del_transcoders()
51.106 +# Server
51.107 +
51.108 +
51.109 +
51.110 +def serve_forever(host="0.0.0.0", port=40000):
51.111 + addr = (host, port)
51.112 + RequestHandler.protocol_version = "HTTP/1.0"
51.113 + httpd = Server(addr, RequestHandler)
51.114 + httpd.serve_forever()
51.115 +# serve_forever()
51.116 +
51.117 +
51.118 +def load_plugins_transcoders(directory):
51.119 + RequestHandler.load_plugins_transcoders(directory)
51.120 +# load_plugins_transcoders()
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/gmyth-stream/server/lib/transcoder.py Wed Aug 29 14:42:10 2007 +0100
52.3 @@ -0,0 +1,58 @@
52.4 +#!/usr/bin/env python
52.5 +
52.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
52.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
52.8 +__license__ = "GPL"
52.9 +__version__ = "0.4"
52.10 +
52.11 +__all__ = ("Transcoder")
52.12 +
52.13 +class Transcoder(object):
52.14 + """Transcoder's Class: parent class to implement
52.15 + a plugin for transcoding data."""
52.16 + priority = 0 # negative values have higher priorities
52.17 + name = None # to be used in requests
52.18 + status = None
52.19 + log = None
52.20 + tid = -1
52.21 +
52.22 + def __init__(self, params):
52.23 + self.params = params
52.24 + # __init__()
52.25 +
52.26 + def params_first(self, key, default=None):
52.27 + if default is None:
52.28 + return self.params[key][0]
52.29 + else:
52.30 + try:
52.31 + return self.params[key][0]
52.32 + except:
52.33 + return default
52.34 + # params_first()
52.35 +
52.36 + def get_mimetype(self):
52.37 + return "application/octet-stream"
52.38 + # get_mimetype()
52.39 +
52.40 + def start(self, outfile):
52.41 + pass
52.42 + # start()
52.43 +
52.44 + def stop(self):
52.45 + pass
52.46 + # stop()
52.47 +
52.48 + def get_legth (self):
52.49 + pass
52.50 + # get_leght ()
52.51 +
52.52 + def get_progress (self):
52.53 + pass
52.54 + # get_progress ()
52.55 +
52.56 + def __str__(self):
52.57 + return '%s: %s( params=%s ) - Status: %s%%' % \
52.58 + (self.__class__.__name__, self.tid,
52.59 + self.params, self.status)
52.60 + # __str__()
52.61 +# Transcoder
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/gmyth-stream/server/lib/utils.py Wed Aug 29 14:42:10 2007 +0100
53.3 @@ -0,0 +1,193 @@
53.4 +#!/usr/bin/env
53.5 +
53.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
53.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
53.8 +__license__ = "GPL"
53.9 +__version__ = "0.3"
53.10 +
53.11 +import os
53.12 +import stat
53.13 +import sys
53.14 +import logging
53.15 +import urllib
53.16 +import gobject
53.17 +import imp
53.18 +
53.19 +import gmsconfig
53.20 +
53.21 +log = logging.getLogger("gms.utils")
53.22 +config = gmsconfig.GmsConfig()
53.23 +
53.24 +__all__ = ("which", "load_plugins", "PluginSet", "getHTML",
53.25 + "progress_bar", "create_tid", "list_media_files")
53.26 +
53.27 +def which(app):
53.28 + """Function to implement which(1) unix command"""
53.29 + pl = os.environ["PATH"].split(os.pathsep)
53.30 + for p in pl:
53.31 + path = os.path.join(p, app)
53.32 + if os.path.isfile(path):
53.33 + st = os.stat(path)
53.34 + if st[stat.ST_MODE] & 0111:
53.35 + return path
53.36 + return ""
53.37 +# which()
53.38 +
53.39 +
53.40 +def _load_module(pathlist, name):
53.41 + fp, path, desc = imp.find_module(name, pathlist)
53.42 + try:
53.43 + module = imp.load_module(name, fp, path, desc)
53.44 + return module
53.45 + finally:
53.46 + if fp:
53.47 + fp.close()
53.48 +# _load_module()
53.49 +
53.50 +
53.51 +class PluginSet(object):
53.52 + def __init__(self, basetype, *items):
53.53 + self.basetype = basetype
53.54 + self.map = {}
53.55 + self.list = []
53.56 +
53.57 + for i in items:
53.58 + self._add(i)
53.59 + self._sort()
53.60 + # __init__()
53.61 +
53.62 +
53.63 + def _add(self, item):
53.64 + self.map[item.name] = item
53.65 + self.list.append(item)
53.66 + # _add()
53.67 +
53.68 +
53.69 + def add(self, item):
53.70 + self._add()
53.71 + self._sort()
53.72 + # add()
53.73 +
53.74 +
53.75 + def __getitem__(self, spec):
53.76 + if isinstance(spec, basestring):
53.77 + return self.map[spec]
53.78 + else:
53.79 + return self.list[spec]
53.80 + # __getitem__()
53.81 +
53.82 +
53.83 + def get(self, name, default=None):
53.84 + return self.map.get(name, default)
53.85 + # get()
53.86 +
53.87 +
53.88 + def __iter__(self):
53.89 + return self.list.__iter__()
53.90 + # __iter__()
53.91 +
53.92 +
53.93 + def __len__(self):
53.94 + return len(self.list)
53.95 + # __len__()
53.96 +
53.97 +
53.98 + def _sort(self):
53.99 + self.list.sort(lambda a, b: cmp(a.priority, b.priority))
53.100 + # _sort()
53.101 +
53.102 +
53.103 + def update(self, pluginset):
53.104 + self.map.update(pluginset.map)
53.105 + self.list.extend(pluginset.list)
53.106 + self._sort()
53.107 + # update()
53.108 +
53.109 +
53.110 + def load_from_directory(self, directory):
53.111 + for i in load_plugins(directory, self.basetype):
53.112 + self._add(i)
53.113 + self._sort()
53.114 + # load_from_directory()
53.115 +
53.116 +
53.117 + def __str__(self):
53.118 + lst = []
53.119 + for o in self.list:
53.120 + lst.append('"%s" (%s)' % (o.name, o.__name__))
53.121 +
53.122 + return "%s(basetype=%s, items=[%s])" % \
53.123 + (self.__class__.__name__,
53.124 + self.basetype.__name__,
53.125 + ", ".join(lst))
53.126 + # __str__()
53.127 +# PluginSet
53.128 +
53.129 +
53.130 +def load_plugins(directory, basetype):
53.131 + """Function to load plugins from a given directory"""
53.132 + tn = basetype.__name__
53.133 + log.debug("Loading plugins from %s, type=%s" % (directory, tn))
53.134 +
53.135 +
53.136 + plugins = []
53.137 + for d in os.listdir(directory):
53.138 + if not d.endswith(".py"):
53.139 + continue
53.140 +
53.141 + name = d[0: -3]
53.142 + if name == "__init__":
53.143 + continue
53.144 +
53.145 + directory.replace(os.path.sep, ".")
53.146 + mod = _load_module([directory], name)
53.147 + for sym in dir(mod):
53.148 + cls = getattr(mod, sym)
53.149 + if isinstance(cls, type) and issubclass(cls, basetype) and \
53.150 + cls != basetype:
53.151 + plugins.append(cls)
53.152 + log.info("Loaded %s (%s) from %s" % \
53.153 + (cls.__name__, tn, os.path.join(directory, d)))
53.154 +
53.155 + return plugins
53.156 +# load_plugins()
53.157 +
53.158 +def getHTML(html_file, params={}):
53.159 + """This function parses an html file with the given
53.160 + parameters and returns a formated web-page"""
53.161 + try:
53.162 + filename = os.path.join(sys.path[0], "html", html_file + ".html")
53.163 + html = open(filename).read() % params
53.164 + return html
53.165 + except Exception, e:
53.166 + return "HTML format error. Wrong keys: %s" % e
53.167 +
53.168 +# getHTML
53.169 +
53.170 +def _create_html_item(opt):
53.171 + """Create an <li> item using HTML."""
53.172 + return "<li>%s</li>\n" % opt
53.173 +# _create_html_item
53.174 +
53.175 +def progress_bar(value, max, barsize):
53.176 + """Creates and displays a progressbar. By OSantana"""
53.177 + chars = int(value * barsize / float(max))
53.178 + percent = int((value / float(max)) * 100)
53.179 + sys.stdout.write("#" * chars)
53.180 + sys.stdout.write(" " * (barsize - chars + 2))
53.181 + if value >= max:
53.182 + sys.stdout.write("done.\n\n")
53.183 + else:
53.184 + sys.stdout.write("[%3i%%]\r" % (percent))
53.185 + sys.stdout.flush()
53.186 + return percent
53.187 +# progress_bar() by osantana
53.188 +
53.189 +def create_tid(last_tid):
53.190 + """Function to generate TIDs (ids for transcoders).
53.191 + At first it just do +1 on last_tid but can be implemented
53.192 + to generate more sparse TIDs"""
53.193 + tid = last_tid + 1
53.194 + return tid
53.195 +# create_id()
53.196 +
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/gmyth-stream/server/plugins/transcoders/gmencoder.py Wed Aug 29 14:42:10 2007 +0100
54.3 @@ -0,0 +1,134 @@
54.4 +#!/usr/bin/env python
54.5 +
54.6 +__author__ = "Renato Filho"
54.7 +__author_email__ = "renato.filho@indt.org.br"
54.8 +__license__ = "GPL"
54.9 +__version__ = "0.2"
54.10 +
54.11 +import os
54.12 +import sys
54.13 +import shlex
54.14 +import signal
54.15 +import subprocess
54.16 +import time
54.17 +
54.18 +import select
54.19 +import fcntl
54.20 +
54.21 +import lib.utils as utils
54.22 +import lib.server as server
54.23 +import lib.transcoder as transcoder
54.24 +
54.25 +__all__ = ("TranscoderGMencoder",)
54.26 +
54.27 +class TranscoderGMencoder(transcoder.Transcoder):
54.28 + gmencoder_path = utils.which("gmencoder")
54.29 + name = "gmencoder"
54.30 + priority = -1
54.31 + proc = None
54.32 +
54.33 + def __init__(self, params):
54.34 + self.status = 0
54.35 + transcoder.Transcoder.__init__(self, params)
54.36 + self.opts = []
54.37 + self.opts.append (self.gmencoder_path)
54.38 + self.opts.append ("-d")
54.39 + self._parser_params ()
54.40 +
54.41 + # __init__()
54.42 +
54.43 + def _insert_param (self, name, value):
54.44 + if (value != ""):
54.45 + self.opts.append(name)
54.46 + self.opts.append(value)
54.47 +
54.48 + def _parser_params (self):
54.49 + self._insert_param("-i", \
54.50 + "%s://%s" % (self.params_first("type", "file"),
54.51 + self.params_first("uri", "")))
54.52 + self._insert_param("--video-encode", self.params_first("ve", "ffenc_mpeg1video"))
54.53 + self._insert_param("--video-opts", "bitrate=300000,pass=512,quantizer=0.01,quant-type=1")
54.54 + #self._insert_param("--video-fps", self.params_first("fps", ""))
54.55 + self._insert_param("--video-fps", self.params_first("fps", "10"))
54.56 + self._insert_param("--video-width", self.params_first("width", "320"))
54.57 + self._insert_param("--video-height", self.params_first("height", "240"))
54.58 + self._insert_param("--audio-rate", "32000")
54.59 + self._insert_param("--audio-encode", self.params_first("ae", ""))
54.60 + # _parse_params
54.61 +
54.62 + def start(self, outfd):
54.63 + outfile = self.params_first("outfile", "")
54.64 +
54.65 + if outfile != "":
54.66 + path = os.path.join(utils.config.get_transcoded_location(), outfile)
54.67 + self._insert_param("-o", "file://%s" % path)
54.68 + else:
54.69 + self._insert_param ("-o", "fd://%d" % outfd.fileno())
54.70 + self.opts.append ("-c")
54.71 +
54.72 + cmd = " ".join(self.opts)
54.73 + self.log.info(self.tid, "GMencoder: %s" % cmd)
54.74 +
54.75 + try:
54.76 + self.proc = subprocess.Popen(self.opts, stdin=subprocess.PIPE,
54.77 + stdout=subprocess.PIPE)
54.78 +
54.79 + if outfile:
54.80 + outfd.write("OK ")
54.81 +
54.82 + except Exception, e:
54.83 + self.log.error(self.tid, "Error: executing GMencoder: %s" % e)
54.84 + outfd.write("Error: GMencoder: %s" % e)
54.85 + return False
54.86 +
54.87 + try:
54.88 + if not outfile:
54.89 + p = select.poll()
54.90 + p.register (outfd, select.POLLNVAL | select.POLLERR | select.POLLHUP | select.POLLIN )
54.91 +
54.92 + while (self.proc and self.proc.poll() == None):
54.93 + r, w, x = select.select([self.proc.stdout], [], [], 1)
54.94 + if self.proc.stdout in r:
54.95 + progress = self.proc.stdout.readline()
54.96 + if (progress.find ("PROGRESS") >= 0):
54.97 + self.status = progress.split (":")[1]
54.98 + elif (progress.find ("Erro") >= 0):
54.99 + return False
54.100 +
54.101 + if not outfile:
54.102 + ret = p.poll(0)
54.103 + if ret:
54.104 + self.log.info(self.tid, "Lost connection")
54.105 + self.stop ()
54.106 + return False
54.107 +
54.108 + except Exception, e:
54.109 + self.log.error(self.tid, "Problems handling data: %s" % e)
54.110 + return False
54.111 +
54.112 + self.status = 100;
54.113 +
54.114 +
54.115 + return True
54.116 + # start()
54.117 +
54.118 +
54.119 + def stop(self):
54.120 + if self.proc:
54.121 + self.log.info(self.tid, "Stopped GMencoder plugin")
54.122 + try:
54.123 + os.kill(self.proc.pid, signal.SIGKILL)
54.124 + self.proc.wait()
54.125 + except Exception, e:
54.126 + pass
54.127 +
54.128 + self.proc = None
54.129 + # stop()
54.130 +
54.131 + def get_progress(self):
54.132 + return self.status
54.133 +
54.134 + def get_lenght(self):
54.135 + return -1
54.136 +
54.137 +# TranscoderGMencoder
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/gmyth-stream/server/plugins/transcoders/mencoder.py Wed Aug 29 14:42:10 2007 +0100
55.3 @@ -0,0 +1,334 @@
55.4 +#!/usr/bin/env python
55.5 +
55.6 +__author__ = "Artur Duque de Souza"
55.7 +__author_email__ = "artur.souza@indt.org.br"
55.8 +__license__ = "GPL"
55.9 +__version__ = "0.3"
55.10 +
55.11 +import os
55.12 +import time
55.13 +import fcntl
55.14 +import shlex
55.15 +import socket
55.16 +import struct
55.17 +import signal
55.18 +import subprocess
55.19 +
55.20 +import lib.utils as utils
55.21 +import lib.server as server
55.22 +import plugins.transcoders.mencoder_lib.mythtv as mythtv
55.23 +
55.24 +from select import select
55.25 +import lib.transcoder as transcoder
55.26 +
55.27 +__all__ = ("TranscoderMencoder",)
55.28 +
55.29 +class TranscoderMencoder(transcoder.Transcoder):
55.30 + """Transcoder class that implements a transcoder using Mencoder"""
55.31 + mencoder_path = utils.which("mencoder")
55.32 + name = "mencoder"
55.33 + priority = -1
55.34 + args = {}
55.35 + proc = None
55.36 + gmyth = None
55.37 +
55.38 + # only works with avi container
55.39 + status = 0
55.40 +
55.41 + def _setup_params(self):
55.42 + params_first = self.params_first
55.43 +
55.44 + # general_opts
55.45 + self.args["local"] = params_first("local", False)
55.46 + self.args["language"] = params_first("language", False)
55.47 + self.args["subtitle"] = params_first("subtitle", False)
55.48 + self.args["format"] = params_first("format", "mpeg1")
55.49 + self.args["outfile"] = params_first("outfile", "-")
55.50 +
55.51 + # input_opt
55.52 + self.args["type"] = params_first("type", "file")
55.53 + self.args["input"] = params_first("uri", "-")
55.54 +
55.55 + # audio_opts
55.56 + self.args["acodec"] = params_first("acodec", "mp2")
55.57 + self.args["abitrate"] = params_first("abitrate", 192)
55.58 + self.args["volume"] = params_first("volume", 5)
55.59 +
55.60 + # video_opts
55.61 + self.args["mux"] = params_first("mux", "mpeg")
55.62 + self.args["fps"] = params_first("fps", 25)
55.63 + self.args["vcodec"] = params_first("vcodec", "mpeg1video")
55.64 + self.args["vbitrate"] = params_first("vbitrate", 400)
55.65 + self.args["width"] = params_first("width", 320)
55.66 + self.args["height"] = params_first("height", 240)
55.67 + # _setup_params()
55.68 +
55.69 +
55.70 + def _setup_audio(self):
55.71 + if self.args["acodec"] == "mp3lame":
55.72 + audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
55.73 + self.args["abitrate"], self.args["volume"])
55.74 + else:
55.75 + audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
55.76 + self.args["acodec"], self.args["abitrate"])
55.77 +
55.78 + return audio
55.79 + # _setup_audio()
55.80 +
55.81 +
55.82 + def _setup_video(self):
55.83 + video = " -of %s" % self.args["mux"]
55.84 + video += " -ofps %s" % self.args["fps"]
55.85 +
55.86 + vcodec = self.args["vcodec"]
55.87 + if vcodec == "nuv" or vcodec == "xvid"\
55.88 + or vcodec == "qtvideo" or vcodec == "copy":
55.89 + video += " -ovc %s" % vcodec
55.90 + else:
55.91 + video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
55.92 + vcodec, self.args["vbitrate"])
55.93 +
55.94 + if self.args["mux"] == "mpeg":
55.95 + video += " -mpegopts format=%s" % self.args["format"]
55.96 +
55.97 + video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
55.98 + return video
55.99 + # _setup_video()
55.100 +
55.101 +
55.102 + def _arg_append(self, args, options):
55.103 + for arg in shlex.split(options):
55.104 + args.append(arg)
55.105 + # arg_append()
55.106 +
55.107 + def _setup_mencoder_opts(self, args):
55.108 + args.append(self.mencoder_path)
55.109 +
55.110 + if self.args["type"] and self.args["type"] == "tv":
55.111 + self._arg_append(args, self.args["tv"])
55.112 + elif self.args["outfile"] == "-" and self.args["type"]:
55.113 + args.append(self.args["input"])
55.114 + else:
55.115 + args.append("-")
55.116 +
55.117 + if self.args["language"]:
55.118 + self._arg_append(args, "-alang %s" % self.args["language"])
55.119 +
55.120 + if self.args["subtitle"]:
55.121 + self._arg_append(args, "-slang %s" % self.args["subtitle"])
55.122 + self._arg_append(args, "-subfps %s" % self.args["fps"])
55.123 +
55.124 + self._arg_append(args, "-idx")
55.125 + self._arg_append(args, "-cache 1024")
55.126 + self._arg_append(args, self._setup_audio())
55.127 + self._arg_append(args, self._setup_video())
55.128 +
55.129 + self._arg_append(args, "-really-quiet")
55.130 +
55.131 + if self.args["outfile"] != "-":
55.132 + self.args["outfile"] = ".transcoded/%s" % (
55.133 + os.path.basename(self.args["outfile"]))
55.134 +
55.135 + self._arg_append(args, "-o %s" % self.args["outfile"])
55.136 + self._arg_append(args, "2>%s" % os.devnull)
55.137 + # _setup_args()
55.138 +
55.139 + def _setup_filename(self):
55.140 + """This function setups the file to encode parsing the uri.
55.141 + So, type can be:
55.142 + * file
55.143 + * dvd
55.144 + * myth
55.145 +
55.146 + If the last one is detected we have to parse the uri to find args.
55.147 + Then we store all the args inside a dictionary: self.args['gmyth-cat']
55.148 + """
55.149 + _type = self.args["type"]
55.150 +
55.151 + if _type == "file":
55.152 + if not os.path.exists(self.args["input"]):
55.153 + raise IOError,\
55.154 + "File requested does not exist: %s." % self.args["input"]
55.155 + else:
55.156 + self.args["input"] = "file://%s" % self.args["input"]
55.157 +
55.158 + elif _type == "dvd":
55.159 + self.args["input"] = "dvd://%s" % self.args["input"]
55.160 +
55.161 + elif _type == "myth":
55.162 + self.args["gmyth-cat"] = mythtv._setup_mythfilename(self)
55.163 +
55.164 + elif _type == "tv":
55.165 + driver = self.params_first("driver", "v4l2")
55.166 + norm = self.params_first("norm", "pal-m")
55.167 + channel = self.params_first("channel", "13")
55.168 + chanlist = self.params_first("chanlist", "us-bcast")
55.169 + outfmt = self.params_first("outfmt", "yuy2")
55.170 + vdev = self.params_first("vdev", "/dev/video0")
55.171 + adev = self.params_first("adev", "/dev/dsp")
55.172 + self.args["tv"] = "tv:// -v -tv driver=%s:norm=%s:channel=%s:" \
55.173 + "chanlist=%s:width=%s:height=%s:outfmt=%s:" \
55.174 + "device=%s:adevice=%s" % (driver, norm,
55.175 + channel, chanlist,
55.176 + self.args["width"],
55.177 + self.args["height"],
55.178 + outfmt, vdev, adev)
55.179 + # _setup_filename()
55.180 +
55.181 +
55.182 + def __init__(self, params):
55.183 + transcoder.Transcoder.__init__(self, params)
55.184 + self.mencoder_opts = []
55.185 +
55.186 + try:
55.187 + self._setup_params()
55.188 + self._setup_filename()
55.189 + self._setup_mencoder_opts(self.mencoder_opts)
55.190 + except Exception, e:
55.191 + if self.log:
55.192 + self.log.error(self.tid, "Error: %s" % e)
55.193 + else:
55.194 + raise
55.195 + # __init__()
55.196 +
55.197 +
55.198 + def _check_opened_file(self, stdw, _stdin):
55.199 + loop = True
55.200 + while loop:
55.201 + try:
55.202 + return open(self.args["outfile"])
55.203 + except:
55.204 + os.write(stdw, _stdin.read(1024))
55.205 + # _check_opened_file
55.206 +
55.207 +
55.208 + def _start_outfile(self, outfd):
55.209 + finished = False
55.210 +
55.211 + # Configuring stdin
55.212 + try:
55.213 + filename = self.args["input"].split("://")[1]
55.214 + _stdin = open(filename)
55.215 + size = int(os.path.getsize(filename))
55.216 + except Exception, e:
55.217 + self.log.error(self.tid, "Error: Mencoder stdin"\
55.218 + " setup error: %s" % e)
55.219 + outfd.write("Error: Mencoder stdin setup error: %s" %e)
55.220 + return False
55.221 +
55.222 + self.status = 0
55.223 + total_read = 0
55.224 +
55.225 + # Configuring pipes
55.226 + stdr, stdw = os.pipe()
55.227 +
55.228 + if not self._run_mencoder(input=stdr):
55.229 + return False
55.230 +
55.231 + stdout = self._check_opened_file(stdw, _stdin)
55.232 + outfd.write("OK ")
55.233 +
55.234 + try:
55.235 + while self.proc and self.proc.poll() == None:
55.236 + if not finished:
55.237 + data_in = _stdin.read(4096)
55.238 + if data_in != "":
55.239 + os.write(stdw, data_in)
55.240 + total_read += 4096
55.241 + d = stdout.read(4096)
55.242 + self.status = utils.progress_bar(total_read,
55.243 + size, 50)
55.244 + else:
55.245 + finished = True
55.246 + os.close(stdw)
55.247 +
55.248 + else:
55.249 + d = stdout.read(4096)
55.250 +
55.251 + except Exception, e:
55.252 + self.log.error(self.tid, "Error: %s" % e)
55.253 + self.stop()
55.254 + return False
55.255 +
55.256 + self.log.info(self.tid, "OK: Done")
55.257 + return True
55.258 + # _start_outfile()
55.259 +
55.260 +
55.261 + def _start(self, outfd):
55.262 + # Play a file on disk or DVD
55.263 + if not self._run_mencoder(output=subprocess.PIPE):
55.264 + return False
55.265 +
55.266 + try:
55.267 + while self.proc and self.proc.poll() == None:
55.268 + d = self.proc.stdout.read(1024)
55.269 + outfd.write(d)
55.270 + except Exception, e:
55.271 + self.log.error(self.tid, "Error: %s" % e)
55.272 + return False
55.273 +
55.274 + self.log.info(self.tid, "OK: Done")
55.275 + return True
55.276 + # _start()
55.277 +
55.278 + def _run_mencoder(self, input=None, output=None):
55.279 + try:
55.280 + self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
55.281 + stdout=output, close_fds=True)
55.282 + except Exception, e:
55.283 + self.log.error(self.tid, "Error: Mencoder: %s" % e)
55.284 + return False
55.285 +
55.286 + return True
55.287 + # _run_mencoder()
55.288 +
55.289 + def start(self, outfd):
55.290 + cmd = " ".join(self.mencoder_opts)
55.291 + self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
55.292 + self.log.debug(self.tid, "Mencoder: %s" % cmd)
55.293 +
55.294 + ret = False
55.295 +
55.296 + if self.args["outfile"] == "-" and \
55.297 + self.args["type"] in ["file", "dvd", "tv"]:
55.298 + ret = self._start(outfd)
55.299 +
55.300 + elif self.args["type"] == "myth":
55.301 + ret = mythtv.start_myth(self, outfd)
55.302 +
55.303 + else:
55.304 + ret = self._start_outfile(outfd)
55.305 +
55.306 + self.stop()
55.307 +
55.308 + if not ret:
55.309 + self.log.error(self.tid, "Error: Problems while "\
55.310 + "starting streaming.")
55.311 +
55.312 + return ret
55.313 + # start()
55.314 +
55.315 + def _aux_stop(self, obj, next=False):
55.316 + if obj:
55.317 + try:
55.318 + os.kill(obj.pid, signal.SIGKILL)
55.319 + if next:
55.320 + os.kill(obj.pid+1, signal.SIGKILL)
55.321 + except OSError, e:
55.322 + pass
55.323 +
55.324 + try:
55.325 + obj.wait()
55.326 + except Exception, e:
55.327 + pass
55.328 +
55.329 + obj = None
55.330 + # _aux_stop
55.331 +
55.332 + def stop(self):
55.333 + self._aux_stop(self.proc, True)
55.334 + self._aux_stop(self.gmyth)
55.335 + # stop()
55.336 +
55.337 +# TranscoderMencoder
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/gmyth-stream/server/plugins/transcoders/mencoder_lib/mythtv.py Wed Aug 29 14:42:10 2007 +0100
56.3 @@ -0,0 +1,109 @@
56.4 +import os
56.5 +import subprocess
56.6 +import fcntl
56.7 +
56.8 +import lib.utils as utils
56.9 +import lib.server as server
56.10 +
56.11 +from select import select
56.12 +
56.13 +def _setup_mythfilename(self):
56.14 + # mythtv:mythtv@192.168.3.110:6543/1002_20070426230000.nuv
56.15 + try:
56.16 + _mysql = self.args["input"].split("@")[0].split(":")
56.17 + except IndexError, e:
56.18 + _mysql = ["mythtv", "mythtv"]
56.19 +
56.20 + try:
56.21 + _args = self.args["input"].split("@")[1].split(":")
56.22 + except IndexError, e:
56.23 + _args = self.args["input"].split(":")
56.24 +
56.25 + gmyth_dict = {}
56.26 + gmyth_dict["mysql"] = _mysql
56.27 + gmyth_dict["backend"] = _args[0]
56.28 + gmyth_dict["port"] = _args[1].split("/", 1)[0]
56.29 +
56.30 + _tmp_file = _args[1].split("/", 1)[1]
56.31 +
56.32 + if _tmp_file.find("channel") >= 0:
56.33 + gmyth_dict["kind"] = "c"
56.34 + gmyth_dict["cfile"] = _tmp_file.split("=")[1]
56.35 + else:
56.36 + gmyth_dict["kind"] = "f"
56.37 + gmyth_dict["cfile"] = _tmp_file
56.38 +
56.39 + self.args["input"] = "-"
56.40 + return gmyth_dict
56.41 +# _setup_mythfilename
56.42 +
56.43 +def _setup_mythfile(err):
56.44 + size = err.readline().split("Size:")[1]
56.45 + flags = fcntl.fcntl (err, fcntl.F_GETFL, 0) | os.O_NONBLOCK
56.46 + fcntl.fcntl(err, fcntl.F_SETFL, flags)
56.47 + return size
56.48 +# _setup_mythfile
56.49 +
56.50 +def _setup_gmythcat(self):
56.51 + gmyth_cat = utils.which("gmyth-cat")
56.52 + if self.args.has_key("gmyth-cat"):
56.53 + return [ utils.which("gmyth-cat"),
56.54 + "-h", self.args["gmyth-cat"]["backend"],
56.55 + "-p", self.args["gmyth-cat"]["port"],
56.56 + "-" + self.args["gmyth-cat"]["kind"],
56.57 + self.args["gmyth-cat"]["cfile"]
56.58 + ]
56.59 + else:
56.60 + self.log.error(self.tid, "Error: URI error")
56.61 + return []
56.62 +# _setup_gmythcat
56.63 +
56.64 +def start_myth(self, outfd):
56.65 + opts = _setup_gmythcat(self)
56.66 + try:
56.67 + self.gmyth = subprocess.Popen(opts, stdout=subprocess.PIPE,
56.68 + stderr=subprocess.PIPE,
56.69 + close_fds=True)
56.70 + except Exception, e:
56.71 + self.log.error(self.tid, "Error: gmyth-cat: %s" % e)
56.72 + return False
56.73 +
56.74 + if not self._run_mencoder(input=self.gmyth.stdout,
56.75 + output=subprocess.PIPE):
56.76 + return False
56.77 +
56.78 + if self.args["gmyth-cat"]["kind"] == "f":
56.79 + try:
56.80 + size = _setup_mythfile(self.gmyth.stderr)
56.81 + self.log.debug(self.tid, "Info: Size of file: %s" % size)
56.82 + except Exception, e:
56.83 + self.log.error(self.tid, "Error: Problems getting size of"\
56.84 + " file: %s" % e)
56.85 + outfd.write("Error: Problems getting size of file: %s" % e)
56.86 + return False
56.87 +
56.88 + outfd.write("OK ")
56.89 +
56.90 + try:
56.91 + while self.proc and self.proc.poll() == None:
56.92 + r, w, x = select([self.gmyth.stderr, self.proc.stdout],
56.93 + [], [], 0)
56.94 + if self.proc.stdout in r:
56.95 + d = self.proc.stdout.read(4096)
56.96 + outfd.write(d)
56.97 +
56.98 + if self.gmyth.stderr in r:
56.99 + partial = self.gmyth.stderr.readline()
56.100 + if partial != "":
56.101 + self.status = utils.progress_bar(int(partial),
56.102 + int(size), 50)
56.103 +
56.104 + except IndexError, e:
56.105 + pass
56.106 + except Exception, e:
56.107 + self.log.error(self.tid, "Error: %s" % e)
56.108 + return False
56.109 +
56.110 + self.log.info(self.tid, "OK: Done")
56.111 + return True
56.112 +# _start_myth()
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/gmyth-stream/server/server.conf Wed Aug 29 14:42:10 2007 +0100
57.3 @@ -0,0 +1,2 @@
57.4 +[PATHS]
57.5 +transcoded=./.transcoded
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/gmyth-stream/server/setup.py Wed Aug 29 14:42:10 2007 +0100
58.3 @@ -0,0 +1,17 @@
58.4 +from distutils.core import setup
58.5 +from glob import glob
58.6 +
58.7 +setup(name='gms',
58.8 + version='0.6',
58.9 + description='carman rich view package',
58.10 + long_description='carman rich view (SDL based) package',
58.11 + url='http://www.indt.org.br',
58.12 + scripts=['gms.py'],
58.13 + package_dir={'lib': 'lib', 'plugins' : 'plugins','data' : 'data' },
58.14 + packages=['lib','plugins','plugins.transcoders','plugins.transcoders.mencoder_lib'],
58.15 + data_files = [
58.16 + ('share/gms/html', glob("html/*")),
58.17 + ('etc/init.d', ['data/gmsd']),
58.18 + ('etc/gms', ['data/server.conf'])
58.19 + ],
58.20 + )