예제 #1
0
    def insertGame(self, game_row, isUpdate, gameId, allowUpdate):

        #HACK: delete first element as we do not want to insert or update the id
        del game_row[0]

        # Check if exists and insert/update as appropriate; move this functionality to the Game object
        try:
            if not isUpdate:
                log.info(u"Game does not exist in database. Insert game: %s" % game_row[DataBaseObject.COL_NAME])
                Game(self.gdb).insert(game_row)
                return self.gdb.cursor.lastrowid
            else:
                if allowUpdate:
                    # check if we are allowed to update with null values
                    allowOverwriteWithNullvalues = __addon__.getSetting(
                        util.SETTING_RCB_ALLOWOVERWRITEWITHNULLVALUES).upper() == 'TRUE'
                    log.info("allowOverwriteWithNullvalues: {0}".format(allowOverwriteWithNullvalues))

                    log.info(u"Game does exist in database. Update game: %s" % game_row[DataBaseObject.COL_NAME])
                    #remove id from column list
                    columns = Game.FIELDNAMES[1:]
                    Game(self.gdb).update(columns, game_row, gameId, allowOverwriteWithNullvalues)
                else:
                    log.info(
                        u"Game does exist in database but update is not allowed for current rom collection. game: %s" % game_row[DataBaseObject.COL_NAME])

                return gameId
        except Exception as exc:
            log.error(u"An error occured while adding game '%s'. Error: %s" % (game_row[DataBaseObject.COL_NAME], exc))
            return None
    def __extract_files(self, archive_file, filenames, directory_to):
        log.info("ArchiveHandler.__extract_files")
        files_out = list()

        if self.__is_7z_on_windows(archive_file):
            return self.__getArchives7z(archive_file, filenames, directory_to)

        archive_path = self.__get_archive_file_name(archive_file)

        for ff in filenames:
            file_from = os.path.join(archive_path, ff).replace('\\', '/')
            success = xbmcvfs.copy(
                file_from, os.path.join(xbmcvfs.translatePath(directory_to),
                                        ff))
            if not success:
                log.error(
                    'Error extracting file %(ff)s from archive %(archive_file)s'
                    % {
                        'ff': ff,
                        'archive_file': archive_file
                    })
            else:
                log.debug(
                    'Extracted file %(ff)s from archive %(archive_file)s' % {
                        'ff': ff,
                        'archive_file': archive_file
                    })
                files_out.append(
                    os.path.join(xbmcvfs.translatePath(directory_to), ff))

        return files_out
예제 #3
0
	def __handleCompressedFile(self, gui, filext, rom, emuParams):

		log.info("__handleCompressedFile")

		# Note: Trying to delete temporary files (from zip or 7z extraction) from last run
		# Do this before launching a new game. Otherwise game could be deleted before launch
		tempDir = os.path.join(util.getTempDir(), 'extracted', self.romCollection.name)
		# check if folder exists
		if not xbmcvfs.exists(tempDir +'\\'):
			log.info("Create temporary folder: " +tempDir)
			xbmcvfs.mkdir(tempDir)

		try:
			if xbmcvfs.exists(tempDir +'\\'):
				log.info("Trying to delete temporary rom files")
				#can't use xbmcvfs.listdir here as it seems to cache the file list and RetroPlayer won't find newly created files anymore
				files = os.listdir(tempDir)
				for f in files:
					#RetroPlayer places savestate files next to the roms. Don't delete these files.
					fname, ext = os.path.splitext(f)
					if(ext not in ('.sav', '.xml', '.png')):
						xbmcvfs.delete(os.path.join(tempDir, f))
		except Exception, (exc):
			log.error("Error deleting files after launch emu: " + str(exc))
			gui.writeMsg(util.localize(32036) + ": " + str(exc))
예제 #4
0
    def get_scraper_by_name(self, sname):
        """Given a scraper name, returns the scraper class

		Args:
			sname: Name of the scraper, e.g. thegamesdb.net or MAME

		Raises:
			ConfigScraperSiteDoesNotExistException: No scraper matches the name

		"""
        try:
            target = self.scrapers[sname]
        except KeyError as e:
            raise ConfigScraperSiteDoesNotExistException(
                "Unsupported scraper: {0}".format(sname))

        log.debug("Instantiating scraper class {0} - {1}".format(
            sname, target))
        try:
            module = __import__(target.lower())
            class_ = getattr(module, target)
            instance = class_()
        except ImportError:
            log.error("Unable to find scraper {0}".format(sname))
            raise

        return instance
    def __getArchives7z(self, filepath, archiveList, directory_to):
        try:
            import py7zlib
        except ImportError:
            # 32039 = Error launching .7z file.
            # 32129 = Please check kodi.log for details.
            message = "%s[CR]%s" % (util.localize(32039), util.localize(32129))
            xbmcgui.Dialog().ok(util.SCRIPTNAME, message)
            msg = (
                "You have tried to launch a .7z file but you are missing required libraries to extract the file. "
                "You can download the latest RCB version from RCBs project page. It contains all required libraries."
            )
            log.error(msg)
            return None

        fp = open(str(filepath), 'rb')
        archive = py7zlib.Archive7z(fp)
        archivesDecompressed = [(name, archive.getmember(name).read())
                                for name in archiveList]
        fp.close()

        if archivesDecompressed is None:
            log.warn("Error handling compressed file")
            return []
        for archive in archivesDecompressed:
            newPath = os.path.join(directory_to, archive[0])
            log.info("Putting extracted file in %s" % newPath)
            fo = open(str(newPath), 'wb')
            fo.write(archive[1])
            fo.close()

        return archivesDecompressed
예제 #6
0
    def search(self, gamename, platform=None):

        #use description to search for the game name as the name attribute also contains the region
        #FIXME TODO
        #currently not working with MAME xml files as the rom files don't use the friendly game name
        pattern = "\<description\>(.*%s.*)\</description\>" % GameNameUtil(
        ).prepare_gamename_for_searchrequest(gamename)
        results = []

        try:
            with io.open(self._get_xml_path(), 'r',
                         encoding="utf-8") as xmlfile:
                for line in xmlfile:
                    result = re.search(pattern, line)
                    if result:
                        gamename = result.groups()[0]
                        results.append({
                            'id': gamename,
                            'title': gamename,
                            'SearchKey': [gamename]
                        })
        except Exception as e:
            log.error(e)
            raise

        return results
예제 #7
0
    def __handleCompressedFile(self, gui, filext, rom, emuParams):

        log.info("__handleCompressedFile")

        # Note: Trying to delete temporary files (from zip or 7z extraction) from last run
        # Do this before launching a new game. Otherwise game could be deleted before launch
        tempDir = os.path.join(util.getTempDir(), 'extracted',
                               self.romCollection.name)
        # check if folder exists
        if not xbmcvfs.exists(tempDir + '\\'):
            log.info("Create temporary folder: " + tempDir)
            xbmcvfs.mkdir(tempDir)

        try:
            if xbmcvfs.exists(tempDir + '\\'):
                log.info("Trying to delete temporary rom files")
                #can't use xbmcvfs.listdir here as it seems to cache the file list and RetroPlayer won't find newly created files anymore
                files = os.listdir(tempDir)
                for f in files:
                    #RetroPlayer places savestate files next to the roms. Don't delete these files.
                    fname, ext = os.path.splitext(f)
                    if (ext not in ('.sav', '.xml', '.png')):
                        xbmcvfs.delete(os.path.join(tempDir, f))
        except Exception, (exc):
            log.error("Error deleting files after launch emu: " + str(exc))
            gui.writeMsg(util.localize(32036) + ": " + str(exc))
예제 #8
0
    def search(self, gamename, platform=None):
        #use description to search for the game name as the name attribute also contains the region
        pattern = "\<description\>(.*%s.*)\</description\>" % GameNameUtil(
        ).prepare_gamename_for_searchrequest(gamename)
        if platform in self._MAME_style_platforms:
            pattern = 'name="(.*%s.*)"' % GameNameUtil(
            ).prepare_gamename_for_searchrequest(gamename)

        results = []

        try:
            fh = xbmcvfs.File(self._get_xml_path())
            text = fh.read()
            text = util.html_unescape(text)
            fh.close()
            for line in text.splitlines():
                #HACK: Apostrophes are removed in prepare_gamename_for_searchrequest. So we also have to do it here.
                result = re.search(pattern, line.replace("'", ""))
                if result:
                    gamename = result.groups()[0]
                    results.append({
                        'id': gamename,
                        'title': gamename,
                        'SearchKey': [gamename]
                    })
        except Exception as e:
            log.error(e)
            raise

        return results
    def _parseSearchResults(self, response):
        """
        Parse the json response from the Games/ByGameName API call
        Returns a list of dicts with id, title and releaseDate
        """
        results = []

        code = response['code']
        status = response['status']

        if code != 200 or status != "Success":
            log.error("thegamesdb returned an error. Code = %s, Status = %s" %
                      (code, status))
            return results

        data = response['data']
        self.resultdata = {}

        for result in data['games']:
            results.append({
                'id': result['id'],
                'title': result['game_title'],
                'releaseDate': result['release_date'],
                'SearchKey': [result['game_title']]
            })
            #store result for later use in retrieve method
            self.resultdata[result['id']] = result

        log.info(u"Found {0} results using json response: {1}".format(
            len(results), results))

        return results
예제 #10
0
    def buildMediaTypeList(self, configObj, isUpdate):
        #build fileTypeList
        fileTypeList = []

        if isUpdate:
            fileTypes = configObj.tree.findall('FileTypes/FileType')
        else:
            #build fileTypeList
            configFile = util.joinPath(util.getAddonInstallPath(), 'resources',
                                       'database', 'config_template.xml')

            if not xbmcvfs.exists(configFile):
                log.error(
                    "File config_template.xml does not exist. Place a valid config file here: "
                    + str(configFile))
                return None, util.localize(32040)

            tree = ElementTree().parse(configFile)
            fileTypes = tree.findall('FileTypes/FileType')

        for fileType in fileTypes:
            name = fileType.attrib.get('name')
            if name != None:
                mediaType = fileType.find('type')
                if mediaType != None and mediaType.text == 'video':
                    name = name + ' (video)'
                fileTypeList.append(name)

        return fileTypeList, ''
예제 #11
0
	def get_scraper_by_name(self, sname):
		"""Given a scraper name, returns the scraper class

		Args:
			sname: Name of the scraper, e.g. thegamesdb.net or MAME

		Raises:
			ConfigScraperSiteDoesNotExistException: No scraper matches the name

		"""
		try:
			target = self.scrapers[sname]
		except KeyError as e:
			raise ConfigScraperSiteDoesNotExistException("Unsupported scraper: {0}".format(sname))

		log.debug("Instantiating scraper class {0} - {1}".format(sname, target))
		try:
			module = __import__(target.lower())
			class_ = getattr(module, target)
			instance = class_()
		except ImportError:
			log.error("Unable to find scraper {0}".format(sname))
			raise

		return instance
예제 #12
0
	def search(self, gamename, platform=None):
		""" Ignore platform """
		# Newer versions support multi systems, $info=XXX indicates an arcade ROM
		startmarker = "$info=%s," %gamename
		gamedata = False
		data = ""

		historyfile_path = self._get_history_path()

		try:
			with io.open(historyfile_path, 'r', encoding="utf-8") as historyfile:
				for line in historyfile:
					if line.startswith(startmarker):
						gamedata = True

					if gamedata:
						data += line

					if line.startswith("$end"):
						gamedata = False

		except Exception as e:
			log.error(e)
			raise

		try:
			# Note the regex has to search for either Windows-style line endings (\r\n) or Unix-style (\n)
			# Earlier history.dat files had 3 line breaks, newer versions have 2
			# We also rename manufacturer and Publisher, and Description is all data between the bio heading and the first
			# subheading (e.g. - TECHNICAL - or - CONTRIBUTE -). The romset entry is delimited by the $end.
			# Japanese (or other foreign titles) have the translated name in brackets underneath.
			# Newer versions have an age-based reference (e.g. A 24-year-old SNK Neo-Geo MVS Cart) between the $bio
			# and title line
			pattern = r"\$bio(\r?\n){2}" \
			           "(?P<AgeRef>.*?(\r?\n){2})?" \
			           "(?P<Game>.*?) \(c\) (?P<ReleaseYear>\d{4}) (?P<Publisher>.*?)\.(\r?\n)" \
			           "(\((?P<Translation>.*?)\))?(\r?\n){1,2}" \
			           "(?P<Description>.*?)(\r?\n){2,3}" \
			           "- [A-Z]"

			rdata = re.search(pattern, data, re.DOTALL | re.MULTILINE | re.UNICODE)

			if rdata is None:
				raise ScraperNoSearchResultsFoundException("Unable to find %s in MAME history dat file" %gamename)

		except Exception as e:
			print "Error searching for game %s using regex: %s" %(gamename, str(e))
			return []

		self.resultdata = [rdata.groupdict()]
		self.resultdata[0]['id'] = self.resultdata[0]['Game']
		self.resultdata[0]['SearchKey'] = self.resultdata[0]['Game']

		# HACK - This is only used to retain backwards compatibility with existing scraper, where each key value was a
		# list, even if only one value is in that list
		for k, v in self.resultdata[0].iteritems():
			self.resultdata[0][k] = [v]

		return self.resultdata
예제 #13
0
    def getControlById(self, controlId):
        try:
            control = self.getControl(controlId)
        except:
            log.error("Control with id: %s could not be found. Check WindowXML file." % str(controlId))
            self.writeMsg(util.localize(32025) % str(controlId))
            return None

        return control
예제 #14
0
    def getThumbFromOnlineSource(self, gamedescription, fileType, fileName, artworkurls):
        log.info("Get thumb from online source")

        try:
            # maybe we got a thumb url from desc parser
            thumbKey = 'Filetype' + fileType
            log.info("using key: %s" % thumbKey)
            thumbUrl = self.resolveParseResult(gamedescription, thumbKey)
            if thumbUrl == '':
                return True, artworkurls

            artworkurls[fileType] = thumbUrl

            log.info("Get thumb from url: %s" % thumbUrl)

            rootExtFile = os.path.splitext(fileName)
            rootExtUrl = os.path.splitext(thumbUrl)

            files = []
            if len(rootExtUrl) == 2 and len(rootExtFile) != 0:
                fileName = rootExtFile[0] + rootExtUrl[1]
                gameName = rootExtFile[0] + ".*"
                files = self.getFilesByWildcard(gameName)
            del rootExtFile, rootExtUrl

            if len(files) > 0:
                log.info("File already exists. Won't download again.")
                return True, artworkurls

            log.info("File %s does not exist, starting download" % fileName)
            # Dialog Status Art Download

            # Update progress dialog to state we are downloading art
            try:
                #32123 = Importing Game
                #32210 = downloading artwork
                msg = "%s: %s[CR]%s: %s" % (util.localize(32123), self._guiDict["gameNameKey"],
                                            self._guiDict["scraperSiteKey"][thumbKey], util.localize(32210))
                self._gui.writeMsg(msg, self._guiDict["fileCountKey"])
            except KeyError:
                log.warn("Unable to retrieve key from GUI dict")

            try:
                self.download_thumb(thumbUrl, fileName)

            except Exception as exc:
                log.error("Could not create file: '%s'. Error message: '%s'" % (fileName, exc))
                # xbmcgui.Dialog().ok(util.localize(32012), util.localize(32011))
                return False, artworkurls

            log.info("Download finished.")

        except Exception as exc:
            log.warn("Error in getThumbFromOnlineSource: %s" % exc)

        return True, artworkurls
    def onClick(self, controlID):

        log.info('onClick')

        if controlID == CONTROL_BUTTON_EXIT:
            # Close window button
            log.info('Close')
            self.close()
        elif controlID == CONTROL_BUTTON_CANCEL:
            # Cancel button
            self.close()
        elif controlID == CONTROL_BUTTON_SAVE:
            # OK
            log.info('Save')

            # Store selectedRomCollection
            if self.selectedRomCollection is not None:
                # Code to Remove Roms
                log.info('Removing Roms')
                self._setDeleteStatus(True)
                # Code to Remove Collection
                if self.romDelete == 'RCollection':
                    self._setRCDeleteStatus(True)
                    Logutil.log('Removing Rom Collection', util.LOG_LEVEL_INFO)
                    configWriterRCDel = ConfigXmlWriter(False)
                    RCName = str(self.selectedRomCollection.name)
                    success, message = configWriterRCDel.removeRomCollection(
                        RCName)
                    if success is False:
                        log.error(message)
                        #32019 = Error
                        #32020 = Error Deleting Rom Collection
                        xbmcgui.Dialog().ok(util.localize(32019),
                                            util.localize(32020))
            log.info('Click Close')
            self.close()

        elif self.selectedControlId in (CONTROL_BUTTON_RC_DOWN,
                                        CONTROL_BUTTON_RC_UP):
            # Changing selection in Rom Collection list
            if self.selectedRomCollection is not None:
                # Store previous selectedRomCollections state
                self.romCollections[
                    self.selectedRomCollection.id] = self.selectedRomCollection

            # HACK: add a little wait time as XBMC needs some ms to execute the MoveUp/MoveDown actions from the skin
            xbmc.sleep(util.WAITTIME_UPDATECONTROLS)
            self.updateControls()
        elif self.selectedControlId in (CONTROL_BUTTON_DEL_DOWN,
                                        CONTROL_BUTTON_DEL_UP):
            # Changing selection in Delete Option list
            control = self.getControlById(CONTROL_LIST_DELETEOPTIONS)
            selectedDeleteOption = str(control.getSelectedItem().getLabel2())
            log.info('selectedDeleteOption = {0}'.format(selectedDeleteOption))
            self.romDelete = selectedDeleteOption
예제 #16
0
    def insertGame(self, gameName, description, romCollectionId, publisherId,
                   developerId, reviewerId, yearId, players, rating, votes,
                   url, region, media, perspective, controller, originalTitle,
                   alternateTitle, translatedBy, version, isFavorite,
                   launchCount, isUpdate, gameId, allowUpdate):
        # Check if exists and insert/update as appropriate; move this functionality to the Game object
        try:
            if not isUpdate:
                log.info(u"Game does not exist in database. Insert game: %s" %
                         gameName)
                Game(self.gdb).insert(
                    (gameName, description, None, None, romCollectionId,
                     publisherId, developerId, reviewerId, yearId, players,
                     rating, votes, url, region, media, perspective,
                     controller, int(isFavorite), int(launchCount),
                     originalTitle, alternateTitle, translatedBy, version))
                return self.gdb.cursor.lastrowid
            else:
                if allowUpdate:

                    # check if we are allowed to update with null values
                    allowOverwriteWithNullvalues = __addon__.getSetting(
                        util.SETTING_RCB_ALLOWOVERWRITEWITHNULLVALUES).upper(
                        ) == 'TRUE'
                    log.info("allowOverwriteWithNullvalues: {0}".format(
                        allowOverwriteWithNullvalues))

                    log.info(u"Game does exist in database. Update game: %s" %
                             gameName)
                    Game(self.gdb).update(
                        ('name', 'description', 'romCollectionId',
                         'publisherId', 'developerId', 'reviewerId', 'yearId',
                         'maxPlayers', 'rating', 'numVotes', 'url', 'region',
                         'media', 'perspective', 'controllerType',
                         'originalTitle', 'alternateTitle', 'translatedBy',
                         'version', 'isFavorite', 'launchCount'),
                        (gameName, description, romCollectionId, publisherId,
                         developerId, reviewerId, yearId, players, rating,
                         votes, url, region, media, perspective, controller,
                         originalTitle, alternateTitle, translatedBy, version,
                         int(isFavorite), int(launchCount)), gameId,
                        allowOverwriteWithNullvalues)
                else:
                    log.info(
                        u"Game does exist in database but update is not allowed for current rom collection. game: %s"
                        % gameName)

                return gameId
        except Exception, (exc):
            log.error(u"An error occured while adding game '%s'. Error: %s" %
                      (gameName, exc))
            return None
 def __delete_temp_files(self, temp_dir):
     log.info("ArchiveHandler.__delete_temp_files")
     try:
         if xbmcvfs.exists(temp_dir + '\\'):
             log.info("Trying to delete temporary rom files")
             #can't use xbmcvfs.listdir here as it seems to cache the file list and RetroPlayer won't find newly created files anymore
             files = os.listdir(temp_dir)
             for f in files:
                 #RetroPlayer places savestate files next to the roms. Don't delete these files.
                 fname, ext = os.path.splitext(f)
                 if ext not in ('.sav', '.xml', '.png'):
                     xbmcvfs.delete(os.path.join(temp_dir, f))
     except Exception as exc:
         log.error("Error deleting files after launch emu: " + str(exc))
         self.gui.writeMsg(util.localize(32036) + ": " + str(exc))
	def onClick(self, controlID):

		log.info('onClick')

		if controlID == CONTROL_BUTTON_EXIT:
			# Close window button
			log.info('Close')
			self.close()
		elif controlID == CONTROL_BUTTON_CANCEL:
			# Cancel button
			self.close()
		elif controlID == CONTROL_BUTTON_SAVE:
			# OK
			log.info('Save')

			# Store selectedRomCollection
			if self.selectedRomCollection is not None:
				# Code to Remove Roms
				log.info('Removing Roms')
				self._setDeleteStatus(True)
				# Code to Remove Collection
				if self.romDelete == 'RCollection':
					self._setRCDeleteStatus(True)
					Logutil.log('Removing Rom Collection', util.LOG_LEVEL_INFO)
					configWriterRCDel = ConfigXmlWriter(False)
					RCName = str(self.selectedRomCollection.name)
					success, message = configWriterRCDel.removeRomCollection(RCName)
					if success is False:
						log.error(message)
						xbmcgui.Dialog().ok(util.localize(32019), util.localize(32020))
			log.info('Click Close')
			self.close()

		elif self.selectedControlId in (CONTROL_BUTTON_RC_DOWN, CONTROL_BUTTON_RC_UP):
			# Changing selection in Rom Collection list
			if self.selectedRomCollection is not None:
				# Store previous selectedRomCollections state
				self.romCollections[self.selectedRomCollection.id] = self.selectedRomCollection

			# HACK: add a little wait time as XBMC needs some ms to execute the MoveUp/MoveDown actions from the skin
			xbmc.sleep(util.WAITTIME_UPDATECONTROLS)
			self.updateControls()
		elif self.selectedControlId in (CONTROL_BUTTON_DEL_DOWN, CONTROL_BUTTON_DEL_UP):
			# Changing selection in Delete Option list
			control = self.getControlById(CONTROL_LIST_DELETEOPTIONS)
			selectedDeleteOption = str(control.getSelectedItem().getLabel2())
			log.info('selectedDeleteOption = {0}'.format(selectedDeleteOption))
			self.romDelete = selectedDeleteOption
예제 #19
0
	def __getArchives7z(self, filepath, archiveList):

		try:
			import py7zlib
		except ImportError:
			xbmcgui.Dialog().ok(util.SCRIPTNAME, util.localize(32039), util.localize(32129))
			msg = ("You have tried to launch a .7z file but you are missing required libraries to extract the file. "
				   "You can download the latest RCB version from RCBs project page. It contains all required libraries.")
			log.error(msg)
			return None

		fp = open(str(filepath), 'rb')
		archive = py7zlib.Archive7z(fp)
		archivesDecompressed = [(name, archive.getmember(name).read())for name in archiveList]
		fp.close()
		return archivesDecompressed
예제 #20
0
	def __getNames7z(self, filepath):

		try:
			import py7zlib
		except ImportError as e:
			xbmcgui.Dialog().ok(util.SCRIPTNAME, util.localize(32039), util.localize(32129))
			msg = ("You have tried to launch a .7z file but you are missing required libraries to extract the file. "
				   "You can download the latest RCB version from RCBs project page. It contains all required libraries.")
			log.error(msg)
			log.error("Error: " + str(e))
			return None

		fp = open(str(filepath), 'rb')
		archive = py7zlib.Archive7z(fp)
		names = archive.getnames()
		fp.close()
		return names
예제 #21
0
    def launch_game(self, gameid, listitem):
        log.info("AbstractLauncher.launch_game()")
        try:
            launcher = self.get_launcher_by_gameid(gameid)
            if (launcher is None):
                log.error("Launcher could not be created.")
                return

            precmd, postcmd, cmd, roms = launcher.prepare(
                self.romCollection, self.gameRow)
            launcher.pre_launch(self.romCollection, self.gameRow, precmd)
            launcher.launch(self.romCollection, self.gameRow, cmd, roms,
                            listitem)
            launcher.post_launch(self.romCollection, self.gameRow, postcmd)
        except Exception as exc:
            error = "%s: %s" % (util.localize(32035), str(exc))
            traceback.print_exc()
            self.gui.writeMsg(error)
예제 #22
0
    def __getArchives7z(self, filepath, archiveList):

        try:
            import py7zlib
        except ImportError:
            # 32039 = Error launching .7z file.
            # 32129 = Please check kodi.log for details.
            message = "%s[CR]%s" % (util.localize(32039), util.localize(32129))
            xbmcgui.Dialog().ok(util.SCRIPTNAME, message)
            msg = ("You have tried to launch a .7z file but you are missing required libraries to extract the file. "
                   "You can download the latest RCB version from RCBs project page. It contains all required libraries.")
            log.error(msg)
            return None

        fp = open(str(filepath), 'rb')
        archive = py7zlib.Archive7z(fp)
        archivesDecompressed = [(name, archive.getmember(name).read()) for name in archiveList]
        fp.close()
        return archivesDecompressed
예제 #23
0
    def __getNames7z(self, filepath):

        try:
            import py7zlib
        except ImportError as e:
            xbmcgui.Dialog().ok(util.SCRIPTNAME, util.localize(32039),
                                util.localize(32129))
            msg = (
                "You have tried to launch a .7z file but you are missing required libraries to extract the file. "
                "You can download the latest RCB version from RCBs project page. It contains all required libraries."
            )
            log.error(msg)
            log.error("Error: " + str(e))
            return None

        fp = open(str(filepath), 'rb')
        archive = py7zlib.Archive7z(fp)
        names = archive.getnames()
        fp.close()
        return names
    def search(self, gamename, platform=None):

        #use description to search for the game name as the name attribute also contains the region
        #FIXME TODO
        #currently not working with MAME xml files as the rom files don't use the friendly game name
        pattern = "\<description\>(.*%s.*)\</description\>" % GameNameUtil().prepare_gamename_for_searchrequest(gamename)
        results = []

        try:
            with io.open(self._get_xml_path(), 'r', encoding="utf-8") as xmlfile:
                for line in xmlfile:
                    result = re.search(pattern, line)
                    if result:
                        gamename = result.groups()[0]
                        results.append({'id': gamename,
                                        'title': gamename,
                                        'SearchKey': [gamename]})
        except Exception as e:
            log.error(e)
            raise

        return results
예제 #25
0
    def get_scraper_by_name(self, sname):
        """Given a scraper name, returns the scraper class

        Args:
            sname: Name of the scraper, e.g. thegamesdb.net or MAME

        Raises:
            ConfigScraperSiteDoesNotExistException: No scraper matches the name

        """
        try:
            target = self.scrapers[sname]
        except KeyError:
            raise ConfigScraperSiteDoesNotExistException(
                "Unsupported scraper: {0}".format(sname))

        #check if we already have instantiated this scraper
        instance = None
        try:
            instance = self._instantiated_scrapers[sname]
            log.debug(
                "Using previously instantiated scraper class {0} - {1}".format(
                    sname, target))
        except KeyError:
            pass

        if not instance:
            log.debug("Instantiating scraper class {0} - {1}".format(
                sname, target))
            try:
                module = __import__(target.lower())
                class_ = getattr(module, target)
                instance = class_()
                self._instantiated_scrapers[sname] = instance
            except ImportError:
                log.error("Unable to find scraper {0}".format(sname))
                raise

        return instance
예제 #26
0
    def insertGame(self, gameName, description, romCollectionId, publisherId, developerId, reviewerId, yearId,
                   players, rating, votes, url, region, media, perspective, controller, originalTitle, alternateTitle,
                   translatedBy, version, isFavorite, launchCount, isUpdate, gameId, allowUpdate):
        # Check if exists and insert/update as appropriate; move this functionality to the Game object
        try:
            if not isUpdate:
                log.info(u"Game does not exist in database. Insert game: %s" % gameName)
                Game(self.gdb).insert(
                    (gameName, description, None, None, romCollectionId, publisherId, developerId, reviewerId, yearId,
                     players, rating, votes, url, region, media, perspective, controller, int(isFavorite),
                     int(launchCount), originalTitle, alternateTitle, translatedBy, version))
                return self.gdb.cursor.lastrowid
            else:
                if allowUpdate:

                    # check if we are allowed to update with null values
                    allowOverwriteWithNullvalues = __addon__.getSetting(
                        util.SETTING_RCB_ALLOWOVERWRITEWITHNULLVALUES).upper() == 'TRUE'
                    log.info("allowOverwriteWithNullvalues: {0}".format(allowOverwriteWithNullvalues))

                    log.info(u"Game does exist in database. Update game: %s" % gameName)
                    Game(self.gdb).update(('name', 'description', 'romCollectionId', 'publisherId', 'developerId',
                                           'reviewerId', 'yearId', 'maxPlayers', 'rating', 'numVotes',
                                           'url', 'region', 'media', 'perspective', 'controllerType', 'originalTitle',
                                           'alternateTitle', 'translatedBy', 'version', 'isFavorite', 'launchCount'),
                                          (gameName, description, romCollectionId, publisherId, developerId, reviewerId,
                                           yearId, players, rating, votes, url, region, media, perspective, controller,
                                           originalTitle, alternateTitle, translatedBy, version, int(isFavorite),
                                           int(launchCount)),
                                          gameId, allowOverwriteWithNullvalues)
                else:
                    log.info(
                        u"Game does exist in database but update is not allowed for current rom collection. game: %s" % gameName)

                return gameId
        except Exception, (exc):
            log.error(u"An error occured while adding game '%s'. Error: %s" % (gameName, exc))
            return None
    def __getNames7z(self, filepath):

        try:
            import py7zlib
        except ImportError as e:
            # 32039 = Error launching .7z file.
            # 32129 = Please check kodi.log for details.
            message = "%s[CR]%s" % (util.localize(32039), util.localize(32129))
            xbmcgui.Dialog().ok(util.SCRIPTNAME, message)
            msg = (
                "You have tried to launch a .7z file but you are missing required libraries to extract the file. "
                "You can download the latest RCB version from RCBs project page. It contains all required libraries."
            )
            log.error(msg)
            log.error("Error: " + str(e))
            return None

        fp = open(str(filepath), 'rb')
        archive = py7zlib.Archive7z(fp)
        names = archive.getnames()
        log.debug('names = {0}'.format(names))
        fp.close()
        return names
    def __handle_indexed_roms(self, disk_prefix, names, emu_params, rom,
                              temp_dir):
        log.info("ArchiveHandler.__handle_indexed_roms")
        if disk_prefix == '':
            return None

        match = re.search(disk_prefix.lower(), str(names).lower())

        if '%I%' not in emu_params or not match:
            return None

        log.info("Extracting %d files" % len(names))

        try:
            extracted_files = self.__extract_files(rom, names, temp_dir)
        except Exception as exc:
            log.error("Error handling compressed file: " + str(exc))
            return None

        if extracted_files is None:
            log.warning("Error handling compressed file")
            return None

        return extracted_files
예제 #29
0
    def get_launcher_by_gameid(self, gameid):
        """Returns the launcher class based on romCollection.useBuiltinEmulator

        Args:
            gameid: the id of the game we want to launch
        """
        log.info("AbstractLauncher.get_launcher_by_gameid()")
        self.gameRow = GameView(self.gdb).getObjectById(gameid)
        if self.gameRow is None:
            log.error("Game with id %s could not be found in database" %
                      gameid)
            return None

        try:
            self.romCollection = self.config.romCollections[str(
                self.gameRow[GameView.COL_romCollectionId])]
        except KeyError:
            log.error("Cannot get rom collection with id: " +
                      str(self.gameRow[GameView.COL_romCollectionId]))
            self.gui.writeMsg(util.localize(32034))
            return

        self.gui.writeMsg(
            util.localize(32163) + " " + self.gameRow[DataBaseObject.COL_NAME])

        launchername = self.CMD_LAUNCHER
        if (self.romCollection.useBuiltinEmulator):
            launchername = self.RETROPLAYER_LAUNCHER

        #check if we already have instantiated this launcher
        instance = None
        try:
            instance = self._instantiated_launcher[launchername]
            log.debug(
                "Using previously instantiated launcher class {0}".format(
                    launchername))
        except KeyError:
            pass

        if not instance:
            log.debug("Instantiating launcher class {0}".format(launchername))
            try:
                module = __import__(launchername.lower())
                class_ = getattr(module, launchername)
                instance = class_()
                self._instantiated_launcher[launchername] = instance
            except ImportError:
                log.error("Unable to find launcher {0}".format(launchername))
                raise

        instance.gdb = self.gdb
        instance.gui = self.gui
        instance.config = self.config
        return instance
    def extract_archive(self, rom_collection, rom, emu_params):
        log.info("ArchiveHandler.extract_archive")

        temp_dir = self.__get_temp_dir_path(rom_collection.name)

        self.__delete_temp_files(temp_dir)

        try:
            files_in_archive = self.__get_rom_names_from_archive(rom)
        except Exception as exc:
            log.error("Error handling compressed file: " + str(exc))
            return []

        if files_in_archive is None or len(files_in_archive) == 0:
            log.error("Error handling compressed file")
            return []

        roms = self.__handle_indexed_roms(rom_collection.diskPrefix,
                                          files_in_archive, emu_params, rom,
                                          temp_dir)
        if roms:
            return roms

        try:
            # Extract all files to %TMP%
            extracted_files = self.__extract_files(rom, files_in_archive,
                                                   temp_dir)
        except Exception as exc:
            log.error("Error handling compressed file: " + str(exc))
            return []

        if extracted_files is None:
            log.warn("Error handling compressed file")
            return []

        chosen_rom = 0
        if len(files_in_archive) > 1:
            log.info("The Archive has %d files" % len(files_in_archive))
            chosen_rom = xbmcgui.Dialog().select('Choose a ROM',
                                                 files_in_archive)
        # Point file name to the chosen file and continue as usual
        roms = [os.path.join(temp_dir, files_in_archive[chosen_rom])]

        log.debug("roms decompressed = " + str(roms))
        if len(roms) == 0:
            return []

        return roms
예제 #31
0
    def useSingleScrapers(self, romCollection, romFile, gamenameFromFile, progDialogRCHeader, fileCount):
        """Scrape site for game metadata

		Args:
			romCollection:
			gamenameFromFile:
			progDialogRCHeader:
			fileCount:

		Returns:
			dict for the game result:
				{'SearchKey': ['Chrono Trigger'],
				 'Publisher': ['Squaresoft'],
				 'Description': ["The millennium. A portal is opened. The chain of time is broken...],
				 'Players': ['1'],
				 'Platform': ['Super Nintendo (SNES)'],
				 'Game': ['Chrono Trigger'],
				 'Filetypeboxfront': ['http://thegamesdb.net/banners/boxart/original/front/1255-1.jpg'],
				 'Filetypeboxback': ['http://thegamesdb.net/banners/boxart/original/back/1255-1.jpg'],
				 'Filetypescreenshot': ['http://thegamesdb.net/banners/screenshots/1255-1.jpg', 'http://thegamesdb.net/banners/screenshots/1255-2.jpg', 'http://thegamesdb.net/banners/screenshots/1255-3.jpg', 'http://thegamesdb.net/banners/screenshots/1255-4.jpg', 'http://thegamesdb.net/banners/screenshots/1255-5.jpg'],
				 'Filetypefanart': ['http://thegamesdb.net/banners/fanart/original/1255-1.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-10.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-11.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-2.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-3.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-4.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-5.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-6.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-7.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-8.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-9.jpg'],
				 'Genre': ['Role-Playing'],
				 'Developer': ['Squaresoft']}
			dict for artwork urls:
				{'Filetypefanart': 'thegamesdb.net', 'Filetypeboxback': 'thegamesdb.net', 'Filetypescreenshot': 'thegamesdb.net', 'Filetypeboxfront': 'thegamesdb.net'}
				Note - this only contains entries for artwork that was found (i.e. is not empty list)
		"""
        gameresult = {}
        artScrapers = {}

        scraperSite = romCollection.scraperSites[0]

        try:
            #first check if a local nfo file is available
            nfoscraper = NFO_Scraper()
            nfofile = nfoscraper.get_nfo_path(gamenameFromFile, romCollection.name, romFile)
            if xbmcvfs.exists(nfofile) and __addon__.getSetting(util.SETTING_RCB_PREFERLOCALNFO).upper() == 'TRUE':
                log.info("Found local nfo file. Using this to scrape info.")
                newscraper = nfoscraper
            else:
                newscraper = AbstractScraper().get_scraper_by_name(scraperSite.name)
                #set path to desc file (only useful for offline scrapers)
                newscraper.path = scraperSite.path

            results = newscraper.search(gamenameFromFile, romCollection.name)
            log.debug(u"Searching for %s - found %s results: %s" % (gamenameFromFile, len(results), results))
        except ScraperExceededAPIQuoteException as ke:
            # API key is invalid - we need to stop scraping
            log.error("Scraper exceeded API key, stopping scraping")
            raise
        except Exception as e:
            log.error("Error searching for %s using scraper %s - %s %s" % (
            gamenameFromFile, scraperSite.name, type(e), e))
            return gameresult, artScrapers

        if results == []:
            log.warn("No search results found for %s using scraper %s" % (gamenameFromFile, scraperSite.name))
            return gameresult, artScrapers

        matched = Matcher().getBestResults(results, gamenameFromFile)
        if matched is None:
            log.error("No matches found for %s, skipping" % gamenameFromFile)
            return gameresult, artScrapers
        log.debug("After matching: %s" % matched)

        try:
            retrievedresult = newscraper.retrieve(matched['id'], romCollection.name)
            log.debug(u"Retrieving %s - found %s" % (matched['id'], retrievedresult))
        except Exception as e:
            # FIXME TODO Catch exceptions specifically
            log.error("Error retrieving %s - %s %s" % (matched['id'], type(e), e))
            return gameresult, artScrapers

        # Update the gameresult with any new fields
        gameresult = self.addNewElements(gameresult, retrievedresult)

        self._gui.writeMsg(progDialogRCHeader, util.localize(32123) + ": " + gamenameFromFile,
                           scraperSite.name + " - " + util.localize(32131), fileCount)

        # Find Filetypes and Scrapers for Art Download
        # FIXME TODO The following is kept to keep artwork downloading working as it currently is. We already have
        # the URLs and so could handle/download here, rather than deferring
        if len(gameresult) > 0:
            for path in romCollection.mediaPaths:
                thumbKey = 'Filetype' + path.fileType.name
                if len(self.resolveParseResult(gameresult, thumbKey)) > 0:
                    if (thumbKey in artScrapers) == 0:
                        artScrapers[thumbKey] = scraperSite.name

        log.debug(u"After scraping, result = %s, artscrapers = %s" % (gameresult, artScrapers))
        return gameresult, artScrapers
예제 #32
0
    def updateDB(self, gdb, gui, romCollections, isRescrape):
        self.gdb = gdb
        self._gui = gui

        log.info("Start Update DB")

        log.info("Iterating Rom Collections")
        rccount = 1

        # always do full reimports when in rescrape-mode
        enableFullReimport = isRescrape or __addon__.getSetting(util.SETTING_RCB_ENABLEFULLREIMPORT).upper() == 'TRUE'
        log.info("enableFullReimport: {0}".format(enableFullReimport))

        continueUpdate = True
        # Added variable to allow user to continue on errors
        ignoreErrors = False

        for romCollection in romCollections.values():

            # timestamp1 = time.clock()

            # check if import was canceled
            if not continueUpdate:
                log.info("Game import canceled")
                break

            # prepare Header for ProgressDialog
            progDialogRCHeader = util.localize(32122) + " (%i / %i): %s" % (
            rccount, len(romCollections), romCollection.name)
            rccount += 1

            log.info("current Rom Collection: {0}".format(romCollection.name))

            # Read settings for current Rom Collection
            log.info("ignoreOnScan: {0}".format(romCollection.ignoreOnScan))
            if romCollection.ignoreOnScan:
                log.info("current Rom Collection will be ignored.")
                # self.scrapeResultsFile.write('Rom Collection will be ignored.\n')
                continue

            log.info("update is allowed for current rom collection: {0}".format(romCollection.allowUpdate))
            log.info("max folder depth: {0}".format(romCollection.maxFolderDepth))

            files = self.getRomFilesByRomCollection(romCollection, enableFullReimport)
            if len(files) == 0:
                log.info(u"No files found for rom collection {0}, skipping".format(romCollection.name))
                continue

            log.info(u"Found {0} game files for rom collection {1}".format(len(files), romCollection.name))

            # itemCount is used for percentage in ProgressDialogGUI
            self._gui.itemCount = len(files) + 1

            successfulFiles = 0
            lastgamename = ''
            lastGameId = None

            for fileidx, filename in enumerate(files):

                try:
                    #Give kodi a chance to interrupt the process
                    #HACK: we should use monitor.abortRequested() or monitor.waitForAbort()
                    #but for some reason only xbmc.abortRequested returns True
                    if monitor.abortRequested() or xbmc.abortRequested:
                        log.info("Kodi requests abort. Cancel Update.")
                        break

                    log.info("Scraping for %s" % filename)
                    gamenameFromFile = romCollection.getGamenameFromFilename(filename)

                    # check if we are handling one of the additional disks of a multi rom game
                    isMultiRomGame = (gamenameFromFile == lastgamename)
                    lastgamename = gamenameFromFile

                    if isMultiRomGame:
                        # Add this entry as a file under the game ID and move on
                        log.info("Detected %s as a multirom game (previous game was %s)" % (filename, lastgamename))
                        if lastGameId is None:
                            log.error("Game detected as multi rom game, but lastGameId is None.")
                            continue
                        fileType = FileType()
                        fileType.id, fileType.name, fileType.parent = 0, "rcb_rom", "game"
                        self.insertFile(filename, lastGameId, fileType, None, None, None)
                        self.gdb.commit()
                        del fileType
                        continue

                    log.info("Start scraping info for game: %s" % gamenameFromFile)

                    continueUpdate = self._gui.writeMsg(progDialogRCHeader,
                                                        util.localize(32123) + ": " + gamenameFromFile, "", fileidx + 1)
                    if not continueUpdate:
                        log.info("Game import canceled by user")
                        break

                    # check if this file already exists in DB
                    continueUpdate, isUpdate, gameId = self.checkRomfileAlreadyExists(filename, enableFullReimport)
                    if not continueUpdate:
                        continue

                    results = {}
                    foldername = self.getFoldernameFromRomFilename(filename)

                    artScrapers = {}
                    results, artScrapers = self.useSingleScrapers(romCollection, filename, gamenameFromFile,
                                                                      progDialogRCHeader, fileidx + 1)

                    if len(results) == 0:
                        # lastgamename = ""
                        results = None

                    # Variables to process Art Download Info
                    self._guiDict.update({'dialogHeaderKey': progDialogRCHeader, 'gameNameKey': gamenameFromFile,
                                          'scraperSiteKey': artScrapers, 'fileCountKey': (fileidx + 1)})
                    del artScrapers

                    #Give kodi a chance to interrupt the process
                    #HACK: we should use monitor.abortRequested() or monitor.waitForAbort()
                    #but for some reason only xbmc.abortRequested returns True
                    if monitor.abortRequested() or xbmc.abortRequested:
                        log.info("Kodi requests abort. Cancel Update.")
                        break

                    # Add 'gui' and 'dialogDict' parameters to function
                    lastGameId = self.insertGameFromDesc(results, gamenameFromFile, romCollection, [filename],
                                                         foldername, isUpdate, gameId)
                    del results, foldername

                    if lastGameId is not None:
                        log.info("Successfully added %s" % gamenameFromFile)
                        successfulFiles += 1

                    # Check if all first 10 games have errors - Modified to allow user to continue on errors
                    if fileidx > 9 and successfulFiles == 0 and not ignoreErrors:
                        options = [util.localize(32124), util.localize(32125), util.localize(32126)]
                        answer = xbmcgui.Dialog().select(util.localize(32127), options)
                        if answer == 1:
                            # Continue and ignore errors
                            ignoreErrors = True
                        elif answer == 2:
                            # Cancel
                            xbmcgui.Dialog().ok(util.SCRIPTNAME, util.localize(32128), util.localize(32129))
                            continueUpdate = False
                            break

                except ScraperExceededAPIQuoteException as ke:
                    xbmcgui.Dialog().ok(util.localize(32128), "The API key for a scraper was exceeded")
                    # Abort the scraping entirely
                    break
                except Exception as exc:
                    log.warn(u"An error occurred while adding game %s: %s" % (gamenameFromFile, exc))
                    self.missingDescFile.add_entry(gamenameFromFile)

                    continue

        # timestamp2 = time.clock()
        # diff = (timestamp2 - timestamp1) * 1000
        # print "load %i games in %d ms" % (self.getListSize(), diff)

        self._gui.writeMsg("Done.", "", "", self._gui.itemCount)
        log.info("Update finished")
        return True, ''
예제 #33
0
    def getThumbFromOnlineSource(self, gamedescription, fileType, fileName,
                                 artworkurls):
        log.info("Get thumb from online source")

        try:
            # maybe we got a thumb url from desc parser
            thumbKey = 'Filetype' + fileType
            log.info("using key: %s" % thumbKey)
            thumbUrl = self.resolveParseResult(gamedescription, thumbKey)
            if thumbUrl == '':
                return True, artworkurls

            artworkurls[fileType] = thumbUrl

            log.info("Get thumb from url: %s" % thumbUrl)

            rootExtFile = os.path.splitext(fileName)
            rootExtUrl = os.path.splitext(thumbUrl)

            files = []
            if len(rootExtUrl) == 2 and len(rootExtFile) != 0:
                fileName = rootExtFile[0] + rootExtUrl[1]
                gameName = rootExtFile[0] + ".*"
                files = self.getFilesByWildcard(gameName)
            del rootExtFile, rootExtUrl

            if len(files) > 0:
                log.info("File already exists. Won't download again.")
                return True, artworkurls

            # Create folder if it doesn't already exist
            dirname = os.path.join(
                os.path.dirname(fileName),
                '')  # Add the trailing slash that xbmcvfs.exists expects
            log.debug("Checking for artwork directory %s" % dirname)
            if KodiVersions.getKodiVersion() >= KodiVersions.KRYPTON:
                exists = xbmcvfs.exists(dirname)
            else:
                exists = os.path.exists(dirname)
            if not exists:
                log.info("Artwork directory %s doesn't exist, creating it" %
                         dirname)
                success = xbmcvfs.mkdirs(dirname)
                log.info("Directory successfully created: %s" % success)
                if not success:
                    #HACK: check if directory was really not created.
                    directoryExists = xbmcvfs.exists(dirname)
                    log.info("Directory exists: %s" % directoryExists)
                    if not directoryExists:
                        log.error("Could not create artwork directory: '%s'" %
                                  dirname)
                        xbmcgui.Dialog().ok(util.localize(32010),
                                            util.localize(32011))
                        del dirname
                        return False, artworkurls

            log.info("File %s does not exist, starting download" % fileName)
            # Dialog Status Art Download

            # Update progress dialog to state we are downloading art
            try:
                msg = "%s: %s" % (util.localize(32123),
                                  self._guiDict["gameNameKey"])
                submsg = "%s - downloading art" % self._guiDict[
                    "scraperSiteKey"][thumbKey]
                self._gui.writeMsg(self._guiDict["dialogHeaderKey"], msg,
                                   submsg, self._guiDict["fileCountKey"])
            except KeyError:
                log.warn("Unable to retrieve key from GUI dict")

            try:
                self.download_thumb(thumbUrl, fileName)

            except Exception, (exc):
                log.error("Could not create file: '%s'. Error message: '%s'" %
                          (fileName, exc))
                # xbmcgui.Dialog().ok(util.localize(32012), util.localize(32011))
                return False, artworkurls

            Logutil.log("Download finished.", util.LOG_LEVEL_INFO)
예제 #34
0
    def search(self, gamename, platform=None):
        """ Ignore platform """
        # Newer versions support multi systems, $info=XXX indicates an arcade ROM
        startmarker = "$info=%s," % gamename
        gamedata = False
        data = ""

        historyfile_path = self._get_history_path()

        try:
            fh = xbmcvfs.File(historyfile_path)
            historyfile = fh.read()
            historyfile = util.convertToUnicodeString(historyfile)
            fh.close()
            for line in historyfile.splitlines():
                if line.startswith(startmarker):
                    gamedata = True

                if gamedata:
                    data += line + os.linesep

                if line.startswith("$end"):
                    gamedata = False

        except Exception as e:
            log.error(e)
            raise

        try:
            # Note the regex has to search for either Windows-style line endings (\r\n) or Unix-style (\n)
            # Earlier history.dat files had 3 line breaks, newer versions have 2
            # We also rename manufacturer and Publisher, and Description is all data between the bio heading and the first
            # subheading (e.g. - TECHNICAL - or - CONTRIBUTE -). The romset entry is delimited by the $end.
            # Japanese (or other foreign titles) have the translated name in brackets underneath.
            # Newer versions have an age-based reference (e.g. A 24-year-old SNK Neo-Geo MVS Cart) between the $bio
            # and title line

            pattern = r"\$bio(\r?\n){2}" \
                      "(?P<AgeRef>.*?(\r?\n){2})?" \
                      "(?P<Game>.*?) \(c\) (?P<ReleaseYear>\d{4}) (?P<Publisher>.*?)\.(\r?\n)" \
                      "(\((?P<Translation>.*?)\))?(\r?\n){1,2}" \
                      "(?P<Description>.*?)(\r?\n){2,3}" \
                      "- [A-Z]"

            rdata = re.search(pattern, data, re.DOTALL | re.MULTILINE | re.UNICODE)

            if rdata is None:
                raise ScraperNoSearchResultsFoundException("Unable to find %s in MAME history dat file" % gamename)

        except Exception as e:
            print ("Error searching for game %s using regex: %s" % (gamename, str(e)))
            return []

        self.resultdata = [rdata.groupdict()]
        self.resultdata[0]['id'] = self.resultdata[0]['Game']
        #don't use a search key as we should always have 1 result that perfectly fits
        #search key is used in matcher to compare the rom name with the game name and this will usually not match
        #self.resultdata[0]['SearchKey'] = self.resultdata[0]['Game']

        # HACK - This is only used to retain backwards compatibility with existing scraper, where each key value was a
        # list, even if only one value is in that list
        for k, v in self.resultdata[0].items():
            self.resultdata[0][k] = [v]

        return self.resultdata
예제 #35
0
					fname, ext = os.path.splitext(f)
					if(ext not in ('.sav', '.xml', '.png')):
						xbmcvfs.delete(os.path.join(tempDir, f))
		except Exception, (exc):
			log.error("Error deleting files after launch emu: " + str(exc))
			gui.writeMsg(util.localize(32036) + ": " + str(exc))

		roms = []

		log.info("Treating file as a compressed archive")
		compressed = True

		try:
			names = self.__getNames(filext, rom)
		except Exception, (exc):
			log.error("Error handling compressed file: " + str(exc))
			return []

		if names is None:
			log.error("Error handling compressed file")
			return []

		chosenROM = -1

		# check if we should handle multiple roms
		match = False
		if self.romCollection.diskPrefix != '':
			match = re.search(self.romCollection.diskPrefix.lower(), str(names).lower())

		if '%I%' in emuParams and match:
			log.info("Loading %d archives" % len(names))
예제 #36
0
    def __handleCompressedFile(self, gui, filext, rom, emuParams):

        log.info("__handleCompressedFile")

        # Note: Trying to delete temporary files (from zip or 7z extraction) from last run
        # Do this before launching a new game. Otherwise game could be deleted before launch
        tempDir = os.path.join(util.getTempDir(), 'extracted', self.romCollection.name)
        # check if folder exists
        if not xbmcvfs.exists(tempDir + '\\'):
            log.info("Create temporary folder: " + tempDir)
            xbmcvfs.mkdir(tempDir)

        try:
            if xbmcvfs.exists(tempDir + '\\'):
                log.info("Trying to delete temporary rom files")
                #can't use xbmcvfs.listdir here as it seems to cache the file list and RetroPlayer won't find newly created files anymore
                files = os.listdir(tempDir)
                for f in files:
                    #RetroPlayer places savestate files next to the roms. Don't delete these files.
                    fname, ext = os.path.splitext(f)
                    if ext not in ('.sav', '.xml', '.png'):
                        xbmcvfs.delete(os.path.join(tempDir, f))
        except Exception as exc:
            log.error("Error deleting files after launch emu: " + str(exc))
            gui.writeMsg(util.localize(32036) + ": " + str(exc))

        roms = []

        log.info("Treating file as a compressed archive")

        try:
            names = self.__getNames(filext, rom)
        except Exception as exc:
            log.error("Error handling compressed file: " + str(exc))
            return []

        if names is None:
            log.error("Error handling compressed file")
            return []

        chosenROM = -1

        # check if we should handle multiple roms
        match = False
        if self.romCollection.diskPrefix != '':
            match = re.search(self.romCollection.diskPrefix.lower(), str(names).lower())

        if '%I%' in emuParams and match:
            log.info("Loading %d archives" % len(names))

            try:
                archives = self.__getArchives(filext, rom, names)
            except Exception as exc:
                log.error("Error handling compressed file: " + str(exc))
                return []

            if archives is None:
                log.warning("Error handling compressed file")
                return []
            for archive in archives:
                newPath = os.path.join(tempDir, archive[0])
                fp = open(newPath, 'wb')
                fp.write(archive[1])
                fp.close()
                roms.append(newPath)

        elif len(names) > 1:
            log.info("The Archive has %d files" % len(names))
            chosenROM = xbmcgui.Dialog().select('Choose a ROM', names)
        elif len(names) == 1:
            log.info("Archive only has one file inside; picking that one")
            chosenROM = 0
        else:
            log.error("Archive had no files inside!")
            return []

        if chosenROM != -1:
            # Extract all files to %TMP%
            archives = self.__getArchives(filext, rom, names)
            if archives is None:
                log.warn("Error handling compressed file")
                return []
            for archive in archives:
                newPath = os.path.join(tempDir, archive[0])
                log.info("Putting extracted file in %s" % newPath)
                fo = open(str(newPath), 'wb')
                fo.write(archive[1])
                fo.close()

            # Point file name to the chosen file and continue as usual
            roms = [os.path.join(tempDir, names[chosenROM])]

        return roms
예제 #37
0
    def launchEmu(self, gdb, gui, gameId, config, listitem):
        log.info("Begin launcher.launchEmu")

        gameRow = Game(gdb).getObjectById(gameId)
        if gameRow is None:
            log.error("Game with id %s could not be found in database" %
                      gameId)
            return

        try:
            self.romCollection = config.romCollections[str(
                gameRow[util.GAME_romCollectionId])]
        except KeyError:
            log.error("Cannot get rom collection with id: " +
                      str(gameRow[util.GAME_romCollectionId]))
            gui.writeMsg(util.localize(32034))
            return

        gui.writeMsg(util.localize(32163) + " " + gameRow[util.ROW_NAME])

        # Remember viewstate
        gui.saveViewState(False)

        cmd = ""
        precmd = ""
        postcmd = ""

        filenameRows = File(gdb).getRomsByGameId(gameRow[util.ROW_ID])
        log.info("files for current game: " + str(filenameRows))

        cmd, precmd, postcmd, roms = self.__buildCmd(gui, filenameRows,
                                                     gameRow, False)

        if not self.romCollection.useBuiltinEmulator:
            if cmd == '':
                log.info("No cmd created. Game will not be launched.")
                return
            if precmd.strip() == '' or precmd.strip() == 'call':
                log.info("No precmd created.")

            if postcmd.strip() == '' or postcmd.strip() == 'call':
                log.info("No postcmd created.")

            # solo mode
            if self.romCollection.useEmuSolo:

                self.__copyLauncherScriptsToUserdata()

                # communicate with service via settings
                __addon__.setSetting(util.SETTING_RCB_LAUNCHONSTARTUP, 'true')

                # invoke script file that kills xbmc before launching the emulator
                basePath = os.path.join(util.getAddonDataPath(), 'scriptfiles')

                if self.env == "win32":
                    if __addon__.getSetting(util.SETTING_RCB_USEVBINSOLOMODE
                                            ).lower() == 'true':
                        # There is a problem with quotes passed as argument to windows command shell. This only works with "call"
                        # use vb script to restart xbmc
                        cmd = 'call \"' + os.path.join(
                            basePath, 'applaunch-vbs.bat') + '\" ' + cmd
                    else:
                        # There is a problem with quotes passed as argument to windows command shell. This only works with "call"
                        cmd = 'call \"' + os.path.join(
                            basePath, 'applaunch.bat') + '\" ' + cmd
                else:
                    cmd = os.path.join(basePath, 'applaunch.sh ') + cmd
            else:
                # use call to support paths with whitespaces
                if self.env == "win32":
                    cmd = 'call ' + cmd

        # update LaunchCount
        launchCount = gameRow[util.GAME_launchCount]
        Game(gdb).update(('launchCount', ), (launchCount + 1, ),
                         gameRow[util.ROW_ID], True)
        gdb.commit()

        log.info("cmd: " + cmd)
        log.info("precmd: " + precmd)
        log.info("postcmd: " + postcmd)

        try:
            self.__launchNonXbox(cmd, gameRow, precmd, postcmd, roms, gui,
                                 listitem)

            gui.writeMsg("")

        except Exception, (exc):
            log.error("Error while launching emu: " + str(exc))
            gui.writeMsg(util.localize(32035) + ": " + str(exc))
예제 #38
0
                    fname, ext = os.path.splitext(f)
                    if (ext not in ('.sav', '.xml', '.png')):
                        xbmcvfs.delete(os.path.join(tempDir, f))
        except Exception, (exc):
            log.error("Error deleting files after launch emu: " + str(exc))
            gui.writeMsg(util.localize(32036) + ": " + str(exc))

        roms = []

        log.info("Treating file as a compressed archive")
        compressed = True

        try:
            names = self.__getNames(filext, rom)
        except Exception, (exc):
            log.error("Error handling compressed file: " + str(exc))
            return []

        if names is None:
            log.error("Error handling compressed file")
            return []

        chosenROM = -1

        # check if we should handle multiple roms
        match = False
        if self.romCollection.diskPrefix != '':
            match = re.search(self.romCollection.diskPrefix.lower(),
                              str(names).lower())

        if '%I%' in emuParams and match:
예제 #39
0
	def launchEmu(self, gdb, gui, gameId, config, listitem):
		log.info("Begin launcher.launchEmu")

		gameRow = Game(gdb).getObjectById(gameId)
		if gameRow is None:
			log.error("Game with id %s could not be found in database" % gameId)
			return

		try:
			self.romCollection = config.romCollections[str(gameRow[util.GAME_romCollectionId])]
		except KeyError:
			log.error("Cannot get rom collection with id: " + str(gameRow[util.GAME_romCollectionId]))
			gui.writeMsg(util.localize(32034))
			return

		gui.writeMsg(util.localize(32163) + " " + gameRow[util.ROW_NAME])

		# Remember viewstate
		gui.saveViewState(False)

		cmd = ""
		precmd = ""
		postcmd = ""

		filenameRows = File(gdb).getRomsByGameId(gameRow[util.ROW_ID])
		log.info("files for current game: " + str(filenameRows))

		cmd, precmd, postcmd, roms = self.__buildCmd(gui, filenameRows, gameRow, False)

		if not self.romCollection.useBuiltinEmulator:
			if cmd == '':
				log.info("No cmd created. Game will not be launched.")
				return
			if precmd.strip() == '' or precmd.strip() == 'call':
				log.info("No precmd created.")

			if postcmd.strip() == '' or postcmd.strip() == 'call':
				log.info("No postcmd created.")

			# solo mode
			if self.romCollection.useEmuSolo:

				self.__copyLauncherScriptsToUserdata()

				# communicate with service via settings
				__addon__.setSetting(util.SETTING_RCB_LAUNCHONSTARTUP, 'true')

				# invoke script file that kills xbmc before launching the emulator
				basePath = os.path.join(util.getAddonDataPath(), 'scriptfiles')

				if self.env == "win32":
					if __addon__.getSetting(util.SETTING_RCB_USEVBINSOLOMODE).lower() == 'true':
						# There is a problem with quotes passed as argument to windows command shell. This only works with "call"
						# use vb script to restart xbmc
						cmd = 'call \"' + os.path.join(basePath,
													   'applaunch-vbs.bat') + '\" ' + cmd
					else:
						# There is a problem with quotes passed as argument to windows command shell. This only works with "call"
						cmd = 'call \"' + os.path.join(basePath, 'applaunch.bat') + '\" ' + cmd
				else:
					cmd = os.path.join(basePath, 'applaunch.sh ') + cmd
			else:
				# use call to support paths with whitespaces
				if self.env == "win32":
					cmd = 'call ' + cmd

		# update LaunchCount
		launchCount = gameRow[util.GAME_launchCount]
		Game(gdb).update(('launchCount',), (launchCount + 1,), gameRow[util.ROW_ID], True)
		gdb.commit()

		log.info("cmd: " + cmd)
		log.info("precmd: " + precmd)
		log.info("postcmd: " + postcmd)

		try:
			self.__launchNonXbox(cmd, gameRow, precmd, postcmd, roms, gui, listitem)

			gui.writeMsg("")

		except Exception, (exc):
			log.error("Error while launching emu: " + str(exc))
			gui.writeMsg(util.localize(32035) + ": " + str(exc))
예제 #40
0
    def useSingleScrapers(self, romCollection, romFile, gamenameFromFile, progDialogRCHeader, fileCount):
        """Scrape site for game metadata

        Args:
            romCollection:
            romFile:
            gamenameFromFile:
            progDialogRCHeader:
            fileCount:

        Returns:
            dict for the game result:
                {'SearchKey': ['Chrono Trigger'],
                 'Publisher': ['Squaresoft'],
                 'Description': ["The millennium. A portal is opened. The chain of time is broken...],
                 'Players': ['1'],
                 'Platform': ['Super Nintendo (SNES)'],
                 'Game': ['Chrono Trigger'],
                 'Filetypeboxfront': ['http://thegamesdb.net/banners/boxart/original/front/1255-1.jpg'],
                 'Filetypeboxback': ['http://thegamesdb.net/banners/boxart/original/back/1255-1.jpg'],
                 'Filetypescreenshot': ['http://thegamesdb.net/banners/screenshots/1255-1.jpg', 'http://thegamesdb.net/banners/screenshots/1255-2.jpg', 'http://thegamesdb.net/banners/screenshots/1255-3.jpg', 'http://thegamesdb.net/banners/screenshots/1255-4.jpg', 'http://thegamesdb.net/banners/screenshots/1255-5.jpg'],
                 'Filetypefanart': ['http://thegamesdb.net/banners/fanart/original/1255-1.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-10.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-11.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-2.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-3.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-4.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-5.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-6.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-7.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-8.jpg', 'http://thegamesdb.net/banners/fanart/original/1255-9.jpg'],
                 'Genre': ['Role-Playing'],
                 'Developer': ['Squaresoft']}
            dict for artwork urls:
                {'Filetypefanart': 'thegamesdb.net', 'Filetypeboxback': 'thegamesdb.net', 'Filetypescreenshot': 'thegamesdb.net', 'Filetypeboxfront': 'thegamesdb.net'}
                Note - this only contains entries for artwork that was found (i.e. is not empty list)
        """
        gameresult = {}
        artScrapers = {}

        scraperSite = None

        #search for default scraper if there are more than one
        for site in romCollection.scraperSites:
            if site.default:
                scraperSite = site
                break

        #if no default site was found, just use the first one
        if not scraperSite:
            if len(romCollection.scraperSites) >= 1:
                scraperSite = romCollection.scraperSites[0]

        try:
            #first check if a local nfo file is available
            nfoscraper = NFO_Scraper()
            nfofile = nfoscraper.get_nfo_path(gamenameFromFile, romCollection.name, romFile)
            if xbmcvfs.exists(nfofile) and __addon__.getSetting(util.SETTING_RCB_PREFERLOCALNFO).upper() == 'TRUE':
                log.info("Found local nfo file. Using this to scrape info.")
                newscraper = nfoscraper
            else:
                newscraper = AbstractScraper().get_scraper_by_name(scraperSite.name)
                #set path to desc file (only useful for offline scrapers)
                newscraper.path = scraperSite.path

            log.info("Using scraper: %s" % newscraper.name)
            # 32123 = Importing Game
            # 32131 = downloading info
            msg = "%s: %s[CR]%s: %s" %(util.localize(32123), gamenameFromFile, newscraper.name, util.localize(32131))
            self._gui.writeMsg(msg, fileCount)

            results = newscraper.search(gamenameFromFile, romCollection.name)
            log.debug(u"Searching for %s - found %s results: %s" % (gamenameFromFile, len(results), results))
        except ScraperExceededAPIQuoteException as ke:
            # API key is invalid - we need to stop scraping
            log.error("Scraper exceeded API key, stopping scraping")
            raise
        except Exception as e:
            log.error("Error searching for %s using scraper %s - %s %s" % (
                gamenameFromFile, scraperSite.name, type(e), e))
            return gameresult, artScrapers

        if results == []:
            log.warn("No search results found for %s using scraper %s" % (gamenameFromFile, scraperSite.name))
            return gameresult, artScrapers

        matched = Matcher().getBestResults(results, gamenameFromFile)
        if matched is None:
            log.error("No matches found for %s, skipping" % gamenameFromFile)
            return gameresult, artScrapers
        log.debug("After matching: %s" % matched)

        try:
            retrievedresult = newscraper.retrieve(matched['id'], romCollection.name)
            log.debug(u"Retrieving %s - found %s" % (matched['id'], retrievedresult))
        except Exception as e:
            # FIXME TODO Catch exceptions specifically
            log.error("Error retrieving %s - %s %s" % (matched['id'], type(e), e))
            return gameresult, artScrapers

        # Update the gameresult with any new fields
        gameresult = self.addNewElements(gameresult, retrievedresult)

        # Find Filetypes and Scrapers for Art Download
        # FIXME TODO The following is kept to keep artwork downloading working as it currently is. We already have
        # the URLs and so could handle/download here, rather than deferring
        if len(gameresult) > 0:
            for path in romCollection.mediaPaths:
                thumbKey = 'Filetype' + path.fileType.name
                if len(self.resolveParseResult(gameresult, thumbKey)) > 0:
                    if (thumbKey in artScrapers) == 0:
                        artScrapers[thumbKey] = scraperSite.name

        log.debug(u"After scraping, result = %s, artscrapers = %s" % (gameresult, artScrapers))
        return gameresult, artScrapers
예제 #41
0
    def updateDB(self, gdb, gui, romCollections, isRescrape):
        self.gdb = gdb
        self._gui = gui

        log.info("Start Update DB")

        #at start, check if we need to create any artwork directories
        if not helper.createArtworkDirectories(romCollections):
            #32010: Error: Could not create artwork directory.
            return False, util.localize(32010)

        log.info("Iterating Rom Collections")
        rccount = 1

        # always do full reimports when in rescrape-mode
        enableFullReimport = isRescrape or __addon__.getSetting(util.SETTING_RCB_ENABLEFULLREIMPORT).upper() == 'TRUE'
        log.info("enableFullReimport: {0}".format(enableFullReimport))

        continueUpdate = True
        # Added variable to allow user to continue on errors
        ignoreErrors = False

        for romCollection in list(romCollections.values()):

            # timestamp1 = time.clock()

            # check if import was canceled
            if not continueUpdate:
                log.info("Game import canceled")
                break

            # prepare Header for ProgressDialog
            # 32122 = Importing Rom Collection
            progDialogRCHeader = util.localize(32122) + " (%i / %i): %s" % (
                rccount, len(romCollections), romCollection.name)
            rccount += 1

            log.info("current Rom Collection: {0}".format(romCollection.name))

            # Read settings for current Rom Collection
            log.info("ignoreOnScan: {0}".format(romCollection.ignoreOnScan))
            if romCollection.ignoreOnScan:
                log.info("current Rom Collection will be ignored.")
                # self.scrapeResultsFile.write('Rom Collection will be ignored.\n')
                continue

            log.info("update is allowed for current rom collection: {0}".format(romCollection.allowUpdate))
            log.info("max folder depth: {0}".format(romCollection.maxFolderDepth))

            files = self.getRomFilesByRomCollection(romCollection, enableFullReimport)
            if len(files) == 0:
                log.info(u"No files found for rom collection {0}, skipping".format(romCollection.name))
                continue

            log.info(u"Found {0} game files for rom collection {1}".format(len(files), romCollection.name))

            # itemCount is used for percentage in ProgressDialogGUI
            self._gui.itemCount = len(files) + 1

            successfulFiles = 0
            lastgamename = ''
            lastGameId = None

            for fileidx, filename in enumerate(files):

                try:
                    #Give kodi a chance to interrupt the process
                    #HACK: we should use monitor.abortRequested() or monitor.waitForAbort()
                    #but for some reason only xbmc.abortRequested returns True
                    if monitor.abortRequested():
                        log.info("Kodi requests abort. Cancel Update.")
                        break

                    log.info("Scraping for %s" % filename)
                    gamenameFromFile = romCollection.getGamenameFromFilename(filename)

                    # check if we are handling one of the additional disks of a multi rom game
                    isMultiRomGame = (gamenameFromFile == lastgamename)
                    lastgamename = gamenameFromFile

                    if isMultiRomGame:
                        # Add this entry as a file under the game ID and move on
                        log.info("Detected %s as a multirom game (previous game was %s)" % (filename, lastgamename))
                        if lastGameId is None:
                            log.error("Game detected as multi rom game, but lastGameId is None.")
                            continue
                        fileType = FileType()
                        fileType.id, fileType.name, fileType.parent = 0, "rcb_rom", "game"
                        self.insertFile(filename, lastGameId, fileType, None, None, None)
                        self.gdb.commit()
                        del fileType
                        continue

                    log.info("Start scraping info for game: %s" % gamenameFromFile)

                    # 32123 = Importing Game
                    msg = "%s: %s" %(util.localize(32123), gamenameFromFile)
                    continueUpdate = self._gui.writeMsg(msg, fileidx + 1)
                    if not continueUpdate:
                        log.info("Game import canceled by user")
                        break

                    # check if this file already exists in DB
                    continueUpdate, isUpdate, gameId = self.checkRomfileAlreadyExists(filename, enableFullReimport)
                    if not continueUpdate:
                        continue

                    foldername = self.getFoldernameFromRomFilename(filename)

                    results, artScrapers = self.useSingleScrapers(romCollection, filename, gamenameFromFile,
                                                                  progDialogRCHeader, fileidx + 1)

                    if len(results) == 0:
                        # lastgamename = ""
                        results = None

                    # Variables to process Art Download Info
                    self._guiDict.update({'dialogHeaderKey': progDialogRCHeader, 'gameNameKey': gamenameFromFile,
                                          'scraperSiteKey': artScrapers, 'fileCountKey': (fileidx + 1)})
                    del artScrapers

                    #Give kodi a chance to interrupt the process
                    #HACK: we should use monitor.abortRequested() or monitor.waitForAbort()
                    #but for some reason only xbmc.abortRequested returns True
                    if monitor.abortRequested():
                        log.info("Kodi requests abort. Cancel Update.")
                        break

                    # Add 'gui' and 'dialogDict' parameters to function
                    lastGameId = self.insertGameFromDesc(results, gamenameFromFile, romCollection, [filename],
                                                         foldername, isUpdate, gameId)
                    del results, foldername

                    if lastGameId is not None:
                        log.info("Successfully added %s" % gamenameFromFile)
                        successfulFiles += 1

                    # Check if all first 10 games have errors - Modified to allow user to continue on errors
                    if fileidx > 9 and successfulFiles == 0 and not ignoreErrors:
                        #32124 = Continue
                        #32125 = Continue and Ignore Errors
                        #32126 = Cancel
                        #32127 = First 10 games could not be imported.
                        options = [util.localize(32124), util.localize(32125), util.localize(32126)]
                        answer = xbmcgui.Dialog().select(util.localize(32127), options)
                        if answer == 1:
                            # Continue and ignore errors
                            ignoreErrors = True
                        elif answer == 2:
                            # Cancel
                            #32128 = Import canceled.
                            #32129 = Please check kodi.log for details.
                            message = "%s[CR]%s" % (util.localize(32128), util.localize(32129))
                            xbmcgui.Dialog().ok(util.SCRIPTNAME, message)
                            continueUpdate = False
                            break

                except ScraperExceededAPIQuoteException:
                    #32128 = Import canceled.
                    #32043 = API quota for current scraper exceeded.
                    xbmcgui.Dialog().ok(util.localize(32128), util.localize(32043))
                    # Abort the scraping entirely
                    break
                except Exception as exc:
                    log.warn(u"An error occurred while adding game %s: %s" % (gamenameFromFile, exc))
                    self.missingDescFile.add_entry(gamenameFromFile)

                    continue

        # timestamp2 = time.clock()
        # diff = (timestamp2 - timestamp1) * 1000
        # print "load %i games in %d ms" % (self.getListSize(), diff)

        self._gui.writeMsg("Done.", self._gui.itemCount)
        log.info("Update finished")
        return True, ''
예제 #42
0
    def getThumbFromOnlineSource(self, gamedescription, fileType, fileName, artworkurls):
        log.info("Get thumb from online source")

        try:
            # maybe we got a thumb url from desc parser
            thumbKey = 'Filetype' + fileType
            log.info("using key: %s" % thumbKey)
            thumbUrl = self.resolveParseResult(gamedescription, thumbKey)
            if thumbUrl == '':
                return True, artworkurls

            artworkurls[fileType] = thumbUrl

            log.info("Get thumb from url: %s" % thumbUrl)

            rootExtFile = os.path.splitext(fileName)
            rootExtUrl = os.path.splitext(thumbUrl)

            files = []
            if len(rootExtUrl) == 2 and len(rootExtFile) != 0:
                fileName = rootExtFile[0] + rootExtUrl[1]
                gameName = rootExtFile[0] + ".*"
                files = self.getFilesByWildcard(gameName)
            del rootExtFile, rootExtUrl

            if len(files) > 0:
                log.info("File already exists. Won't download again.")
                return True, artworkurls

            # Create folder if it doesn't already exist
            dirname = os.path.join(os.path.dirname(fileName), '')  # Add the trailing slash that xbmcvfs.exists expects
            log.debug("Checking for artwork directory %s" % dirname)
            if KodiVersions.getKodiVersion() >= KodiVersions.KRYPTON:
                exists = xbmcvfs.exists(dirname)
            else:
                exists = os.path.exists(dirname)
            if not exists:
                log.info("Artwork directory %s doesn't exist, creating it" % dirname)
                success = xbmcvfs.mkdirs(dirname)
                log.info("Directory successfully created: %s" %success)
                if not success:
                    #HACK: check if directory was really not created.
                    directoryExists = xbmcvfs.exists(dirname)
                    log.info("Directory exists: %s" %directoryExists)
                    if not directoryExists:
                        log.error("Could not create artwork directory: '%s'" % dirname)
                        xbmcgui.Dialog().ok(util.localize(32010), util.localize(32011))
                        del dirname
                        return False, artworkurls

            log.info("File %s does not exist, starting download" % fileName)
            # Dialog Status Art Download

            # Update progress dialog to state we are downloading art
            try:
                msg = "%s: %s" % (util.localize(32123), self._guiDict["gameNameKey"])
                submsg = "%s - downloading art" % self._guiDict["scraperSiteKey"][thumbKey]
                self._gui.writeMsg(self._guiDict["dialogHeaderKey"], msg, submsg, self._guiDict["fileCountKey"])
            except KeyError:
                log.warn("Unable to retrieve key from GUI dict")

            try:
                self.download_thumb(thumbUrl, fileName)

            except Exception, (exc):
                log.error("Could not create file: '%s'. Error message: '%s'" % (fileName, exc))
                # xbmcgui.Dialog().ok(util.localize(32012), util.localize(32011))
                return False, artworkurls

            Logutil.log("Download finished.", util.LOG_LEVEL_INFO)
예제 #43
0
    def showGame(self):

        log.info("Begin showGameList UIGameInfoView")

        self.clearList()

        game = GameView(self.gdb).getGameById(self.selectedGameId)

        item = xbmcgui.ListItem(game[DataBaseObject.COL_NAME], str(game[GameView.COL_ID]))

        romcollection_id = str(game[GameView.COL_romCollectionId])
        try:
            romCollection = self.config.romCollections[romcollection_id]
        except KeyError:
            log.error('Cannot get rom collection with id: ' + romcollection_id)

        item.setProperty('romCollectionId', romcollection_id)
        item.setProperty('romcollection', romCollection.name)
        item.setProperty('console', romCollection.name)
        item.setProperty('gameId', str(game[GameView.COL_ID]))
        item.setProperty('plot', game[GameView.COL_description])
        item.setProperty('developer', game[GameView.COL_developer])
        item.setProperty('publisher', game[GameView.COL_publisher])
        item.setProperty('year', game[GameView.COL_year])
        item.setProperty('genre', game[GameView.COL_genre])
        item.setProperty('gameCmd', game[GameView.COL_gameCmd])
        item.setProperty('alternateGameCmd', game[GameView.COL_alternateGameCmd])
        item.setProperty('playcount', str(game[GameView.COL_launchCount]))
        item.setProperty('originalTitle', game[GameView.COL_originalTitle])
        item.setProperty('alternateTitle', game[GameView.COL_alternateTitle])

        item.setProperty('rating', str(game[GameView.COL_rating]))
        item.setProperty('media', str(game[GameView.COL_media]))
        item.setProperty('controllertype', str(game[GameView.COL_controllerType]))
        item.setProperty('region', str(game[GameView.COL_region]))
        item.setProperty('maxplayers', str(game[GameView.COL_maxPlayers]))
        item.setProperty('url', str(game[GameView.COL_url]))

        if game[GameView.COL_isFavorite] == 1:
            item.setProperty('isfavorite', '1')
        else:
            item.setProperty('isfavorite', '')

        item.setArt({
            'icon': helper.get_file_for_control_from_db(
                romCollection.imagePlacingMain.fileTypesForGameList, game),
            'thumb': helper.get_file_for_control_from_db(
                romCollection.imagePlacingMain.fileTypesForGameListSelected, game),

            IMAGE_CONTROL_BACKGROUND: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewBackground, game),
            IMAGE_CONTROL_GAMEINFO_BIG: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoBig, game),

            IMAGE_CONTROL_GAMEINFO_UPPERLEFT: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoUpperLeft, game),
            IMAGE_CONTROL_GAMEINFO_UPPERRIGHT: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoUpperRight, game),
            IMAGE_CONTROL_GAMEINFO_LOWERLEFT: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoLowerLeft, game),
            IMAGE_CONTROL_GAMEINFO_LOWERRIGHT: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoLowerRight, game),

            IMAGE_CONTROL_GAMEINFO_UPPER: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoUpper, game),
            IMAGE_CONTROL_GAMEINFO_LOWER: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoLower, game),
            IMAGE_CONTROL_GAMEINFO_LEFT: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoLeft, game),
            IMAGE_CONTROL_GAMEINFO_RIGHT: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainViewGameInfoRight, game),

            IMAGE_CONTROL_1: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainView1, game),
            IMAGE_CONTROL_2: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainView2, game),
            IMAGE_CONTROL_3: helper.get_file_for_control_from_db(
                romCollection.imagePlacingInfo.fileTypesForMainView3, game)
        })

        #add item to listcontrol
        listcontrol = self.getControlById(CONTROL_GAME_LIST)
        listcontrol.addItem(item)

        self.writeMsg("")

        log.info("End showGameList UIGameInfoView")