LINUX.ORG.RU

Крякозябры в radiotray. Как исправить?

 ,


2

2

Есть Debian 8 с radiotray и вот такие 1 , 2 радиостанции, с которых названия треков на кириллице идут крякозябрами. Гуглится один способ лечения:

1. При наведении мышкой на иконку RadioTray в системном лотке появляется маленькое сообщение с текущей песней. Чтобы там не было кракозябр - открываем файл /usr/lib/python2.7/site-packages/radiotray/StateMediator.py Последние 5 строк файла меняем. Было:

    def on_song_changed(self, data):
            print data
            if('artist' in data.keys()):
                self.context.artist = data['artist']
            if('title' in data.keys()):
                self.context.title = data['title']

Стало:

            def on_song_changed(self, data):
            print data
            if('artist' in data.keys()):
                self.context.artist = data['artist'].encode('latin-1').decode('cp1251').encode('utf8')
            if('title' in data.keys()):
                self.context.title = data['title'].encode('latin-1').decode('cp1251').encode('utf8')

2. Дальше плагин, который показывает название песни в правом-верхнем углу. Плагин называется Notification. Открываем файл /usr/share/radiotray/plugins/NotificationPlugin.py. Предпоследнюю строку, которая выглядела:

    self.notif.update(title, message)

Меняем на:

    self.notif.update(title.encode('latin-1').decode('cp1251').encode('utf8'), message.encode('latin-1').decode('cp1251').encode('utf8'))

3. Плагин истории прослушанных песен. Открываем файл /usr/share/radiotray/plugins/HistoryPlugin.py. Находим строку:

    title = data['title']

И прямо под ней добавляем новую строку. Должно получиться так:

    title = data['title']
    title=title.encode('latin-1').decode('cp1251').encode('utf8')

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

Вопрос к знатокам, ЧЯДНТ или как сделать нормально?

P.S. Выкинуть radiotray на мороз не предлагать, привык к нему.


Ну можешь попробовать детектор кодировок прикрутить.

apt-get install python-chardet или python3-chardet, не знаю, какой у тебя питон. В StateMediator.py там где все импорты добавь import chardet, а в def on_song_changed(self, data) под print(data) добавь print(chardet.detect(data['artist'])). Ну и покажи, чего определилось.

fluorite ★★★★★
()
Ответ на: комментарий от peregrine

В смысле, могут ли они у себя кодировки поправить? Я думаю вряд-ли это им надо, через веб-проигрыватели все норм отображает, кто там будет ради одного человека делать что-то.

Autumn
() автор топика
Ответ на: комментарий от Autumn

Я не про то, то что такой фикс может ломать кодировки на нормальных станциях понятно, а вот проблемные станции начинают отображаться нормально? Если нет, то смотри в какой кодировке на самом деле идут данные.

peregrine ★★★★★
()
Ответ на: комментарий от fluorite

Вот только сейчас заметил, что print(data) у меня нет в коде, и если добавить, то

poul@localhost:~$ radiotray
Traceback (most recent call last):
  File "/usr/bin/radiotray", line 7, in <module>
    from radiotray import radiotray
  File "/usr/lib/python2.7/dist-packages/radiotray/radiotray.py", line 6, in <module>
    from RadioTray import RadioTray
  File "/usr/lib/python2.7/dist-packages/radiotray/RadioTray.py", line 24, in <module>
    from StateMediator import StateMediator
  File "/usr/lib/python2.7/dist-packages/radiotray/StateMediator.py", line 137
    print(data)
        ^
IndentationError: expected an indented block

Autumn
() автор топика
Ответ на: комментарий от peregrine

Нет, нормально на этих двух что с фиксом, что без не становится. Только когда по разному переставляешь кодировки, начинает писать вместо \u0411\u0440\u0438\u043b\u043b\u0438\u0430 такое Маяк

Autumn
() автор топика
Ответ на: комментарий от Autumn

Это потому что print(data) должно быть сдвинуто на один символ табуляции (или 4 пробела, если в коде пробелы) от def on_song_changed(self, data):.

Попробуй сделать, как тебе предложили выше:

  • Выполнить apt-get install python-chardet
  • В начало файла /usr/lib/python2.7/site-packages/radiotray/StateMediator.py добавить
    import chardet
    
  • Исправить on_song_changed
                def on_song_changed(self, data):
                    print(data)
                    if('artist' in data.keys()):
                        self.context.artist = data['artist'].encode('latin-1').decode('cp1251').encode('utf8')
                        print(chardet.detect(data['artist']))
                    if('title' in data.keys()):
                        self.context.title = data['title'].encode('latin-1').decode('cp1251').encode('utf8')
                        print(chardet.detect(data['title']))
    
  • И посмотреть, что выведет скрипт после запуска. Это будет строка вида:
    {'confidence': 0.99, 'encoding': 'utf-8'}
    
  • Если сработает, добавить декодирование в остальные файлы, не забывая про импорт chardet. Декодирование будет выглядеть как-то так:
    title.decode(chardet.detect(title)['encoding'])
    

    Где title — декодируемая переменная.

grazor ★★
()
Ответ на: комментарий от grazor

И верно, на 4 пробела сдвинуть надо было.

Сделал всё, после запуска:

poul@localhost:~$ radiotray
Sleep Timer, Stops playing after a predefined time, SleepTimerPlugin.py, Carlos Ribeiro
HelloWorld, This is a test plugin, HelloWorld.py, Carlos Ribeiro
started
Notifications, Shows message notifications on the desktop, NotificationPlugin.py, Carlos Ribeiro
Mate Media Keys, Controls Radio Tray through keyboard multimedia keys, MateMediaKeysPlugin.py, Ken
Gnome Media Keys, Controls Radio Tray through keyboard multimedia keys, GnomeMediaKeysPlugin.py, Carlos Ribeiro
History, Shows song history, HistoryPlugin.py, Carlos Ribeiro
{'station': '42 fm', 'title': u'Sirenia - Lithium And A Lover'}
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/radiotray/AudioPlayerGStreamer.py", line 189, in on_message
    self.eventManager.notify(EventManager.SONG_CHANGED, metadata)
  File "/usr/lib/python2.7/dist-packages/radiotray/events/EventManager.py", line 46, in notify
    callback(data)
  File "/usr/lib/python2.7/dist-packages/radiotray/StateMediator.py", line 142, in on_song_changed
    print(chardet.detect(data['title']))
  File "/usr/lib/python2.7/dist-packages/chardet/__init__.py", line 25, in detect
    raise ValueError('Expected a bytes object, not a unicode object')
ValueError: Expected a bytes object, not a unicode object
Autumn
() автор топика
Ответ на: комментарий от Autumn

А вот трек с кириллицей:

poul@localhost:~$ radiotray
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/radiotray/AudioPlayerGStreamer.py", line 189, in on_message
    self.eventManager.notify(EventManager.SONG_CHANGED, metadata)
  File "/usr/lib/python2.7/dist-packages/radiotray/events/EventManager.py", line 46, in notify
    callback(data)
  File "/usr/lib/python2.7/dist-packages/radiotray/NotificationManager.py", line 83, in on_song_changed
    self.eventManagerWrapper.notify(msgTitle, msg)
  File "/usr/lib/python2.7/dist-packages/radiotray/events/EventMngNotificationWrapper.py", line 31, in notify
    self.eventManager.notify(self.eventManager.NOTIFICATION, {'title': title, 'message':message})
  File "/usr/lib/python2.7/dist-packages/radiotray/events/EventManager.py", line 46, in notify
    callback(data)
  File "/usr/share/radiotray/plugins/NotificationPlugin.py", line 75, in on_notification
    self.notif.update(title.encode('latin-1').decode('cp1251').encode('utf8'), message.encode('latin-1').decode('cp1251').encode('utf8'))
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-2: ordinal not in range(256)
Autumn
() автор топика
Ответ на: комментарий от Autumn

Давай просто посмотрим, что лежит в title и artist

def on_song_changed(self, data):
    print(data)
    if('artist' in data.keys()):
        print(data['artist'], type(data['artist']))
        self.context.artist = data['artist']
    if('title' in data.keys()):        
        print(data['title'], type(data['title']))
        self.context.title = data['title']
        

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Вот, что там лежит:

poul@localhost:~$ radiotray
{'station': '42 fm', 'title': u'Anathema - Get Off, Get Out'}
(u'Anathema - Get Off, Get Out', <type 'unicode'>)
{'station': '42 fm', 'title': u'\u0412\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u0438\u0435 - \u041a\u0442\u043e \u0412\u0438\u043d\u043e\u0432\u0430\u0442'}
(u'\u0412\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u0438\u0435 - \u041a\u0442\u043e \u0412\u0438\u043d\u043e\u0432\u0430\u0442', <type 'unicode'>)
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/radiotray/AudioPlayerGStreamer.py", line 189, in on_message
    self.eventManager.notify(EventManager.SONG_CHANGED, metadata)
  File "/usr/lib/python2.7/dist-packages/radiotray/events/EventManager.py", line 46, in notify
    callback(data)
  File "/usr/share/radiotray/plugins/HistoryPlugin.py", line 62, in on_song_changed
    title = title.encode('latin-1').decode('cp1251').encode('utf8')
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-10: ordinal not in range(256)
Autumn
() автор топика
Ответ на: комментарий от Autumn

Вообще title выглядит как нормальная юникодная строка, у тебя в системе не юникод? Вот так что в консоль выводит?

def on_song_changed(self, data):
    print(data)
    if('artist' in data.keys()):
        print(data['artist'].encode('utf-8'))
        self.context.artist = data['artist']
    if('title' in data.keys()):        
        print(data['title'].encode('utf-8'))
        self.context.title = data['title']
И замени в HistoryPlugin.py 'latin-1' на 'utf-8', чтоб не падало.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

у тебя в системе не юникод?

poul@localhost:~$ locale
LANG=ru_RU.utf8
LANGUAGE=
LC_CTYPE="ru_RU.utf8"
LC_NUMERIC="ru_RU.utf8"
LC_TIME="ru_RU.utf8"
LC_COLLATE="ru_RU.utf8"
LC_MONETARY="ru_RU.utf8"
LC_MESSAGES="ru_RU.utf8"
LC_PAPER="ru_RU.utf8"
LC_NAME="ru_RU.utf8"
LC_ADDRESS="ru_RU.utf8"
LC_TELEPHONE="ru_RU.utf8"
LC_MEASUREMENT="ru_RU.utf8"
LC_IDENTIFICATION="ru_RU.utf8"
LC_ALL=

Переустановил на всякий случай radiotray, и внезапно у одной станции теги стали нормально отображаться. И в хистори и в трее кириллицу видно. А вторая никак что-то:

    def on_song_changed(self, data):
        print(data) 
        if('artist' in data.keys()):
            print(data['artist'], type(data['artist']))
            print(data['artist'].encode('utf8'))
            self.context.artist = data['artist']
        if('title' in data.keys()):
            print(data['title'], type(data['title']))
            print(data['title'].encode('utf8'))
            self.context.title = data['title']
poul@localhost:~$ radiotray
{'station': 'Provodach', 'title': u"I am waiting for you last summer - Dreamers' shelter"}
(u"I am waiting for you last summer - Dreamers' shelter", <type 'unicode'>)
I am waiting for you last summer - Dreamers' shelter
{'station': 'Provodach', 'title': u'&#1052;&#1072;&#1103;&#1082; - &#1042;&#1099;&#1096;&#1077; &#1079;&#1074;&#1077;&#1079;&#1076;'}
(u'&#1052;&#1072;&#1103;&#1082; - #1042;&#1099;&#1096;&#1077; &#1079;&#1074;&#1077;&#1079;&#1076;', <type 'unicode'>)
&#1052;&#1072;&#1103;&#1082; - &#1042;&#1099;&#1096;&#1077; &#1079;&#1074;&#1077;&#1079;&#1076;

Её админ говорит, что в UTF-8 теги отдаются, хз тогда, почему такая шляпа происходит.

Autumn
() автор топика
Ответ на: комментарий от Autumn

В импорты добавь import HTMLParser

def on_song_changed(self, data):
    h = HTMLParser.HTMLParser()
    if('artist' in data.keys()):
        self.context.artist = h.unescape(data['artist'])
        print(self.context.artist.encode('utf-8'))
    if('title' in data.keys()):
        self.context.title = h.unescape(data['title'])
        print(self.context.title.encode('utf-8'))

fluorite ★★★★★
()
Последнее исправление: fluorite (всего исправлений: 1)
Ответ на: комментарий от fluorite
poul@localhost:~$ radiotray
DDC∆† - Уходя каждый миг, я навек остаюсь
De▲d Idols - Miracle

В консоли нормально теперь. Как бы этот результат к сообщениям и хистори прикрутить?

Autumn
() автор топика
Ответ на: комментарий от Autumn

Да так же, наверное, добавить import HTMLParser в NotificationPlugin.py и HistoryPlugin.py.

h = HTMLParser.HTMLParser()
self.notif.update(h.unescape(title), h.unescape(message))

h = HTMLParser.HTMLParser()
title = h.unescape(data['title'])
fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Заработало! Завтра погоняю еще на обоих станциях, и, если все нормально, то и тред закрою.

Autumn
() автор топика
Ответ на: комментарий от fluorite

Все работает нормально, спасибо за помощь, добра тебе! Если кому-то тоже понадобится, то в окончательном варианте так:

StateMediator.py:

    def on_song_changed(self, data):
        h = HTMLParser.HTMLParser()
        if('artist' in data.keys()):
            self.context.artist = h.unescape(data['artist'])
            print(self.context.artist.encode('utf-8'))
        if('title' in data.keys()):
            self.context.title = h.unescape(data['title'])
            print(self.context.title.encode('utf-8'))

NotificationPlugin.py:

            else:
                self.set_icon(data)
                h = HTMLParser.HTMLParser()
                self.notif.update(h.unescape(title), h.unescape(message))
                self.notif.show()

HistoryPlugin.py:

    def on_song_changed(self, data):

        if('title' in data.keys()):
            h = HTMLParser.HTMLParser()
            title = h.unescape(data['title'])
            if title != self.last_title:

Во все три добавить import HTMLParser

Autumn
() автор топика
28 июля 2017 г.
Ответ на: комментарий от Autumn

Ошибка

Добрый день. пробую по инструкции из последнего поста, получаю ошибку AttributeError: class HTMLParser has no attribute 'HTMLParser' Гугл не помог (Python 2.7)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.