summaryrefslogtreecommitdiff
path: root/voctogui/lib/videodisplay.py
blob: 42724acbab20fa8a2a51202730ad4a25ddd6ca1f (plain)
  1. import logging
  2. from gi.repository import Gst, Gtk
  3. class VideoDisplay:
  4. """ Displays a Voctomix-Video-Stream into a GtkWidget """
  5. def __init__(self, port, videowidget, audiolevelwidget=None, playaudio=False, allowoverlay=False):
  6. self.log = logging.getLogger('VideoDisplay[%u]' % port)
  7. pipeline = """
  8. videotestsrc !
  9. timeoverlay !
  10. video/x-raw,width=1920,height=1080 !
  11. """.format(
  12. port=port
  13. )
  14. if allowoverlay:
  15. pipeline += """
  16. videoconvert !
  17. cairooverlay name=overlay !
  18. videoconvert !
  19. """
  20. pipeline += """
  21. xvimagesink name=v
  22. """
  23. if audiolevelwidget or playaudio:
  24. pipeline += """
  25. audiotestsrc wave=blue-noise !
  26. audio/x-raw !
  27. level name=lvl interval=50000000 !
  28. """
  29. if playaudio:
  30. pipeline += """
  31. alsasink
  32. """
  33. else:
  34. pipeline += """
  35. fakesink
  36. """
  37. self.log.info('launching gstreamer-pipeline for widget %s "%s":\n%s', videowidget.get_name(), Gtk.Buildable.get_name(videowidget), pipeline)
  38. self.pipeline = Gst.parse_launch(pipeline)
  39. videowidget.realize()
  40. self.xid = videowidget.get_property('window').get_xid()
  41. bus = self.pipeline.get_bus()
  42. bus.add_signal_watch()
  43. bus.enable_sync_message_emission()
  44. bus.connect('message::error', self.on_error)
  45. bus.connect("sync-message::element", self.on_syncmsg)
  46. self.draw_callback = None
  47. if audiolevelwidget:
  48. self.levelrms = [0, 0]
  49. self.audiolevelwidget = audiolevelwidget
  50. self.audiolevelwidget.connect('draw', self.on_level_draw)
  51. bus.connect("message::element", self.on_level)
  52. def run(self):
  53. self.pipeline.set_state(Gst.State.PLAYING)
  54. def set_overlay_callback(self, callback):
  55. if callback:
  56. if not self.draw_callback:
  57. self.draw_callback = self.pipeline.get_by_name('overlay').connect('draw', callback)
  58. else:
  59. print('disconnect')
  60. self.pipeline.get_by_name('overlay').disconnect(self.draw_callback)
  61. self.draw_callback = None
  62. def on_syncmsg(self, bus, msg):
  63. if msg.get_structure().get_name() == "prepare-window-handle":
  64. self.log.info('setting xvimagesink window-handle to %s', self.xid)
  65. msg.src.set_window_handle(self.xid)
  66. def on_error(self, bus, msg):
  67. self.log.error('on_error(): %s', msg.parse_error())
  68. def on_level_draw(self, widget, cr):
  69. cr.set_source_rgb(1, 1, 1)
  70. cr.set_line_width(10)
  71. cr.move_to(15, 0)
  72. cr.line_to(15, self.levelrms[0]*-20)
  73. cr.stroke()
  74. def on_level(self, bus, msg):
  75. if msg.src.name != 'lvl':
  76. return
  77. if msg.type != Gst.MessageType.ELEMENT:
  78. return
  79. self.levelpeaks = msg.get_structure().get_value('peak')
  80. self.levelrms = msg.get_structure().get_value('rms')
  81. self.audiolevelwidget.queue_draw()