irecorder 0.0.4-linux → 0.0.5-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +14 -6
- data/Rakefile +11 -5
- data/bin/irecorder.rb +55 -207
- data/lib/bbcnet.rb +34 -7
- data/lib/cache.rb +115 -0
- data/lib/download.rb +32 -19
- data/lib/irecorder_resource.rb +264 -0
- data/lib/mylibs.rb +11 -11
- data/lib/programmewin.rb +182 -0
- data/lib/settings.rb +0 -3
- data/lib/taskwin.rb +72 -78
- data/resources/bbcstyle.qss +14 -0
- metadata +9 -9
data/lib/mylibs.rb
CHANGED
@@ -218,17 +218,17 @@ module Enumerable
|
|
218
218
|
end
|
219
219
|
|
220
220
|
#
|
221
|
-
class Hash
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
end
|
221
|
+
# class Hash
|
222
|
+
# alias old_blaket []
|
223
|
+
# def [](key)
|
224
|
+
# unless key.kind_of?(Regexp)
|
225
|
+
# return old_blaket(key)
|
226
|
+
# end
|
227
|
+
#
|
228
|
+
# retk, retv = self.find { |k,v| k =~ key }
|
229
|
+
# retv
|
230
|
+
# end
|
231
|
+
# end
|
232
232
|
|
233
233
|
class Qt::Action
|
234
234
|
def setVData(data)
|
data/lib/programmewin.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
|
2
|
+
#---------------------------------------------------------------------------------------------
|
3
|
+
#
|
4
|
+
#
|
5
|
+
class ProgrammeTableWidget < Qt::TableWidget
|
6
|
+
slots 'filterChanged(const QString &)'
|
7
|
+
|
8
|
+
#
|
9
|
+
#
|
10
|
+
class Programme
|
11
|
+
attr_reader :titleItem, :categoriesItem, :updatedItem
|
12
|
+
attr_reader :content, :link
|
13
|
+
|
14
|
+
def initialize(title, categories, updated, content, link)
|
15
|
+
@titleItem = Item.new(title)
|
16
|
+
@categoriesItem = Item.new(categories)
|
17
|
+
@updatedItem = Item.new(updated)
|
18
|
+
@content = content
|
19
|
+
@link = link
|
20
|
+
end
|
21
|
+
|
22
|
+
def title
|
23
|
+
@titleItem.text
|
24
|
+
end
|
25
|
+
|
26
|
+
def categories
|
27
|
+
@categoriesItem.text
|
28
|
+
end
|
29
|
+
|
30
|
+
def updated
|
31
|
+
@updatedItem.text
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
#
|
37
|
+
class Item < Qt::TableWidgetItem
|
38
|
+
def initialize(text)
|
39
|
+
super(text)
|
40
|
+
self.flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled
|
41
|
+
self.toolTip = text
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
#------------------------------------------------------------------------
|
47
|
+
#
|
48
|
+
#
|
49
|
+
attr_accessor :mediaFilter
|
50
|
+
|
51
|
+
def initialize()
|
52
|
+
super(0, 3)
|
53
|
+
|
54
|
+
setHorizontalHeaderLabels(['Title', 'Category', 'Updated'])
|
55
|
+
self.horizontalHeader.stretchLastSection = true
|
56
|
+
self.selectionBehavior = Qt::AbstractItemView::SelectRows
|
57
|
+
self.alternatingRowColors = true
|
58
|
+
self.sortingEnabled = true
|
59
|
+
sortByColumn(2, Qt::DescendingOrder )
|
60
|
+
|
61
|
+
@mediaFilter = ''
|
62
|
+
|
63
|
+
# Hash table : key column_0_item => Programme entry.
|
64
|
+
@table = Hash.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def addEntry( row, title, categories, updated, content, link )
|
68
|
+
entry = Programme.new(title, categories, updated, content, link)
|
69
|
+
setItem( row, 0, entry.titleItem )
|
70
|
+
setItem( row, 1, entry.categoriesItem )
|
71
|
+
setItem( row, 2, entry.updatedItem )
|
72
|
+
@table[entry.titleItem] = entry
|
73
|
+
end
|
74
|
+
|
75
|
+
# return Programme object.
|
76
|
+
def [](row)
|
77
|
+
@table[item(row,0)]
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
#
|
82
|
+
# slot : called when filterLineEdit text is changed.
|
83
|
+
#
|
84
|
+
public
|
85
|
+
|
86
|
+
def filterChanged(text)
|
87
|
+
return unless text
|
88
|
+
|
89
|
+
text += ' ' + @mediaFilter unless @mediaFilter.empty?
|
90
|
+
|
91
|
+
regxs = text.split(/[,\s]+/).map do |w|
|
92
|
+
/#{Regexp.escape(w.strip)}/i
|
93
|
+
end
|
94
|
+
rowCount.times do |r|
|
95
|
+
i0 = item(r,0)
|
96
|
+
i1 = item(r,1)
|
97
|
+
i2 = item(r,2)
|
98
|
+
txt = ((i0 && i0.text) || '') + ((i1 && i1.text) || '') + ((i2 && i2.text) || '')
|
99
|
+
if regxs.all? do |rx| rx =~ txt end then
|
100
|
+
showRow(r)
|
101
|
+
else
|
102
|
+
hideRow(r)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
GroupName = "ProgrammeTable"
|
108
|
+
def writeSettings
|
109
|
+
config = $config.group(GroupName)
|
110
|
+
config.writeEntry('Header', horizontalHeader.saveState)
|
111
|
+
end
|
112
|
+
|
113
|
+
def readSettings
|
114
|
+
config = $config.group(GroupName)
|
115
|
+
horizontalHeader.restoreState(config.readEntry('Header', horizontalHeader.saveState))
|
116
|
+
end
|
117
|
+
|
118
|
+
protected
|
119
|
+
def contextMenuEvent(e)
|
120
|
+
item = itemAt(e.pos)
|
121
|
+
menu = createPopup
|
122
|
+
execPopup(menu, e.globalPos, item)
|
123
|
+
end
|
124
|
+
|
125
|
+
def createPopup()
|
126
|
+
menu = Qt::Menu.new
|
127
|
+
insertPlayerActions(menu)
|
128
|
+
menu
|
129
|
+
end
|
130
|
+
|
131
|
+
def execPopup(menu, pos, item)
|
132
|
+
action = menu.exec(pos)
|
133
|
+
if action then
|
134
|
+
action.data
|
135
|
+
# $log.code { "execute : '#{action.vData}'" }
|
136
|
+
cmd, exe = action.vData.split(/@/, 2)
|
137
|
+
# $log.code { "cmd(#{cmd}), exe(#{exe})" }
|
138
|
+
case cmd
|
139
|
+
when 'play'
|
140
|
+
playMedia(exe, item)
|
141
|
+
else
|
142
|
+
# self.method(cmd).call(item)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
menu.deleteLater
|
146
|
+
end
|
147
|
+
|
148
|
+
def insertPlayerActions(menu)
|
149
|
+
Mime::services('.wma').each do |s|
|
150
|
+
if s.exec then
|
151
|
+
exeName = s.exec[/\w+/]
|
152
|
+
a = menu.addAction(KDE::Icon.new(exeName), 'Play with ' + exeName)
|
153
|
+
a.setVData('play@' + s.exec)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def playMedia(exe, item)
|
159
|
+
begin
|
160
|
+
prog = self[item.row]
|
161
|
+
url = prog.content[UrlRegexp] # String[] method extract only 1st one.
|
162
|
+
|
163
|
+
$log.info { "episode Url : #{url}" }
|
164
|
+
minfo = BBCNet::MetaInfo.get(url).update
|
165
|
+
url = minfo.wma.url
|
166
|
+
|
167
|
+
cmd, args = exe.split(/\s+/, 2)
|
168
|
+
args = args.split(/\s+/).map do |a|
|
169
|
+
a.gsub(/%\w/, url)
|
170
|
+
end
|
171
|
+
# $log.debug { "execute cmd '#{cmd}', args '#{args.inspect}'" }
|
172
|
+
proc = Qt::Process.new(self)
|
173
|
+
proc.start(cmd, args)
|
174
|
+
|
175
|
+
rescue => e
|
176
|
+
$log.error { e }
|
177
|
+
KDE::MessageBox::information(self, i18n("There is not direct stream for this programme."))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
|
data/lib/settings.rb
CHANGED
@@ -313,9 +313,6 @@ class PlayerSettingsPage < Qt::Widget
|
|
313
313
|
@SelectWebPlayerDlg = SelectWebPlayerDlg.new(self, IRecSettings.webPlayerName)
|
314
314
|
@SelectDirectPlayerDlg = SelectDirectPlayerDlg.new(self, IRecSettings.directPlayerName)
|
315
315
|
IRecSettings.instance.regConverter(@SelectWebPlayerDlg, @SelectDirectPlayerDlg)
|
316
|
-
puts "web player:" + IRecSettings.webPlayerCommand.to_s
|
317
|
-
puts "direct player:" + IRecSettings.directPlayerCommand.to_s
|
318
|
-
|
319
316
|
|
320
317
|
@playerTypeSmall = Qt::RadioButton.new(i18n('small iplayer'))
|
321
318
|
@playerTypeBeta = Qt::RadioButton.new(i18n('beta iplayer'))
|
data/lib/taskwin.rb
CHANGED
@@ -122,33 +122,28 @@ class TaskWindow < Qt::Widget
|
|
122
122
|
poRow = wItem.row
|
123
123
|
poColumn = wItem.column
|
124
124
|
$log.misc { "right clicked item (row:#{poRow}, column:#{poColumn})" }
|
125
|
-
|
126
|
-
sts = taskItemAtRow(wItem.row).status
|
125
|
+
process = taskItemAtRow(wItem.row).process
|
127
126
|
|
128
127
|
menu = Qt::Menu.new
|
129
|
-
insertDefaultActions(menu, poColumn,
|
130
|
-
|
131
|
-
menu.addSeparator
|
132
|
-
insertPlayerActions(menu, url)
|
133
|
-
menu.addSeparator
|
134
|
-
insertMPlayerAction(menu)
|
135
|
-
end
|
128
|
+
insertDefaultActions(menu, poColumn, process)
|
129
|
+
createPlayerMenu(menu, poColumn, process)
|
136
130
|
action = menu.exec(pos)
|
137
131
|
if action then
|
138
132
|
$log.code { "execute : '#{action.data.toString}'" }
|
139
133
|
cmd, exe = action.data.toString.split(/@/, 2)
|
140
134
|
$log.code { "cmd(#{cmd}), exe(#{exe})" }
|
141
|
-
|
142
|
-
|
143
|
-
|
135
|
+
if cmd =~ /^play/
|
136
|
+
playMedia(cmd, process, exe)
|
137
|
+
elsif self.respond_to?(cmd)
|
138
|
+
self.method(cmd).call(process, wItem)
|
144
139
|
else
|
145
|
-
|
140
|
+
$log.warn { "No method #{cmd} in contextmenu." }
|
146
141
|
end
|
147
142
|
end
|
148
143
|
menu.deleteLater
|
149
144
|
end
|
150
145
|
|
151
|
-
def insertDefaultActions(menu, poColumn,
|
146
|
+
def insertDefaultActions(menu, poColumn, process)
|
152
147
|
a = menu.addAction(KDE::Icon.new('edit-copy'), 'Copy Text')
|
153
148
|
a.setVData('copyText@')
|
154
149
|
if poColumn == FILE
|
@@ -157,13 +152,15 @@ class TaskWindow < Qt::Widget
|
|
157
152
|
a = menu.addAction(KDE::Icon.new('kfm'), 'Open Temp Folder')
|
158
153
|
a.setVData('openTempFolder@')
|
159
154
|
end
|
160
|
-
if
|
155
|
+
if process.error?
|
161
156
|
a = menu.addAction(KDE::Icon.new('view-refresh'), 'Retry')
|
162
157
|
a.setVData('retryTask@')
|
163
158
|
a = menu.addAction(KDE::Icon.new('list-remove'), 'Remove')
|
164
159
|
a.setVData('removeTask@')
|
160
|
+
a = menu.addAction(KDE::Icon.new('list-remove-data'), 'Remove Task and Data')
|
161
|
+
a.setVData('removeTaskData@')
|
165
162
|
end
|
166
|
-
if
|
163
|
+
if process.running?
|
167
164
|
a = menu.addAction(KDE::Icon.new('edit-delete'), 'Cancel')
|
168
165
|
a.setVData('cancelTask@')
|
169
166
|
end
|
@@ -174,125 +171,122 @@ class TaskWindow < Qt::Widget
|
|
174
171
|
end
|
175
172
|
|
176
173
|
|
177
|
-
def insertMPlayerAction(menu)
|
178
|
-
player = 'mplayer'
|
179
|
-
mplayerPath = %x(which #{player})
|
180
|
-
return if mplayerPath =~ /no #{player}/
|
181
|
-
insertPlayer(menu, player, player + ' %U')
|
182
|
-
end
|
183
174
|
|
184
|
-
def
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
175
|
+
def createPlayerMenu(menu, poColumn, process)
|
176
|
+
case poColumn
|
177
|
+
when SOURCE
|
178
|
+
menu.addSeparator
|
179
|
+
createPlayers(menu, i18n('Play Source with'), "playSource@", '.wma')
|
180
|
+
when FILE
|
181
|
+
menu.addSeparator
|
182
|
+
if process.rawDownloaded? then
|
183
|
+
createPlayers(menu, i18n('Play File with'), "playMP3@", '.mp3')
|
189
184
|
end
|
185
|
+
createPlayers(menu, i18n('Play Temp File with'), "playTemp@", '.wma')
|
190
186
|
end
|
191
187
|
end
|
192
188
|
|
193
|
-
def
|
194
|
-
|
195
|
-
|
189
|
+
def createPlayers(menu, playText, playerCmd, url)
|
190
|
+
playersMenu = Qt::Menu.new(playText)
|
191
|
+
Mime::services(url).each do |s|
|
192
|
+
exeName = s.exec[/\w+/]
|
193
|
+
a = playersMenu.addAction(KDE::Icon.new(exeName), 'Play with ' + exeName)
|
194
|
+
a.setVData(playerCmd + s.exec)
|
195
|
+
end
|
196
|
+
menu.addMenu(playersMenu)
|
196
197
|
end
|
197
198
|
|
198
199
|
|
199
|
-
def
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
ti.process.rawDownloaded? ? filePath : rawFilePath
|
209
|
-
else
|
210
|
-
nil
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
200
|
+
def playMedia(cmd, process, exe)
|
201
|
+
case cmd
|
202
|
+
when /Temp/
|
203
|
+
url = process.rawFilePath
|
204
|
+
when /Source/
|
205
|
+
url = process.sourceUrl
|
206
|
+
when /MP3/
|
207
|
+
url = process.outFilePath
|
208
|
+
end
|
214
209
|
|
215
|
-
|
216
|
-
def playMedia(exe, wItem)
|
217
|
-
url = getContextUrl(wItem)
|
218
|
-
return unless url
|
219
|
-
cmd, args = exe.split(/\s+/, 2)
|
210
|
+
playCmd, args = exe.split(/\s+/, 2)
|
220
211
|
args = args.split(/\s+/).map do |a|
|
221
212
|
a.gsub(/%\w/, url)
|
222
213
|
end
|
223
|
-
|
224
|
-
$log.debug { "execute cmd '#{cmd}', args '#{args.inspect}'" }
|
214
|
+
$log.debug { "execute cmd '#{playCmd}', args '#{args.inspect}'" }
|
225
215
|
proc = Qt::Process.new(self)
|
226
|
-
proc.start(
|
216
|
+
proc.start(playCmd, args)
|
227
217
|
end
|
228
218
|
|
229
219
|
# contextMenu Event
|
230
|
-
def copyText(wItem)
|
220
|
+
def copyText(process, wItem)
|
231
221
|
$app.clipboard.setText(wItem.text)
|
232
222
|
end
|
233
223
|
|
234
224
|
# contextMenu Event
|
235
|
-
def retryTask(wItem)
|
236
|
-
|
237
|
-
|
238
|
-
ti.process.retryTask
|
225
|
+
def retryTask(process, wItem)
|
226
|
+
if process.error? then
|
227
|
+
process.retryTask
|
239
228
|
$log.info { "task restarted." }
|
240
229
|
end
|
241
230
|
end
|
242
231
|
|
243
232
|
# contextMenu Event
|
244
|
-
def cancelTask(wItem)
|
245
|
-
|
246
|
-
|
247
|
-
ti.process.cancelTask
|
233
|
+
def cancelTask(process, wItem)
|
234
|
+
if process.running? then
|
235
|
+
process.cancelTask
|
248
236
|
$log.info { "task canceled." }
|
249
237
|
end
|
250
238
|
end
|
251
239
|
|
252
240
|
# contextMenu Event
|
253
|
-
def removeTask(wItem)
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
$log.info { "task canceled." }
|
241
|
+
def removeTask(process, wItem)
|
242
|
+
if process.running? then
|
243
|
+
process.cancelTask
|
244
|
+
$log.info { "task removed." }
|
258
245
|
end
|
246
|
+
ti = taskItemAtRow(wItem.row)
|
259
247
|
deleteItem(ti)
|
260
248
|
end
|
261
249
|
|
262
250
|
# contextMenu Event
|
263
|
-
def
|
251
|
+
def removeTaskData(process, wItem)
|
252
|
+
if process.running? then
|
253
|
+
process.removeData
|
254
|
+
$log.info { "task and data removed." }
|
255
|
+
end
|
264
256
|
ti = taskItemAtRow(wItem.row)
|
265
|
-
|
266
|
-
|
257
|
+
deleteItem(ti)
|
258
|
+
end
|
259
|
+
|
260
|
+
# contextMenu Event
|
261
|
+
def openFolder(process, wItem)
|
262
|
+
outFilePath = File.dirname(process.outFilePath)
|
267
263
|
proc = Qt::Process.new(self)
|
268
|
-
proc.start('dolphin', [
|
264
|
+
proc.start('dolphin', [outFilePath ])
|
269
265
|
end
|
270
266
|
|
271
267
|
# contextMenu Event
|
272
|
-
def openTempFolder(wItem)
|
273
|
-
|
274
|
-
return unless ti
|
275
|
-
rawFilePath = File.join(IRecSettings.rawDownloadDir.path, File.dirname(ti.savePath))
|
268
|
+
def openTempFolder(process, wItem)
|
269
|
+
rawFilePath = File.dirname(process.rawFilePath)
|
276
270
|
proc = Qt::Process.new(self)
|
277
271
|
proc.start('dolphin', [rawFilePath])
|
278
272
|
end
|
279
273
|
|
280
274
|
# contextMenu Event
|
281
|
-
def clearAllFinished(wItem)
|
275
|
+
def clearAllFinished(process, wItem)
|
282
276
|
self.each do |i|
|
283
277
|
deleteItem(i) if i.process.finished?
|
284
278
|
end
|
285
279
|
end
|
286
280
|
|
287
281
|
# contextMenu Event
|
288
|
-
def clearAllErrors(wItem)
|
282
|
+
def clearAllErrors(process, wItem)
|
289
283
|
self.each do |i|
|
290
284
|
deleteItem(i) if i.process.error?
|
291
285
|
end
|
292
286
|
end
|
293
|
-
|
294
287
|
end
|
295
288
|
|
289
|
+
|
296
290
|
#--------------------------------------------
|
297
291
|
#
|
298
292
|
#
|