import rhythmdb, rb
import gtk
from gettext import gettext as _

class GstPluginInstall (rb.Plugin):

	def __init__ (self):
		rb.Plugin.__init__ (self)

		self.awaiting_install = {}		
		self.mime_plugin_map = {
			'audio/mpeg': 'mad',
			'application/x-id3': 'id3demux'
		}
			
	def activate (self, shell):
		self.db = shell.get_property('db')
		self.ie_id = self.db.connect('import-error', self.import_error)
	
	def deactivate (self, shell):
		self.db.disconnect (self.ie_id)
		self.db = None

	def import_error (self, db, uri, type, mimetype, error):
		if not mimetype in self.mime_plugin_map:
			# we don't know what plugin to use, so display the error
			return False
		plugin = self.mime_plugin_map[mimetype]

		if plugin in self.awaiting_install:
			# just add it to the list of files to reload
			track = {'db': db, 'uri': uri, 'entry-type': type}
			list = self.awaiting_install[plugin]
			list.append(track)
			return True

		if not self.can_install (plugin):
			# it should already be installed, but isn't working
			return False

		# ask the user whether they want to install it
		dialog = gtk.MessageDialog(message_format=_("Install GStreamer Plugin"),
					   type=gtk.MESSAGE_QUESTION,
					   buttons=gtk.BUTTONS_YES_NO)
		dialog.format_secondary_text((_("The GStreamer plugin '%s' is necessary to play some of your tracks. Would you like to install it?") % plugin))

		response = dialog.run()
		dialog.hide()
		dialog = None
		if response == gtk.RESPONSE_NO:
			return False

		# put it into the "awaiting files" list
		track = {'db': db, 'uri': uri, 'entry-type': type}
		list = [track]
		self.awaiting_install[plugin] = list

		return self.install(plugin)

	def plugin_installed (self, plugin):
		# scan for new plugins
		print 'reload gstreamer plugins'

		for track in self.awaiting_install[plugin]:
			track['db'].add_uri_with_type (track['uri'], track['entry-type'])
		del self.awaiting_install[plugin]


import apt, apt_pkg

class GstPluginInstallApt (GstPluginInstall):

	def __init__ (self):
		GstPluginInstall.__init__ (self)

		self.cache = None
		self.plugin_package_map = {
			'mad': 'gstreamer0.10-plugins-ugly',
			'id3demux': 'gstreamer0.10-plugins-good'
		}

	def activate (self, shell):
		GstPluginInstall.activate (self, shell)

	def deactivate (self, shell):
		self.cache = None

		GstPluginInstall.deactivate (self, shell)

	def can_install (self, plugin):
		package = self.plugin_package_map[plugin]

		if self.cache is None:
			self.cache = apt.Cache()

		if not self.cache.has_key (package):
			return False

		candidate = self.cache[package].candidateVersion
		installed = self.cache[package].installedVersion

		if candidate is None:
			return False
		elif installed is None:
			return True
		else:
			return (apt_pkg.VersionCompare(candidate, installed) > 0)

	def install (self, plugin):
		if not plugin in self.plugin_package_map:
			return False
		package = self.plugin_package_map[plugin]

		# should be done asynchronously
		worker = PackageWorker()
		worker.perform_action (package)

		self.plugin_installed (plugin)
		return True



# stolen from gnome-app-install, and then hack up
# (c) 2005 Canonical, GPL

import subprocess
import thread
import time
import gtk
import tempfile

class PackageWorker:
    def run_synaptic(self, lock, package):
        cmd = ["/usr/bin/gksu",
               "--",
               "/usr/sbin/synaptic",
               "--hide-main-window",
               "--non-interactive"]

        # create tempfile for install (here because it must survive
        # durng the synaptic call
        f = tempfile.NamedTemporaryFile()
        f.write("%s\tinstall\n" % package)
        cmd.append("--set-selections-file")
        cmd.append("%s" % f.name)
        f.flush()

        retcode = subprocess.call(cmd)

        f.close()
        lock.release()
    
    def perform_action(self, package):
        lock = thread.allocate_lock()
        lock.acquire()
        t = thread.start_new_thread(self.run_synaptic,(lock,package))
        while lock.locked():
            while gtk.events_pending():
                gtk.main_iteration()
            time.sleep(0.05)
