Advertisement
Guest User

Untitled

a guest
Apr 19th, 2015
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.34 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. import gi
  4. gi.require_version('Gst', '1.0')
  5. from gi.repository import GObject, Gst, Gtk, Gdk
  6. import socket
  7. import sys
  8. import _thread as thread
  9. from time import sleep
  10.  
  11. # Needed for window.get_xid(), xvimagesink.set_window_handle(), respectively:
  12. from gi.repository import GdkX11, GstVideo
  13.  
  14. GObject.threads_init()
  15. Gst.init(None)
  16.  
  17.  
  18. # Connect the socket to the port where the server is listening
  19. server_address = '/tmp/uds_dnvff'
  20.  
  21. window_width = 800
  22. window_height = 480
  23.  
  24. video_width = 320
  25. video_height = 240
  26.  
  27. class Buttons:
  28.     blink_left = 1
  29.     blink_right = 1
  30.     dead_mans1 = 1
  31.     dead_mans2 = 1
  32.     horn = 1
  33.     joy_sw = 1
  34.     lights_far = 1
  35.     lights_near = 1
  36.     phone = 1
  37.     wiper = 1
  38.     joy_y = 0
  39.     volume = 0
  40.     fans = 0
  41.  
  42.  
  43. class Webcam:
  44.  
  45.     def __init__(self):
  46.    
  47.        
  48.         self.window = Gtk.Window()
  49.         self.window.set_title("Hello")
  50.  
  51.         self.window.connect('destroy', self.quit)
  52.         self.window.set_default_size(window_width, window_height)
  53.  
  54.         self.geometry = Gdk.Geometry()
  55.         self.geometry.max_width = window_width
  56.         self.geometry.max_height = window_height
  57.         self.geometry.min_width = 0
  58.         self.geometry.min_height = 0
  59.        
  60.         self.hints = Gdk.WindowHints(Gdk.WindowHints.MAX_SIZE)
  61.        
  62.         self.window.set_geometry_hints(self.window,
  63.                                        self.geometry,
  64.                                        self.hints)
  65.                                        
  66.         self.window.set_position(Gtk.WindowPosition.CENTER)
  67.         self.window.fullscreen()
  68.  
  69.         self.drawingarea = Gtk.DrawingArea()
  70.         #self.drawingarea.set_size_request(video_width, video_height)
  71.        
  72.         self.buttons = Buttons()
  73.         self.counter = 0
  74.        
  75.         self.outer_grid = Gtk.Grid()
  76.         self.outer_grid.set_column_spacing(5)
  77.         self.outer_grid.set_row_spacing(5)
  78.        
  79.         self.window.add(self.outer_grid)
  80.        
  81.         number_of_buttons = 5
  82.         button_height = int((480 - (5*(number_of_buttons-1)))/number_of_buttons)
  83.         button_width = 80
  84.         # stuff that goes in outer grid: (MAIN MENU)
  85.         info_button = Gtk.Button(label="Info")
  86.         info_button.set_size_request(button_width, button_height)
  87.         info_button.connect("clicked", self.info_button_on_click)
  88.        
  89.         video_button = Gtk.Button(label="Video")
  90.         video_button.set_size_request(button_width, button_height)
  91.         video_button.connect("clicked", self.video_button_on_click)
  92.        
  93.         map_button = Gtk.Button(label="Map")
  94.         map_button.set_size_request(button_width, button_height)
  95.         #video_button.connect("clicked", self.map_button_on_click)
  96.        
  97.         phone_button = Gtk.Button(label="Extra")
  98.         phone_button.set_size_request(button_width, button_height)
  99.         phone_button.connect("clicked", self.phone_button_on_click)
  100.        
  101.         race_button = Gtk.Button(label="Race")
  102.         race_button.set_size_request(button_width, button_height)
  103.         race_button.connect("clicked", self.race_button_on_click)
  104.        
  105.         self.race_grid = Gtk.Grid()
  106.         self.video_grid = Gtk.Grid()
  107.         self.map_grid = Gtk.Grid()
  108.         self.phone_grid = Gtk.Grid()
  109.         self.info_grid = Gtk.Grid()
  110.        
  111.         ######################################## info grid ##############################################
  112.         self.info_grid.set_column_spacing(5)
  113.         self.info_grid.set_row_spacing(5)
  114.         info_header = Gtk.Label()
  115.         info_header.set_markup('<big>Information/diagnostics</big>')
  116.        
  117.         self.button_blink_label = Gtk.Label('Blink: -')
  118.         self.button_dead_label = Gtk.Label('Dead-mans: -')
  119.         self.button_horn_label = Gtk.Label('Horn: -')
  120.         self.button_joy_sw_label = Gtk.Label('Joy sw: -')
  121.         self.button_lights_label = Gtk.Label('Lights: -')
  122.         self.button_phone_label = Gtk.Label('Phone: -')
  123.         self.button_wiper_label = Gtk.Label('Wiper: -')
  124.         self.button_volume_label = Gtk.Label('Volume: -')
  125.         self.button_fans_label = Gtk.Label('Fans: -')
  126.         self.button_joy_y_label = Gtk.Label('Joystick: -')
  127.        
  128.        
  129.         self.info_grid.attach(info_header, 0, 0, 1, 1)
  130.         self.info_grid.attach(self.button_blink_label, 0, 1, 1, 1)
  131.         self.info_grid.attach(self.button_dead_label, 0, 2, 1, 1)
  132.         self.info_grid.attach(self.button_horn_label, 0, 3, 1, 1)
  133.         self.info_grid.attach(self.button_joy_sw_label, 0, 4, 1, 1)
  134.         self.info_grid.attach(self.button_lights_label, 0, 5, 1, 1)
  135.         self.info_grid.attach(self.button_phone_label, 0, 6, 1, 1)
  136.         self.info_grid.attach(self.button_wiper_label, 0, 7, 1, 1)
  137.         self.info_grid.attach(self.button_volume_label, 0, 8, 1, 1)
  138.         self.info_grid.attach(self.button_fans_label, 0, 9, 1, 1)
  139.         self.info_grid.attach(self.button_joy_y_label, 0, 10, 1, 1)
  140.        
  141.         ######################################## race grid ##############################################
  142.         race_header = Gtk.Label()
  143.         race_header.set_text('race')
  144.         self.race_grid.attach(race_header, 0,0,1,1)
  145.         self.race_grid.attach(self.drawingarea, 1, 0, 1, 1)
  146.         self.drawingarea.set_size_request(video_width, video_height)
  147.        
  148.        
  149.        
  150.         #button4 = Gtk.Button(label="Button 4")
  151.         #button5 = Gtk.Button(label="Button 5")
  152.         #button6 = Gtk.Button(label="Button 6")
  153.  
  154.         #grid.add(button1)
  155.        
  156.         #put stuff in outer grid:
  157.         self.outer_grid.attach(race_button, 0, 0, 1, 1)
  158.         self.outer_grid.attach(video_button, 0, 1, 1, 1)
  159.         self.outer_grid.attach(map_button, 0, 2, 1, 1)
  160.         self.outer_grid.attach(phone_button, 0, 3, 1, 1)
  161.         self.outer_grid.attach(info_button, 0, 4, 1, 1)
  162.         self.outer_grid.attach(self.race_grid, 1, 0, 1, number_of_buttons)
  163.        
  164.        
  165.         #grid.insert_row(1)
  166.         #grid.attach(button2, 0, 2, 2, 2)
  167.         #grid.attach(button3, 0, 4, 2, 2)
  168.         #grid.attach(button4, 0, 6, 2, 2)
  169.         #grid.attach(button5, 0, 8, 2, 2)
  170.        
  171.        
  172.         #grid.attach_next_to(button4, button3, Gtk.PositionType.RIGHT, 2, 1)
  173.         #grid.attach(self.drawingarea, 1, 2, 1, 1)
  174.         #grid.attach_next_to(button6, button5, Gtk.PositionType.RIGHT, 1, 1)
  175.        
  176.  
  177.         # Create GStreamer pipeline
  178.         self.pipeline = Gst.Pipeline()
  179.        
  180.         #################################### local stuff: #############################################################
  181.         #source:
  182.         self.rpi_cam_src = Gst.ElementFactory.make('rpicamsrc', None)
  183.         self.rpi_cam_src.set_property('bitrate', 1000000)
  184.         self.rpi_cam_src.set_property('preview', False)
  185.         self.rpi_cam_src.set_property('image-effect', 'none')
  186.        
  187.         #caps
  188.         gst_caps = Gst.caps_from_string('video/x-h264,width=' + str(video_width) + ',height=' + str(video_height))
  189.        
  190.         #capsfilter
  191.         gst_capsfilter = Gst.ElementFactory.make('capsfilter', None)
  192.         gst_capsfilter.set_property('caps', gst_caps)
  193.        
  194.         #decodebin
  195.         gst_decodebin = Gst.ElementFactory.make('decodebin', None)
  196.        
  197.         #queue
  198.         gst_queue_local = Gst.ElementFactory.make('queue', None)
  199.         self.gst_queue_local_2 = Gst.ElementFactory.make('queue', None)
  200.        
  201.         #videoconvert
  202.         gst_videoconvert = Gst.ElementFactory.make('videoconvert', None)
  203.        
  204.         #sink
  205.         gst_localsink = Gst.ElementFactory.make("ximagesink", None)
  206.         ####################################################################################################################
  207.        
  208.         #gst-launch-1.0 rpicamsrc bitrate=1000000 ! video/x-h264,width=640,height=480! h264parse ! flvmux ! rtmpsink location='rtmp://live.twitch.tv/app/'
  209.         ############################################## udp stuff ###########################################################
  210.        
  211.         #tee (split)
  212.         gst_tee = Gst.ElementFactory.make('tee', None)
  213.        
  214.         #udp queue
  215.         gst_queue_udp = Gst.ElementFactory.make('queue', None)
  216.        
  217.         #h264parser
  218.         gst_h264parse = Gst.ElementFactory.make('h264parse', None)
  219.        
  220.         #flvmux
  221.         gst_flvmux = Gst.ElementFactory.make('flvmux', None)
  222.        
  223.         #rtmpsink
  224.         gst_rtmpsink = Gst.ElementFactory.make('rtmpsink', None)
  225.         temp_file = open('twitch.key', 'r')
  226.         twitch_key = temp_file.readline().rstrip()
  227.         print(twitch_key)
  228.         temp_file.close()
  229.         gst_rtmpsink.set_property('location', 'rtmp://live.twitch.tv/app/' + twitch_key)
  230.        
  231.        
  232.         self.pipeline.add(self.rpi_cam_src)
  233.         self.pipeline.add(gst_capsfilter)
  234.         self.pipeline.add(gst_tee)
  235.         self.pipeline.add(gst_queue_local)
  236.         self.pipeline.add(gst_decodebin)
  237.         self.pipeline.add(self.gst_queue_local_2)
  238.         self.pipeline.add(gst_videoconvert)
  239.         self.pipeline.add(gst_localsink)
  240.         self.pipeline.add(gst_queue_udp)
  241.         self.pipeline.add(gst_h264parse)
  242.         self.pipeline.add(gst_flvmux)
  243.         self.pipeline.add(gst_rtmpsink)
  244.        
  245.         #link local stuff:
  246.         print('linking..')
  247.         print(self.rpi_cam_src.link(gst_capsfilter))
  248.         print(gst_capsfilter.link(gst_tee))
  249.         gst_tee_pad1 = gst_tee.get_request_pad('src_%u')
  250.        
  251.         print(gst_tee_pad1.link(gst_queue_local.get_static_pad('sink')))
  252.         #print(gst_tee.link(gst_queue_local))
  253.         print(gst_queue_local.link(gst_decodebin))
  254.         #print(gst_decodebin.link(gst_queue_local_2))  # dont link it here, do it with a callback:
  255.         gst_decodebin.connect("pad-added", self.decodebin_pad_added)
  256.        
  257.        
  258.         print(self.gst_queue_local_2.link(gst_videoconvert))
  259.         print(gst_videoconvert.link(gst_localsink))
  260.        
  261.         #link udp stuff:
  262.         gst_tee_pad2 = gst_tee.get_request_pad('src_%u')
  263.         print(gst_tee_pad2.link(gst_queue_udp.get_static_pad('sink')))
  264.         #print(gst_tee.link(gst_queue_udp))
  265.         print(gst_queue_udp.link(gst_h264parse))
  266.         print(gst_h264parse.link(gst_flvmux))
  267.         print(gst_flvmux.link(gst_rtmpsink))
  268.        
  269.         self.video_playing = False
  270.        
  271.         self.bus = self.pipeline.get_bus()
  272.         self.bus.add_signal_watch()
  273.         self.bus.connect('message::error', self.on_error)
  274.  
  275.         # This is needed to make the video output in our DrawingArea:
  276.         self.bus.enable_sync_message_emission()
  277.         self.bus.connect('sync-message::element', self.on_sync_message)
  278.        
  279.         self.ximage_sink = None
  280.  
  281.        
  282.         ################################################################## SOCKET STUFF ########################################################################
  283.        
  284.         self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
  285.         try:
  286.             thread.start_new_thread( self.update_button_info, () )
  287.             thread.start_new_thread( self.listen_on_TCP, () )
  288.            
  289.         except Exception as inst:
  290.             print(type(inst))
  291.            
  292.     def decodebin_pad_added(self, decodebin, pad):
  293.         print('linking decodebin')
  294.         pad.link(self.gst_queue_local_2.get_static_pad('sink'))
  295.        
  296.     def info_button_on_click(self, button):
  297.         for wid in self.outer_grid.get_children():
  298.             if wid.get_name() == 'GtkGrid':
  299.                 print('found grid. removing')
  300.                 self.outer_grid.remove(wid)
  301.         if self.video_playing:
  302.             self.pipeline.set_state(Gst.State.NULL)
  303.             self.rpi_cam_src.set_property('preview', False)
  304.             self.pipeline.set_state(Gst.State.PLAYING)
  305.             self.video_playing = False
  306.            
  307.         self.outer_grid.attach(self.info_grid, 1, 0, 1, 5)
  308.         self.window.show_all()
  309.  
  310.            
  311.     def video_button_on_click(self, button):
  312.         #self.rpi_cam_src.set_property('image-effect', 'cartoon')
  313.        
  314.         if not self.video_playing:
  315.             print('attempting to go to fullscreen')
  316.             print(self.pipeline.set_state(Gst.State.READY))
  317.             print(self.rpi_cam_src.set_property('preview', True))
  318.             print(self.pipeline.set_state(Gst.State.PLAYING))
  319.             self.video_playing = True
  320.             #video_pipeline = 'rpicamsrc bitrate=1000000 preview=false ! video/x-h264,width=' + str(video_width) + ',height=' + str(video_height) +' ! decodebin ! queue ! videoconvert ! autovideosink'
  321.             #video_pipeline = 'v4l2src ! autovideosink'
  322.             #video_pipeline = 'rpicamsrc bitrate=1000000 ! decodebin ! queue ! videoconvert ! autovideosink'
  323.  
  324.             #print ('pipeline :' + video_pipeline)
  325.             #self.pipeline = Gst.parse_launch(video_pipeline)
  326.  
  327.             # Create bus to get events from GStreamer pipeline
  328.             pass
  329.            
  330.            
  331.        
  332.     def phone_button_on_click(self, button):
  333.         #wiringpi.digitalWrite(7, 0)
  334.         sys.exit(1)
  335.         pass
  336.        
  337.     def race_button_on_click(self, button):
  338.         #wiringpi.digitalWrite(7, 0)
  339.         for wid in self.outer_grid.get_children():
  340.             if wid.get_name() == 'GtkGrid':
  341.                 print('found grid. removing')
  342.                 self.outer_grid.remove(wid)
  343.                
  344.         if self.video_playing:
  345.             self.pipeline.set_state(Gst.State.READY)
  346.             self.rpi_cam_src.set_property('preview', False)
  347.             self.pipeline.set_state(Gst.State.PLAYING)
  348.             self.video_playing = False        
  349.         #if self.video_playing:
  350.         #    self.pipeline.set_state(Gst.State.PAUSED)
  351.        
  352.         self.outer_grid.attach(self.race_grid, 1, 0, 1, 5)
  353.         self.window.show_all()
  354.         self.xid = self.drawingarea.get_property('window').get_xid()
  355.         print (self.xid)
  356.         self.ximage_sink.set_window_handle(self.xid)
  357.    
  358.     def update_button_info(self):
  359.         print('starting update')
  360.         while 1:
  361.             #print('woop woop')
  362.             self.button_joy_y_label.set_text('Joystick: %d' % (self.buttons.joy_y))
  363.  
  364.             if self.buttons.blink_left == 0:
  365.                 self.button_blink_label.set_text('Blink: %s' % ('Left'))
  366.             elif self.buttons.blink_right == 0:
  367.                  self.button_blink_label.set_text('Blink: %s' % ('Right'))
  368.             else:
  369.                 self.button_blink_label.set_text('Blink: %s' % ('Off'))
  370.  
  371.             if self.buttons.dead_mans1 == 0 or self.buttons.dead_mans2 == 0:
  372.                 self.button_dead_label.set_text('Dead-mans: %s' % ('Ok'))
  373.             else:
  374.                 self.button_dead_label.set_text('Dead-mans: %s' % ('NOT Ok'))
  375.  
  376.             if self.buttons.horn == 0:
  377.                 self.button_horn_label.set_text('Horn: %s' % ('On'))
  378.             else:
  379.                 self.button_horn_label.set_text('Horn: %s' % ('Off'))
  380.  
  381.             if self.buttons.horn == 0:
  382.                 self.button_joy_sw_label.set_text('Joy sw: %s' % ('On'))
  383.             else:
  384.                 self.button_joy_sw_label.set_text('Joy sw: %s' % ('Off'))
  385.  
  386.            
  387.             if self.buttons.lights_far == 0:
  388.                 self.button_lights_label.set_text('Lights: %s' % ('Far'))
  389.             elif self.buttons.lights_near == 0:
  390.                 self.button_lights_label.set_text('Lights: %s' % ('Near'))
  391.             else:
  392.                 self.button_lights_label.set_text('Lights: %s' % ('Off'))
  393.      
  394.                
  395.            
  396.             self.button_phone_label.set_text('Phone: %d' % (self.buttons.phone))
  397.             self.button_wiper_label.set_text('Wiper: %d' % (self.buttons.wiper))
  398.             self.button_volume_label.set_text('Volume: %d' % (self.buttons.volume))
  399.             self.button_fans_label.set_text('Fans: %d' % (self.buttons.fans))
  400.             self.button_joy_y_label.set_text('Joystick: %d' % (self.buttons.joy_y))
  401.             #self.window.show_all()
  402.             sleep(0.1) # sleep 100 ms
  403.        
  404.        
  405.     def parse_data(self, data):
  406.         #print('parsing')
  407.         if len(data)<13:
  408.             print('too short')
  409.             return
  410.            
  411.         if data[0] == 254 and data[1] == 1 and data[2] == 254 and data[11] == 255:
  412.        
  413.                        
  414.             self.buttons.blink_left = (data[3] & (1<<7)) >> 7
  415.             self.buttons.blink_right = (data[3] & (1<<6)) >> 6
  416.             self.buttons.dead_mans1 = (data[3] & (1<<5)) >> 5
  417.             self.buttons.dead_mans2 = (data[3] & (1<<4)) >> 4
  418.             self.buttons.horn = (data[3] & (1<<3)) >> 3
  419.             self.buttons.joy_sw = (data[3] & (1<<2)) >> 2
  420.             self.buttons.lights_far = (data[3] & (1<<1)) >> 1
  421.             self.buttons.lights_near = (data[3] & (1<<0)) >> 0
  422.             self.buttons.phone = (data[4] & (1<<7)) >> 7
  423.             self.buttons.wiper = (data[4] & (1<<6)) >> 6
  424.  
  425.             self.buttons.joy_y = (data[5] << 2)
  426.             self.buttons.joy_y = self.buttons.joy_y | (data[6])
  427.  
  428.             self.buttons.volume = (data[7] << 2)
  429.             self.buttons.volume = self.buttons.volume | (data[8])
  430.  
  431.  
  432.             self.buttons.fans = (data[9] << 2)
  433.             self.buttons.fans = self.buttons.fans | (data[10])
  434.             #print('updated buttons')
  435.             #self.update_button_info()
  436.  
  437.        
  438.     def run(self):
  439.         self.window.show_all()
  440.         # You need to get the XID after window.show_all().  You shouldn't get it
  441.         # in the on_sync_message() handler because threading issues will cause
  442.         # segfaults there.
  443.         #self.xid = self.drawingarea.get_property('window').get_xid()
  444.         #print (self.xid)
  445.         #self.pipeline.set_state(Gst.State.PLAYING)
  446.         #Gdk.threads_init()
  447.         self.xid = self.drawingarea.get_property('window').get_xid()
  448.         print (self.xid)
  449.         print(self.pipeline.set_state(Gst.State.PLAYING))
  450.        
  451.         Gtk.main()
  452.  
  453.     def quit(self, window):
  454.         self.pipeline.set_state(Gst.State.NULL)
  455.         Gtk.main_quit()
  456.  
  457.     def on_sync_message(self, bus, msg):
  458.  
  459.         if msg.get_structure().get_name() == 'prepare-window-handle':
  460.             print('prepare-window-handle')
  461.             msg.src.set_property('force-aspect-ratio', True)
  462.             msg.src.set_window_handle(self.xid)
  463.             self.ximage_sink = msg.src
  464.  
  465.     def on_error(self, bus, msg):
  466.         print('on_error():', msg.parse_error())
  467.    
  468.        
  469.     def listen_on_TCP(self):
  470.         while True:
  471.             # Create a UDS socket
  472.  
  473.             try:
  474.                 self.sock.connect(server_address)
  475.             except socket.error as msg:
  476.                 #print(msg)
  477.                 sleep(10)
  478.                 continue
  479.                 #try again in 10 seconds
  480.    
  481.             print('Listening..')
  482.             while True:
  483.                 try:
  484.                     data = self.sock.recv(16)
  485.                     if data:
  486.                         #print(data[1])
  487.                         self.parse_data(data)
  488.                         #self.sock.send(data)
  489.                     else:
  490.                         self.sock.close()
  491.                         break
  492.                    
  493.                 except:
  494.                     print('something went wrong. closing socket')
  495.                     print ('Unexpected error:')
  496.                     print(sys.exc_info()[0])
  497.                     self.sock.close()
  498.                     break
  499.  
  500. webcam = Webcam()
  501. webcam.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement