You are not logged in.

#1 2017-06-25 06:50:16

Debasish Patra
Member
Registered: 2014-03-06
Posts: 64

[Solved] Python GtkScale Issue/Confusion

Hi,
I am trying to make a simple music player which takes GST 1.0 and GTK 3 into consideration.
The program is quite simple. But i am getting confused over GtkScale Widget which is used to move the slider as the music plays like a progressbar.

But the progressbar should also be clickable and can be used to seek.
I can only see "value-changed" event used for GtkScale to change value.

There is a separate thread which keeps updating the GtkScale

But if i drag the Scale widget, it create a delay or shuttering while playing music. Until i do that the music just plays fine.

Please note that i have not handled how the additional thread is stopped yet.
There could be some redundant code as well which needs cleanup.

If the whole program looks overwhelming, anyone can just download the program and run like "<filename> full_path_of_audio_file" i.e. "./MusicPlayer $PWD/1.mp3"

Any suggesstion/help would be nice.

#!/usr/bin/python
import sys
import gi
import threading
import time
gi.require_version('Gst', '1.0')
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gst, GLib, GObject
from subprocess import call
from time import strftime
from threading import Thread

class Main(Gtk.Window):
	def __init__(self):
		Gtk.init()
		Gst.init()

		self.seekbarposition = 0.0

		Gtk.Window.__init__(self, title="Music Player")
		self.set_border_width(20)
		self.set_resizable(True)

		self.playbutton = Gtk.Button.new_from_stock(Gtk.STOCK_MEDIA_PLAY)
		self.pausebutton = Gtk.Button.new_from_stock(Gtk.STOCK_MEDIA_PAUSE)
		self.resetbutton = Gtk.Button.new_from_stock(Gtk.STOCK_MEDIA_STOP)
		self.timestatus = Gtk.Label("")

		self.grid = Gtk.Grid()
		self.add(self.grid)
#		self.grid.set_homogeneous(True)
#		self.grid.set_spacing(True)

		self.resetbutton.connect("clicked",self.reset)
		self.add(self.resetbutton)


		self.playbutton.connect("clicked",self.play)
		self.add(self.playbutton)

		self.pausebutton.connect("clicked",self.pause)
		self.add(self.pausebutton)

		self.add(self.timestatus)

		self.grid.attach(self.resetbutton,1,0,1,1)
		self.grid.attach(self.playbutton,2,0,1,1)
		self.grid.attach(self.pausebutton,3,0,1,1)

		self.adjust1 = Gtk.Adjustment(0, 0, 100, 5, 100, 0)
		self.adjust2 = Gtk.Adjustment(0, 0, 100, 1, 100, 0)

		self.volbutton = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL, adjustment=self.adjust1)
		self.volbutton.set_hexpand(True)
		self.volbutton.connect("value-changed", self.change_volume)
		self.grid.attach(self.volbutton,1,2, 3, 1)

		self.seekbar = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL, adjustment=self.adjust2)
		self.seekbar.set_hexpand(True)
		self.seekbar.set_draw_value(False)
		self.seekbar.connect("value-changed", self.origseek)
		self.grid.attach(self.seekbar,1,3, 3, 1)
		self.grid.attach_next_to(self.timestatus,self.seekbar,Gtk.PositionType.BOTTOM,3,1)

		self.pipeline = Gst.Pipeline.new("Pipe");
		print("Now PLaying : "+sys.argv[1])
		self.player = Gst.ElementFactory.make("playbin","src")
		self.player.set_property("uri","file://"+sys.argv[1])
		self.pipeline.add(self.player)
		self.pipeline.set_state(Gst.State.NULL)

		self.activity_mode = False
		self.breakThread = True
		self.startupdating = True
		self.t1 = Thread(target=self.hello, args=())
		self.t1.start()

#		self.timeUpdateThread = Thread(target=self.updateTimeInMusic, args=())
#		self.timeUpdateThread.start()
		print("In the End")
#		self.seekbar.set_value(110*float(self.pipeline.query_position(Gst.Format.TIME)[1]/self.pipeline.query_duration(Gst.Format.TIME)[1]+0.1))

	def play(self, widget):
		print("Play")
		self.pipeline.set_state(Gst.State.PLAYING)

	def origseek():
#		self.startupdating = False
#		self.pipeline.set_state(Gst.State.PAUSED)
		#t1 = Thread(target=self.hello, args=())
		print("Inside Seek")
#		print((self.pipeline.query_duration(Gst.Format.TIME)[1]*self.seekbar.get_value())/100)
#		self.pipeline.set_state(Gst.State.PAUSED)
		self.pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, (self.pipeline.query_duration(Gst.Format.TIME)[1]*self.seekbar.get_value())/100)
#		self.pipeline.set_state(Gst.State.PLAYING)
#		self.pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, (self.pipeline.query_duration(Gst.Format.TIME)[1]*self.seekbar.get_value())/100)
#		self.pipeline.set_state(Gst.State.PLAYING)
#		t1 = Thread(target=self.hello, args=())
#		t1.start()
#		t2 = Thread(target=self.hello,args=())
#		self.startupdating = True
#		t2.start()
#	def updateTimeInMusic(self):
#		while True:
#			time.sleep(1.0)
#			Glib.idle_add(self.timestatus,set_text(str(self.gettime(self.pipeline.query_position(Gst.Format.TIME)[1]))+"/"+str(self.gettime(self.pipeline.query_duration(Gst.Format.TIME)[1]))))

	def hello(self):
#		while self.startupdating:
		while True:
#			self.stopupdating=True
#			t1 = Thread(target=self.hello, args=())
#			t1.start()
#			self.stopupdating=False
			print("Got Inside")
			time.sleep(1.0)
			if self.pipeline.query_duration(Gst.Format.TIME)[1] != 0:
				print(100*float(self.pipeline.query_position(Gst.Format.TIME)[1]/self.pipeline.query_duration(Gst.Format.TIME)[1]))
				GLib.idle_add(self.seekbar.set_value,(100*float(self.pipeline.query_position(Gst.Format.TIME)[1]/self.pipeline.query_duration(Gst.Format.TIME)[1])))
				GLib.idle_add(self.timestatus.set_text,(str(self.gettime(self.pipeline.query_position(Gst.Format.TIME)[1]))+"/"+str(self.gettime(self.pipeline.query_duration(Gst.Format.TIME)[1]))))
				print(str(self.gettime(self.pipeline.query_position(Gst.Format.TIME)[1]))+"/"+str(self.gettime(self.pipeline.query_duration(Gst.Format.TIME)[1])))
				print(float(self.pipeline.query_position(Gst.Format.TIME)[1]/self.pipeline.query_duration(Gst.Format.TIME)[1]))
			else:
				self.timestatus.set_text("")
#			if self.stopupdating == False:
#				return False

	def pause(self,widget):
		print("Pause")
		self.pipeline.set_state(Gst.State.PAUSED)
		self.breakThread = False

	def reset(self,widget):
		print("reset")
		self.pipeline.set_state(Gst.State.NULL)
		self.pipeline.set_state(Gst.State.READY)

	def change_volume(self, widget):
		call(["amixer", "--quiet", "set", "Master", str(int(widget.get_value()))+"%"])

	def gettime(self, num):
		hr = int(num/(1000000000*3600))
		min = int(num/(1000000000*60)) - hr*60
		sec = int(num/1000000000) - hr*3600 - min*60
		return str(hr).zfill(2)+":"+str(min).zfill(2)+":"+str(sec).zfill(2)

win = Main()
win.connect("destroy", Gtk.main_quit,"Wm destroy")
win.set_default_size(300,50)
win.show_all()
Gtk.main()

Last edited by Debasish Patra (2017-07-01 12:09:32)


Keep Calm, And Enjoy Life smile

Offline

Board footer

Powered by FluxBB