gtk+ vlc, MediaPlayerEndReached event does not play next video - python

So, I'm using GTK+/VLC to create a window with a video playback area and a "next" button.
It starts by playing the first video file and clicking next button will skip to the next media file, playing it. Everything working great so far.
My problem is, if I wait for MediaPlayerEndReached to be fired, button_Next() is executed but the video does not change.
Am I missing anything?
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
import time
from os import listdir
from os.path import join
startingPath = './files/'
# ----------------------------------
class MediaWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Media Player")
self.set_decorated(False) # removes titlebar
self.move(300,150)
self.connect("destroy", Gtk.main_quit)
self.currFldrIdx = 0
self.currFileIdx = 0
self.Fldrs = []
for fldrs in sorted(listdir(startingPath)):
self.Fldrs.append(join(startingPath,fldrs))
print self.Fldrs
self.num_Fldrs = len(self.Fldrs)
# vlc
self.vlcInstance = vlc.Instance('--no-xlib')
self.vlcPlayer = self.vlcInstance.media_player_new()
def setup_objects_and_events(self):
self.pause_nextImg = Gtk.Image.new_from_icon_name(
"gtk-media-forward",
Gtk.IconSize.MENU
)
# Buttons
self.button_Next = Gtk.Button()
self.button_Next.set_image(self.pause_nextImg)
self.button_Next.connect("clicked", self.on_button_NextImg)
# Area
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(800,480)
self.draw_area.connect("realize",self._realized)
# Grid ------------------------------------
self.hbox1 = Gtk.Box()
self.hbox1.pack_start(self.draw_area, True, True, 0)
self.hbox2 = Gtk.Box()
self.hbox2.pack_start(self.button_Next, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.hbox1, True, True, 0)
self.vbox.pack_start(self.hbox2, False, True, 0)
def on_button_NextImg(self, widget):
print 'next!'
num_FldrFiles = len(listdir(self.Fldrs[self.currFldrIdx]))
self.currFileIdx = self.currFileIdx+1 if self.currFileIdx+1<num_FldrFiles else 0
fileToShow = join(self.Fldrs[self.currFldrIdx], sorted(listdir(self.Fldrs[self.currFldrIdx]))[self.currFileIdx])
print 'now showing' + fileToShow
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.vlcPlayer.play()
def _realized(self, widget, data=None):
fileToShow = join(self.Fldrs[self.currFldrIdx], sorted(listdir(self.Fldrs[self.currFldrIdx]))[self.currFileIdx])
self.win_id = widget.get_window().get_xid()
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.events = self.vlcPlayer.event_manager()
self.events.event_attach(vlc.EventType.MediaPlayerEndReached, self.EventManager)
self.vlcPlayer.play()
def EventManager(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
print "Event reports - finished, playing next"
self.button_Next.clicked()
# ----------------------------------
if __name__ == '__main__':
# Create
win = MediaWindow()
# Setup
win.setup_objects_and_events()
win.show_all()
Gtk.main()

Your problem is described here:
the libvlc API is not reentrant within its callbacks https://forum.videolan.org/viewtopic.php?f=32&t=80305
and here: https://forum.videolan.org/viewtopic.php?t=82502
You should typically have a mainloop in your application (gobject.mainloop(), or Qt mainloop), so you should instead register a method to restart the player from there
This is bit mucked about with for the file names but your code now registers the GObject.idle_add() function that is required.
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
import time
from os import listdir
from os.path import join
startingPath = './files/'
# ----------------------------------
class MediaWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Media Player")
self.autoPlay = 0
self.set_decorated(False) # removes titlebar
self.move(300,150)
self.connect("destroy", Gtk.main_quit)
self.currFldrIdx = 0
self.currFileIdx = 0
self.Fldrs = ['/home/public/2005.mp3','/home/public/happy.mp3','/home/public/vp.mp3']
#for fldrs in sorted(listdir(startingPath)):
# self.Fldrs.append(join(startingPath,fldrs))
self.num_Fldrs = len(self.Fldrs) - 1
# vlc
self.vlcInstance = vlc.Instance('--no-xlib')
self.vlcPlayer = self.vlcInstance.media_player_new()
def setup_objects_and_events(self):
self.pause_nextImg = Gtk.Image.new_from_icon_name(
"gtk-media-forward",
Gtk.IconSize.MENU
)
# Buttons
self.button_Next = Gtk.Button()
self.button_Next.set_image(self.pause_nextImg)
self.button_Next.connect("clicked", self.on_button_NextImg)
# Area
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(800,480)
self.draw_area.connect("realize",self._realized)
# Grid ------------------------------------
self.hbox1 = Gtk.Box()
self.hbox1.pack_start(self.draw_area, True, True, 0)
self.hbox2 = Gtk.Box()
self.hbox2.pack_start(self.button_Next, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.hbox1, True, True, 0)
self.vbox.pack_start(self.hbox2, False, True, 0)
def on_button_NextImg(self, widget=None):
self.currFileIdx += 1
if self.currFileIdx > self.num_Fldrs:
self.currFileIdx = 0
fileToShow = self.Fldrs[self.currFileIdx]
media = self.vlcInstance.media_new_path(fileToShow)
self.vlcPlayer.set_media(media)
if self.vlcPlayer.play() == -1:
print ("error playing",fileToShow)
else:
print("now playing",fileToShow)
def _realized(self, widget, data=None):
fileToShow = self.Fldrs[self.currFldrIdx]
self.win_id = widget.get_window().get_xid()
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.events = self.vlcPlayer.event_manager()
self.events.event_attach(vlc.EventType.MediaPlayerEndReached, self.EventManager)
self.vlcPlayer.play()
def EventManager(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
GObject.idle_add(self.on_button_NextImg)
# ----------------------------------
if __name__ == '__main__':
# Create
win = MediaWindow()
# Setup
win.setup_objects_and_events()
win.show_all()
Gtk.main()

Related

Making GStreamer video/audio in Python smooth and loop

I'm trying to use GStreamer to loop MPEG-4 files smoothly. I want to play the video and audio if there is any and loop the playback. My app uses GTK for UI.
Right now I have three problems:
The video playback is choppy/jerky on the Raspberry Pi 4, I'm running it on. By choppy/jerky, I mean that every ~1-2 seconds, playback freezes for some fraction of a second. When playing the same video in the VLC app, it is smooth.
Audio is not played. Again, when played in VLC, the audio is there as expected. It was my understanding that playbin elements automatically play both audio and video.
When the end of the video is reached, the last frame is frozen for 1-2 seconds before the video starts playing from the first frame again.
I currently have the following code.
video_player.py:
#!/usr/bin/python3
import os
import gi
gi.require_version("Gst", "1.0")
gi.require_version("Gtk", "3.0")
gi.require_version("GstVideo", "1.0")
from gi.repository import Gst, Gtk, GstVideo
class VideoPlayer(Gtk.DrawingArea):
def __init__(self, video_uri: str, loop: bool):
super().__init__()
self.__loop = loop
self.__video_uri = "file:///" + os.path.abspath(video_uri)
self.__xid = None
Gst.init(None)
self.connect("realize", self.__on_realize)
self.set_size_request(1920, 1080) # Hardcoded for this example
self.__playbin = Gst.ElementFactory.make("playbin", "player")
self.__bus = self.__playbin.get_bus()
self.__bus.add_signal_watch()
self.__bus.connect("message::eos", self.__on_video_end)
self.__bus.enable_sync_message_emission()
self.__bus.connect("sync-message::element", self.__on_sync_message)
self.__playbin.set_property("uri", self.__video_uri)
def __on_realize(self, widget: Gtk.Window, data=None) -> None:
window = widget.get_window()
self.__xid = window.get_xid()
def __on_sync_message(self, bus: Gst.Bus, message: Gst.Message) -> None:
if message.get_structure().get_name() == "prepare-window-handle":
image_sink = message.src
image_sink.set_property("force-aspect-ratio", True)
image_sink.set_window_handle(self.__xid)
def __on_video_end(self, bus: Gst.Bus, message: Gst.Message) -> None:
if self.__loop:
self.__playbin.set_state(Gst.State.NULL)
self.__playbin.set_state(Gst.State.PLAYING)
def play(self) -> None:
if self.__playbin.get_state(0).state != Gst.State.PLAYING:
self.__playbin.set_state(Gst.State.PLAYING)
main.py:
#!/usr/bin/python3
from video_player import VideoPlayer
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
window = Gtk.Window()
video_player = VideoPlayer("test_video.mp4", loop=True)
window.add(video_player)
window.fullscreen()
window.show_all()
video_player.play()
Gtk.main()
This answer provides an example that uses VLC; This was accepted by the author of the question (see comments) - GStreamer on Raspberry Pi 4 and other similar SOCs is often times laggy and a soft solution, without starting to modify the Gstreamer library, is probably not going to help the OP.
Please notice that the code has been inspired by https://www.codementor.io/#princerapa/python-media-player-vlc-gtk-favehuy2b but has been modified to accommodate for your needs.
The required change to make the video loop, which is not provided in the aforementioned link is passing the argument '--input-repeat=-1' to the vlcinstance.
Install dependencies (this assumes you already have gtk installed)
pip install python-vlc
Your code:
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
MRL = "" # File to play
WIDTH = 300
HEIGHT = 300
class ApplicationWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Python-Vlc Media Player")
self.player_paused=False
self.is_player_active = False
self.connect("destroy",Gtk.main_quit)
def show(self):
self.show_all()
def setup_objects_and_events(self):
self.playback_button = Gtk.Button()
self.stop_button = Gtk.Button()
self.play_image = Gtk.Image.new_from_icon_name(
"gtk-media-play",
Gtk.IconSize.MENU
)
self.pause_image = Gtk.Image.new_from_icon_name(
"gtk-media-pause",
Gtk.IconSize.MENU
)
self.stop_image = Gtk.Image.new_from_icon_name(
"gtk-media-stop",
Gtk.IconSize.MENU
)
self.playback_button.set_image(self.play_image)
self.stop_button.set_image(self.stop_image)
self.playback_button.connect("clicked", self.toggle_player_playback)
self.stop_button.connect("clicked", self.stop_player)
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(WIDTH,HEIGHT)
self.draw_area.connect("realize",self._realized)
self.hbox = Gtk.Box(spacing=6)
self.hbox.pack_start(self.playback_button, True, True, 0)
self.hbox.pack_start(self.stop_button, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.draw_area, True, True, 0)
self.vbox.pack_start(self.hbox, False, False, 0)
def stop_player(self, widget, data=None):
self.player.stop()
self.is_player_active = False
self.playback_button.set_image(self.play_image)
def toggle_player_playback(self, widget, data=None):
"""
Handler for Player's Playback Button (Play/Pause).
"""
if self.is_player_active == False and self.player_paused == False:
self.player.play()
self.playback_button.set_image(self.pause_image)
self.is_player_active = True
elif self.is_player_active == True and self.player_paused == True:
self.player.play()
self.playback_button.set_image(self.pause_image)
self.player_paused = False
elif self.is_player_active == True and self.player_paused == False:
self.player.pause()
self.playback_button.set_image(self.play_image)
self.player_paused = True
else:
pass
def _realized(self, widget, data=None):
self.vlcInstance = vlc.Instance("--no-xlib", "--input-repeat=-1")
self.player = self.vlcInstance.media_player_new()
win_id = widget.get_window().get_xid()
self.player.set_xwindow(win_id)
self.player.set_mrl(MRL)
self.player.play()
self.playback_button.set_image(self.pause_image)
self.is_player_active = True
if __name__ == '__main__':
if not sys.argv[1:]:
print("Exiting \nMust provide the MRL.")
sys.exit(1)
if len(sys.argv[1:]) == 1:
MRL = sys.argv[1]
window = ApplicationWindow()
window.setup_objects_and_events()
window.show()
Gtk.main()
window.player.stop()
window.vlcInstance.release()

How to filter Gtk.Flowbox() children with Gtk.EntrySearch()?

I would like Gtk.FlowBox() to display only children that correspond to the text inserted in Gtk.SearchEntry(), like a search filter.
I think it is possible to do that with Gtk.FlowBox.FilterFunc() and/or Gtk.FlowBox.set_filter_func() but I don't know how and found no example using these functions on the web.
Here is my code:
#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
class FlowBoxWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_border_width(10)
self.set_default_size(300, 200)
header = Gtk.HeaderBar(title="Flow Box")
header.set_subtitle("Flowbox filtering")
header.props.show_close_button = True
self.set_titlebar(header)
box = Gtk.Box()
box.set_orientation(Gtk.Orientation.VERTICAL)
search_entry = Gtk.SearchEntry()
search_entry.connect('search_changed', self.flowbox_filter)
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
scrolled.set_min_content_height(200)
self.flowbox = Gtk.FlowBox()
self.flowbox.set_valign(Gtk.Align.START)
self.flowbox.set_max_children_per_line(8)
# Fill flowbox
text = ['ABC','A','BCD','TCUNF','GNCBC','JFABC','LDNAB',
'JJVIC','HZACB','BESEI','VEISEI','GJBVV','abcii','fjbci',
'fsefsi','aabc','fesfoo','fffba','jjfsi'
]
for t in text:
label = Gtk.Label(t)
self.flowbox.add(label)
scrolled.add(self.flowbox)
box.pack_start(search_entry, False, False, 2)
box.pack_start(scrolled, False, False, 2)
self.add(box)
self.show_all()
def flowbox_filter(self, search_entry):
def filter_func(fb_child, text):
if text in [label.get_text() for label in fb_child.get_children()]:
return True
else:
return False
text = search_entry.get_text()
self.flowbox.set_filter_func(filter_func, text)
win = FlowBoxWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
Thank you in advance.
I found the solution : instead of searching for the text in FlowBoxChild.get_children(), assign a name to each child while creating them, then check if text match with this name when filtering. It works fine, like that and FlowBox Children get back when clearing search entry field.
Here is the code :
#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
class FlowBoxWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_border_width(10)
self.set_default_size(300, 200)
header = Gtk.HeaderBar(title="Flow Box")
header.set_subtitle("Flowbox filtering")
header.props.show_close_button = True
self.set_titlebar(header)
box = Gtk.Box()
box.set_orientation(Gtk.Orientation.VERTICAL)
search_entry = Gtk.SearchEntry()
search_entry.connect('search_changed', self.flowbox_filter)
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
scrolled.set_min_content_height(200)
self.flowbox = Gtk.FlowBox()
self.flowbox.set_valign(Gtk.Align.START)
self.flowbox.set_max_children_per_line(8)
# Fill flowbox
text = ['ABC','A','BCD','TCUNF','GNCBC','JFABC','LDNAB',
'JJVIC','HZACB','BESEI','VEISEI','GJBVV','abcii','fjbci',
'fsefsi','aabc','fesfoo','fffba','jjfsi'
]
for t in text:
label = Gtk.Label(t)
child = Gtk.FlowBoxChild()
child.set_name(t)
child.add(label)
self.flowbox.add(child)
scrolled.add(self.flowbox)
box.pack_start(search_entry, False, False, 2)
box.pack_start(scrolled, False, False, 2)
self.add(box)
self.show_all()
def flowbox_filter(self, search_entry):
def filter_func(fb_child, text):
if text in fb_child.get_name():
return True
else:
return False
text = search_entry.get_text()
self.flowbox.set_filter_func(filter_func, text)
win = FlowBoxWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

How to properly show and hide GTK window in python

So I have the following code (python 2.7) that checks for a combination of keypresses and shows/hides a gtk window with a few gtk entry boxes. The show/hide works until the window locks up and stops responding, and the inner part of the window turns black. I have to kill the process and start it up again once that window turns black. I've tried all different combinations of show_all() and returning True after hiding the window to no avail. I'm not sure what I'm doing wrong here.
In the end I'd like to be able to press this key combination and show/hide this window without the contents going away.
#!/usr/bin/python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import pyxhook
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Configurator")
self.box = Gtk.Box(spacing=6)
self.add(self.box)
self.ipEntry = Gtk.Entry()
self.ipEntry.set_text("IP Address")
self.maskEntry = Gtk.Entry()
self.maskEntry.set_text("NetMask")
self.gatewayEntry = Gtk.Entry()
self.gatewayEntry.set_text("gatewayEntry")
self.button1 = Gtk.Button(label="Save")
self.button1.connect("clicked", self.on_button1_clicked)
self.box.pack_start(self.ipEntry, True, True, 0)
self.box.pack_start(self.maskEntry, True, True, 0)
self.box.pack_start(self.gatewayEntry, True, True, 0)
self.box.pack_start(self.button1, True, True, 0)
#catch window destroy event and stop it from happening
self.connect('delete-event', self.on_destroy)
def on_button1_clicked(self, widget):
print("Hello")
def on_destroy(self, widget=None, *data):
print("tried to destroy")
self.hide()
return True
#list of ascii keypresses to test if a certain combination of keys is pressed
keypresses = []
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
win.set_keep_above(True)
def OnKeyboardEvent(event):
#ascii 227 is l_control, ascii 225 is l_shift, ascii 120 is x
#bring the following external variables into the scope of this function
global keypresses
global win
#check if gtk window is hidden or visible
isVisible = win.get_property("visible")
#store our keypress if it is worthy of being stored (we started with a control character)
if event.Ascii == 227 or ( len(keypresses) >= 1 and keypresses[0] == 227 ):
print("here" + str(len(keypresses)))
keypresses.append(event.Ascii)
#check if we have three items in keypresses to compare, then see if it's the right combination
if len(keypresses) == 3 and keypresses[0] == 227 and keypresses[1] == 225 and keypresses[2] == 120:
#show/hide our window
if isVisible:
win.hide()
del keypresses[:]
keypresses = []
else:
win.show_all()
#clear out our list to compare again
del keypresses[:]
keypresses = []
elif len(keypresses) >= 3:
del keypresses[:]
keypresses = []
#create instance of hook manager
HookManager = pyxhook.HookManager()
#define our callback to fire when a key is pressed
HookManager.KeyDown = OnKeyboardEvent
#hook the keyboard
HookManager.HookKeyboard()
#start our listener
HookManager.start()
Gtk.main()
#close the hook listener when gtk main loop exits
HookManager.cancel()
Here is a small hack that tests the window show/hide when pressing F5. When you press it a second window will show or hide and i've tested for sometime without problems. Maybe it's the HookManager that somehow is messing with the Gtk/Glib mainloop. Nonetheless my method only works if there is a window to grab the key presses, so you will need, indeed, some form of grabbing key presses if your goal is to have no GUI:
#!/usr/bin/python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
#import pyxhook
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Configurator")
self.box = Gtk.Box(spacing=6)
self.add(self.box)
self.ipEntry = Gtk.Entry()
self.ipEntry.set_text("IP Address")
self.maskEntry = Gtk.Entry()
self.maskEntry.set_text("NetMask")
self.gatewayEntry = Gtk.Entry()
self.gatewayEntry.set_text("gatewayEntry")
self.button1 = Gtk.Button(label="Save")
self.button1.connect("clicked", self.on_button1_clicked)
self.box.pack_start(self.ipEntry, True, True, 0)
self.box.pack_start(self.maskEntry, True, True, 0)
self.box.pack_start(self.gatewayEntry, True, True, 0)
self.box.pack_start(self.button1, True, True, 0)
#catch window destroy event and stop it from happening
self.connect('delete-event', self.on_destroy)
self.connect('key-press-event', self.on_keypress)
def on_keypress(self, widget, event):
global w
if event.keyval == Gdk.KEY_F5:
isVisible = w.get_property("visible")
if (isVisible):
w.hide()
else:
w.show()
print("Keypress")
def on_button1_clicked(self, widget):
print("Hello")
def on_destroy(self, widget=None, *data):
print("tried to destroy")
self.hide()
return False
w = MyWindow()
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
win.set_keep_above(True)
Gtk.main()

Music not playing in Gtk3/Gstreamer app

I have looked at this tutorial,http://lzone.de/media+player+with+gstreamer+and+pygi, on how to stream audio from the web using Gtk3 and Gstreamer. I have working code minus the ability for actual music to be played. I need help, I'm new to making apps, but I think the issues stems from self.player.set_property('uri', self.uri) not doing its magic to fetch the music from the url self.uri = 'http://mp3channels.webradio.antenne.de/chillout'
Here is my source:
import sys, os, pygtk
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gtk
from gi.repository import Gst
GObject.threads_init()
Gst.init(None)
class PlaybackInterface():
def __init__(self):
self.playing = False
# A free example sound track
self.uri = 'http://mp3channels.webradio.antenne.de/chillout'
# GTK window and widgets
self.window = Gtk.Window()
self.window.set_size_request(300,50)
vbox = Gtk.Box(Gtk.Orientation.HORIZONTAL, 0)
vbox.set_margin_top(3)
vbox.set_margin_bottom(3)
self.window.add(vbox)
self.playButtonImage = Gtk.Image()
self.playButtonImage.set_from_stock("gtk-media-play", Gtk.IconSize.BUTTON)
self.playButton = Gtk.Button.new()
self.playButton.add(self.playButtonImage)
self.playButton.connect("clicked", self.playToggled)
Gtk.Box.pack_start(vbox, self.playButton, False, False, 0)
self.slider = Gtk.HScale()
self.slider.set_margin_left(6)
self.slider.set_margin_right(6)
self.slider.set_draw_value(False)
self.slider.set_range(0, 100)
self.slider.set_increments(1, 10)
Gtk.Box.pack_start(vbox, self.slider, True, True, 0)
self.label = Gtk.Label(label='0:00')
self.label.set_margin_left(6)
self.label.set_margin_right(6)
Gtk.Box.pack_start(vbox, self.label, False, False, 0)
self.window.show_all()
# GStreamer Setup
self.player = Gst.ElementFactory.make('playbin', None)
self.player.set_property('uri', self.uri)
# Set properties
# bus = self.player.get_bus()
# bus.connect("message", self.on_message)
# self.player.connect("about-to-finish", self.on_finished)
def on_message(self, bus, message):
t = message.type
if t == Gst.Message.EOS:
self.player.set_state(Gst.State.NULL)
self.playing = False
elif t == Gst.Message.ERROR:
self.player.set_state(Gst.State.NULL)
err, debug = message.parse_error()
print "Error: %s" % err, debug
self.playing = False
self.updateButtons()
def on_finished(self, player):
self.playing = False
self.slider.set_value(0)
self.label.set_text("0:00")
self.updateButtons()
def play(self):
self.player.set_state(Gst.State.PLAYING)
GObject.timeout_add(1000, self.updateSlider)
def stop(self):
self.player.set_state(Gst.State.NULL)
def playToggled(self, w):
self.slider.set_value(0)
self.label.set_text("0:00")
if(self.playing == False):
self.play()
else:
self.stop()
self.playing=not(self.playing)
self.updateButtons()
def updateSlider(self):
if(self.playing == False):
return False # cancel timeout
try:
if self.IS_GST010:
nanosecs = self.player.query_position(Gst.Format.TIME)[2]
duration_nanosecs = self.player.query_duration(Gst.Format.TIME)[2]
else:
nanosecs = self.player.query_position(Gst.Format.TIME)[1]
duration_nanosecs = self.player.query_duration(Gst.Format.TIME)[1]
# block seek handler so we don't seek when we set_value()
# self.slider.handler_block_by_func(self.on_slider_change)
duration = float(duration_nanosecs) / Gst.SECOND
position = float(nanosecs) / Gst.SECOND
self.slider.set_range(0, duration)
self.slider.set_value(position)
self.label.set_text ("%d" % (position / 60) + ":%02d" % (position % 60))
except Exception as e:
# pipeline must not be ready and does not know position
print e
pass
return True
def updateButtons(self):
if(self.playing == False):
self.playButtonImage.set_from_stock("gtk-media-play", Gtk.IconSize.BUTTON)
else:
self.playButtonImage.set_from_stock("gtk-media-stop", Gtk.IconSize.BUTTON)
player = PlaybackInterface()
Gtk.main()
Gstreamer has a lot of dependencies. Peep the link https://raw.githubusercontent.com/Psychtoolbox-3/Psychtoolbox-3/beta/Psychtoolbox/PsychDocumentation/GStreamer.m. I uploaded working code on my Github account (At least on my machine) that will play and stop an audio stream from an http source. https://github.com/jchiefelk/musicplayer

Python Gtk3 Box doesn't hide

I'm writing an application. It has a sidebar, which I want to be shut on startup. I have tried using self.sidebarbox.hide(). This only seems to work when I put it in a function that is linked to a button. When I press the button it shows/hides. How can I fix this?
Here is my code (It's written in python3 but will run in python2.):
from gi.repository import Gtk, Gio
from gi.repository import WebKit
HEIGHT = 500
WIDTH = 800
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Resolution")
self.set_border_width(0)
self.set_default_size(WIDTH, HEIGHT)
hb = Gtk.HeaderBar()
hb.props.show_close_button = True
hb.props.title = "Resolution"
hb.props.subtitle = "Digital Maths Revision Guide"
self.set_titlebar(hb)
button = Gtk.Button()
icon = Gio.ThemedIcon(name="emblem-system-symbolic")
image = Gtk.Image.new_from_gicon(icon, 1)
button.add(image)
button.connect("clicked", self.sidebarShowHide)
button.set_focus_on_click(False)
hb.pack_start(button)
self.sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
toplevelbox.pack_start(self.sidebarbox, False, False, 0)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
self.sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
self.sidebarbox.pack_start(label, True, True, 0)
scroller = Gtk.ScrolledWindow()
content = WebKit.WebView()
scroller.add(content)
toplevelbox.pack_start(scroller, True, True, 0)
content.open("/home/oliver/resolution/placeholder.html")
#This should make the sidebar hide.
self.sidebarbox.hide()
#This works. The sidebar does show/hide.
def sidebarShowHide(self, button):
if self.sidebarbox.get_visible():
self.sidebarbox.hide()
else:
self.sidebarbox.show()
def search_changed(self, searchentry):
pass
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
You're calling show_all() which changes the state of all contained widgets to visible, including the sidebar.
If you still like to use it (it's convenient after all) one way is you're own method, which will hide the sidebar after showing all, e.g:
from gi.repository import Gtk, Gio
from gi.repository import WebKit
HEIGHT = 500
WIDTH = 800
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Resolution")
self.set_border_width(0)
self.set_default_size(WIDTH, HEIGHT)
hb = Gtk.HeaderBar()
hb.props.show_close_button = True
hb.props.title = "Resolution"
hb.props.subtitle = "Digital Maths Revision Guide"
self.set_titlebar(hb)
button = Gtk.Button()
icon = Gio.ThemedIcon(name="emblem-system-symbolic")
image = Gtk.Image.new_from_gicon(icon, 1)
button.add(image)
button.connect("clicked", self.sidebarShowHide)
button.set_focus_on_click(False)
hb.pack_start(button)
self.sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
toplevelbox.pack_start(self.sidebarbox, False, False, 0)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
self.sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
self.sidebarbox.pack_start(label, True, True, 0)
scroller = Gtk.ScrolledWindow()
content = WebKit.WebView()
scroller.add(content)
toplevelbox.pack_start(scroller, True, True, 0)
content.open("/home/oliver/resolution/placeholder.html")
def inital_show(self):
win.show_all()
self.sidebarbox.hide();
#This works. The sidebar does show/hide.
def sidebarShowHide(self, button):
if self.sidebarbox.get_visible():
self.sidebarbox.hide()
else:
self.sidebarbox.show()
def search_changed(self, searchentry):
pass
if __name__ == '__main__':
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.inital_show()
Gtk.main()
Note the initial_show() method, and calling it from the main section.

Categories