New GUI for 2016 edition
[libre-streamer.git] / stream_2016 / libre-streamer.py
CommitLineData
6fdd41d9
DT
1#!/usr/bin/env python3.4
2
3# This file is part of Libre-Streamer.
4#
5# Libre-Streamer is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Libre-Streamer is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Libre-Streamer. If not, see <http://www.gnu.org/licenses/>.
17#
18# Copyright (c) 2016 David Testé
19
20# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21# TODO list:
22# ----------
23# - Create a module for the pipeline construction section to clarify the code
24# - Create a module for the network configuration (ifconfig, stream server,etc)
25# - Generate a log file during runtime. (e.g. this will let you know if the network configuration
26# and the pipeline construction went well (or not))
27# - Add an input source choice for the user (camera on IP or webcam)
28# - Add a VU-meter to check if audio feed is emitting signal
29# - Investigate this error (at stream launching during prototyping phase):
30# (libre-streamer.py:7856): Gdk-ERROR **: The program 'libre-streamer.py' received an X Window System error.
31# This probably reflects a bug in the program.
32# The error was 'BadIDChoice (invalid resource ID chosen for this connection)'.
33# (Details: serial 592 error_code 14 request_code 1 (core protocol) minor_code 0)
34# - Add the FSF logo (need to do some pixel art) as an application icon
35# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
36
37import sys
38
39import gi
40gi.require_version('Gtk', '3.0')
41from gi.repository import Gtk
42from gi.repository import Gst
43from gi.repository import GdkX11
44from gi.repository import GstVideo
45
46##import networkinit
47##import gstpipeline
48
49
50class Streamgui(object):
51
52
53 def __init__(self):
54
55 self.multimedia_file=""
56 # Create the global pipeline (might wanna use a general bin instead)
57 self.pipel = self.constructpipeline()
58 # Create the GUI
59 self.win = Gtk.Window()
60 self.win.set_title("Libre-Streamer")
61 self.win.connect("delete_event",
62 lambda w,e: Gtk.main_quit())
63 vbox = Gtk.VBox(False, 0)
64 hbox = Gtk.HBox(False, 0)
65 self.load_file = Gtk.FileChooserButton("Choose Audio File")
66 self.stream_button = Gtk.Button("Stream")
67 self.videowidget = Gtk.DrawingArea()
68 self.videowidget.set_size_request(600, 400)
69 self.load_file.connect("selection-changed", self.on_file_selected)
70 self.stream_button.connect("clicked", self.on_stream_clicked)
71
72 hbox.pack_start(self.stream_button, False, True, 0)
73 vbox.pack_start(self.load_file, False, True, 0)
74 vbox.pack_start(self.videowidget, True, True, 0)
75 vbox.pack_start(hbox, False, True, 0)
76 self.win.add(vbox)
77 self.win.set_position(Gtk.WindowPosition.CENTER)
78 self.win.show_all()
79
80 bus = self.pipel.get_bus()
81 bus.add_signal_watch()
82 bus.enable_sync_message_emission()
83 # Used to get messages that GStreamer emits.
84 bus.connect("message", self.on_message)
85 # Used for connecting video to your application.
86 bus.connect("sync-message::element", self.on_sync_message)
87
88 def constructpipeline (self):
89
90 """Add and link elements in a GStreamer pipeline"""
91
92 # Create the pipelines instance.
93 self.streampipe = Gst.Pipeline()
94## self.storepipe_hi = Gst.Pipeline()
95## self.storepipe_lo = Gst.Pipeline()
96
97 # Define pipeline elements.
98 ## The next line WILL NOT display the camera's video feed
99 ## self.videosrc = Gst.ElementFactory.make('location', 'rtsp://192.168.48.2:554')
100 self.videosrc = Gst.ElementFactory.make('videotestsrc', 'source')
101 self.queue = Gst.ElementFactory.make('queue')
102 ## self.oggstreamsink = Gst.ElementFactory.make()
103 ## self.oggdisksink = Gst.ElementFactory.make()
104
105 ## self.jpegdisksink = Gst.ElementFactory.make()
106
107 self.screensink = Gst.ElementFactory.make('xvimagesink', 'rawfeed')
108
109 ## self.webmdisksink = Gst.ElementFactory.make()
110 ## self.webmstreamsink = Gst.ElementFactory.make()
111
112 # Add the elements to the pipeline.
113 self.streampipe.add(self.videosrc)
114 self.streampipe.add(self.queue)
115 self.streampipe.add(self.screensink)
116 # Link the elements in the pipeline.
117 self.videosrc.link(self.queue)
118 self.queue.link(self.screensink)
119
120 return self.streampipe
121
122 def on_message(self, bus, message):
123
124 t = message.type
125 if t == Gst.MessageType.EOS:
126 self.player.set_state(Gst.State.NULL)
127 elif t == Gst.MessageType.ERROR:
128 self.player.set_state(Gst.State.NULL)
129 err, debug = message.parse_error()
130 print ("Error: %s" % err, debug)
131
132 def on_sync_message(self, bus, message):
133
134 if message.get_structure().get_name() == 'prepare-window-handle':
135 imagesink = message.src
136 imagesink.set_property('force-aspect-ratio', True)
137 imagesink.set_window_handle(self.videowidget.get_property('window').get_xid())
138
139
140 # USE THAT FUNCTION TO GET THE SOURCE CHOICE (ELPHEL OR WEBCAM)
141 def on_file_selected(self, widget):
142
143 self.multimedia_file = self.load_file.get_filename()
144
145 def on_stream_clicked(self, widget):
146
147 # Put here the script to launch streaming and start recording
148## self.streampipe.uri_construct('rtsp', '://192.168.48.2:554')
149 labelname = self.stream_button.get_label()
150 if labelname == 'Stream':
151 self.pipel.set_state(Gst.State.PLAYING)
152 self.stream_button.set_label('ON AIR')
153 elif labelname == 'ON AIR':
154 self.pipel.set_state(Gst.State.NULL)
155 self.stream_button.set_label('Stream')
156
157
158if __name__ == "__main__":
159 Gst.init()
160 Streamgui()
161 Gtk.main()