我正在尝试编写一个 Gstreamer Python 程序来控制我家中的整个家庭音频系统。基本前提是我将有多种不同的来源选择(Pandora、MP3、谷歌音乐等),并且能够在我家的不同“区域”中播放它们。我已经让它可以动态地将一个区域添加到当前正在播放的管道中,但是当我尝试删除一个区域时,音频会停止在所有区域中播放。这是相关代码,如有需要我可以发布更多:
基本设置:
def __init__(self, username, password, zones=[]):
# initialize the player
self.player = gst.element_factory_make('playbin2', 'pandora_player')
fakesink = gst.element_factory_make('fakesink', 'fakesink')
self.player.set_property('video-sink', fakesink)
# enable progressive download (GST_PLAY_FLAG_DOWNLOAD)
self.player.props.flags |= (1 << 7)
# create bin
teebin = gst.element_factory_make('bin', 'master')
tee = gst.element_factory_make('tee', 'tee')
teebin.add(tee)
ghost_pad = gst.GhostPad('sink', tee.get_pad('sink'))
teebin.add_pad(ghost_pad)
# set bin as audio sink
self.player.set_property('audio-sink', teebin)
# set volume
self.player.set_property('volume', 0.01)
bus = self.player.get_bus()
bus.add_signal_watch()
bus.connect('message', self.on_message)
# make everything accessible
self.tee = tee
self.teebin = teebin
def add_zone(self, zone_id):
# create out first audio output device
zone_name = 'zone_{0}'.format(zone_id)
device_name = 'mono{0}'.format(zone_id)
bin_name = 'bin_{0}'.format(zone_id)
queue_name = 'q_{0}'.format(zone_id)
# wrap everything in a convenient zone object
zone = gst.element_factory_make('bin', bin_name)
# handle sending to the proper sound device
zone_device = gst.element_factory_make('alsasink', zone_name)
zone_device.set_property('device', device_name)
# create a queue to handle asynchronous playback
zone_queue = gst.element_factory_make('queue', queue_name)
zone.add(zone_queue, zone_device)
zone_queue.link(zone_device)
# add sink into element
zone_ghost = gst.GhostPad('sink', zone_queue.get_pad('sink'))
zone.add_pad(zone_ghost)
self.zones[zone_id] = zone
self.teebin.add(zone)
zone.sync_state_with_parent()
self.tee.link(zone)
def remove_zone(self, zone_id):
# get zone
zone = self.zones[zone_id]
# get src pad that is sending audio
pad = zone.get_pad('sink').get_peer()
# block src pad
pad.set_blocked(True)
# set zone state null
zone.set_state(gst.STATE_NULL)
# unlink and remove zone
self.tee.unlink(zone)
self.teebin.remove(zone)
# remove zone reference
del self.zones[zone_id]