irecorder 0.0.7

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.
@@ -0,0 +1,185 @@
1
+
2
+ #---------------------------------------------------------------------------------------------
3
+ #
4
+ #
5
+ class ProgrammeTableWidget < Qt::TableWidget
6
+ #
7
+ #
8
+ class Programme
9
+ attr_reader :titleItem, :categoriesItem, :updatedItem
10
+ attr_reader :content, :link
11
+
12
+ def initialize(title, categories, updated, content, link)
13
+ @titleItem = Item.new(title)
14
+ @categoriesItem = Item.new(categories)
15
+ @updatedItem = Item.new(updated)
16
+ @content = content
17
+ @link = link
18
+ end
19
+
20
+ def title
21
+ @titleItem.text
22
+ end
23
+
24
+ def categories
25
+ @categoriesItem.text
26
+ end
27
+
28
+ def updated
29
+ @updatedItem.text
30
+ end
31
+ end
32
+
33
+ #
34
+ #
35
+ class Item < Qt::TableWidgetItem
36
+ def initialize(text)
37
+ super(text)
38
+ self.flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled
39
+ self.toolTip = text
40
+ end
41
+ end
42
+
43
+
44
+ #------------------------------------------------------------------------
45
+ #
46
+ #
47
+
48
+ def initialize()
49
+ super(0, 3)
50
+
51
+ setHorizontalHeaderLabels(['Title', 'Category', 'Updated'])
52
+ self.horizontalHeader.stretchLastSection = true
53
+ self.selectionBehavior = Qt::AbstractItemView::SelectRows
54
+ self.alternatingRowColors = true
55
+ self.sortingEnabled = true
56
+ sortByColumn(2, Qt::DescendingOrder )
57
+
58
+
59
+ # Hash table : key column_0_item => Programme entry.
60
+ @table = Hash.new
61
+ end
62
+
63
+ def addEntry( row, title, categories, updated, content, link )
64
+ entry = Programme.new(title, categories, updated, content, link)
65
+ setItem( row, 0, entry.titleItem )
66
+ setItem( row, 1, entry.categoriesItem )
67
+ setItem( row, 2, entry.updatedItem )
68
+ @table[entry.titleItem] = entry
69
+ end
70
+
71
+ # return Programme object.
72
+ def [](row)
73
+ @table[item(row,0)]
74
+ end
75
+
76
+
77
+ #
78
+ # slot : called when filterLineEdit text is changed.
79
+ #
80
+ public
81
+ slots 'filterChanged(const QString &)'
82
+ def filterChanged(text)
83
+ return unless text
84
+
85
+ regxs = text.split(/[,\s]+/).map do |w|
86
+ /#{Regexp.escape(w.strip)}/i
87
+ end
88
+ rowCount.times do |r|
89
+ i0 = item(r,0)
90
+ i1 = item(r,1)
91
+ i2 = item(r,2)
92
+ txt = ((i0 && i0.text) || '') + ((i1 && i1.text) || '') + ((i2 && i2.text) || '')
93
+ if regxs.all? do |rx| rx =~ txt end then
94
+ showRow(r)
95
+ else
96
+ hideRow(r)
97
+ end
98
+ end
99
+ end
100
+
101
+ GroupName = "ProgrammeTable"
102
+ def writeSettings
103
+ config = $config.group(GroupName)
104
+ config.writeEntry('Header', horizontalHeader.saveState)
105
+ end
106
+
107
+ def readSettings
108
+ config = $config.group(GroupName)
109
+ horizontalHeader.restoreState(config.readEntry('Header', horizontalHeader.saveState))
110
+ end
111
+
112
+ protected
113
+ def contextMenuEvent(e)
114
+ prog = self[itemAt(e.pos).row]
115
+ menu = createPopup
116
+ action = menu.exec(e.globalPos)
117
+ action and execPopup(action, prog)
118
+ menu.deleteLater
119
+ end
120
+
121
+ def createPopup()
122
+ menu = Qt::Menu.new
123
+ a = menu.addAction(KDE::Icon.new('search'), i18n('Search Same Programme'))
124
+ a.setVData('searchSame@')
125
+ a = menu.addAction(KDE::Icon.new('search'), i18n('Search Same Category tags'))
126
+ a.setVData('searchSameTags@')
127
+ menu.addSeparator
128
+ insertPlayerActions(menu)
129
+ menu
130
+ end
131
+
132
+ def execPopup(action, item)
133
+ $log.code { "execute : '#{action.vData}'" }
134
+ cmd, exe = action.vData.split(/@/, 2)
135
+ $log.code { "cmd(#{cmd}), exe(#{exe})" }
136
+ if cmd == 'play'
137
+ playMedia(exe, item)
138
+ elsif self.respond_to?(cmd)
139
+ self.method(cmd).call(item)
140
+ else
141
+ $log.warn { "No method #{cmd} in contextmenu." }
142
+ end
143
+ end
144
+
145
+ def insertPlayerActions(menu)
146
+ Mime::services('.wma').each do |s|
147
+ exeName = s.exec[/\w+/]
148
+ a = menu.addAction(KDE::Icon.new(exeName), 'Play with ' + exeName)
149
+ a.setVData('play@' + s.exec)
150
+ end
151
+ end
152
+
153
+ def playMedia(exe, prog)
154
+ begin
155
+ url = prog.content[UrlRegexp] # String[] method extract only 1st one.
156
+
157
+ $log.info { "episode Url : #{url}" }
158
+ minfo = BBCNet::MetaInfo.get(url).update
159
+ url = minfo.wma.url
160
+
161
+ cmd, args = exe.split(/\s+/, 2)
162
+ args = args.split(/\s+/).map do |a|
163
+ a.gsub(/%\w/, url)
164
+ end
165
+ $log.debug { "execute cmd '#{cmd}', args '#{args.inspect}'" }
166
+ proc = Qt::Process.new(self)
167
+ proc.start(cmd, args)
168
+
169
+ rescue => e
170
+ $log.error { e }
171
+ KDE::MessageBox::information(self, i18n("There is not direct stream for this programme."))
172
+ end
173
+ end
174
+
175
+ signals 'filterRequest(const QString &)'
176
+ def searchSame(prog)
177
+ emit filterRequest( prog.title.sub(/:.*/, '') )
178
+ end
179
+
180
+ def searchSameTags(prog)
181
+ emit filterRequest( prog.categories )
182
+ end
183
+ end
184
+
185
+
@@ -0,0 +1,376 @@
1
+ #
2
+ # 2007 by ruby.twiddler@gmail.com
3
+ #
4
+ require "mylibs.rb"
5
+
6
+
7
+ #--------------------------------------------------------------------------
8
+ #
9
+ # select from traders, system menu, arbitarary file.
10
+ #
11
+ class SelectServiceDlg < KDE::Dialog
12
+ def initialize(parent, defaultName=nil)
13
+ super(parent)
14
+ @message = i18n('Select Application')
15
+ userInitialize
16
+ self.windowTitle = @message
17
+ @selectedName = @services[0].name
18
+ createWidget
19
+ setSelected(defaultName)
20
+ end
21
+
22
+ def userInitialize
23
+ @message = i18n('Select Application for .html file.')
24
+ @services = Mime.services('.html')
25
+ end
26
+
27
+ def name
28
+ @selectedName
29
+ end
30
+
31
+ def iconName
32
+ SelectServiceDlg.exeName2IconName(serviceFromName(name).exec)
33
+ end
34
+
35
+ def accept
36
+ @selectedName = @serviceList.selectedItems.first.text
37
+ super
38
+ end
39
+
40
+ def commandFromName(name)
41
+ i = serviceFromName(name)
42
+ i && i.exec
43
+ end
44
+
45
+ def serviceFromName(name)
46
+ name.gsub!(/&/, '')
47
+ return nil if @services.size == 0
48
+ service = @services.find(@services[0]) do |s| s.name == name end
49
+ end
50
+
51
+ def setSelected(name)
52
+ return unless name
53
+ name.gsub!(/&/, '')
54
+ return if @services.size == 0
55
+ unless name then
56
+ @serviceList.takeItem(0).setSelected(true)
57
+ else
58
+ items = @serviceList.findItems(name, Qt::MatchExactly)
59
+ if items.size > 0 then
60
+ items[0].setSelected(true)
61
+ end
62
+ end
63
+ end
64
+
65
+ def self.exeName2IconName(exeName)
66
+ iconName = exeName.gsub(%r{[^ ]*/}, '')[/([-_\w\d])+/] .
67
+ gsub(/(dragon)/, '\1player').gsub(/kfmclient/, 'konqueror')
68
+ end
69
+
70
+ protected
71
+ def createWidget
72
+ mainWidget = VBoxLayoutWidget.new
73
+ mainWidget.addWidget(Qt::Label.new(@message))
74
+ @serviceList = KDE::ListWidget.new
75
+ @services.each do |s|
76
+ iconName = SelectServiceDlg.exeName2IconName(s.exec)
77
+ @serviceList.addItem( Qt::ListWidgetItem.new(KDE::Icon.new(iconName), s.name) )
78
+ end
79
+ @selectFromMenu = KDE::PushButton.new(i18n('Select Other from Menu'))
80
+ mainWidget.addWidget(@serviceList)
81
+ # mainWidget.addWidget(@selectFromMenu)
82
+
83
+ setMainWidget(mainWidget)
84
+ end
85
+ end
86
+
87
+
88
+ class SelectWebPlayerDlg < SelectServiceDlg
89
+ def userInitialize
90
+ @message = i18n('Select Web Player for iPlayer page.')
91
+ @services = Mime.services('.html').select do |s|
92
+ s.name !~ /office/i and
93
+ s.serviceTypes.find do |st|
94
+ st =~ /application\//
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ class SelectDirectPlayerDlg < SelectServiceDlg
101
+ def userInitialize
102
+ @message = i18n('Select Direct Stream Player.')
103
+ @services = Mime.services('.wma')
104
+ end
105
+ end
106
+
107
+
108
+
109
+
110
+ #--------------------------------------------------------------------------
111
+ #
112
+ # IRecorder Settings
113
+ #
114
+ class IRecSettings < SettingsBase
115
+ def initialize
116
+ super()
117
+
118
+ setCurrentGroup("Preferences")
119
+
120
+ # meta programed version.
121
+ addStringItem(:rawDownloadDir, Qt::Dir::tempPath + '/RadioRaw')
122
+ addStringItem(:downloadDir, KDE::GlobalSettings.musicPath)
123
+ addBoolItem(:dirAddMediaName, true)
124
+ addBoolItem(:dirAddChannelName, false)
125
+ addBoolItem(:dirAddGenreName, true)
126
+ addStringItem(:fileAddHeadStr, 'BBC ')
127
+ addBoolItem(:fileAddMediaName, true)
128
+ addBoolItem(:fileAddChannelName, false)
129
+ addBoolItem(:fileAddGenreName, true)
130
+ addBoolItem(:leaveRawFile, false)
131
+
132
+ addBoolItem(:playerTypeSmall, false)
133
+ addBoolItem(:playerTypeBeta, true)
134
+
135
+ addBoolItem(:useInnerPlayer, true)
136
+ addBoolItem(:useWebPlayer, false)
137
+ addStringItem(:webPlayerName, 'Konqueror')
138
+ addBoolItem(:useDirectPlayer, false)
139
+ addStringItem(:directPlayerName, 'KMPlayer')
140
+ end
141
+
142
+ def webPlayerCommand
143
+ @webPlayerCnv.commandFromName(self.webPlayerName)
144
+ end
145
+
146
+ def self.webPlayerCommand
147
+ self.instance.webPlayerCommand
148
+ end
149
+
150
+ def directPlayerCommand
151
+ @directPlayerCnv.commandFromName(self.directPlayerName)
152
+ end
153
+
154
+ def self.directPlayerCommand
155
+ self.instance.directPlayerCommand
156
+ end
157
+
158
+ def regConverter(webPlayerCnv, directPlayerCnv)
159
+ @webPlayerCnv = webPlayerCnv
160
+ @directPlayerCnv = directPlayerCnv
161
+ end
162
+ end
163
+
164
+
165
+ #--------------------------------------------------------------------------
166
+ #
167
+ #
168
+ class SettingsDlg < KDE::ConfigDialog
169
+ def initialize(parent)
170
+ super(parent, "Settings", IRecSettings.instance)
171
+ addPage(FolderSettingsPage.new, i18n("Folder"), 'folder', i18n('Folder and File Name'))
172
+ addPage(PlayerSettingsPage.new, i18n("Player"), 'internet-web-browser', i18n('Player and web Browser'))
173
+ end
174
+ end
175
+
176
+
177
+ #--------------------------------------------------------------------------
178
+ #
179
+ #
180
+ class FolderSettingsPage < Qt::Widget
181
+ def initialize(parent=nil)
182
+ super(parent)
183
+ createWidget
184
+ end
185
+
186
+ protected
187
+
188
+ def createWidget
189
+ @rawFileDirLine = FolderSelectorLineEdit.new(KDE::GlobalSettings.downloadPath)
190
+ @downloadDirLine = FolderSelectorLineEdit.new(KDE::GlobalSettings.downloadPath)
191
+
192
+ @dirSampleLabel = Qt::Label.new('Example) ')
193
+ @dirAddMediaName = Qt::CheckBox.new(i18n('Add media directory'))
194
+ @dirAddChannelName = Qt::CheckBox.new(i18n('Add channel directory'))
195
+ @dirAddGenreName = Qt::CheckBox.new(i18n('Add genre directory'))
196
+ [ @dirAddMediaName, @dirAddChannelName, @dirAddGenreName ].each do |w|
197
+ w.connect(SIGNAL('stateChanged(int)')) do |s| updateSampleDirName end
198
+ end
199
+
200
+ @fileSampleLabel = Qt::Label.new('Example) ')
201
+ @fileAddHeadStr = KDE::LineEdit.new do |w|
202
+ w.connect(SIGNAL('textChanged(const QString&)')) do |t| updateSampleFileName end
203
+ end
204
+ @fileAddMediaName = Qt::CheckBox.new(i18n('Add media name'))
205
+ @fileAddChannelName = Qt::CheckBox.new(i18n('Add channel name'))
206
+ @fileAddGenreName = Qt::CheckBox.new(i18n('Add genre name'))
207
+
208
+ [ @fileAddMediaName, @fileAddChannelName, @fileAddGenreName ].each do |w|
209
+ w.connect(SIGNAL('stateChanged(int)')) do |s| updateSampleFileName end
210
+ end
211
+ @leaveRawFile = Qt::CheckBox.new(i18n('Leave raw file.(don\'t delete it)'))
212
+
213
+ # set objectNames
214
+ # 'kcfg_' + class Settings's instance name.
215
+ @rawFileDirLine.objectName = 'kcfg_rawDownloadDir'
216
+ @downloadDirLine.objectName = 'kcfg_downloadDir'
217
+ @dirAddMediaName.objectName = 'kcfg_dirAddMediaName'
218
+ @dirAddChannelName.objectName = 'kcfg_dirAddChannelName'
219
+ @dirAddGenreName.objectName = 'kcfg_dirAddGenreName'
220
+ @fileAddHeadStr.objectName = 'kcfg_fileAddHeadStr'
221
+ @fileAddMediaName.objectName = 'kcfg_fileAddMediaName'
222
+ @fileAddChannelName.objectName = 'kcfg_fileAddChannelName'
223
+ @fileAddGenreName.objectName = 'kcfg_fileAddGenreName'
224
+ @leaveRawFile.objectName = 'kcfg_leaveRawFile'
225
+
226
+
227
+ # layout
228
+ lo = Qt::VBoxLayout.new do |l|
229
+ l.addWidget(Qt::Label.new(i18n('Download Directory')))
230
+ l.addWidgets(' ', @downloadDirLine)
231
+ l.addWidget(Qt::Label.new(i18n('Temporary Raw File Download Directory')))
232
+ l.addWidgets(' ', @rawFileDirLine)
233
+ l.addWidget(Qt::GroupBox.new(i18n('Generating directory')) do |g|
234
+ vbx = Qt::VBoxLayout.new do |vb|
235
+ vb.addWidget(@dirSampleLabel)
236
+ vb.addWidget(@dirAddMediaName)
237
+ # vb.addWidget(@dirAddChannelName)
238
+ vb.addWidget(@dirAddGenreName)
239
+ end
240
+ g.setLayout(vbx)
241
+ end
242
+ )
243
+ l.addWidget(Qt::GroupBox.new(i18n('Generating file name')) do |g|
244
+ vbx = Qt::VBoxLayout.new do |vb|
245
+ vb.addWidget(@fileSampleLabel)
246
+ vb.addWidgets(i18n('Head Text'), @fileAddHeadStr)
247
+ vb.addWidget(@fileAddMediaName)
248
+ # vb.addWidget(@fileAddChannelName)
249
+ vb.addWidget(@fileAddGenreName)
250
+ end
251
+ g.setLayout(vbx)
252
+ end
253
+ )
254
+ l.addWidget(@leaveRawFile)
255
+ l.addStretch
256
+ end
257
+
258
+ setLayout(lo)
259
+ end
260
+
261
+ def updateSampleFileName
262
+ @fileSampleLabel.text = 'Example) ' + getSampleFileName
263
+ end
264
+
265
+ def checkState(checkBox)
266
+ checkBox.checkState== Qt::Checked
267
+ end
268
+
269
+ def getSampleFileName
270
+ head = @fileAddHeadStr.text
271
+ head += 'Radio ' if checkState(@fileAddMediaName)
272
+ head += 'Radio 7 ' if checkState(@fileAddChannelName)
273
+ head += 'Drama ' if checkState(@fileAddGenreName)
274
+ head += "- " unless head.empty?
275
+ baseName = head + 'Space Hacks Lost in Space Ship.mp3'
276
+ baseName.gsub(%r{[\/]}, '-')
277
+ end
278
+
279
+
280
+ def updateSampleDirName
281
+ @dirSampleLabel.text = 'Example) ... /' + getSampleDirName
282
+ end
283
+
284
+ def getSampleDirName
285
+ dir = []
286
+ dir << 'Radio' if checkState(@dirAddMediaName)
287
+ dir << 'Radio 7' if checkState(@dirAddChannelName)
288
+ dir << 'Drama' if checkState(@dirAddGenreName)
289
+ File.join(dir.compact)
290
+ end
291
+
292
+ end
293
+
294
+ #--------------------------------------------------------------------------
295
+ #
296
+ #
297
+ class PlayerSettingsPage < Qt::Widget
298
+ def initialize(parent=nil)
299
+ super(parent)
300
+ createWidget
301
+ end
302
+
303
+ protected
304
+
305
+ def createWidget
306
+ @SelectWebPlayerDlg = SelectWebPlayerDlg.new(self, IRecSettings.webPlayerName)
307
+ @SelectDirectPlayerDlg = SelectDirectPlayerDlg.new(self, IRecSettings.directPlayerName)
308
+ IRecSettings.instance.regConverter(@SelectWebPlayerDlg, @SelectDirectPlayerDlg)
309
+
310
+ @playerTypeSmall = Qt::RadioButton.new(i18n('small iplayer'))
311
+ @playerTypeBeta = Qt::RadioButton.new(i18n('beta iplayer'))
312
+
313
+ @innerPlayer = Qt::RadioButton.new(i18n('inner Player'))
314
+ @webPlayer = Qt::RadioButton.new(i18n('Web Player'))
315
+ @directPlayer = Qt::RadioButton.new(i18n('Direnct Stream Player'))
316
+
317
+ @webPlayerName = KDE::PushButton.new('Konqueror')
318
+ @webPlayerName.connect(SIGNAL(:pressed)) do
319
+ @SelectWebPlayerDlg.setSelected(@webPlayerName.text)
320
+ if @SelectWebPlayerDlg.exec == Qt::Dialog::Accepted then
321
+ @webPlayerName.text = @SelectWebPlayerDlg.name
322
+ # @webPlayerName.setIcon(KDE::Icon.new(@SelectWebPlayerDlg.iconName))
323
+ @webPlayer.checked = true
324
+ end
325
+ end
326
+ @webPlayerName.setProperty("kcfg_property", Qt::Variant.new("text"))
327
+
328
+ @directPlayerName = KDE::PushButton.new('KMPlayer')
329
+ @directPlayerName.connect(SIGNAL(:pressed)) do
330
+ @SelectDirectPlayerDlg.setSelected(@directPlayerName.text)
331
+ if @SelectDirectPlayerDlg.exec == Qt::Dialog::Accepted then
332
+ @directPlayerName.text = @SelectDirectPlayerDlg.name
333
+ # @directPlayerName.setIcon(KDE::Icon.new(@SelectDirectPlayerDlg.iconName))
334
+ @directPlayer.checked = true
335
+ end
336
+ end
337
+ @directPlayerName.setProperty("kcfg_property", Qt::Variant.new("text"))
338
+
339
+ # set objectNames
340
+ # 'kcfg_' + class Settings's instance name.
341
+ @playerTypeSmall.objectName = 'kcfg_playerTypeSmall'
342
+ @playerTypeBeta.objectName = 'kcfg_playerTypeBeta'
343
+ @innerPlayer.objectName = 'kcfg_useInnerPlayer'
344
+ @webPlayer.objectName = 'kcfg_useWebPlayer'
345
+ @directPlayer.objectName = 'kcfg_useDirectPlayer'
346
+ @webPlayerName.objectName = 'kcfg_webPlayerName'
347
+ @directPlayerName.objectName = 'kcfg_directPlayerName'
348
+
349
+
350
+ # layout
351
+ lo = Qt::VBoxLayout.new do |l|
352
+ l.addWidget(Qt::GroupBox.new(i18n('iPlayer Type')) do |g|
353
+ vbx = Qt::VBoxLayout.new do |vb|
354
+ vb.addWidget(@playerTypeSmall)
355
+ vb.addWidget(@playerTypeBeta)
356
+ end
357
+ g.setLayout(vbx)
358
+ end
359
+ )
360
+ l.addWidget(Qt::GroupBox.new(i18n('Player')) do |g|
361
+ vbx = Qt::VBoxLayout.new do |vb|
362
+ vb.addWidget(@innerPlayer)
363
+ vb.addWidget(@webPlayer)
364
+ vb.addWidgets(' ', @webPlayerName, nil)
365
+ vb.addWidget(@directPlayer)
366
+ vb.addWidgets(' ', @directPlayerName, nil)
367
+ end
368
+ g.setLayout(vbx)
369
+ end
370
+ )
371
+ l.addStretch
372
+ end
373
+
374
+ setLayout(lo)
375
+ end
376
+ end