smooth stream switch
Fixed using pty and select to pipe streamNum to a running nrsc5 without disrupting process operation.
This commit is contained in:
parent
1f1aaaa556
commit
157419e838
40
nrsc5-dui.py
40
nrsc5-dui.py
@ -21,7 +21,7 @@
|
|||||||
# Updated and enhanced by markjfine ~ 2021
|
# Updated and enhanced by markjfine ~ 2021
|
||||||
|
|
||||||
#import os, sys, shutil, re, gtk, gobject, json, datetime, numpy, glob, time, platform
|
#import os, sys, shutil, re, gtk, gobject, json, datetime, numpy, glob, time, platform
|
||||||
import os, sys, shutil, re, json, datetime, numpy, glob, time, platform
|
import os, pty, select, sys, shutil, re, json, datetime, numpy, glob, time, platform
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from threading import Timer, Thread
|
from threading import Timer, Thread
|
||||||
from dateutil import tz
|
from dateutil import tz
|
||||||
@ -72,6 +72,8 @@ class NRSC5_DUI(object):
|
|||||||
self.mapFile = os.path.join(resDir, "map.png")
|
self.mapFile = os.path.join(resDir, "map.png")
|
||||||
self.defaultSize = [490,250] # default width,height of main app
|
self.defaultSize = [490,250] # default width,height of main app
|
||||||
self.nrsc5 = None # nrsc5 process
|
self.nrsc5 = None # nrsc5 process
|
||||||
|
self.nrsc5master = None
|
||||||
|
self.nrsc5slave = None
|
||||||
self.playerThread = None # player thread
|
self.playerThread = None # player thread
|
||||||
self.playing = False # currently playing
|
self.playing = False # currently playing
|
||||||
self.statusTimer = None # status update timer
|
self.statusTimer = None # status update timer
|
||||||
@ -85,6 +87,7 @@ class NRSC5_DUI(object):
|
|||||||
self.lastXHDR = "" # the last XHDR data received
|
self.lastXHDR = "" # the last XHDR data received
|
||||||
self.stationStr = "" # current station frequency (string)
|
self.stationStr = "" # current station frequency (string)
|
||||||
self.streamNum = 0 # current station stream number
|
self.streamNum = 0 # current station stream number
|
||||||
|
self.nrsc5msg = "" # send key command to nrsc5 (streamNum)
|
||||||
self.update_btns = True
|
self.update_btns = True
|
||||||
self.set_program_btns()
|
self.set_program_btns()
|
||||||
self.bookmarks = [] # station bookmarks
|
self.bookmarks = [] # station bookmarks
|
||||||
@ -136,12 +139,12 @@ class NRSC5_DUI(object):
|
|||||||
262 : "Private Data Network",
|
262 : "Private Data Network",
|
||||||
263 : "Service Maintenance",
|
263 : "Service Maintenance",
|
||||||
264 : "HD Radio System Services",
|
264 : "HD Radio System Services",
|
||||||
265 : "Audio Related Data",
|
265 : "Audio-Related Objects",
|
||||||
511 : "Test_Str_E"
|
511 : "Test_Str_E"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ProgramType = {
|
self.ProgramType = {
|
||||||
0 : "Undefined",
|
0 : "None",
|
||||||
1 : "News",
|
1 : "News",
|
||||||
2 : "Information",
|
2 : "Information",
|
||||||
3 : "Sports",
|
3 : "Sports",
|
||||||
@ -157,8 +160,8 @@ class NRSC5_DUI(object):
|
|||||||
13 : "Nostalgia",
|
13 : "Nostalgia",
|
||||||
14 : "Jazz",
|
14 : "Jazz",
|
||||||
15 : "Classical",
|
15 : "Classical",
|
||||||
16 : "Rhythm And Blues",
|
16 : "Rhythm and Blues",
|
||||||
17 : "Soft Rhythm And Blues",
|
17 : "Soft Rhythm and Blues",
|
||||||
18 : "Foreign Language",
|
18 : "Foreign Language",
|
||||||
19 : "Religious Music",
|
19 : "Religious Music",
|
||||||
20 : "Religious Talk",
|
20 : "Religious Talk",
|
||||||
@ -167,7 +170,7 @@ class NRSC5_DUI(object):
|
|||||||
23 : "College",
|
23 : "College",
|
||||||
24 : "Spanish Talk",
|
24 : "Spanish Talk",
|
||||||
25 : "Spanish Music",
|
25 : "Spanish Music",
|
||||||
26 : "Hip Hop",
|
26 : "Hip-Hop",
|
||||||
29 : "Weather",
|
29 : "Weather",
|
||||||
30 : "Emergency Test",
|
30 : "Emergency Test",
|
||||||
31 : "Emergency",
|
31 : "Emergency",
|
||||||
@ -281,6 +284,9 @@ class NRSC5_DUI(object):
|
|||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
self.proccessWeatherMaps()
|
self.proccessWeatherMaps()
|
||||||
#self..connect('check-resize',self.on_window_resized) # TODO: fix on resize infinite loop
|
#self..connect('check-resize',self.on_window_resized) # TODO: fix on resize infinite loop
|
||||||
|
|
||||||
|
# set up pty
|
||||||
|
self.nrsc5master,self.nrsc5slave = pty.openpty()
|
||||||
|
|
||||||
def img_to_pixbuf(self,img):
|
def img_to_pixbuf(self,img):
|
||||||
"""convert PIL.Image to GdkPixbuf.Pixbuf"""
|
"""convert PIL.Image to GdkPixbuf.Pixbuf"""
|
||||||
@ -580,13 +586,14 @@ class NRSC5_DUI(object):
|
|||||||
self.streamInfo["Logo"] = ""
|
self.streamInfo["Logo"] = ""
|
||||||
self.streamInfo["Bitrate"] = 0
|
self.streamInfo["Bitrate"] = 0
|
||||||
self.set_program_btns()
|
self.set_program_btns()
|
||||||
#if self.playing:
|
if self.playing:
|
||||||
# self.display_logo()
|
self.nrsc5msg = str(self.streamNum)
|
||||||
|
self.displayLogo()
|
||||||
#TODO: fix so stream change is smoother - should be able to pipe new stream number to running application and update display_logo()
|
#TODO: fix so stream change is smoother - should be able to pipe new stream number to running application and update display_logo()
|
||||||
# For now, just restart
|
# For now, just restart
|
||||||
if (self.playing):
|
#if (self.playing):
|
||||||
self.on_btnStop_clicked(None)
|
# self.on_btnStop_clicked(None)
|
||||||
self.on_btnPlay_clicked(None)
|
# self.on_btnPlay_clicked(None)
|
||||||
|
|
||||||
def set_program_btns(self):
|
def set_program_btns(self):
|
||||||
self.btnAudioPrgs0.set_active(self.update_btns and self.streamNum == 0)
|
self.btnAudioPrgs0.set_active(self.update_btns and self.streamNum == 0)
|
||||||
@ -689,9 +696,16 @@ class NRSC5_DUI(object):
|
|||||||
FTMP = open('tmp.log','w')
|
FTMP = open('tmp.log','w')
|
||||||
|
|
||||||
# run nrsc5 and output stdout & stderr to pipes
|
# run nrsc5 and output stdout & stderr to pipes
|
||||||
self.nrsc5 = Popen(self.nrsc5Args, stderr=PIPE, stdout=PIPE, universal_newlines=True)
|
#self.nrsc5 = Popen(self.nrsc5Args, stdout=PIPE, stderr=PIPE, universal_newlines=True)
|
||||||
|
self.nrsc5 = Popen(self.nrsc5Args, shell=False, stdin=self.nrsc5slave, stdout=PIPE, stderr=PIPE, universal_newlines=True)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
# send input to nrsc5 if needed
|
||||||
|
if (self.nrsc5msg != ""):
|
||||||
|
select.select([],[self.nrsc5master],[])
|
||||||
|
os.write(self.nrsc5master,str.encode(self.nrsc5msg))
|
||||||
|
#print(self.nrsc5msg)
|
||||||
|
self.nrsc5msg = ""
|
||||||
# read output from nrsc5
|
# read output from nrsc5
|
||||||
output = self.nrsc5.stderr.readline()
|
output = self.nrsc5.stderr.readline()
|
||||||
# parse the output
|
# parse the output
|
||||||
@ -712,7 +726,7 @@ class NRSC5_DUI(object):
|
|||||||
# restart nrsc5 if it crashes
|
# restart nrsc5 if it crashes
|
||||||
self.debugLog("Restarting NRSC5")
|
self.debugLog("Restarting NRSC5")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.nrsc5 = Popen(self.nrsc5Args, stderr=PIPE, stdout=PIPE, universal_newlines=True)
|
self.nrsc5 = Popen(self.nrsc5Args, stdin=PIPE, stderr=PIPE, stdout=PIPE, universal_newlines=True)
|
||||||
|
|
||||||
def set_synchronization(self, state):
|
def set_synchronization(self, state):
|
||||||
self.imgNoSynch.set_visible(state == 0)
|
self.imgNoSynch.set_visible(state == 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user