Пишем приложение для удаленного управления плеером MPV из RetroOrangePi

от автора

Многие пользователи медиацентра KODI, входящего в состав RetroOrangePi, наверняка заметили, что там используется внешний плеер MPV, который, в отличии от штатного, имеет поддержку аппаратного декодирования. Это позволяет проигрывать контент 1080P без лагов, однако есть и большая проблема — единственный способ управлять плеером это клавиатура. Более того — у плеера нет даже минимального GUI, так что какой продолжительности фильм вы смотрите, и сколько еще осталось до конца — увы, не узнать.
Я, признаюсь, очень ленивый человек, и таскать за собой еще и клавиатуру, с учетом того, что сам KODI управляется с телефона — очень не удобно. Погуглив пару минут, я с удивлением узнал, что не существует готовых решений для удаленного управления MPV с смартфона. Ну что делать — придется написать самому. Кстати, как оказалось, в центре Витебска купить недорогую беспроводную клавиатуру за 1 час обеденного перерыва — тот еще квест.

MPV поддерживает несколько языков для написания скриптов, один из них Lua. На Гитхабе я нашел проект mpv-network-commands, написанный на Lua и позволяющий управлять минимум функций MPV, при помощи команд, передаваемых посредством UDP. Убедившись, что он работает, я во время обеденного перерыва написал простейшее приложение, которое реализовывало максимально примитивный функционал — по сути, оно позволяло поставить на паузу, запустить воспроизведение с паузы и закрыть плеер.

Выглядело оно примерно так.
Что бы иметь возможность перематывать видео, а так же видеть прогресс-бар, пришлось модифицировать исходный скрипт, добавив следующую функцию:

function send_name() local title =mp.get_property("media-title"); local length = math.floor(mp.get_property("length")); local pos=math.floor(mp.get_property("time-pos")); conn_up:sendto(title.."$"..length.."$"..pos, "192.168.100.168", 756); end

Самое смешное — это то, что код, обрабатывающий входящие данные со стороны телефона, получился куда более громоздким:

И это еще без кода таймера

 thread {             // this thread receives incoming massages from MPV and updates views accordingly to received info              try {                 chnl.socket().bind(InetSocketAddress(756))                  chnl.configureBlocking(false)                 var timerStarted: Boolean = false                 var timer = Timer()                 while (true) {                     var buf = ByteBuffer.allocate(1024)                     buf.clear()                     var last_pos = ""                     if (!timerStarted) {                         timer = Timer()                         timer.schedule(myTimerTask(textView5, textView6, textView4, seekBar3), 2000, 1000)                         //this timer will clear views, if no info received in last 2 seconds                         timerStarted = true                     }                     if (chnl.isOpen) {                         if (chnl.receive(buf) != null) {                             if (timerStarted) {                                 timer.cancel()                                 timerStarted = false                             }                             var data_length = buf.position()                             buf.flip()                             var str = String(buf.array(), 0, data_length, UTF_8)                             Log.d("received data", str)                             val arr = str.split("$")                             if (arr.size >= 3) {                                 media_length = arr[1].toInt()                                 runOnUiThread {                                     if (textView4.text != arr[0]) textView4.text = arr[0]                                     if (last_pos != arr[1]) {                                         last_pos = arr[1]                                         textView6.text = convertSecsToFullTime(last_pos)                                     }                                     if (!blockview) {                                         textView5.text = convertSecsToFullTime(arr[2])                                     seekBar3.max = arr[1].toInt()                                         seekBar3.progress = arr[2].toInt()                                     }                                  }                             }                         }                     }                 }             } catch (e: Exception) {                 runOnUiThread {                     Toast.makeText(this, e.message, Toast.LENGTH_SHORT).show()                 }                 Log.d("In MPVremote", e.message.toString())             }         } 

В результате получилось вот это:

Исходные коды, а также apk, лежат на Гитхабе.
Сразу предупреждаю — могут быть точно есть баги.
Основной недостаток — требуется фиксированный IP для телефона в вашей локальной сети, в которой работает OrangePi. Он необходим, что бы скрипт знал, куда ему отправлять инфу о воспроизводимом файле. Самый простой способ — в настройках DHCP сервера вашего роутера указать выдавать один и тот же IP устройствам с МАК-адресом телефона.
Также нет никаких элементов безопасности — любой пользователь в вашей сети сможет поставить видео на паузу или закрыть плеер, зная IP медиацентра. Правда, узнать что воспроизводится и воспроизводится ли вообще — нет.
Кстати, использование обмена данными через UDP безо всяких подтверждений порождает побочный эффект — поскольку прием входящих данных от плеера крутится в отдельном потоке, то вы можете ставить/снимать паузу и закрывать плеер, даже если не указали серверному скрипту правильный IP вашего телефона. Главное, что бы вы знали IP вашего медиацентра.
Установка.
Перейдите в Desktop RetroOrangePi. Сначала надо установить Lua и LuaSocket.

sudo apt-get install lua5.1 luasocket

Затем перейдите в директорию /home/pi/.config/mpv/ и создайте там директорию lua.
В lua скопируйте server.lua
Откройте server.lua тем же nano и в строке

conn_up:sendto(title.."$"..length.."$"..pos, "192.168.100.168", 756);

замените IP адрес на адрес вашего телефона.
Сохраните и перезагрузите OrangePi.
Установите приложение на телефон. Собранный apk лежит на Гитхабе. Запустите его, перейдите в Settings. Задайте там IP вашего медиацентра и порт 755. Нажмите Save.
Все, можно пользоваться.


ссылка на оригинал статьи https://habr.com/post/423765/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *