diff options
Diffstat (limited to 'MplayerReproductor.py')
-rw-r--r-- | MplayerReproductor.py | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/MplayerReproductor.py b/MplayerReproductor.py new file mode 100644 index 0000000..366fb1d --- /dev/null +++ b/MplayerReproductor.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# MplayerReproductor.py por: +# Flavio Danesse <fdanesse@gmail.com> +# CeibalJAM! - Uruguay + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import time +import os +import subprocess +#import platform + +import gi +from gi.repository import GObject + +STDOUT = "/tmp/jamediaout%d" % time.time() +STDERR = "/dev/null" +MPLAYER = "mplayer" + +#if "olpc" in platform.platform(): MPLAYER = "./mplayer" +#if "Strawberry" in platform.platform(): MPLAYER = "./mplayer" + +class MplayerReproductor(GObject.GObject): + """ + Reproductor de Audio, Video y Streaming de + Radio y Television. Implementado sobre: + + python 2.7.3 + Gtk 3 + mplayer (a traves de python.subprocess) + """ + + __gsignals__ = {"endfile":(GObject.SIGNAL_RUN_FIRST, + GObject.TYPE_NONE, []), + "estado":(GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, + (GObject.TYPE_STRING,)), + "newposicion":(GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, + (GObject.TYPE_INT,)), + "volumen":(GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, + (GObject.TYPE_FLOAT,))} + + # Estados: playing, paused, None + + def __init__(self, ventana_id): + """ Recibe el id de un DrawingArea + para mostrar el video. """ + + GObject.GObject.__init__(self) + self.name = "MplayerReproductor" + self.ventana_id = ventana_id + self.mplayer = None + self.salida = None + self.entrada = None + self.estado = None + self.duracion = 0 + self.posicion = 0 + self.volumen = 0 + self.actualizador = None + self.uri = None + + def stop(self): + """Detiene todo.""" + + try: + if self.entrada: + self.entrada.write('%s 0\n' % "quit") + self.entrada.flush() + self.new_handle(False) + except Exception, e: + #print "HA OCURRIDO UN ERROR EN QUIT DEL REPRODUCTOR", e + pass + self.posicion = 0 + if os.path.exists(STDOUT): os.unlink(STDOUT) + import commands + commands.getoutput('killall mplayer') + self.estado = None + self.emit("estado", "None") + + def load(self, uri): + """Carga y Reproduce un archivo o streaming.""" + + self.stop() + self.uri = uri + if os.path.exists(self.uri): + uri = "%s%s%s" % ("\"", self.uri, "\"") + + cache_pantalla = "%s -cache %i -wid %i" % (MPLAYER, 1024, self.ventana_id) + estructura = "%s -slave -idle -nolirc -rtc -nomouseinput -noconsolecontrols -nojoystick" % (cache_pantalla) + self.mplayer = subprocess.Popen(estructura, shell = True, stdin = subprocess.PIPE, + stdout = open(STDOUT,"w+b"), stderr=open(STDOUT,"r+b"), universal_newlines=True) + self.entrada = self.mplayer.stdin + self.salida = open(STDOUT,"r") + self.entrada.write("loadfile %s 0\n" % uri) + self.entrada.flush() + self.new_handle(True) + + def handle(self): + """Consulta el estado y progreso del + la reproduccion actual.""" + + if not self.entrada.closed: + # Control por tiempo + #self.entrada.write("%s 0\n" % ("get_time_length")) + #self.entrada.flush() + #duracion = self.salida.readline() + #if "ANS_LENGTH" in duracion: + # duracion = float(duracion.split("=")[1]) # Duración en Segundos + # print "dur", duracion + + #self.entrada.write("%s 0\n" % ("get_time_pos")) + #self.entrada.flush() + #posicion = self.salida.readline() + #if "ANS_TIME_POSITION" in posicion: + # posicion = float(posicion.split("=")[1]) # Posición en Segundos + # print "pos", posicion + + self.entrada.write("%s 0\n" % ("get_property percent_pos")) + self.entrada.flush() + linea = self.salida.readline() + if linea: + if "ANS_percent_pos" in linea: + "Información sobre el porcentaje Reproducido hasta el momento. Ejemplo:" + "ANS_percent_pos=0" + self.get_progress_in_mplayer(linea) + self.get_volumen() + + elif "Video: no video" in linea or "Audio only file format detected" in linea: + "Cuando no hay video en la fuente. Ejemplo" + "Audio only file format detected." + "Video: no video" + #self.emit("video", False) + pass + + elif "Cache" in linea: + "Información Sobre Carga de caché. Ejemplo:" + "Cache fill: 6.25% (65536 bytes)" + #self.get_progress_cache_in_mplayer(linea) + pass + + elif "Movie-Aspect" in linea: + "Información sobre el aspecto del video. Ejemplo:" + "Movie-Aspect is 1.78:1 - prescaling to correct movie aspect." + #self.emit("video", True) + pass + + elif "Starting playback" in linea: + "Cuando comienza la Reproducción. Ejemplo:" + "Starting playback..." + self.estado = "playing" + self.emit("estado", "playing") + + elif "AO:" in linea: + "Información Sobre Audio en la pista. Ejemplo:" + "AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample)" + pass + + elif "VO:" in linea: + "Información sobre Video en la pista. Ejemplo:" + "VO: [xv] 428x240 => 428x240 Planar YV12" + pass + + elif "Resolving" in linea: + "Información sobre Resolución de Streamings. Ejemplo:" + "Resolving radio1.oceanofm.com for AF_INET6..." + pass + + elif "Connecting" in linea: + "Información sobre Conexión a un Streaming. Ejemplo:" + "Connecting to server main-office.rautemusik.fm[87.230.101.9]: 80..." + pass + + elif "Name" in linea: + "El nombre de una streaming de Radio. Ejemplo:" + "Name : #MUSIK.MAIN - WWW.RAUTEMUSIK.FM - 24H TOP 40 POP HITS 80S 90S DANCE HOUSE ROCK RNB AND MORE!" + pass + + elif "Playing" in linea: + "La Pista que se está reproduciendo. Ejemplo:" + "Playing /media/4E432D364BC64012/E - Videos/Tylor swift/Back to December-Taylor Swift Lyrics." + pass + + elif "Genre" in linea or "Website" in linea or "Bitrate" in linea: + "Información Sobre un Streaming de Radio. Ejemplo:" + "Genre : Pop Rock Top 40 RnB 80s" + "Website: http://www.RauteMusik.FM/" + "Bitrate: 128kbit/s" + pass + + elif "Opening" in linea or "AUDIO" in linea or "Selected" in linea: + "Información sobre Codecs Utilizados. Ejemplo:" + "Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family" + "Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264)" + "Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders" + "AUDIO: 44100 Hz, 2 ch, s16le, 98.6 kbit/6.99% (ratio: 12323->176400)" + "Selected audio codec: [ffaac] afm: ffmpeg (FFmpeg AAC (MPEG-2/MPEG-4 Audio))" + pass + + else: + "Información Diversa. Ejemplo:" + "Failed to open /dev/rtc: Permission denied (it should be readable by the us" + "Unsupported PixelFormat 61" + "Unsupported PixelFormat 53" + "Unsupported PixelFormat 81" + "eo (h264), -vid 0" + "[lavf] stream 1: audio (aac), -aid 0" + "VIDEO: [H264] 640x480 0bpp 30.000 fps 218.3 kbps (26.6 kbyte/s)" + "Clip info:" + "starttime: 0" + "totalduration: 226" + "totaldatarate: 338" + "bytelength: 9570679" + "canseekontime: true" + "sourcedata: BC8280065HH1341966475963833" + "purl: " + "pmsg: " + "Load subtitles in /media/4E432D364BC64012/E - Videos/Tylor swift/" + "==========================================================================" + "libavcodec version 53.35.0 (external)" + "Mismatching header version 53.32.2" + "==========================================================================" + "==========================================================================" + "==========================================================================" + "A: 0.0 V: 0.0 A-V: 0.014 ct: 0.000 0/ 0 ??% ??% ??,?% 0 0 90%" + "A: 123.2 V: 123.2 A-V: -0.000 ct: 0.033 0/ 0 2% 1% 0.4% 0 0 50%" + + "Cuando no se puede Acceder a un Streaming. Ejemplo:" + "Failed to get value of property 'percent_pos'." + "Failed to get value of property 'percent_ANS_ERFailed to get value of" + "prANS_ERROR=PROPERTY_UNAFailed toANS_ERROR=PROPERTY_UNAVAILABLE" + "ANS_ERROR=PROPERTY_UNAVAILABLE" + pass + + return True + + def get_progress_in_mplayer(self, linea): + """Obtiene el progreso de la reproduccion y lo + envia en una señal para actualizar la barra de + progreso.""" + + pos = 0 + try: + if "Cache size" in linea: return + pos = int(linea.split('=')[1]) + if pos != self.posicion: + self.posicion = pos + self.emit("newposicion", self.posicion) + if self.posicion >= 100: + self.emit("endfile") + except Exception, e: + print "Error en Progreso de Reproducción: %s" % (e) + + def pause_play(self): + """Llama a play() o pause() + segun el estado actual del reproductor.""" + + try: + if self.entrada: + if self.estado == "playing": # pausa + self.pause() + elif self.estado == "paused": + self.pause(True) + self.estado = "playing" + self.emit("estado", "playing") + else: + #if self.uri: self.load(self.uri) + pass + except Exception, e: + print "HA OCURRIDO UN ERROR EN PAUSE_PLAY DEL REPRODUCTOR", e + + def pause(self, reset = False): + """Pone en pause o unpause a mplayer""" + + self.entrada.write('pause 0\n') + self.entrada.flush() + self.new_handle(reset) + self.estado = "paused" + self.emit("estado", "paused") + + def play(self): + """No hace nada. mplayer utiliza: + pause, unpause y load en lugar de play.""" + + pass + + def new_handle(self, reset): + """Elimina o reinicia la funcion que + envia los datos de actualizacion para + la barra de progreso del reproductor.""" + + if self.actualizador: + GObject.source_remove(self.actualizador) + self.actualizador = None + if reset: + self.actualizador = GObject.timeout_add(35, self.handle) + + def set_position(self, posicion): + """Funcion que permite desplazarse por + el archivo que se esta reproduciendo.""" + + # FIXME: Actualmente no funciona bien + posicion = int(posicion) + if posicion != self.posicion: + self.posicion = posicion + self.entrada.write('seek %s %i 0\n' % (posicion, 1)) + self.entrada.flush() + + def get_volumen(self): + """Obtiene el volumen de reproducción. + Lo hace solo al reproducir el primer archivo + o streaming y envía el dato para actualizar + el control de volúmen.""" + + if self.volumen != 0: return + if self.entrada: + self.entrada.write("%s 0\n" % ("get_property volume")) + self.entrada.flush() + linea = self.salida.readline() + if "ANS_volume" in linea: + valor = float(linea.split("=")[1]) + if self.volumen == 0: + self.volumen = valor + self.emit('volumen', valor) + + def set_volumen(self, valor): + """Cambia el volúmen de Reproducción.""" + + if self.entrada: + if valor != self.volumen: + self.volumen = valor + self.entrada.write("%s %s0\n" % ("set_property volume", valor)) + self.entrada.flush() +
\ No newline at end of file |