This file is indexed.

/usr/share/gpodder/extensions/sonos.py is in gpodder 3.10.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# -*- coding: utf-8 -*-
# Extension script to stream podcasts to Sonos speakers
# Requirements: gPodder 3.x and the soco module (https://pypi.python.org/pypi/soco)
# (c) 2013-01-19 Stefan Kögl <stefan@skoegl.net>
# Released under the same license terms as gPodder itself.

from functools import partial

import gpodder
_ = gpodder.gettext

import logging
logger = logging.getLogger(__name__)

import soco
import requests


__title__ = _('Stream to Sonos')
__description__ = _('Stream podcasts to Sonos speakers')
__authors__ = 'Stefan Kögl <stefan@skoegl.net>'
__category__ = 'interface'
__only_for__ = 'gtk'


SONOS_CAN_PLAY = lambda e: 'audio' in e.file_type()


class gPodderExtension:
    def __init__(self, container):
        sd = soco.SonosDiscovery()
        speaker_ips = sd.get_speaker_ips()

        logger.info('Found Sonos speakers: %s' % ', '.join(speaker_ips))

        self.speakers = {}
        for speaker_ip in speaker_ips:
            controller = soco.SoCo(speaker_ip)

            try:
                info = controller.get_speaker_info()

            except requests.ConnectionError as ce:
                # ignore speakers we can't connect to
                continue

            name = info.get('zone_name', None)

            # devices that do not have a name are probably bridges
            if name:
                self.speakers[speaker_ip] = name

    def _stream_to_speaker(self, speaker_ip, episodes):
        """ Play or enqueue selected episodes """

        urls = [episode.url for episode in episodes if SONOS_CAN_PLAY(episode)]
        logger.info('Streaming to Sonos %s: %s'%(speaker_ip, ', '.join(urls)))

        controller = soco.SoCo(speaker_ip)

        # enqueue and play
        for episode in episodes:
            controller.play_uri(episode.url)
            episode.playback_mark()

        controller.play()

    def on_episodes_context_menu(self, episodes):
        """ Adds a context menu for each Sonos speaker group """

        # Only show context menu if we can play at least one file
        if not any(SONOS_CAN_PLAY(e) for e in episodes):
            return []

        menu_entries = []
        for speaker_ip, name in self.speakers.items():
            callback = partial(self._stream_to_speaker, speaker_ip)

            item = ('/'.join((_('Stream to Sonos'), name)), callback)
            menu_entries.append(item)

        return menu_entries