Check-in [41405a6488]
Overview
| Comment: | fixed channels/timer gtk signal_connect handling, st2main now provides an amendable slot dict |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
41405a6488758582e7ee2afcdffa4101 |
| User & Date: | mario on 2014-01-05 03:30:44 |
| Original Comment: | (no comment) |
| Other Links: | manifest | tags |
Context
|
2014-01-06
| ||
| 22:45 | prepare for gtk3 check-in: c0702405f8 user: mario tags: trunk | |
|
2014-01-05
| ||
| 03:30 | fixed channels/timer gtk signal_connect handling, st2main now provides an amendable slot dict check-in: 41405a6488 user: mario tags: trunk | |
| 01:23 | fix Pixbuf has_alpha bug due to redundant typecast prior liststore appending check-in: caee086b9c user: mario tags: trunk, 2.0.9 | |
Changes
Modified _pack from [b488883eba] to [b33b7021fe].
| ︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
pax -wvJf streamtuner2-$VERSION.src.txz \
streamtuner2/*.py streamtuner2/*.xml streamtuner2/channels/*.{py,png} \
streamtuner2/*.png streamtuner2/*.svg streamtuner2/*.desktop \
streamtuner2/README streamtuner2/help/* streamtuner2/contrib/* \
streamtuner2/PKG-INFO streamtuner2/version streamtuner2/_pack streamtuner2/*.epm
# streamtuner2/scripts
cd -
echo "-------------------- .deb -----------------------"
fakeroot epm -vvv -n -a all -f deb DEP=deb streamtuner2 _package.epm
echo "------------------ slackware --------------------"
epm -vvv -n -a all -f slackware streamtuner2 _package.epm
echo "-------------- .tar.gz installer ---------------"
epm -vvv -n -a all -f portable -s streamtuner2.png streamtuner2 _package.epm
echo "-------------------- .rpm -----------------------"
epm -vvv -n -a all -f rpm streamtuner2 _package.epm
/usr/bin/rpmbuild -bb --buildroot "/home/mario/projects/streamtuner2/linux-3.0-all/buildroot" --target all linux-3.0-all/streamtuner2.spec
| > | > > > > > > > | 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 |
pax -wvJf streamtuner2-$VERSION.src.txz \
streamtuner2/*.py streamtuner2/*.xml streamtuner2/channels/*.{py,png} \
streamtuner2/*.png streamtuner2/*.svg streamtuner2/*.desktop \
streamtuner2/README streamtuner2/help/* streamtuner2/contrib/* \
streamtuner2/PKG-INFO streamtuner2/version streamtuner2/_pack streamtuner2/*.epm
# streamtuner2/scripts
cd -
mv ../streamtuner2-*.txz linux-3.0-all/
echo "-------------------- .deb -----------------------"
fakeroot epm -vvv -n -a all -f deb DEP=deb streamtuner2 _package.epm
echo "------------------ slackware --------------------"
epm -vvv -n -a all -f slackware streamtuner2 _package.epm
echo "-------------- .tar.gz installer ---------------"
epm -vvv -n -a all -f portable -s streamtuner2.png streamtuner2 _package.epm
echo "-------------------- .rpm -----------------------"
epm -vvv -n -a all -f rpm streamtuner2 _package.epm
/usr/bin/rpmbuild -bb --buildroot "/home/mario/projects/streamtuner2/linux-3.0-all/buildroot" --target all linux-3.0-all/streamtuner2.spec
mv linux-3.0-all/RPMS/all/*.rpm linux-3.0-all/streamtuner2-$VERSION.rpm
rm -r linux-3.0-all/RPMS
rm -r linux-3.0-all/rpms
rm -r linux-3.0-all/buildroot
rmdir linux-3.0-all/streamtuner2-$VERSION
rm linux-3.0-all/streamtuner2.spec
echo "-------------------- win32 -----------------------"
for pkg in "win32"
do
epm-win32sfx -v streamtuner2 _package.epm
done
mv win32/*exe linux-3.0-all/
rmdir win32
|
Modified channels/shoutcast.py from [20027a66d7] to [59a1f308de].
| ︙ | ︙ | |||
119 120 121 122 123 124 125 |
# loop
entries = []
next = 0
max = int(conf.max_streams)
count = max
rx_stream = None
rx_next = re.compile("""onclick="showMoreGenre""")
| > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# loop
entries = []
next = 0
max = int(conf.max_streams)
count = max
rx_stream = None
rx_next = re.compile("""onclick="showMoreGenre""")
try:
while (next < max):
# page
url = "http://www.shoutcast.com/genre-ajax/" + ucat
referer = url.replace("/genre-ajax", "/radio")
params = { "strIndex":"0", "count":str(count), "ajax":"true", "mode":"listeners", "order":"desc" }
html = http.ajax(url, params, referer) #,feedback=self.parent.status)
__print__(html)
# regular expressions
if not conf.get("pyquery") or not pq:
# new extraction regex
if not rx_stream:
rx_stream = re.compile(
"""
<a\s+class="?playbutton\d?[^>]+id="(\d+)".+?
<a\s+class="[\w\s]*title[\w\s]*"[^>]+href="(http://[^">]+)"[^>]*>([^<>]+)</a>.+?
(?:Recently\s*played|Coming\s*soon|Now\s*playing):\s*([^<]*).+?
ners">(\d*)<.+?
bitrate">(\d*)<.+?
type">([MP3AAC]*)
""",
re.S|re.I|re.X
)
# extract entries
self.parent.status("parsing document...")
__print__("loop-rx")
for m in rx_stream.findall(html):
(id, homepage, title, playing, ls, bit, fmt) = m
__print__(uu)
entries += [{
"title": self.entity_decode(title),
"url": "http://yp.shoutcast.com/sbin/tunein-station.pls?id=" + id,
"homepage": http.fix_url(homepage),
"playing": self.entity_decode(playing),
"genre": cat, #self.strip_tags(uu[4]),
"listeners": int(ls),
"max": 0, #int(uu[6]),
"bitrate": int(bit),
"format": self.mime_fmt(fmt),
}]
# PyQuery parsing
else:
# iterate over DOM
for div in (pq(e) for e in pq(html).find("div.dirlist")):
entries.append({
"title": div.find("a.playbutton,a.playbutton1").attr("title"),
"url": div.find("a.playbutton,a.playbutton1").attr("href"),
"homepage": http.fix_url(div.find("a.div_website").attr("href")),
"playing": div.find("div.playingtext").attr("title"),
# "title": div.find("a.clickabletitleGenre, div.stationcol a").attr("title"),
# "url": div.find("a.playbutton, a.playbutton1, a.playimage").attr("href"),
# "homepage": http.fix_url(div.find("a.playbutton.clickabletitle, a[target=_blank], a.clickabletitleGenre, a.clickabletitle, div.stationcol a, a").attr("href")),
# "playing": div.find("div.playingtextGenre, div.playingtext").attr("title"),
"listeners": int(div.find("div.dirlistners").text()),
"bitrate": int(div.find("div.dirbitrate").text()),
"format": self.mime_fmt(div.find("div.dirtype").text()),
"max": 0,
"genre": cat,
# "title2": e.find("a.playbutton").attr("name"),
})
# display partial results (not strictly needed anymore, because we fetch just one page)
self.parent.status()
self.update_streams_partially_done(entries)
# more pages to load?
if (re.search(rx_next, html)):
next += count
else:
next = 99999
except:
return entries
#fin
__print__(entries)
return entries
|
Modified channels/timer.py from [c3eb5a36c2] to [c50adafaed].
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | # Okay, while programming this, I missed the broadcast I wanted to hear. Again(!) # But still this is a useful extension, as it allows recording and playing specific # stations at a programmed time and interval. It accepts a natural language time # string when registering a stream. (Via streams menu > extension > add timer) # # Programmed events are visible in "timer" under the "bookmarks" channel. Times # are stored in the description field, and can thus be edited. However, after editing | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # Okay, while programming this, I missed the broadcast I wanted to hear. Again(!) # But still this is a useful extension, as it allows recording and playing specific # stations at a programmed time and interval. It accepts a natural language time # string when registering a stream. (Via streams menu > extension > add timer) # # Programmed events are visible in "timer" under the "bookmarks" channel. Times # are stored in the description field, and can thus be edited. However, after editing # times manually, streamtuner2 must be restarted for the changes to take effect. # from channels import * import kronos from mygtk import mygtk from action import action |
| ︙ | ︙ | |||
63 64 65 66 67 68 69 |
# target channel
if not self.bookmarks.streams.get("timer"):
self.bookmarks.streams["timer"] = [{"title":"--- timer events ---"}]
self.bookmarks.add_category("timer")
self.streams = self.bookmarks.streams["timer"]
# widgets
| | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# target channel
if not self.bookmarks.streams.get("timer"):
self.bookmarks.streams["timer"] = [{"title":"--- timer events ---"}]
self.bookmarks.add_category("timer")
self.streams = self.bookmarks.streams["timer"]
# widgets
parent.add_signals.update({
"timer_ok": self.add_timer,
"timer_cancel": lambda w,*a: self.parent.timer_dialog.hide() or 1,
})
# prepare spool
self.sched = kronos.ThreadedScheduler()
for row in self.streams:
|
| ︙ | ︙ |
Modified st2.py from [2dd481062a] to [26d82d3fb9].
| ︙ | ︙ | |||
118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# object containers
widgets = {} # non-glade widgets (the manually instantiated ones)
channels = {} # channel modules
features = {} # non-channel plugins
working = [] # threads
# status variables
channel_names = ["bookmarks"] # order of channel notebook tabs
current_channel = "bookmarks" # currently selected channel name (as index in self.channels{})
# constructor
| > | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# object containers
widgets = {} # non-glade widgets (the manually instantiated ones)
channels = {} # channel modules
features = {} # non-channel plugins
working = [] # threads
add_signals = {} # channel gtk-handler signals
# status variables
channel_names = ["bookmarks"] # order of channel notebook tabs
current_channel = "bookmarks" # currently selected channel name (as index in self.channels{})
# constructor
|
| ︙ | ︙ | |||
169 170 171 172 173 174 175 |
self.current_channel = self.current_channel_gtk()
try: self.channel().first_show()
except: print("channel .first_show() initialization error")
# bind gtk/glade event names to functions
gui_startup(0.95)
| | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
self.current_channel = self.current_channel_gtk()
try: self.channel().first_show()
except: print("channel .first_show() initialization error")
# bind gtk/glade event names to functions
gui_startup(0.95)
self.connect_signals(dict( {
"gtk_main_quit" : self.gtk_main_quit, # close window
# treeviews / notebook
"on_stream_row_activated" : self.on_play_clicked, # double click in a streams list
"on_category_clicked": self.on_category_clicked, # new selection in category list
"on_notebook_channels_switch_page": self.channel_switch, # channel notebook tab changed
"station_context_menu": lambda tv,ev: station_context_menu(tv,ev),
# toolbar
|
| ︙ | ︙ | |||
219 220 221 222 223 224 225 |
"search_google": search.google,
"search_cancel": search.cancel,
"true": lambda w,*args: True,
"streamedit_open": streamedit.open,
"streamedit_save": streamedit.save,
"streamedit_new": streamedit.new,
"streamedit_cancel": streamedit.cancel,
| | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
"search_google": search.google,
"search_cancel": search.cancel,
"true": lambda w,*args: True,
"streamedit_open": streamedit.open,
"streamedit_save": streamedit.save,
"streamedit_new": streamedit.new,
"streamedit_cancel": streamedit.cancel,
}.items() + self.add_signals.items() ))
# actually display main window
gui_startup(0.99)
self.win_streamtuner2.show()
# WHY DON'T YOU WANT TO WORK?!
#self.shoutcast.gtk_list.set_enable_search(True)
|
| ︙ | ︙ | |||
468 469 470 471 472 473 474 |
if module not in self.channel_names: # skip (glade) built-in channels
self.channel_names.append(module)
# other plugin types
else:
self.features[module] = plugin_class(parent=self)
except Exception, e:
| | > | | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
if module not in self.channel_names: # skip (glade) built-in channels
self.channel_names.append(module)
# other plugin types
else:
self.features[module] = plugin_class(parent=self)
except Exception, e:
print("error initializing:", module, ", exception:")
import traceback
traceback.print_exc()
# default plugins
conf.add_plugin_defaults(self.channels["bookmarks"].config, "bookmarks")
#conf.add_plugin_defaults(self.channels["shoutcast"].config, "shoutcast")
# store window/widget states (sizes, selections, etc.)
def app_state(self, widget):
|
| ︙ | ︙ |