2013-06-08 2 views
1

집에서 Whole Home Audio 시스템을 제어 할 Gstreamer Python 프로그램을 작성하려고합니다. 기본적인 전제는 내가 소스 (판도라, MP3, 구글 뮤직 등)에 대해 여러 가지 옵션을 가질 것이고, 내 집에서 다른 "존"에서 재생할 수 있다는 것이다. 현재 재생중인 파이프 라인에 영역을 동적으로 추가하기 위해 작동하도록했지만, 영역을 제거하려고 시도하면 오디오가 모든 영역에서 재생되는 것을 멈 춥니 다. 아마 전체 파이프 라인이 일시 정지로 전환Python Gstreamer에서 동적 오디오 장치를 추가 및 제거하는 방법

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] 

답변

0

:

기본 설정 : 더 필요한 경우 여기에 관련 코드가, 내가 게시 할 수 있습니다. 그에서 element1의 소스 패드가 연결되지 떠날 것이며 스트리밍 발생할 수있어

봅니다

http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-dynamic-pipelines.html

우리는 단지에서 element1의 소스 패드 에서이 element2의 sinkpad 연결을 해제 할 수없는 문서의 단계를 수행합니다 데이터가 소스 패드에 푸시 될 때 파이프 라인의 오류. 블로킹 패드 프로브

블록에서 element1의 소스 패드 :이 기술은 우리 element4 의해 element2에 변경 전에서 element1의 소스 패드의 흐름을 차단하고 다음 단계와 같이 흐름을 재개한다. 패드가 막히면 프로브 콜백이 호출됩니다.

블록 콜백 내에서 element1과 element2간에 아무 것도 흐르지 않으며 차단 해제 될 때까지 아무 것도 흐르지 않습니다.

링크 1과 요소 2를 연결 해제하십시오.

데이터가 element2에서 플러시되는지 확인하십시오. 어떤 요소는 내부적으로 일부 데이터를 유지할 수 있으므로 에 의해 데이터를 잃지 않도록해야합니다. 다음과 같이 EOS를 element2로 밀어 넣으면됩니다.

element2의 소스 패드에 이벤트 프로브를 둡니다.

EOS를 element2의 싱크 패드로 보냅니다. 이렇게하면 element2 안에있는 모든 데이터 이 강제로 제거됩니다.

EOS 이벤트가 element2의 소스 패드에 나타날 때까지 기다리십시오. EOS가 수신되면이를 놓고 이벤트 프로브를 제거하십시오.

링크 2와 요소 3을 연결 해제하십시오. 이제 파이프 라인을 에서 element2를 제거하고 상태를 NULL로 설정할 수 있습니다.

아직 추가되지 않은 경우, element4를 파이프 라인에 추가하십시오. 요소 4와 요소 3을 연결하십시오. 요소 1과 요소 4를 연결하십시오.

요소 4가 나머지 요소와 동일한 상태에 있는지 확인하십시오. 파이프 라인에 있습니다. 은 버퍼와 이벤트를 수신하기 전에 최소한 PAUSED 상태 여야합니다.

요소 1의 소스 패드 프로브를 차단 해제하십시오.그러면 element4에 새 데이터가 입력되고 스트리밍이 계속됩니다.

위의 알고리즘은 소스 패드가 차단되었을 때, 즉 파이프 라인에 데이터 흐름이있는 경우에 작동합니다. 데이터 흐름이 없다면 요소를 변경하지 않아도 (이 알고리즘은 ) PAUSED 상태에서도이 알고리즘을 사용할 수 있습니다.

+0

그 설명을 발견했습니다. 불행히도, 그들은 한 요소를 다른 것으로 대체하는 것에 대해 이야기하고 있습니다. 나는 단순히 요소를 모두 제거하려고 시도하고있다. 그래서 게시 한 기사에서 권장하는대로 src 패드를 차단하지만 더 이상 필요하지 않기 때문에 완전히 제거합니다. – Amazinzay

+0

element1과 element3을 다시 연결해도 작동하지 않습니까? 또 다른 "트릭"은 대기열을 대체품으로 삽입하는 것일 수 있습니다. –

관련 문제