Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 4, 2010 22:28:25

pasaranax
От:
Зарегистрирован: 2009-06-13
Сообщения: 574
Репутация: +  0  -
Профиль   Отправить e-mail  

Синхронизация stdin/stdout на примере mplayer

Мне нужно общаться через пайпы с 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)

Офлайн

#2 Янв. 5, 2010 00:53:31

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Синхронизация stdin/stdout на примере mplayer

Вот тут можете глянуть, может чего полезного почерпнете:
https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/mediaplayer/MPlayerBackend.py?revision=785&root=mediabox&view=markup
Это работает не на десктопе.



Офлайн

#3 Янв. 5, 2010 01:57:19

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

Синхронизация stdin/stdout на примере mplayer

А если сделать так:
завести себе еще self.inQueue

В communicate формировать элемент inQueue в виде записи (message_id, message, quiet, forceWait) и помещать его туда (в inQueue), после чего (если нужно) запускать цикл ожидания появления ответа в outQueue.
В run делать полную обработку в цикле: достаем из inQueue, посылаем плееру, ждем ответ, пока не получим таймаут или сам ответ, помещаем ответ в outQueue.

Кстати, а почему вы считаете (по вашему алгоритму), что плеер готов получать следующую команду, если еще не ответил на предыдущую? Вы так уверены, что в нем тоже реализована очередь команд и он такую ситуацию нормально отработает?

К тому же зачем вам очередь, если асинхронностью и не пахнет? Если вы используете события, то почему бы не сделать также события ответов (class Mplayer будет их генерировать, а основная программа ловить)?



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version