You are not logged in.
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
Offline