git.fiddlerwoaroof.com
Browse code

temporary commit

fiddlerwoaroof authored on 23/05/2016 22:52:35
Showing 4 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+#!/usr/bin/env python
2
+
3
+from flask import Flask
4
+app = Flask(__name__)
5
+
6
+@app.route('/')
7
+def main():
8
+    return 'Coming Soone!'
9
+
10
+if __name__ == '__main__':
11
+    app.run()
0 12
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+from __future__ import print_function
2
+from twisted.internet.protocol import Protocol, ClientFactory
3
+import sys
4
+
5
+class WelcomeMessage(Protocol):
6
+    def dataReceived(self, data):
7
+        sys.stdout.write(data)
8
+    def connectionMade(self):
9
+        self.transport.write('Hello server, I am the client!\n')
10
+
11
+class WelcomeMessageFactory(ClientFactory):
12
+    def startedConnecting(self, connector):
13
+        print('Started to connect.')
14
+    def buildProtocol(self, addr):
15
+        print('Connected.')
16
+        return WelcomeMessage()
17
+    def clientConnectionLost(self, connector, reason):
18
+        print('Lost connection. Reason:', reason)
19
+    def clientConnectionFailed(self, connector, reason):
20
+        print('Connection failed. Reason:', reason)
21
+
22
+
23
+from twisted.internet import reactor
24
+d = reactor.connectTCP("localhost", 8007, WelcomeMessageFactory())
25
+reactor.run()
... ...
@@ -12,32 +12,54 @@ class SelectableText(urwid.Text):
12 12
     def selectable(self): return True
13 13
 
14 14
 class Playlist(urwid.WidgetWrap):
15
-    def __init__(self, columns, plylst):
16
-        self.playlist = plylst
15
+    def __init__(self, columns, col_display, plylst=None):
16
+        if plylst == None:
17
+            plylst = responsedict.ResponseDict()
17 18
         self.columns = columns
18
-        self.texts = self.get_texts(self.playlist.as_table(), cols)
19
+        self.display_pref = col_display
20
+        self.texts = self.get_texts(plylst.as_list())
21
+        self.body = urwid.SimpleFocusListWalker([])
22
+        self.make_playlist()
19 23
 
20
-        self.titles = urwid.Columns([('weight',w,SelectableText(c)) for w,c,_ in cols],1)
24
+        self.titles = self.make_columns()
21 25
         self.header = urwid.Pile([self.titles, urwid.Divider('-')])
22
-        widget = self.make_playlist()
26
+        widget = urwid.ListBox(self.body)
23 27
         widget = urwid.Frame(widget, self.header)
24 28
         urwid.WidgetWrap.__init__(self, widget)
25 29
 
26
-    def get_texts(self, choices, columns):
30
+    def make_columns(self):
31
+        return urwid.Columns([
32
+                ('weight',self.display_pref[c].weight,SelectableText(self.display_pref[c].dispname))
33
+                    for c in self.columns
34
+            ],1)
35
+
36
+    def get_texts(self, choices):
37
+        #TODO: re-work column info to separate data from presentation info
27 38
         texts = []
28
-        for weight,col,transform in columns:
29
-            texts.append([(weight,transform(x[0])) for x in choices.get(col)])
39
+        for x in choices:
40
+            texts.append([])
41
+            for col in self.columns:
42
+                display = self.display_pref[col]
43
+                texts[-1].append((display.weight,display.transform(x.get(col,[""])[0])))
30 44
         return texts
31 45
 
32
-    def make_playlist(self):
33
-        body = []
34
-        for x in itertools.izip_longest(*self.texts):
46
+    def update_texts(self, choices):
47
+        self.texts = self.get_texts(choices.as_list())
48
+        self.update_playlist()
49
+
50
+    def make_body(self):
51
+        for x in self.texts:
35 52
             new_widg = [('weight',wgt,SelectableText(it,wrap='clip')) for wgt,it in x]
36 53
             new_widg = urwid.Columns(new_widg, 1)
37 54
             new_widg = urwid.AttrMap(new_widg, 'unselected', 'selected')
38
-            body.append(new_widg)
39
-        list_walker = urwid.SimpleFocusListWalker(body)
40
-        return urwid.ListBox(urwid.SimpleFocusListWalker(body[:]))
55
+            self.body.append(new_widg)
56
+
57
+    def update_playlist(self):
58
+        del self.body[:]
59
+        self.make_body()
60
+
61
+    def make_playlist(self):
62
+        self.make_body()
41 63
 
42 64
 def exit_on_q(key):
43 65
     if key in ('q', 'Q'):
... ...
@@ -45,26 +67,73 @@ def exit_on_q(key):
45 67
         finally: reactor.stop()
46 68
 
47 69
 cols = [
48
-    (1,'Pos', lambda x: str(int(x)+1)),
49
-    (4,'Album', lambda x:x),
50
-    (3,'Artist', lambda x:x),
51
-    (5,'Title', lambda x:x)
70
+    'Pos',
71
+    'Date',
72
+    'Album',
73
+    'Artist',
74
+    'AlbumArtist',
75
+    'Title',
52 76
 ]
53 77
 
78
+import collections
79
+class DisplayDict(collections.Mapping):
80
+    def __init__(self, data):
81
+        self.row_class=collections.namedtuple('displaytuple', ['dispname','weight','transform'])
82
+        self.data = self.normalize(data)
83
+    def normalize(self, data):
84
+        out = {}
85
+        for key,val in data.iteritems():
86
+            dispname,weight,transform = None,1,lambda x:x
87
+            if hasattr(val, '__iter__'):
88
+                if len(val) == 3: dispname,weight,transform = val
89
+                if len(val) == 2: dispname,weight = val
90
+            if dispname is None:
91
+                dispname = key
92
+            out[key] = self.row_class(dispname, weight, transform)
93
+        return out
94
+    def __getitem__(self, key):
95
+        head, _, tail = key.partition('.')
96
+        if tail:
97
+            try:
98
+                return getattr(self.data[head], tail)
99
+            except AttributeError, e:
100
+                raise KeyError('Key not found: %s' % key)
101
+        else:
102
+            return self.data[head]
103
+    def __iter__(self):
104
+        return iter(self.data)
105
+    def __len__(self):
106
+        return len(self.data)
107
+
108
+
109
+col_display = DisplayDict(
110
+    dict(
111
+        Pos=('#',1,lambda x: x and str(int(x) + 1)),
112
+        Date=('Year', 4),
113
+        Album=(None,8),
114
+        Artist=(None,8),
115
+        AlbumArtist=('Album Artist',5),
116
+        Title=(None,13),
117
+))
118
+
54 119
 @defer.inlineCallbacks
55 120
 def get_playlist():
56 121
     client = yield mpdprotocol.get_client()
57
-    res = yield client.sendCommand('playlistinfo')
58
-    method, data = res
59
-    loop.widget = Playlist(cols, data)
122
+    method, data = yield client.sendCommand('playlistinfo')
123
+    loop.widget.update_texts(data)
60 124
     loop.draw_screen()
125
+    while True:
126
+        idle = yield client.idle(['playlist'])
127
+        method, data = yield client.sendCommand('playlistinfo')
128
+        loop.widget.update_texts(data)
129
+        loop.draw_screen()
61 130
 
62 131
 from twisted.internet import reactor
63 132
 palette = [
64 133
     ('selected', 'white', 'black'),
65 134
     ('selected', 'black', 'white'),
66 135
 ]
67
-loop = urwid.MainLoop(urwid.SolidFill(), palette, event_loop=urwid.TwistedEventLoop(), unhandled_input=exit_on_q)
136
+loop = urwid.MainLoop(Playlist(cols, col_display), palette, event_loop=urwid.TwistedEventLoop(), unhandled_input=exit_on_q)
68 137
 reactor.callWhenRunning(get_playlist)
69 138
 loop.run()
70 139
 
71 140
new file mode 100644
... ...
@@ -0,0 +1,65 @@
1
+# -*- coding: utf-8 -*-
2
+from twisted.web import server, resource 
3
+from twisted.internet import reactor
4
+from twisted.internet import task
5
+
6
+import mpdprotocol
7
+import jinja2
8
+import json
9
+
10
+class MPDResource(resource.Resource):
11
+    isLeaf = True
12
+    jinja2env = jinja2.Environment(loader=jinja2.FileSystemLoader('templates'))
13
+
14
+    def do(self, mpc, request):
15
+        d = mpc.sendCommand('playlistinfo')
16
+
17
+        cb = self.render_playlist
18
+        if 'json' in request.args:
19
+            if 'table' in request.args:
20
+                cb = self.render_as_table_json
21
+            else:
22
+                cb = self.render_as_json
23
+        d.addCallback(cb, request)
24
+        return d
25
+
26
+    def render_as_table_json(self, result, request):
27
+        method, data = result
28
+        request.setHeader('Content-Type', 'application/json')
29
+        request.write(json.dumps(data.as_table()));
30
+        request.finish()
31
+
32
+    def render_as_json(self, result, request):
33
+        method, data = result
34
+        request.setHeader('Content-Type', 'application/json')
35
+        request.write(json.dumps(data.as_list()));
36
+        request.finish()
37
+
38
+    def render_playlist(self, result, request):
39
+        print('rendering playlist!')
40
+        method, data = result
41
+        template = self.jinja2env.get_template('playlist.html')
42
+        tdata = []
43
+        for datum in data.as_list():
44
+            tdata.append([])
45
+            tdata[-1].append(('pos', datum['Pos']))
46
+            tdata[-1].append(('title', datum['Title']))
47
+            tdata[-1].append(('artist', datum['Artist']))
48
+            tdata[-1].append(('album', datum['Album']))
49
+            tdata[-1].append(('genre', datum['Genre']))
50
+        request.write(template.render(playlist=tdata).encode('utf-8'))
51
+        request.finish()
52
+
53
+    def failed(self, failure, request):
54
+       print "whjat should I do here?"
55
+       print self, failure, request 
56
+       failure.printTraceback()
57
+       failure.raiseException()
58
+
59
+    def render_GET(self, request):
60
+        print('ello world!')
61
+        d = mpdprotocol.get_client().addCallback(self.do, request)
62
+        d.addErrback(self.failed, request)
63
+        return server.NOT_DONE_YET
64
+
65
+resource = MPDResource()