Audio support and UI tidying
This commit is contained in:
parent
31fe3cc2d8
commit
b5a0820ac2
|
|
@ -0,0 +1,64 @@
|
|||
import vlc
|
||||
import time
|
||||
|
||||
#instance = vlc.Instance("-vvv", "--no-video", "--repeat")
|
||||
#player = instance.media_player_new()
|
||||
#media = instance.media_new("rtsp://piscan-arbor:8554/audio", "network-caching=25")
|
||||
#player.set_media(media)
|
||||
#player.play()
|
||||
#while(True):
|
||||
# time.sleep(1)
|
||||
|
||||
class AudioManager:
|
||||
vlc = None
|
||||
player = None
|
||||
media = None
|
||||
|
||||
def __init__(self):
|
||||
self.vlc = vlc.Instance('--no-video', '--repeat', '-v')
|
||||
|
||||
def close(self):
|
||||
|
||||
if self.player:
|
||||
self.player.stop()
|
||||
self.player.release()
|
||||
|
||||
self.vlc.release()
|
||||
|
||||
def startRtspAudioStream(self, host, port):
|
||||
print('create media')
|
||||
self.media = self.vlc.media_new('rtsp://' + host + ':' + port + '/audio', 'network-caching=50')
|
||||
print('create new player')
|
||||
self.player = self.media.player_new_from_media()
|
||||
print('start player')
|
||||
self.player.play()
|
||||
|
||||
def stopRtspAudioStream(self):
|
||||
print('stopping audio')
|
||||
if self.player:
|
||||
self.player.stop()
|
||||
self.player.release()
|
||||
self.player = None
|
||||
self.media.release()
|
||||
self.media = None
|
||||
|
||||
def setAudioVolume(self, level : int):
|
||||
self.player.audio_set_volume(level)
|
||||
|
||||
def setAudioMute(self, mute : bool):
|
||||
self.player.audio_set_mute(mute)
|
||||
|
||||
if __name__ == '__main__':
|
||||
audio = AudioManager()
|
||||
|
||||
audio.startRtspAudioStream("pibox-airglow", "8554")
|
||||
|
||||
try:
|
||||
while(True):
|
||||
time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
audio.stopRtspAudioStream()
|
||||
|
||||
audio.close()
|
||||
|
|
@ -12,6 +12,7 @@ from threading import Thread
|
|||
|
||||
from time import sleep
|
||||
|
||||
import audio_manager
|
||||
import common
|
||||
import constants
|
||||
import connect
|
||||
|
|
@ -27,6 +28,7 @@ import google.protobuf.message as proto
|
|||
|
||||
class PiScanClient(QWidget, common.AppInterface):
|
||||
dataReceived = Signal(bytes)
|
||||
manualDisconnectInitiated = False
|
||||
|
||||
def __init__(self, parent=None, address=None, port=None):
|
||||
super(PiScanClient, self).__init__(parent)
|
||||
|
|
@ -59,6 +61,8 @@ class PiScanClient(QWidget, common.AppInterface):
|
|||
|
||||
self.inmsg = messages_pb2.ServerToClient()
|
||||
|
||||
self.audio = audio_manager.AudioManager()
|
||||
|
||||
def mainWidget(self):
|
||||
return self.window
|
||||
|
||||
|
|
@ -72,16 +76,28 @@ class PiScanClient(QWidget, common.AppInterface):
|
|||
self.setWindowMode(common.WindowMode.DIALOG)
|
||||
|
||||
def receive(self):
|
||||
disconnectMessage = ''
|
||||
|
||||
while True:
|
||||
try:
|
||||
data = self.sock.recv(2048)
|
||||
if not data:
|
||||
disconnectMessage = 'Connection closed by host'
|
||||
break
|
||||
self.dataReceived.emit(data)
|
||||
except ConnectionAbortedError:
|
||||
if not self.manualDisconnectInitiated:
|
||||
disconnectMessage = 'Connection aborted'
|
||||
break
|
||||
except:
|
||||
e = sys.exc_info()[0]
|
||||
self.showConnectDialog(repr(e))
|
||||
disconnectMessage = 'Unhandled exception: ' + str(e)
|
||||
break
|
||||
|
||||
print("Closing connection")
|
||||
print("Closing connection. Reason: " + disconnectMessage)
|
||||
self.audio.stopRtspAudioStream()
|
||||
self.manualDisconnectInitiated = False
|
||||
self.showConnectDialog(disconnectMessage)
|
||||
|
||||
def handleReceived(self, data):
|
||||
self.inmsg.ParseFromString(data)
|
||||
|
|
@ -110,18 +126,13 @@ class PiScanClient(QWidget, common.AppInterface):
|
|||
|
||||
def closeEvent(self, event):
|
||||
print('Exiting...')
|
||||
try:
|
||||
if self.sock:
|
||||
self.sock.close()
|
||||
#self.rcv_thread.join()
|
||||
except:
|
||||
pass
|
||||
self.disconnect()
|
||||
|
||||
## AppInterface methods
|
||||
#def attemptConnection(self, sock):
|
||||
|
||||
|
||||
def completeConnection(self, sock):
|
||||
def completeConnection(self, sock, host, use_audio, audio_port):
|
||||
self.sock = sock
|
||||
self.rcv_thread = Thread(target=self.receive)
|
||||
self.rcv_thread.start()
|
||||
|
|
@ -141,7 +152,12 @@ class PiScanClient(QWidget, common.AppInterface):
|
|||
message3 = messages_pb2.ClientToServer()
|
||||
message3.type = messages_pb2.ClientToServer.Type.Value('GENERAL_REQUEST')
|
||||
message3.generalRequest.type = request_pb2.GeneralRequest.RequestType.Value('SYSTEM_INFO')
|
||||
self.sock.send(message3.SerializeToString())
|
||||
self.sock.send(message3.SerializeToString())
|
||||
|
||||
if use_audio:
|
||||
self.audio.startRtspAudioStream(host, audio_port)
|
||||
self.setAudioVolume(50)
|
||||
self.scanner.setVolumeVisible(use_audio)
|
||||
|
||||
def scan(self):
|
||||
message = messages_pb2.ClientToServer()
|
||||
|
|
@ -216,6 +232,21 @@ class PiScanClient(QWidget, common.AppInterface):
|
|||
else:
|
||||
self.setWindowTitle('PiScan')
|
||||
|
||||
def disconnect(self):
|
||||
self.manualDisconnectInitiated = True
|
||||
try:
|
||||
if self.sock:
|
||||
self.sock.close()
|
||||
#self.rcv_thread.join()
|
||||
except:
|
||||
pass
|
||||
|
||||
def setAudioVolume(self, level):
|
||||
self.audio.setAudioVolume(level)
|
||||
|
||||
def setAudioMute(self, mute):
|
||||
self.audio.setAudioMute(mute)
|
||||
|
||||
class HostWindow(QtWidgets.QMainWindow):
|
||||
def __init__(self, parent=None, address=None, port=None):
|
||||
super(HostWindow, self).__init__(parent)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class AppInterface:
|
|||
#def attemptConnection(self, sock):
|
||||
# pass
|
||||
|
||||
def completeConnection(self, sock):
|
||||
def completeConnection(self, sock, host, use_audio, audio_port):
|
||||
pass
|
||||
|
||||
def scan(self):
|
||||
|
|
@ -75,3 +75,12 @@ class AppInterface:
|
|||
|
||||
def clearWindowTitleInfo(self):
|
||||
pass
|
||||
|
||||
def disconnect(self):
|
||||
pass
|
||||
|
||||
def setAudioVolume(self, level):
|
||||
pass
|
||||
|
||||
def setAudioMute(self, mute):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import sys
|
||||
|
||||
from PySide2.QtUiTools import QUiLoader
|
||||
from PySide2.QtWidgets import QWidget, QLabel, QPushButton, QLineEdit
|
||||
from PySide2.QtWidgets import QWidget, QLabel, QPushButton, QLineEdit, QCheckBox
|
||||
from PySide2.QtCore import QObject
|
||||
from PySide2.QtGui import QMovie, QPixmap
|
||||
|
||||
|
|
@ -21,6 +21,9 @@ class ConnectDialog:
|
|||
self.logo = parentWindow.findChild(QLabel, 'connect_logoImage')
|
||||
self.hostLabel = parentWindow.findChild(QLabel, 'hostLabel')
|
||||
self.portLabel = parentWindow.findChild(QLabel, 'hostPortLabel')
|
||||
self.audioCheckBox = parentWindow.findChild(QCheckBox, 'connect_audioCheckBox')
|
||||
self.rtspPortPanel = parentWindow.findChild(QWidget, 'connect_rtspPortPanel')
|
||||
self.rtspPortLineEdit = parentWindow.findChild(QLineEdit, 'connect_rtspPortLineEdit')
|
||||
|
||||
self.logo.setPixmap(QPixmap("resources/icon-256.png"))
|
||||
self.logo.setVisible(False)
|
||||
|
|
@ -39,6 +42,8 @@ class ConnectDialog:
|
|||
self.hostLineEdit.returnPressed.connect(self.onConfirm)
|
||||
self.portLineEdit.returnPressed.connect(self.onConfirm)
|
||||
|
||||
self.rtspPortPanel.setVisible(False)
|
||||
|
||||
def onConfirm(self):
|
||||
host = self.hostLineEdit.text()
|
||||
port = int(self.portLineEdit.text())
|
||||
|
|
@ -62,11 +67,19 @@ class ConnectDialog:
|
|||
|
||||
self.connectIndicator.setVisible(False)
|
||||
|
||||
common.getApp().completeConnection(sock)
|
||||
use_audio = self.audioCheckBox.isChecked()
|
||||
audio_port = self.rtspPortLineEdit.text()
|
||||
|
||||
common.getApp().completeConnection(sock, address, use_audio, audio_port)
|
||||
except ConnectionRefusedError:
|
||||
self.connectFailed('Connect failed - Connection refused')
|
||||
except gaierror as err:
|
||||
self.connectFailed('Connect failed - ' + str(err))
|
||||
except TimeoutError:
|
||||
self.connectFailed('Connect failed - Timed out')
|
||||
except:
|
||||
e = sys.exc_info()[0]
|
||||
self.connectFailed(repr(e))
|
||||
self.connectFailed('Connect failed - Unhandled exception: ' + str(e))
|
||||
|
||||
|
||||
def contextWait(self):
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -26,7 +26,8 @@ class Scanner:
|
|||
self.modulationLabel = parentWindow.findChild(QLabel, 'scanner_modulationLabel')
|
||||
self.systemTagLabel = parentWindow.findChild(QLabel, 'scanner_systemTagLabel')
|
||||
self.entryNumLabel = parentWindow.findChild(QLabel, 'scanner_entryNumLabel')
|
||||
self.lockoutCheckbox = parentWindow.findChild(QCheckBox, 'scanner_lockoutCheckbox')
|
||||
self.lockoutDurationLabel = parentWindow.findChild(QLabel, 'scanner_lockoutDurationLabel')
|
||||
self.lockoutDurationButton = parentWindow.findChild(QPushButton, 'scanner_lockoutDurationButton')
|
||||
self.scanIndicator = parentWindow.findChild(QLabel, 'scanner_scanIndicator')
|
||||
self.gainSlider = parentWindow.findChild(QSlider, 'scanner_gainSlider')
|
||||
##self.gainLabel = parentWindow.findChild(QLabel, 'scanner_gainLabel')
|
||||
|
|
@ -42,6 +43,16 @@ class Scanner:
|
|||
self.sidebarToggleButton = parentWindow.findChild(QToolButton, 'scanner_sidebarToggle')
|
||||
self.sidebarPanel = parentWindow.findChild(QWidget, 'scanner_sidebarPanel')
|
||||
|
||||
self.disconnectButton = parentWindow.findChild(QToolButton, 'scanner_disconnectButton')
|
||||
self.settingsButton = parentWindow.findChild(QToolButton, 'scanner_settingsButton')
|
||||
self.connectInfoButton = parentWindow.findChild(QToolButton, 'scanner_connectInfoButton')
|
||||
|
||||
self.volumeControlPanel = parentWindow.findChild(QWidget, 'scanner_volumeControl')
|
||||
self.volumeSlider = parentWindow.findChild(QWidget, 'scanner_volumeSlider')
|
||||
self.muteButton = parentWindow.findChild(QWidget, 'scanner_volumeMute')
|
||||
|
||||
self.entryEditButton = parentWindow.findChild(QToolButton, 'scanner_entryEditButton')
|
||||
|
||||
self.fnButton1.clicked.connect(self.onFnButton1)
|
||||
self.fnButton2.clicked.connect(self.onFnButton2)
|
||||
self.fnButton3.clicked.connect(self.onFnButton3)
|
||||
|
|
@ -50,10 +61,22 @@ class Scanner:
|
|||
self.squelchSlider.valueChanged.connect(self.onsquelchSlider)
|
||||
|
||||
self.sidebarToggleButton.clicked.connect(self.onSidebarToggle)
|
||||
self.sidebarOpen = True
|
||||
self.sidebarOpen = False
|
||||
self.sidebarPanel.setVisible(False)
|
||||
|
||||
self.disconnectButton.clicked.connect(self.onDisconnectButton)
|
||||
|
||||
self.volumeSlider.valueChanged.connect(self.onVolumeSlider)
|
||||
self.muteButton.toggled.connect(self.onMuteButton)
|
||||
|
||||
#temporary since settins dialog is not yet implemented
|
||||
self.fnButton4.setEnabled(False)
|
||||
self.volumeControlPanel.setVisible(False)
|
||||
self.lockoutDurationButton.setVisible(False)
|
||||
self.lockoutDurationLabel.setVisible(False)
|
||||
self.fnButton4.setVisible(False)
|
||||
self.settingsButton.setVisible(False)
|
||||
self.connectInfoButton.setVisible(False)
|
||||
self.entryEditButton.setVisible(False)
|
||||
|
||||
movie = QMovie("resources/bar-scan.gif")
|
||||
movie.start()
|
||||
|
|
@ -178,9 +201,11 @@ class Scanner:
|
|||
|
||||
def onSidebarToggle(self):
|
||||
if self.sidebarOpen:
|
||||
self.sidebarToggleButton.setText('<')
|
||||
self.sidebarPanel.setVisible(False)
|
||||
self.sidebarOpen = False
|
||||
else:
|
||||
self.sidebarToggleButton.setText('>')
|
||||
self.sidebarPanel.setVisible(True)
|
||||
self.sidebarOpen = True
|
||||
|
||||
|
|
@ -190,4 +215,17 @@ class Scanner:
|
|||
|
||||
def setGainRange(self, minimum, maximum):
|
||||
self.gainSlider.setMinimum(minimum)
|
||||
self.gainSlider.setMaximum(maximum)
|
||||
self.gainSlider.setMaximum(maximum)
|
||||
|
||||
def onDisconnectButton(self):
|
||||
common.getApp().disconnect()
|
||||
|
||||
def onVolumeSlider(self, value):
|
||||
common.getApp().setAudioVolume(value)
|
||||
|
||||
def onMuteButton(self, value):
|
||||
self.volumeSlider.setEnabled(not value)
|
||||
common.getApp().setAudioMute(value)
|
||||
|
||||
def setVolumeVisible(self, visible):
|
||||
self.volumeControlPanel.setVisible(visible)
|
||||
|
|
|
|||
Loading…
Reference in New Issue