1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# encoding: UTF-8
# api: streamtuner2
# title: Drag and Drop (experimental)
# description: Copy streams/stations from and to other applications.
# depends: uikit
# version: 0.5
# type: interface
# config:
# { name: dnd_format, type: select, value: xspf, select: "pls|m3u|xspf|jspf|asx|smil", description: "Default temporary file format for copying a station." }
# category: ui
# priority: default
# support: experimental
#
# Implements Gtk/X11 drag and drop support for station lists.
# Should allow to export either just stream URLs, or complete
# PLS, XSPF collections.
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# encoding: UTF-8
# api: streamtuner2
# title: Drag and Drop (experimental)
# description: Copy streams/stations from and to other applications.
# depends: uikit
# version: 0.5
# type: interface
# config:
# { name: dnd_format, type: select, value: xspf, select: "pls|m3u|xspf|jspf|asx|smil|desktop", description: "Default temporary file format for copying a station." }
# category: ui
# priority: default
# support: experimental
#
# Implements Gtk/X11 drag and drop support for station lists.
# Should allow to export either just stream URLs, or complete
# PLS, XSPF collections.
|
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
("audio/x-mpegurl", 0, 20),
("application/x-scpls", 0, 21),
("application/xspf+xml", 0, 22),
("application/smil", 0, 23),
("text/html", 0, 23),
("text/richtext", 0, 23),
("application/jspf+json", 0, 25),
# direct srv urls
("text/url", 0, 15), #@TODO: support in action.save_/convert_
("message/external-body", 0, 15),
("url/direct", 0, 15),
# filename, file:// IRL
("FILE_NAME", 0, 3),
("text/uri-list", 0, 4),
|
>
|
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
("audio/x-mpegurl", 0, 20),
("application/x-scpls", 0, 21),
("application/xspf+xml", 0, 22),
("application/smil", 0, 23),
("text/html", 0, 23),
("text/richtext", 0, 23),
("application/jspf+json", 0, 25),
("application/x-desktop", 0, 26),
# direct srv urls
("text/url", 0, 15), #@TODO: support in action.save_/convert_
("message/external-body", 0, 15),
("url/direct", 0, 15),
# filename, file:// IRL
("FILE_NAME", 0, 3),
("text/uri-list", 0, 4),
|
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
# Map target/`info` integers to action. module identifiers
cnv_types = {
20: "m3u",
21: "pls",
22: "xspf",
23: "smil",
25: "jspf",
15: "srv",
4: "temp",
5: "srv",
51: "json",
}
|
>
|
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# Map target/`info` integers to action. module identifiers
cnv_types = {
20: "m3u",
21: "pls",
22: "xspf",
23: "smil",
25: "jspf",
26: "desktop",
15: "srv",
4: "temp",
5: "srv",
51: "json",
}
|
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
# Keep in type request buffer
self.buf[info] = buf
return buf
# -- DESTINATION, when playlist/file gets dragged in from other app --
# Just a notification for incoming drop
def drop(self, widget, context, x, y, time):
log.DND("destβin: drop-probing, possible targets:", context.targets)
# find a matching target
accept = [type[0] for type in self.drag_types if type[0] in context.targets]
context.drop_reply(len(accept) > 0, time)
|
|
|
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
# Keep in type request buffer
self.buf[info] = buf
return buf
# -- DESTINATION, when playlist/file gets dragged into ST2 from other app --
# Just a notification for incoming drop
def drop(self, widget, context, x, y, time):
log.DND("destβin: drop-probing, possible targets:", context.targets)
# find a matching target
accept = [type[0] for type in self.drag_types if type[0] in context.targets]
context.drop_reply(len(accept) > 0, time)
|
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
|
return True
# Received files or payload has to be converted, copied into streams
def import_row(self, info, urls, data, y=5000):
# Internal target dicts
cn = self.parent.channel()
rows = []
print info
# Direct/internal row import
if data and info >= 51:
log.DND("Received row, append, reload")
rows += [ json.loads(data) ]
# Convertible formats as direct payload
elif data and info >= 5:
cnv = action.extract_playlist(data)
add = cnv.rows(self.cnv_types[info] if info>=20 else cnv.probe_fmt() or "raw")
rows += [ cnv.mkrow(row) for row in add ]
# Extract from playlist files, either passed as text/uri-list or single FILE_NAME
elif urls:
for fn in urls or [data]:
if not re.match("^(scp|file)://(localhost)?/|/", fn):
continue
fn = compat2and3.urldecode(re.sub("^\w+://[^/]*", "", fn))
cnv = action.extract_playlist(fn=fn)
if cnv.src:
rows += [ cnv.mkrow(row) for row in cnv.rows() ]
# Insert and update view
if rows:
# Inserting at correct row requires deducing index from dnd `y` position
streams = cn.streams[cn.current]
i_pos = (cn.gtk_list.get_path_at_pos(10, y) or [[len(streams) + 1]])[0][0]
for row in rows:
streams.insert(i_pos - 1, row)
i_pos = i_pos + 1
# Now appending to the liststore directly would be even nicer
uikit.do(lambda *x: cn.load(cn.current))#, cn.gtk_list.scroll_to_point(0, y))
if cn.module == "bookmarks":
cn.save()
#self.parent.streamedit()
else:
self.parent.status("Unsupported station format. Not imported.")
|
<
|
>
>
<
<
<
<
|
<
<
<
|
|
>
>
>
|
|
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
|
return True
# Received files or payload has to be converted, copied into streams
def import_row(self, info, urls, data, y=5000):
# Internal target dicts
cn = self.parent.channel()
rows = []
# Direct/internal row import
if data and info >= 51:
log.DND("Received row in internal format, append+reload")
rows += [ json.loads(data) ]
# Convertible formats as direct payload
elif data and info >= 5:
log.DND("Converting direct payload playlist")
cnv = action.extract_playlist(data)
add = cnv.rows(self.cnv_types[info] if info>=20 else cnv.probe_fmt() or "raw")
rows += [ cnv.mkrow(row) for row in add ]
# Extract from playlist files, either passed as text/uri-list or single FILE_NAME
elif urls:
log.DND("Importing from playlist file")
for fn in urls or [data]:
if not re.match("^(scp|file)://(localhost)?/|/", fn):
continue
fn = compat2and3.urldecode(re.sub("^\w+://[^/]*", "", fn))
cnv = action.extract_playlist(fn=fn)
if cnv.src:
rows += [ cnv.mkrow(row) for row in cnv.rows() ]
# Insert and update view
if rows:
cn.insert_rows(rows, y)
# if cn.module == "bookmarks":
cn.save()
# Show streamedit window if title is empty
if not len(rows[0].get("title", "")):
self.parent.configwin.load_config(rows[0], "streamedit_")
self.parent.win_streamedit.show()
else:
self.parent.status("Unsupported station format. Not imported.")
|