[решено?] mplayer, скриптованные клавиши (run и свойства)

Софт под Linux, разные программы, но только связанные с Linux

Модератор: /dev/random

liaonau
Сообщения: 390
ОС: gentoo

[решено?] mplayer, скриптованные клавиши

Сообщение liaonau »

Биндинги для клавиш в input.conf mplayer определяются из заданного набора команд, никакого скриптования нет. Иногда надо повесить на клавишу несколько действий, к примеру, переключить звуковую дорожку и перемотать на 2 секунды назад. Я решил проблему так config:

Код: Выделить всё

input=file=/var/tmp/mpipe

input.conf:

Код: Выделить всё

a run 'switch_seek.sh'

switch_seek.sh

Код: Выделить всё

exec 5>&1
exec > /var/tmp/mpipe
echo 'switch_audio'
echo 'seek -2'
exec 1>&5 5>&-


Для расширения возможностей скриптования клавиш надо знать значение свойств mplayer. Я имею ввиду те свойства, которые можно получить командой get_property.
Примеры. Для такого удобного мне поведения: клавиша «o» переключает уровень osd не циклически по всем значениям, а только 1 и 3. Клавиша «a» переключает дорожку, а назад отматывает только если эта дорожка № 2 (английская).
Но свойства при get_property отправятся либо на stdout mplayer, либо на osd, если вызывать из меню. Получить их в переменную скрипта вызванного mplayer было бы очень удобно.

Есть ли у кого-нибудь идеи как это сделать? В идеале mplayer стоило бы самому передать в окружение вызываемой им при команде run оболочки свои свойства в качестве переменных, но к сожалению он этого, вроде бы, не делает.
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: [решено?] mplayer, скриптованные клавиши

Сообщение sash-kan »

slave mode вас не устраивает?
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
liaonau
Сообщения: 390
ОС: gentoo

Re: [решено?] mplayer, скриптованные клавиши

Сообщение liaonau »

sash-kan писал(а):
06.05.2011 11:40
slave mode вас не устраивает?

Разумеется. Это же и есть он самый, через fifo. Команды run, get_property и т.д. я и узнал из приведенного вами файла документации. Возможно в первом сообщении я выразил мысль сумбурно. Просто мне надо получить значение свойства (get_property) в переменную скрипта запускаемого командой run, что обеспечит возможность какого-никакого, а скриптинга привязок клавиш mplayer.

Я думаю, что проблема теоретически решаема правкой файла command.c исходников. Теоретически, так как я не знаю C. Пожалуй мне по силам несколько бездумно кое-что копировать и изменить «по образу и подобию», но я не уверен, что этот метод «культа карго» правки исходников не приведет к неочевидным для меня ошибкам времени выполнения. Хочется решить свою небольшую (но жутко утомляющую — дьявол в деталях!) проблему горячих клавиш малой кровью.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5456
ОС: Gentoo

Re: [решено?] mplayer, скриптованные клавиши

Сообщение /dev/random »

liaonau писал(а):
06.05.2011 20:57
Разумеется. Это же и есть он самый, через fifo. Команды run, get_property и т.д. я и узнал из приведенного вами файла документации. Возможно в первом сообщении я выразил мысль сумбурно. Просто мне надо получить значение свойства (get_property) в переменную скрипта запускаемого командой run, что обеспечит возможность какого-никакого, а скриптинга привязок клавиш mplayer.

Разработчики mplayer предполагают, что если его нужно скриптовать, то mplayer должен запускаться из скрипта, а не наоборот. Ваш скрипт должен запустить mplayer, взяв под контроль как ввод, так и вывод (в режиме slave). Если вам нужно получить от mplayer'а какое-то значение, вы передаёте ему на вход соответствующую команду (в вашем случае - get_property), читаете ответ, и в зависимости от него генерируете дальнейшие команды.
Спасибо сказали:
liaonau
Сообщения: 390
ОС: gentoo

Re: [решено?] mplayer, скриптованные клавиши

Сообщение liaonau »

Я могу из скрипта читать клавиатуру и посылать команды mplayer, но ведь в самом окне mplayer клавиши будут значить то, что они значат в input.conf.
Правильно ли я понял?

Код: Выделить всё

#!/usr/bin/perl
use Term::ReadKey;
system("/usr/bin/mplayer -really-quiet /var/media/films/godfather.avi &");
open(TTY, "</dev/tty");
open(STDOUT, ">/var/tmp/mpipe");
while(1){
    ReadMode "raw";
    $key = ReadKey 0, *TTY;
    last if ( !$key || (ord $key == 4) || (ord $key == 3));
    ReadMode "normal";
    if ($key eq 'q') {
        print "switch_audio\n";
        print "seek -2\n";
    }
}

Но q в самом окне mplayer значит выход.

Правильно ли я понимаю, что чтобы подавить интерпретацию клавиш самим mplayer мне надо лишить его своего окна (-wid <Window ID>)? Тогда это не подходит, надо чтобы и через fbdev работало, без X.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5456
ОС: Gentoo

Re: [решено?] mplayer, скриптованные клавиши

Сообщение /dev/random »

liaonau писал(а):
07.05.2011 14:16
Правильно ли я понимаю, что чтобы подавить интерпретацию клавиш самим mplayer мне надо лишить его своего окна (-wid <Window ID>)? Тогда это не подходит, надо чтобы и через fbdev работало, без X.

Это основной способ. Но, в принципе, можно просто переопределить эти клавиши на свои, вымышленные команды. Например, строка в input.conf: "q asd zxc" (без кавычек). При нажатии q mplayer выдаст: "Invalid command for bound key q : asd zxc". Скрипт это увидит и обработает эту "asd zxc".
Спасибо сказали:
liaonau
Сообщения: 390
ОС: gentoo

Re: [решено?] mplayer, скриптованные клавиши

Сообщение liaonau »

/dev/random писал(а):
07.05.2011 15:20
Но, в принципе, можно просто переопределить эти клавиши на свои, вымышленные команды. Например, строка в input.conf: "q asd zxc" (без кавычек). При нажатии q mplayer выдаст: "Invalid command for bound key q : asd zxc". Скрипт это увидит и обработает эту "asd zxc".

Это уже что-то вроде самописного обработчика ошибок получится. Вот попробовал изменять исходники методом копирования и гугла:

Код: Выделить всё

--- command.c.orig      2011-05-07 14:44:10.000000000 +0300
+++ command.c   2011-05-07 19:22:52.000000000 +0300
@@ -3422,7 +3422,22 @@
         case MP_CMD_RUN:
 #ifndef __MINGW32__
             if (!fork()) {
-                execl("/bin/sh", "sh", "-c", cmd->args[0].v.s, NULL);
+                               int i;
+                               char *ans;
+/*                for (i = 0; mp_properties[i].name; i++) {*/
+/*                    const char *name = mp_properties[i].name;*/
+                                       const char *name = "osdlevel";
+                                       const char *prop;
+                                       m_property_do(mp_properties, name, M_PROPERTY_TO_STRING, &prop, mpctx);
+                                       mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_%s=%s\n", name, prop);
+                                       char var[strlen(prop) + 1 + strlen(name) + 1];
+                                       strcpy(var, name);
+                                       strcat(var, "=");
+                                       strcat(var, prop);
+                                       ans = var;
+/*                }*/
+                char *env[] = { ans, (char *)0 };
+                execle("/bin/sh", "sh", "-c", cmd->args[0].v.s, NULL, env);
                 exit(0);
             }
 #endif

Так переменная $osdlevel передается в окружение, но если раскоментировать цикл — перебрать все свойства, то mplayer, выдав их значения, падает, заявляя вот это:
mplayer2: /var/tmp/portage/x11-libs/libX11-1.4.3/work/libX11-1.4.3/src/xcb_io.c:221: poll_for_event: Assertion `(((long) (event_sequence) - (long) (dpy->request)) <= 0)' failed.
MPlayer прерван сигналом 6 в модуле: sleep_timer
- MPlayer рухнул. Это не должно происходить.

C я, как уже говорил выше, не знаю — мне конкатенация строк в вышеприведенном коде стоила час в гугле, но попробую еще покопать. Быть может обращение к какому-то определенному свойству приводит к краху.
Спасибо сказали:
liaonau
Сообщения: 390
ОС: gentoo

Re: [решено?] mplayer, скриптованные клавиши

Сообщение liaonau »

Дело было в fork(), вынес за него — заработало. Если есть желание, то поправьте то, что я сделал неверно (большая вероятность, что такое есть). Теперь работает, по крайней мере, на тех файлах видео, которые у меня есть.

Код: Выделить всё

--- command.c.orig    2011-05-07 23:05:08.000000000 +0300
+++ command.c    2011-05-08 01:39:57.000000000 +0300
@@ -1208,8 +1208,9 @@
         return M_PROPERTY_UNAVAILABLE;

     if (!opts->capture_dump) {
-        mp_tmsg(MSGT_GLOBAL, MSGL_ERR,
-                "Capturing not enabled (forgot -capture parameter?)\n");
+/*это будет надоедать при каждом run*/
+/*        mp_tmsg(MSGT_GLOBAL, MSGL_ERR,*/
+/*                "Capturing not enabled (forgot -capture parameter?)\n");*/
         return M_PROPERTY_ERROR;
     }

@@ -3421,10 +3422,36 @@

         case MP_CMD_RUN:
 #ifndef __MINGW32__
-            if (!fork()) {
-                execl("/bin/sh", "sh", "-c", cmd->args[0].v.s, NULL);
-                exit(0);
-            }
+            {
+                int i;
+                int count = 0;
+                for (i = 0; mp_properties[i].name; i++) { ++count; }
+
+                char* env[count+1];
+                env[count] = (char *)0;
+
+                for (i = 0; i < count; i++) {
+                    const char *name = mp_properties[i].name;
+                    const char *prop;
+                    int r = mp_property_do(name, M_PROPERTY_TO_STRING, &prop, mpctx);
+/*                    FIXME: на многих файлах без этого segfault*/
+                    if (name == "metadata"){
+                        prop = "";
+                    }
+                    env[i] = malloc(8 + strlen(name) + 1 + strlen(prop) + 1);
+                    strcpy(env[i], "mplayer_");
+                    strcat(env[i], name);
+                    strcat(env[i], "=");
+                    strcat(env[i], prop);
+/*                    mp_msg(MSGT_GLOBAL, MSGL_INFO, "%2d ANSWER IS-> %s, %d\n", i, env[i], r);*/
+                }
+
+                if (!fork()) {
+                    execle("/bin/sh", "sh", "-c", cmd->args[0].v.s, NULL, env);
+                    exit(0);
+                }
+                for (i = 0; i < count+1; i++) { free(env[i]); }
+            }
 #endif
             break;

Теперь одной кнопкой можно делать, к примеру, так:

Код: Выделить всё

exec 5>&1
exec > /var/tmp/mpipe
[[ ${mplayer_osdlevel} -ne "" ]] && OSD=$(( 4 - ${mplayer_osdlevel} )) || OSD=1
echo "osd ${OSD}"
exec 1>&5 5>&-


Вроде бы, решено (до первого краха при ошибке сегментации).
Спасибо сказали: