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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [8e8ad5dfeb]

Overview
Comment:Open json/config files in text mode
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | py3
Files: files | file ages | folders
SHA1: 8e8ad5dfeb100c6bf34f5592f860baa52a8bf505
User & Date: mario on 2014-04-11 02:54:16
Other Links: branch diff | manifest | tags
Context
2014-04-11
22:22
Fixed syntax error in deleted_streams diff check-in: 4b78a4eba1 user: mario tags: py3
02:54
Open json/config files in text mode check-in: 8e8ad5dfeb user: mario tags: py3
02:53
use compat2and3.urllib functions check-in: f56be1b41d user: mario tags: py3
Changes

Modified config.py from [4880b97351] to [9c4bf2dcba].

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
            if (not os.path.exists(self.dir)):
                os.makedirs(self.dir)
           

        # store some configuration list/dict into a file                
        def save(self, name="settings", data=None, gz=0, nice=0):
            name = name + ".json"
            if (data == None):
                data = dict(self.__dict__)  # ANOTHER WORKAROUND: typecast to plain dict(), else json filter_data sees it as object and str()s it
                nice = 1
            # check for subdir
            if (name.find("/") > 0):
                subdir = name[0:name.find("/")]
                subdir = self.dir + "/" + subdir
                if (not os.path.exists(subdir)):







|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
            if (not os.path.exists(self.dir)):
                os.makedirs(self.dir)
           

        # store some configuration list/dict into a file                
        def save(self, name="settings", data=None, gz=0, nice=0):
            name = name + ".json"
            if (data is None):
                data = dict(self.__dict__)  # ANOTHER WORKAROUND: typecast to plain dict(), else json filter_data sees it as object and str()s it
                nice = 1
            # check for subdir
            if (name.find("/") > 0):
                subdir = name[0:name.find("/")]
                subdir = self.dir + "/" + subdir
                if (not os.path.exists(subdir)):
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
        # retrieve data from config file            
        def load(self, name):
            name = name + ".json"
            file = self.dir + "/" + name
            try:
                # .gz or normal file
                if os.path.exists(file + ".gz"):
                    f = gzip.open(file + ".gz", "r")
                elif os.path.exists(file):
                    f = open(file, "r")
                else:
                    return # file not found
                # decode
                r = json.load(f)
                f.close()
                return r
            except Exception as e:
                print("PSON parsing error (in "+name+")", e)
            

        # recursive dict update
        def update(self, with_new_data):
            for key,value in with_new_data.items():
                if type(value) == dict:
                    self[key].update(value)







|

|







|







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
        # retrieve data from config file            
        def load(self, name):
            name = name + ".json"
            file = self.dir + "/" + name
            try:
                # .gz or normal file
                if os.path.exists(file + ".gz"):
                    f = gzip.open(file + ".gz", "rt")
                elif os.path.exists(file):
                    f = open(file, "rt")
                else:
                    return # file not found
                # decode
                r = json.load(f)
                f.close()
                return r
            except Exception as e:
                print(dbg.ERR, "PSON parsing error (in "+name+")", e)
            

        # recursive dict update
        def update(self, with_new_data):
            for key,value in with_new_data.items():
                if type(value) == dict:
                    self[key].update(value)

Modified st2.py from [858158ce9f] to [767c1a69b3].

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
#
#


""" project status """
#
# The application runs mostly stable. The GUI interfaces are workable.

# There haven't been any optimizations regarding memory usage and
# performance. The current internal API is acceptable. Documentation is
# coming up.
#
#  current bugs:
#   - audio- and list-format support is not very robust / needs better API
#   - lots of GtkWarning messages
#   - not all keyboard shortcuts work
#   - in-list search doesn't work in our treeviews (???)
#   - JSON files are only trouble: loading of data files might lead to more
#     errors now, even if pson module still falls back on old method
#     (unicode strings from json.load are useless to us, require typecasts)
#     (nonsupport of tuples led to regression in mygtk.app_restore)
#     (sometimes we receive 8bit-content, which the json module can't save)
#
#  features:
#   - treeview lists are created from datamap[] structure and stream{} dicts
#   - channel categories are built-in defaults (can be freshened up however)
#   - config vars and cache data get stored as JSON in ~/.config/streamtuner2/
#
#  missing:







>

|
<



<

<
<
<
<
<
<







28
29
30
31
32
33
34
35
36
37

38
39
40

41






42
43
44
45
46
47
48
#
#


""" project status """
#
# The application runs mostly stable. The GUI interfaces are workable.
# It's supposed to run on Gtk2 and Gtk3. Python3 support is still WIP.
# There haven't been any optimizations regarding memory usage and
# performance. The current internal API is vastly undocumented.

#
#  current bugs:
#   - audio- and list-format support is not very robust / needs better API

#   - not all keyboard shortcuts work






#
#  features:
#   - treeview lists are created from datamap[] structure and stream{} dicts
#   - channel categories are built-in defaults (can be freshened up however)
#   - config vars and cache data get stored as JSON in ~/.config/streamtuner2/
#
#  missing:
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#     to read the config data -> limited risk, since it's only local files
#   - HIGH RISK: no verification of downloaded favicon image files (ico/png),
#     as they are passed to gtk.gdk.Pixbuf (OTOH data pre-filtered by Google)
#   - MEDIUM: audio players / decoders are easily affected by buffer overflows
#     from corrupt mp3/stream data, and streamtuner2 executes them
#      - but since that's the purpose -> no workaround
#
#  still help wanted on:
#   - any of the above
#   - new plugins (local file viewer)
#   - nicer logo (or donations accepted to consult graphics designer)
#



# standard modules
import sys
import os, os.path
import re







<
<
<
<
<







57
58
59
60
61
62
63





64
65
66
67
68
69
70
#     to read the config data -> limited risk, since it's only local files
#   - HIGH RISK: no verification of downloaded favicon image files (ico/png),
#     as they are passed to gtk.gdk.Pixbuf (OTOH data pre-filtered by Google)
#   - MEDIUM: audio players / decoders are easily affected by buffer overflows
#     from corrupt mp3/stream data, and streamtuner2 executes them
#      - but since that's the purpose -> no workaround
#








# standard modules
import sys
import os, os.path
import re