Форум сайта python.su
Мне нужно общаться через пайпы с mplayer-ом, и встал вопрос синхронизации входящих и исходящих сообщений. Думаю, это можно не только к mplayer-у отнести. Нужно наладить диалог с процессом, запущенным в Popen: в stdin посылается сообщение, из stdout читается ответ, если он есть. Проблема в том, что когда процессу сообщения шлются часто, а ответы приходят с задержкой, то следующая строка из stdout не всегда является ответом на строку отправленную в stdin, да еще и не на все сообщения даются ответы.
Mplayer работает так: ему шлется либо команда не требующая ответа, либо запрос на получение какой-то инфы. Запросы начинаются на “get_”, ответы приходят с префиксом “ANS_”, а то что приходит без префикса, это его “монолог”.
Я попытался организовать что-то вроде очереди, и написал какой-то монструозный класс (я постарался все прокомментировать для понятности). Это Thread, который постоянно читает stdout процесса запущенного в Popen.
Мой класс нормально работает на компьютере, но на телефоне вся синхронизация сбивается (а я пишу плеер для телефона), либо надо делать очень большое время ожидания ответа. И если процесс пришлет ответ в то время, когда он не ожидается, то со следующим запросом будет ассоциирован неправильный (уже торчащий в очереди) ответ.
Вот простой пример применения моего класса Mplayer в PyQt:
# -*- coding: utf-8 -*-
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from Mplayer import Mplayer
class Window(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.mplayer = Mplayer(self.winId())
self.mplayer.startMplayer(QFileDialog.getOpenFileName())
def mousePressEvent(self, event):
# кликнув по виджету получим текущую позицию
timePos = self.mplayer.communicate("get_time_pos")
def closeEvent(self, event):
self.mplayer.communicate("quit")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec_()
Отредактировано (Янв. 4, 2010 22:36:35)
Офлайн
Вот тут можете глянуть, может чего полезного почерпнете:
https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/mediaplayer/MPlayerBackend.py?revision=785&root=mediabox&view=markup
Это работает не на десктопе.
Офлайн
А если сделать так:
завести себе еще self.inQueue
В communicate формировать элемент inQueue в виде записи (message_id, message, quiet, forceWait) и помещать его туда (в inQueue), после чего (если нужно) запускать цикл ожидания появления ответа в outQueue.
В run делать полную обработку в цикле: достаем из inQueue, посылаем плееру, ждем ответ, пока не получим таймаут или сам ответ, помещаем ответ в outQueue.
Кстати, а почему вы считаете (по вашему алгоритму), что плеер готов получать следующую команду, если еще не ответил на предыдущую? Вы так уверены, что в нем тоже реализована очередь команд и он такую ситуацию нормально отработает?
К тому же зачем вам очередь, если асинхронностью и не пахнет? Если вы используете события, то почему бы не сделать также события ответов (class Mplayer будет их генерировать, а основная программа ловить)?
Офлайн