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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [b3afb7ed76]

Overview
Comment:Manually implement $XDG_MUSIC_DIR lookup.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b3afb7ed767cbfff19c3590b57b8f316e581a1e2
User & Date: mario on 2015-04-11 19:14:15
Other Links: manifest | tags
Context
2015-04-11
19:14
Cleanup exportcat file extension mapping, and fix docs. check-in: 2b729c9433 user: mario tags: trunk
19:14
Manually implement $XDG_MUSIC_DIR lookup. check-in: b3afb7ed76 user: mario tags: trunk
16:09
Safeguard get_data for plugin_meta(), as global or local extras would be found by module_list, but not get_data(). check-in: d781433c78 user: mario tags: trunk
Changes

Modified channels/file.py from [1012fab795] to [84d7cd76cd].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# api: streamtuner2
# title: File browser
# description: Displays mp3/oggs or m3u/pls files from local media file directories.
# type: channel
# category: local
# version: 0.1
# priority: optional
# depends: mutagen
# config:  
#   { name: file_browser_dir, type: text, value: "~/Music, /media/music", description: "List of directories to scan for audio files." },
#   { name: file_browser_ext, type: text, value: "mp3,ogg, m3u,pls,xspf, avi,flv,mpg,mp4", description: "File type/extension filter." },
#
# Local file browser. Presents files from configured directories.



# modules









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# api: streamtuner2
# title: File browser
# description: Displays mp3/oggs or m3u/pls files from local media file directories.
# type: channel
# category: local
# version: 0.1
# priority: optional
# depends: mutagen
# config:  
#   { name: file_browser_dir, type: text, value: "$XDG_MUSIC_DIR, ~/MP3", description: "List of directories to scan for audio files." },
#   { name: file_browser_ext, type: text, value: "mp3,ogg, m3u,pls,xspf, avi,flv,mpg,mp4", description: "File type/extension filter." },
#
# Local file browser. Presents files from configured directories.



# modules
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107








108
109

110



111
112
113
114
115
116
117
118
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

    

    # prepare    
    def __init__(self, parent):
    
        # data dirs
        self.dir = [s.strip() for s in conf.file_browser_dir.split(",")]
        self.ext = [s.strip() for s in conf.file_browser_ext.split(",")]
        # first run
        if not self.categories or not self.streams:
            self.scan_dirs()
            
        # draw gtk lists
        ChannelPlugin.__init__(self, parent)
        
        # make editable
        #{editable:8}
        
        # add custom context menu
        #self.gtk_list.connect('button-press-event', self.context_menu)

        








        
    # save list?

    #save = lambda *x: None



    # yeah, give it a try
    
    # don't load cache file
    cache = lambda *x: None

        

    # read dirs
    def scan_dirs(self):
        self.categories = []
    
        # add main directory
        for main in self.dir:
          main = os.path.expanduser(os.path.expandvars(main))
          if os.path.exists(main):
            self.categories.append(main)
            
            # prepare subdirectories list
            sub = []
            self.categories.append(sub)

            # look through            
            for dir, subdirs, files in os.walk(main):
                name = os.path.basename(dir)

                while name in self.categories:

                    name = name + "2"
        
                # files in subdir
                if files:
                    sub.append(name)
                    self.streams[name] = [self.file_entry(fn, dir) for fn in files if self.we_like_that_extension(fn)]
                
            # plant a maindir reference to shortname


            self.streams[main] = self.streams[os.path.basename(main)]


    # extract meta data
    def file_entry(self, fn, dir):
        # basic data
        meta = {
            "title": fn,







|














|
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
|




<







<










>
|
>
|







>
>
|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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

    

    # prepare    
    def __init__(self, parent):
    
        # data dirs
        self.dir = [self.env_dir(s) for s in conf.file_browser_dir.split(",")]
        self.ext = [s.strip() for s in conf.file_browser_ext.split(",")]
        # first run
        if not self.categories or not self.streams:
            self.scan_dirs()
            
        # draw gtk lists
        ChannelPlugin.__init__(self, parent)
        
        # make editable
        #{editable:8}
        
        # add custom context menu
        #self.gtk_list.connect('button-press-event', self.context_menu)


    # Interpolate $VARS and XDG_SPECIAL_DIRS
    def env_dir(self, path):
        path = path.strip()
        env = self.fvars()
        # Replace $XDG_ ourselfes and normal $ENV vars per expandvars (because os.environ.update() doesn't do)
        path = re.sub("\$(XDG\w+)", lambda m: env.get(m.group(1), m.group(0)), path)
        path = os.path.expandvars(path)
        return os.path.expanduser(path)

    # Read user-dirs config
    def fvars(self, fn="$HOME/.config/user-dirs.dirs"):
        fn = os.path.expandvars(fn)
        src = open(fn, "r").read() if os.path.exists(fn) else ""
        env = re.findall('^(\w+)=[\"\']?(.+?)[\"\']', src, re.M)
        return dict(env)

    
    # don't load cache file
    cache = lambda *x: None



    # read dirs
    def scan_dirs(self):
        self.categories = []
    
        # add main directory
        for main in self.dir:

          if os.path.exists(main):
            self.categories.append(main)
            
            # prepare subdirectories list
            sub = []
            self.categories.append(sub)

            # look through            
            for dir, subdirs, files in os.walk(main):
                name = os.path.basename(dir)
                sfx = ""
                while name+sfx in self.categories:
                    sfx = str(int(sfx)+1) if sfx else "2"
                name += sfx
        
                # files in subdir
                if files:
                    sub.append(name)
                    self.streams[name] = [self.file_entry(fn, dir) for fn in files if self.we_like_that_extension(fn)]
                
            # plant a maindir reference to shortname
            main_base = os.path.basename(main)
            if self.streams.get(main_base):
                self.streams[main] = self.streams[main_base]


    # extract meta data
    def file_entry(self, fn, dir):
        # basic data
        meta = {
            "title": fn,
169
170
171
172
173
174
175
176
177
178
179
180
    def update_categories(self):
        self.scan_dirs()

        
    # same as init
    def update_streams(self, cat, x=0):
        self.scan_dirs()
        print(self.streams)
        print(self.categories)
        return self.streams.get(os.path.basename(cat))









<
<



183
184
185
186
187
188
189


190
191
192
    def update_categories(self):
        self.scan_dirs()

        
    # same as init
    def update_streams(self, cat, x=0):
        self.scan_dirs()


        return self.streams.get(os.path.basename(cat))