#!/usr/bin/env python3.4 # This file is part of Libre-Streamer. # # Libre-Streamer 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 3 of the License, or # (at your option) any later version. # # Libre-Streamer 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 Libre-Streamer. If not, see . # # Copyright (c) 2016 David Testé # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # TODO list: # ---------- # - Create a module for the pipeline construction section to clarify the code # - Create a module for the network configuration (ifconfig, stream server,etc) # - Generate a log file during runtime. (e.g. this will let you know if the network configuration # and the pipeline construction went well (or not)) # - Add an input source choice for the user (camera on IP or webcam) # - Add a VU-meter to check if audio feed is emitting signal # - Investigate this error (at stream launching during prototyping phase): # (libre-streamer.py:7856): Gdk-ERROR **: The program 'libre-streamer.py' received an X Window System error. # This probably reflects a bug in the program. # The error was 'BadIDChoice (invalid resource ID chosen for this connection)'. # (Details: serial 592 error_code 14 request_code 1 (core protocol) minor_code 0) # - Add the FSF logo (need to do some pixel art) as an application icon # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import sys import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import Gst from gi.repository import GdkX11 from gi.repository import GstVideo ##import networkinit ##import gstpipeline class Streamgui(object): def __init__(self): self.multimedia_file="" # Create the global pipeline (might wanna use a general bin instead) self.pipel = self.constructpipeline() # Create the GUI self.win = Gtk.Window() self.win.set_title("Libre-Streamer") self.win.connect("delete_event", lambda w,e: Gtk.main_quit()) vbox = Gtk.VBox(False, 0) hbox = Gtk.HBox(False, 0) self.load_file = Gtk.FileChooserButton("Choose Audio File") self.stream_button = Gtk.Button("Stream") self.videowidget = Gtk.DrawingArea() self.videowidget.set_size_request(600, 400) self.load_file.connect("selection-changed", self.on_file_selected) self.stream_button.connect("clicked", self.on_stream_clicked) hbox.pack_start(self.stream_button, False, True, 0) vbox.pack_start(self.load_file, False, True, 0) vbox.pack_start(self.videowidget, True, True, 0) vbox.pack_start(hbox, False, True, 0) self.win.add(vbox) self.win.set_position(Gtk.WindowPosition.CENTER) self.win.show_all() bus = self.pipel.get_bus() bus.add_signal_watch() bus.enable_sync_message_emission() # Used to get messages that GStreamer emits. bus.connect("message", self.on_message) # Used for connecting video to your application. bus.connect("sync-message::element", self.on_sync_message) def constructpipeline (self): """Add and link elements in a GStreamer pipeline""" # Create the pipelines instance. self.streampipe = Gst.Pipeline() ## self.storepipe_hi = Gst.Pipeline() ## self.storepipe_lo = Gst.Pipeline() # Define pipeline elements. ## The next line WILL NOT display the camera's video feed ## self.videosrc = Gst.ElementFactory.make('location', 'rtsp://192.168.48.2:554') self.videosrc = Gst.ElementFactory.make('videotestsrc', 'source') self.queue = Gst.ElementFactory.make('queue') ## self.oggstreamsink = Gst.ElementFactory.make() ## self.oggdisksink = Gst.ElementFactory.make() ## self.jpegdisksink = Gst.ElementFactory.make() self.screensink = Gst.ElementFactory.make('xvimagesink', 'rawfeed') ## self.webmdisksink = Gst.ElementFactory.make() ## self.webmstreamsink = Gst.ElementFactory.make() # Add the elements to the pipeline. self.streampipe.add(self.videosrc) self.streampipe.add(self.queue) self.streampipe.add(self.screensink) # Link the elements in the pipeline. self.videosrc.link(self.queue) self.queue.link(self.screensink) return self.streampipe def on_message(self, bus, message): t = message.type if t == Gst.MessageType.EOS: self.player.set_state(Gst.State.NULL) elif t == Gst.MessageType.ERROR: self.player.set_state(Gst.State.NULL) err, debug = message.parse_error() print ("Error: %s" % err, debug) def on_sync_message(self, bus, message): if message.get_structure().get_name() == 'prepare-window-handle': imagesink = message.src imagesink.set_property('force-aspect-ratio', True) imagesink.set_window_handle(self.videowidget.get_property('window').get_xid()) # USE THAT FUNCTION TO GET THE SOURCE CHOICE (ELPHEL OR WEBCAM) def on_file_selected(self, widget): self.multimedia_file = self.load_file.get_filename() def on_stream_clicked(self, widget): # Put here the script to launch streaming and start recording ## self.streampipe.uri_construct('rtsp', '://192.168.48.2:554') labelname = self.stream_button.get_label() if labelname == 'Stream': self.pipel.set_state(Gst.State.PLAYING) self.stream_button.set_label('ON AIR') elif labelname == 'ON AIR': self.pipel.set_state(Gst.State.NULL) self.stream_button.set_label('Stream') if __name__ == "__main__": Gst.init() Streamgui() Gtk.main()