Обзор и программирование под стационарное интернет радио

в 13:57, , рубрики: C, dlna, embedded linux programming, linux, open source, pulseaudio, UPnP, Разработка под Linux, метки:

Несколько лет назад я уже выкладывал статью о том как из роутера сделать сетевую звуковую карту. Тот вариант требовал наличия активного источника звука и колонок. Переносной вариант выглядел бы слишком громоздким, потому было решено приобрести готовый продукт. По причине доступности и как самое дешевое из возможных вариантов (50 евро) я выбрал renkforce IR 1.

image

Из ключевых характеристик мне были важны следующие:

image

DLNA

Наличие DLNA позволяет напрямую перенаправить звук с Linux на интернет радио. Сделать это можно как минимум тремя способами:

  • Пассивный. Записывать всё, что воспроизводится звуковой картой в файл и воспроизводить этот файл на радио через minidlna сервер.
  • Активный. Использовать Rygel, который создаёт виртуальную звуковую карту и транслирует весь звук с неё через DLNA. Запускается скриптами, требует конфигурационных файлов.
  • Активный, простой. Использовать проект https://github.com/masmu/pulseaudio-dlna. Можно установить вручную, через ppa репозиторий в Ubuntu либо бэкпортировать пакет из Ubuntu 16.10.

Подробнее об этих способах можно почитать здесь.

Также можно проигрывать музыку прямиком с Android телефона. Поддержка DLNA была найдена только в предустановленном на телефоне музыкальном плеере от Samsung. Я пытался найти музыкальные проигрыватели с поддержкой DLNA в Google Play, но безуспешно.

WiFi

Единственным незначительным минусом является отсутствие поддержки протокола 802.11n.

Звук

Звук для данной категории устройства вполне приличный (одна колонка на 10W). Я не аудиофил, но разница со встроенными в обычный ноутбук колонками значительна. Басы присутствуют, джаз звучит великолепно, рок и электронная музыка тоже. Есть вариант с двумя колонками (модель renkforce IR 2), но я его не рассматривал за ненадобностью.

Экран

Экран обыкновенный. Интерфейс вполне дружественный...

image

Однако процедура добавления своих радиостанций оставляет желать лучшего.

Плейлист

Из-за плейлиста я и решил написать эту статью. Вручную вбивать URL радиостанции, используя пульт или колесо прокрутки — то еще занятие. Порядок появления символов при использовании цифровых кнопок на ПДУ сильно отличается от такового, к которорому привыкли при наборе SMS в кнопочном телефоне (для 2 это последовательность "2 A B C a b c" и т.д.). Если использовать колесо прокрутки, то приходится прокручивать каждый символ алфавита. Я решил проанализировать, есть ли возможность добавлять плейлист через web интерфейс.

Web интерфейс оказался урезанным. Открытый 80-й порт с заголовком AirMusic показывает только подписи к настройкам. HTML ссылается на несуществующие CSS стили на 8080 порту. Сам 8080 порт по умолчанию отображает 404 Not Found.

К счастью оказался доступен telnet порт. Используя логин root и пароль password мне удалось получить доступ к встроенному busybox. Изучение внутреннего устройства дало следующую информацию:

  • Работает всё это добро на процессоре с архитектурой ARM.
  • httpd сервер слушает порт 8080 и хостит статику, расположенную в /UIData. CSS стилей там не оказалось, равно как и другой полезной информации.
  • UIProto — сердце радио. Статически скомпилированное приложение, которое слушает 80-й порт, запускает mplayer, отображает информацию на экране и многое другое. По количеству упоминаний имени этого бинарника в интернете сложилось впечатление, что он разработан аутсорс компанией (mediayou.net) для большинства китайских интернет радио.

UIProto сохраняет favorites плейлист в бинарном формате в файл /flash/myradio.cfg. Прочесть его через вывод терминала возможно, но только как текст. Чтобы получить файл полностью пришлось чуть чуть попотеть. К счастью busybox на радио скомпилирован с поддержкой команд ftpput и ftpget. Их я и использовал, чтобы скопировать файл на компьютер для дальнейшего изучения, предварительно настроив FTP сервер.

Анализировал бинарный файл утилитой xxd(1). Приблизительно структура файла выглядит так:

Amount of entries: 2b
Every entry len: 366b
  0x00: 1b
  0x00|0x02|0x03: 1b
  0x20 (32): 1b
  0x00: 6b
  0x07|0x05: 1b
  len(0xTITLE+1): 1b
  0x80: 1b
  0xTITLE: 40b
  0x00: 59b
  0xURL: 250b
  0x00: 5b
0x00: 2b

Не исключаю, что некоторые элементы в структуре, являются обычным мусором из необнуленной выделенной памяти. Использование нулей в этих элементах никак не сказывается на конечном результате.

Первоначальный вариант утилиты на C сохранял захардкоженный плейлист. Для хранения структуры в памяти утилиты я использовал односвязные списки. Результат первого запуска дал тестовый бинарный плейлист, который я загрузил на устройство. Даже при наличии нулей в неизвестных мне элементах структуры, новый плейлист успешно прочитался. Окончательный вариант утилиты читает плейлист из CSV файла и записывает его в бинарный формат. Приятным бонусом оказалось использование заголовков для радиостанций вместо их URL (ранее радиостанции в списке отображались как http://1.2.3.4:8080/radio.mp3).

В заключение, ради эксперимента, я попробовал скомпилировать статический нативный бинарник, который смог бы запускаться прямиком на самом радио. Практической пользы от этого нет, но можно попробовать написать httpd демон, который позволит редактировать радиостанции прямиком через web интерфейс. Более глобальная и малоосуществимая идея — написать полностью opensource прошивку для интернет радио.

Как заставить UIProto перечитвать плейлист после обновления я так и не понял. Использую hardcore способ — sync и перезагрузка.

Для удобства загрузки плейлиста на радио я написал скрипты, использующие expect(1).

USB

На плате есть нераспаянный USB. Судя по dmesg(1), он вполне работоспособный. Проверить его работоспособность на практике еще не успел.

image

Ссылки

Автор: kay

Источник

Поделиться новостью

* - обязательные к заполнению поля