Internet radio browser GUI for music/video streams from various directory services.

โŒˆโŒ‹ โŽ‡ branch:  streamtuner2


Check-in [3b7a4ff895]

Overview
Comment:Separate statusbar timer-reset from text/progressbar setter.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3b7a4ff895b794a70d2f1de5a3f90bcfeb377e06
User & Date: mario on 2015-05-01 22:41:31
Other Links: manifest | tags
Context
2015-05-01
22:52
Remove contrib/bieber joke example. check-in: c854934751 user: mario tags: trunk
22:41
Separate statusbar timer-reset from text/progressbar setter. check-in: 3b7a4ff895 user: mario tags: trunk
02:16
Use empty stub {} dict in place of state.json contents on fresh init. check-in: 3d6205d2d3 user: mario tags: trunk
Changes

Modified Makefile from [fb00faeb9d] to [e1a4d7c25a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Requires 
# ยท http://fossil.include-once.org/versionnum/
# ยท http://fossil.include-once.org/xpm/

SHELL   := /bin/bash #(for brace expansion)
NAME    := streamtuner2
VERSION := $(shell version get:plugin st2.py || echo 2.1dev)
DEST    := /usr/share/streamtuner2
INST    := install -m 644
PACK    := xpm
DEPS    := -n $(NAME) -d python -d python-pyquery -d python-gtk2 -d python-requests -d python-keybinder
DEPS_A  := -n $(NAME) -d pygtk -d python2 -d python2-cssselect -d python2-keybinder2 -d python2-lxml -d python2-pillow -d python2-pyquery -d python2-xdg -d python2-requests
OPTS    := -s src -u packfile,man,fixperms -f --prefix=$(DEST) --deb-compression xz --rpm-compression xz --exe-autoextract

# targets
.PHONY:	bin
all:	gtk3 #(most used)
pack:	all ver docs xpm src
gtk3:	gtk3.xml.gz
zip:	pyz











|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Requires 
# ยท http://fossil.include-once.org/versionnum/
# ยท http://fossil.include-once.org/xpm/

SHELL   := /bin/bash #(for brace expansion)
NAME    := streamtuner2
VERSION := $(shell version get:plugin st2.py || echo 2.1dev)
DEST    := /usr/share/streamtuner2
INST    := install -m 644
PACK    := xpm
DEPS    := -n $(NAME) -d python -d python-pyquery -d python-gtk2 -d python-requests -d python-keybinder
DEPS_A  := -n $(NAME) -d pygtk -d python2 -d python2-cssselect -d python2-keybinder2 -d python2-lxml -d python2-pillow -d python2-pyquery -d python2-xdg -d python2-requests --provides streamtuner-python
OPTS    := -s src -u packfile,man,fixperms -f --prefix=$(DEST) --deb-compression=xz --rpm-compression=xz --exe-autoextract

# targets
.PHONY:	bin
all:	gtk3 #(most used)
pack:	all ver docs xpm src
gtk3:	gtk3.xml.gz
zip:	pyz
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
clean:
	rm *.pyc */*.pyc
	rm -r __pycache__ */__pycache__

#-- bundles
xpm: deb pyz tar rpm exe
deb:
	$(PACK) $(OPTS) $(DEPS) -t $@ -p "$(NAME)-VERSION.deb" st2.py
rpm:
	$(PACK) $(OPTS) $(DEPS) -t $@ -p "$(NAME)-VERSION.rpm" st2.py
tar:
	$(PACK) $(OPTS) $(DEPS) -t $@ -p "$(NAME)-VERSION.bin.txz" st2.py
exe:
	$(PACK) $(OPTS) $(DEPS) -t $@ -p "$(NAME)-VERSION.exe" st2.py
arch:
	$(PACK) $(OPTS) $(DEPS_A) -t $@ -p "$(NAME)-VERSION.arch.txz" st2.py
pyz:
        #@BUG: relative package references leave a /tmp/doc/ folder
	$(PACK) -u packfile -s src -t zip --zip-shebang "/usr/bin/env python"	\
		-f -p "$(NAME)-$(VERSION).pyz" --prefix=./  .zip.py st2.py
src:
	cd .. && pax -wvJf streamtuner2/streamtuner2-$(VERSION).src.txz \
		streamtuner2/*.{py,png,svg,desktop} streamtuner2/channels/*.{py,png} \







|

|

|

|

|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
clean:
	rm *.pyc */*.pyc
	rm -r __pycache__ */__pycache__

#-- bundles
xpm: deb pyz tar rpm exe
deb:
	$(PACK) -t $@ $(OPTS) $(DEPS) -p "$(NAME)-VERSION.deb" st2.py
rpm:
	$(PACK) -t $@ $(OPTS) $(DEPS) -p "$(NAME)-VERSION.rpm" st2.py
tar:
	$(PACK) -t $@ $(OPTS) $(DEPS) -p "$(NAME)-VERSION.bin.txz" st2.py
exe:
	$(PACK) -t $@ $(OPTS) $(DEPS) -p "$(NAME)-VERSION.exe" st2.py
arch:
	$(PACK) -t $@ $(OPTS) $(DEPS_A) -p "$(NAME)-VERSION.arch.txz" st2.py
pyz:
        #@BUG: relative package references leave a /tmp/doc/ folder
	$(PACK) -u packfile -s src -t zip --zip-shebang "/usr/bin/env python"	\
		-f -p "$(NAME)-$(VERSION).pyz" --prefix=./  .zip.py st2.py
src:
	cd .. && pax -wvJf streamtuner2/streamtuner2-$(VERSION).src.txz \
		streamtuner2/*.{py,png,svg,desktop} streamtuner2/channels/*.{py,png} \

Modified PKG-INFO from [9170d518b1] to [09ee67ca0a].

1
2
3
4
5
6
7
8
9
10
11
12
Metadata-Version: 1.0
Name: streamtuner2
Version: 2.1.7
Summary: Streamtuner2 is an internet radio browser
Home-page: http://fossil.include-once.org/streamtuner2/
Author: Mario Salzer
Author-email: xmilky+st2@gmail....
License: Public Domain
Description: Streamtuner2 lists radio directory services like Shoutcast, Xiph, Live365, MyOggRadio, Jamendo. It allows listening via any audio player, and recording of streams via streamripper.
Platform: ALL
Keywords: internet-radio, python, streaming, audio



|









1
2
3
4
5
6
7
8
9
10
11
12
Metadata-Version: 1.0
Name: streamtuner2
Version: 2.1.7-dev
Summary: Streamtuner2 is an internet radio browser
Home-page: http://fossil.include-once.org/streamtuner2/
Author: Mario Salzer
Author-email: xmilky+st2@gmail....
License: Public Domain
Description: Streamtuner2 lists radio directory services like Shoutcast, Xiph, Live365, MyOggRadio, Jamendo. It allows listening via any audio player, and recording of streams via streamripper.
Platform: ALL
Keywords: internet-radio, python, streaming, audio

Modified channels/internet_radio.py from [738c122eb2] to [8ca19cbde4].

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
                    "/" + ("page"+str(page) if page>1 else "")
                )
            )

            # Is there a next page?
            if str(page+1) not in rx_pages.findall(html[-1]):
                break
            self.parent.status(float(page)/float(max_pages+1))

        # Alternatively try regex or pyquery parsing
        #log.HTTP(html)
        for use_rx in [not conf.pyquery, conf.pyquery]:
            try:
                entries = (self.with_regex(html) if use_rx else self.with_dom(html))
                if len(entries):







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
                    "/" + ("page"+str(page) if page>1 else "")
                )
            )

            # Is there a next page?
            if str(page+1) not in rx_pages.findall(html[-1]):
                break
            self.parent.status(float(page)/float(max_pages+1), timeout=1)

        # Alternatively try regex or pyquery parsing
        #log.HTTP(html)
        for use_rx in [not conf.pyquery, conf.pyquery]:
            try:
                entries = (self.with_regex(html) if use_rx else self.with_dom(html))
                if len(entries):

Modified st2.py from [a4ef7a55bf] to [49404ca98a].

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380


381
382
383

384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
    def switch_notebook_tabs_position(self, w, pos):
        self.notebook_channels.set_tab_pos(pos);
        




    # Shortcut to statusbar and progressbar.
    # Either pass a string "" or a float 0.5, the message and pulse will be automatically
    # removed after 5 seconds now.
    def status(self, text=None, timeout=3):
        t = time.time() + timeout

        # progressbar
        if isinstance(text, (int, float)):
            if (text <= 0):  # unknown state
                uikit.do(self.progress.pulse, immediate=1)
            elif text >= 0.999 or text < 0.0:  # completed
                uikit.do(self.progress.hide)
            else:  # show percentage
                uikit.do(self.progress.show, immediate=1)
                uikit.do(self.progress.set_fraction, text, immediate=1)
            self.status_last = t
            
        # add text
        elif isinstance(text, (str)):
            uikit.do(self.statusbar.set_text, text)


            self.status_last = t

        # timeout

        if not text or time.time() >= self.status_last:
            self.statusbar.set_text("")
            self.progress.hide()
            return False
        # add timer
        else:
            gobject.timeout_add(int(timeout*1000), self.status)
        return True
    status_last = 0


    # load plugins from /usr/share/streamtuner2/channels/
    def load_plugin_channels(self):

        # initialize plugin modules (pre-ordered)
        ls = module_list()







|
<
<

|
|









<
<



>
>
|

|
>
|



<

<
|
<







354
355
356
357
358
359
360
361


362
363
364
365
366
367
368
369
370
371
372
373


374
375
376
377
378
379
380
381
382
383
384
385
386

387

388

389
390
391
392
393
394
395
    def switch_notebook_tabs_position(self, w, pos):
        self.notebook_channels.set_tab_pos(pos);
        




    # Shortcut to statusbar and progressbar (receives either a string, or a float).


    def status(self, text=None, timeout=3):
        self.status_last = time.time() + timeout
        gobject.timeout_add(int(timeout*1000), self.status_clear)
        # progressbar
        if isinstance(text, (int, float)):
            if (text <= 0):  # unknown state
                uikit.do(self.progress.pulse, immediate=1)
            elif text >= 0.999 or text < 0.0:  # completed
                uikit.do(self.progress.hide)
            else:  # show percentage
                uikit.do(self.progress.show, immediate=1)
                uikit.do(self.progress.set_fraction, text, immediate=1)


        # add text
        elif isinstance(text, (str)):
            uikit.do(self.statusbar.set_text, text)
        # clean up
        else:
            self.status_clear(anyway=True)

    # Clean up after 3 seconds
    def status_clear(self, anyway=False):
        if anyway or time.time() >= self.status_last:
            self.statusbar.set_text("")
            self.progress.hide()
            return False

        else:

            return True



    # load plugins from /usr/share/streamtuner2/channels/
    def load_plugin_channels(self):

        # initialize plugin modules (pre-ordered)
        ls = module_list()