Lots of random conversions to new settings.
[montypc/ni.git] / plugins / Tabs.py
blob48a2a502185b36a025454d8defa602445c61aa43
1 from PyQt4 import QtGui,QtCore
3 import re
4 from thread import start_new_thread
5 from traceback import print_exc
7 from misc import *
8 from clPlugin import *
10 class ResetEvent(QtCore.QEvent):
11 song=None
12 def __init__(self, song=None):
13 QtCore.QEvent.__init__(self,QtCore.QEvent.User)
14 self.song=song
15 class AddHtmlEvent(QtCore.QEvent):
16 html=None
17 def __init__(self,html):
18 QtCore.QEvent.__init__(self,QtCore.QEvent.User)
19 self.html=html
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):
28 " contains the tabs"
29 txt=None
30 p=None # plugin
31 def __init__(self, p, parent=None):
32 QtGui.QWidget.__init__(self, parent)
33 self.p=p
34 self.txt=QtGui.QTextEdit(parent)
35 self.txt.setReadOnly(True)
37 layout=QtGui.QVBoxLayout()
38 layout.addWidget(self.txt)
39 self.setLayout(layout)
42 def refresh(self):
43 song=self.p.monty.getCurrentSong()
44 try:
45 song._data['file']
46 except:
47 self.resetTxt()
48 return
50 self.resetTxt(song)
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()
60 _fetchCnt=0
61 def fetchTabs(self, song):
62 # only allow 1 instance to look tabs!
63 self._mutex.lock()
64 if self._fetchCnt:
65 self._mutex.unlock()
66 return
67 self._fetchCnt=1
68 self._mutex.unlock()
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)
75 if fInfo.isDir():
76 tabsFName=toAscii('%s/%s - %s.txt'%(save_dir,song.getArtist(),song.getTitle()))
77 else:
78 tabsFName=None
79 # does the file exist? if yes, read that one!
80 try:
81 # we have it: load, and return!
82 file=open(tabsFName, 'r')
83 QtCore.QCoreApplication.postEvent(self, AddHtmlEvent(file.read()))
84 file.close()
85 self._fetchCnt=0
86 return
87 except:
88 pass
90 # fetch from inet
91 QtCore.QCoreApplication.postEvent(self, AddHtmlEvent('<i>Searching tabs ...</i>'))
93 lines=self.p.getSetting('sites').split('\n')
94 sites={}
95 for line in lines:
96 if line.strip():
97 sites[line[0:line.find('\t')]]=line[line.find('\t'):].strip()
98 # construct URL to search!
99 SE=self.p.getSetting('engine')
100 try:
101 ret=fetch(SE, sites, song, {}, stripHTML=False)
102 if ret:
103 txt='<pre>%s<br /><br /><a href="%s">%s</a></pre>'%(ret[0],ret[1],ret[1])
104 # save for later use!
105 if tabsFName:
106 # we can't save if the path isn't correct
107 try:
108 file=open(tabsFName, 'w')
109 file.write(ret[0])
110 file.close()
111 except:
112 pass
113 else:
114 txt="No tabs found :'("
116 QtCore.QCoreApplication.postEvent(self, ResetEvent(song))
117 QtCore.QCoreApplication.postEvent(self, AddHtmlEvent(txt))
118 except:
119 print_exc()
120 QtCore.QCoreApplication.postEvent(self, ResetEvent(song))
121 QtCore.QCoreApplication.postEvent(self, AddHtmlEvent('Woops, site unavailable!'\
122 '<br />You have an internet connection?'))
123 self._fetchCnt=0
125 def resetTxt(self, song=None):
126 self.txt.clear()
127 if song:
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):
133 o=None
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)
139 def _load(self):
140 self.o=wgTabs(self, None)
141 self.refresh(None)
142 def _unload(self):
143 self.o=None
144 def getInfo(self):
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):
151 self.o.refresh()
152 def onDisconnect(self, params):
153 self.o.resetTxt()
155 def _getSettings(self):
156 sites=QtGui.QTextEdit()
157 sites.insertPlainText(self.getSetting('sites'))
158 return [
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)