1 from PyQt4
import QtGui
,QtCore
4 from thread
import start_new_thread
5 from traceback
import print_exc
10 class ResetEvent(QtCore
.QEvent
):
12 def __init__(self
, song
=None):
13 QtCore
.QEvent
.__init
__(self
,QtCore
.QEvent
.User
)
15 class AddHtmlEvent(QtCore
.QEvent
):
17 def __init__(self
,html
):
18 QtCore
.QEvent
.__init
__(self
,QtCore
.QEvent
.User
)
21 TABS_DIR_DEFAULT
='/jammin'
22 TABS_ENGINE_DEFAULT
='http://www.google.com/search?q=tabs|chords+"$artist"+"$title"'
23 TABS_SITES_DEFAULT
='azchords.com <pre>(.*?)</pre>\n'\
24 'fretplay.com <P CLASS="tabs">(.*?)</P>\n'\
25 'guitaretab.com <pre style="COLOR: #000000; FONT-SIZE: 11px;">(.*)?</pre>'\
27 class wgTabs(QtGui
.QWidget
):
31 def __init__(self
, p
, parent
=None):
32 QtGui
.QWidget
.__init
__(self
, parent
)
34 self
.txt
=QtGui
.QTextEdit(parent
)
35 self
.txt
.setReadOnly(True)
37 layout
=QtGui
.QVBoxLayout()
38 layout
.addWidget(self
.txt
)
39 self
.setLayout(layout
)
43 song
=self
.p
.monty
.getCurrentSong()
51 start_new_thread(self
.fetchTabs
, (song
,))
53 def customEvent(self
, event
):
54 if isinstance(event
,ResetEvent
):
55 self
.resetTxt(event
.song
)
56 elif isinstance(event
,AddHtmlEvent
):
57 self
.txt
.insertHtml(event
.html
)
59 _mutex
=QtCore
.QMutex()
61 def fetchTabs(self
, song
):
62 # only allow 1 instance to look tabs!
70 QtCore
.QCoreApplication
.postEvent(self
, ResetEvent(song
))
72 # save the data to file!
73 save_dir
=self
.p
.getSetting('dir')
74 fInfo
=QtCore
.QFileInfo(save_dir
)
76 tabsFName
=toAscii('%s/%s - %s.txt'%(save_dir
,song
.getArtist(),song
.getTitle()))
79 # does the file exist? if yes, read that one!
81 # we have it: load, and return!
82 file=open(tabsFName
, 'r')
83 QtCore
.QCoreApplication
.postEvent(self
, AddHtmlEvent(file.read()))
91 QtCore
.QCoreApplication
.postEvent(self
, AddHtmlEvent('<i>Searching tabs ...</i>'))
93 lines
=self
.p
.getSetting('sites').split('\n')
97 sites
[line
[0:line
.find('\t')]]=line
[line
.find('\t'):].strip()
98 # construct URL to search!
99 SE
=self
.p
.getSetting('engine')
101 ret
=fetch(SE
, sites
, song
, {}, stripHTML
=False)
103 txt
='<pre>%s<br /><br /><a href="%s">%s</a></pre>'%(ret
[0],ret
[1],ret
[1])
104 # save for later use!
106 # we can't save if the path isn't correct
108 file=open(tabsFName
, 'w')
114 txt
="No tabs found :'("
116 QtCore
.QCoreApplication
.postEvent(self
, ResetEvent(song
))
117 QtCore
.QCoreApplication
.postEvent(self
, AddHtmlEvent(txt
))
120 QtCore
.QCoreApplication
.postEvent(self
, ResetEvent(song
))
121 QtCore
.QCoreApplication
.postEvent(self
, AddHtmlEvent('Woops, site unavailable!'\
122 '<br />You have an internet connection?'))
125 def resetTxt(self
, song
=None):
128 self
.txt
.insertHtml('<b>%s</b>\n<br /><u>%s</u><br />'\
129 '<br />\n\n'%(song
.getTitle(), song
.getArtist()))
132 class pluginTabs(Plugin
):
134 def __init__(self
, winMain
):
135 Plugin
.__init
__(self
, winMain
, 'Tabs')
136 self
.addMontyListener('onSongChange', self
.refresh
)
137 self
.addMontyListener('onReady', self
.refresh
)
138 self
.addMontyListener('onDisconnect', self
.onDisconnect
)
140 self
.o
=wgTabs(self
, None)
145 return "Show (and fetch) the tabs of the currently playing song."
147 def _getDockWidget(self
):
148 return self
._createDock
(self
.o
)
150 def refresh(self
, params
):
152 def onDisconnect(self
, params
):
155 def _getSettings(self
):
156 sites
=QtGui
.QTextEdit()
157 sites
.insertPlainText(self
.getSetting('sites'))
159 ['engine', 'Search engine', 'The URL that is used to search. $artist, $title and $album are replaced in the URL.', QtGui
.QLineEdit(self
.getSetting('engine'))],
160 ['sites', 'Sites & regexes', 'This field contains all sites, together with the regex needed to fetch the tabs.\nEvery line must look like this: $domain $regex-start(.*?)$regex-end\n$domain is the domain of the tabs website, $regex-start is the regex indicating the start of the tabs, $regex-end indicates the end. E.g. footabs.org <tabs>(.*?)</tabs>', sites
],
161 ['dir', 'Tabs directory', 'Directory where tabs should be stored and retrieved.', QtGui
.QLineEdit(self
.getSetting('dir'))],
163 def afterSaveSettings(self
):
164 self
.o
.onSongChange(None)