Advertisement
Guest User

Untitled

a guest
Jun 1st, 2017
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.48 KB | None | 0 0
  1. import rb, rhythmdb;
  2.  
  3. import gobject;
  4. import gtk;
  5. import datetime;
  6. import hashlib;
  7. import threading, urllib;
  8.  
  9. time = None;
  10. xml_dom = None;
  11.  
  12. def url_open(url, callback, *args):
  13.     data = [];
  14.     def get_url_func(url, data):
  15.         try:
  16.             result = urllib.urlopen(url);
  17.             out = result.read();
  18.             data.append(out);
  19.         except Exception, e:
  20.             data.append(e);
  21.         gtk.main_quit();
  22.     get_url_thread = threading.Thread(target=get_url_func, args=[url, data]);
  23.     get_url_thread.start();
  24.     gtk.main();
  25.     callback(data[0], *args);
  26.  
  27. class AmpacheBrowser(rb.BrowserSource):
  28.     limit = 100
  29.     offset = 0
  30.     url = ''
  31.     auth = None
  32.     auth_stream = None
  33.  
  34.     __gproperties__ = {
  35.         'plugin': (rb.Plugin, 'plugin', 'plugin', gobject.PARAM_WRITABLE|gobject.PARAM_CONSTRUCT_ONLY),
  36.     }
  37.  
  38.     def __init__(self):
  39.             rb.BrowserSource.__init__(self)
  40.  
  41.     def init_ui(self):
  42.         popup_ui = """<ui>
  43.                                <popup name="AmpacheSourcePopup">
  44.                                  <menuitem name="ReloadAmpacheDB" action="ReloadAmpacheDB"/>
  45.                                </popup>
  46.                              </ui>""";
  47.  
  48.         manager = self.shell.get_player().get_property('ui-manager');
  49.         self.action_group = gtk.ActionGroup('AmpachePluginActions');
  50.         action = gtk.Action('ReloadAmpacheDB', _('Reload'),
  51.                     _('Renew session and reload data from Ampache server'),
  52.                     None);
  53.         self.action_group.add_action(action);
  54.         manager.insert_action_group(self.action_group, 0);
  55.         self.ui_id = manager.add_ui_from_string(popup_ui);
  56.         action.connect('activate', self.reload_db);
  57.  
  58.  
  59.     def activate(self, config):
  60.         # Plugin activated
  61.         self.config = config
  62.  
  63.         width, height = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR)
  64.         icon = gtk.gdk.pixbuf_new_from_file_at_size(self.config.get("icon_filename"), width, height)
  65.         self.set_property( "icon",  icon)
  66.  
  67.         self.shell = self.get_property("shell")
  68.         self.db = self.shell.get_property("db")
  69.         self.entry_type = self.get_property("entry-type")
  70.         self.init_ui();
  71.  
  72.         self.__activate = False
  73.  
  74.     # need if we use find_file
  75.     def do_set_property(self, property, value):
  76.         if property.name == 'plugin':
  77.             self.__plugin = value
  78.         else:
  79.             raise AttributeError, 'unknown property %s' % property.name
  80.  
  81.         def do_impl_get_browser_key(self):
  82.                 return "/apps/rhythmbox/plugins/ampache/show_browser"
  83.  
  84.         def do_impl_get_paned_key(self):
  85.                 return "/apps/rhythmbox/plugins/ampache/paned_position"
  86.  
  87.     def load_db(self):
  88.         global time;
  89.         if not time:
  90.             import time;
  91.  
  92.         self.offset = 0;
  93.         url = self.config.get("url")
  94.         username = self.config.get_username();
  95.         password = self.config.get_password();
  96.  
  97.         if not url:
  98.             return
  99.         if not password:
  100.             return
  101.  
  102.         timestamp = int(time.time())
  103.         password = hashlib.sha256(password).hexdigest()
  104.         authkey = hashlib.sha256(str(timestamp) + password).hexdigest()
  105.  
  106.         auth_url = "%s?action=handshake&auth=%s&timestamp=%s&user=%s&version=350001" % (url, authkey, timestamp, username)
  107.         self.url = url
  108.         url_open(auth_url, self.load_db_cb);
  109.         # This is the recommended Rhythmbox plugin recipe, but uses GIO which is causing session errors requiring reboots
  110.         #rb.Loader().get_url(auth_url, self.load_db_cb)
  111.  
  112.     def load_db_cb(self, result):
  113.         global xml_dom;
  114.         if not xml_dom:
  115.             import xml.dom.minidom as xml_dom;
  116.  
  117.         if isinstance(result, Exception) or not result:
  118.             emsg = _("Error connecting to Ampache Server at %s") % (self.url,)
  119.             if result:
  120.                 emsg += ': \n' + str(result.args);
  121.                
  122.             dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, emsg)
  123.             dlg.run()
  124.             dlg.destroy()
  125.             return
  126.  
  127.         dom = xml_dom.parseString(result)
  128.         self.auth = dom.getElementsByTagName("auth")[0].childNodes[0].data
  129.  
  130.         print "Auth: %s" % self.auth
  131.         #gobject.idle_add(self.populate)
  132.         self.populate()
  133.  
  134.     def populate(self):
  135.         #gtk.gdk.threads_enter()
  136.         print "offset: %s, limit: %s" % (self.offset, self.limit) #DEBUG
  137.         request = "%s?offset=%s&limit=%s&action=songs&auth=%s" % (self.url, self.offset, self.limit, self.auth)
  138.         print "url: %s" % request #DEBUG
  139.  
  140.         url_open(request, self.populate_cb, request);
  141.         #See previous use of get_url for why this is no longer is use
  142.         #rb.Loader().get_url(request, self.populate_cb, request)
  143.  
  144.     def populate_cb(self, result, url):
  145.         global xml_dom;
  146.         if not xml_dom:
  147.             import xml.dom.minidom as xml_dom;
  148.  
  149.         if isinstance(result, Exception) or not result:
  150.             emsg = _("Error downloading song database from Ampache Server at %s") % (self.url)
  151.             if result:
  152.                 emsg += ': \n' + str(result.args);
  153.  
  154.             dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, emsg)
  155.             dlg.run()
  156.             dlg.destroy()
  157.             return
  158.  
  159.         def getEltData(node, tagname, default=''):
  160.             try:
  161.                 return node.getElementsByTagName(tagname)[0].childNodes[0].data;
  162.             except:
  163.                 return default;
  164.  
  165.         dom = xml_dom.parseString(result);
  166.         song = 0
  167.         db_set = self.db.set;
  168.         for node in dom.getElementsByTagName('song'):
  169.             song += 1;
  170.  
  171.             #e_id = node.getAttribute('id')
  172.             e_url = getEltData(node, 'url');
  173.             e_title = getEltData(node, 'title');
  174.             e_artist = getEltData(node, 'artist');
  175.             e_album = getEltData(node, 'album');
  176.             e_genre = getEltData(node, 'tag');
  177.             e_track_number = int(getEltData(node, 'track', 0));
  178.             e_duration = int(getEltData(node, 'time', 0));
  179.  
  180.             #print "Processing %s - %s" % (artist, album) #DEBUG
  181.  
  182.             e = self.db.entry_new(self.entry_type, e_url);
  183.             db_set(e, rhythmdb.PROP_TITLE, e_title);
  184.             db_set(e, rhythmdb.PROP_ARTIST, e_artist);
  185.             db_set(e, rhythmdb.PROP_ALBUM, e_album);
  186.             db_set(e, rhythmdb.PROP_GENRE, e_genre);
  187.             db_set(e, rhythmdb.PROP_TRACK_NUMBER, e_track_number);
  188.             db_set(e, rhythmdb.PROP_DURATION, e_duration);
  189.             # FIXME date - not implemented in ampache yet
  190.             #db_set(e, rhythmdb.PROP_DATE, datetime.date(2000, 1, 1).toordinal())
  191.  
  192.         self.db.commit()
  193.  
  194.         if (song < self.limit):
  195.             #gtk.gdk.threads_leave()
  196.             return False
  197.         else:
  198.             self.offset = self.offset + song
  199.         #gtk.gdk.threads_leave()
  200.         self.populate()
  201.         return True
  202.  
  203.  
  204.     # Source is first clicked on
  205.     def do_impl_activate (self):
  206.         # Connect to Ampache if not already
  207.         if not self.__activate:
  208.             self.__activate = True
  209.             self.load_db()
  210.  
  211.         rb.BrowserSource.do_impl_activate(self)
  212.  
  213.     def unload_db(self):
  214.         self.db.entry_delete_by_type(self.entry_type);
  215.  
  216.     def reload_db(self, *args):
  217.         self.unload_db();
  218.         self.load_db();
  219.  
  220.     def do_impl_show_popup(self):
  221.         self.show_source_popup('/AmpacheSourcePopup');
  222.  
  223. gobject.type_register(AmpacheBrowser)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement