Esempio n. 1
0
def itunesImport(pathtoxml):
	if os.path.splitext(pathtoxml)[1] == '.xml':
		pl = XMLLibraryParser(pathtoxml)
		l = Library(pl.dictionary)
		lst = []
		for song in l.songs:
			lst.append(song.artist)
		rawlist = {}.fromkeys(lst).keys()
		artistlist = [f for f in rawlist if f != None]
	else:
		rawlist = os.listdir(pathtoxml)
		artistlist = [f for f in rawlist if f != '.DS_STORE']
	for name in artistlist:
		time.sleep(1)
		artistResults = ws.Query().getArtists(ws.ArtistFilter(string.replace(name, '&', '%38'), limit=1))		
		for result in artistResults:
			time.sleep(1)
			artistid = u.extractUuid(result.artist.id)
			inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), ratings=False, releaseGroups=False)
			artist = ws.Query().getArtistById(artistid, inc)
			conn=sqlite3.connect(database)
			c=conn.cursor()
			c.execute('CREATE TABLE IF NOT EXISTS artists (ArtistID TEXT UNIQUE, ArtistName TEXT, ArtistSortName TEXT, DateAdded TEXT, Status TEXT)')
			c.execute('CREATE TABLE IF NOT EXISTS albums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, DateAdded TEXT, AlbumID TEXT UNIQUE, Status TEXT)')
			c.execute('CREATE TABLE IF NOT EXISTS tracks (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, AlbumID TEXT, TrackTitle TEXT, TrackDuration TEXT, TrackID TEXT)')
			c.execute('SELECT ArtistID from artists')
			artistlist = c.fetchall()
			if any(artistid in x for x in artistlist):
				pass
			else:
				c.execute('INSERT INTO artists VALUES( ?, ?, ?, CURRENT_DATE, ?)', (artistid, artist.name, artist.sortName, 'Active'))
				for release in artist.getReleases():
					time.sleep(1)
					releaseid = u.extractUuid(release.id)
					inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
					results = ws.Query().getReleaseById(releaseid, inc)
					
					for event in results.releaseEvents:
						
						if event.country == 'US':
							
							c.execute('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', (artistid, results.artist.name, results.title, results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id), 'Skipped'))
							conn.commit()
							c.execute('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID="%s"' % u.extractUuid(results.id))
							
							latestrelease = c.fetchall()
							
							if latestrelease[0][0] > latestrelease[0][1]:
								c.execute('UPDATE albums SET Status = "Wanted" WHERE AlbumID="%s"' % u.extractUuid(results.id))
							else:
								pass
							for track in results.tracks:
								c.execute('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', (artistid, results.artist.name, results.title, results.asin, u.extractUuid(results.id), track.title, track.duration, u.extractUuid(track.id)))
							conn.commit()

						else:
							pass
		
			c.close()
Esempio n. 2
0
File: tagger.py Progetto: mafr/mbrip
	def tagTrack(self, todoEntry):
		import eyeD3

		fileName = todoEntry['mp3file'] + '.tmp'
		release = todoEntry['release']
		track = todoEntry['track']

		tag = eyeD3.Tag()
		tag.link(str(fileName)) # eyeD3 doesn't like unicode strings
		tag.header.setVersion(eyeD3.ID3_V2)

		if track.artist is None:
			tag.setArtist(release.artist.name)
		else:
			tag.setArtist(track.artist.name)

		tag.setTitle(track.title)
		tag.setAlbum(release.title)
		tag.setTrackNum( (todoEntry['num'], len(release.tracks)) )

		types = (release.TYPE_OFFICIAL, release.TYPE_PROMOTION,
			release.TYPE_BOOTLEG)

		for t in release.types:
			value = extractFragment(t, NS_MMD_1)
			if t in types:
				tag.addUserTextFrame(ALBUM_TYPE, value)
			else:
				tag.addUserTextFrame(ALBUM_STATUS, value)

		tag.addUserTextFrame(ALBUM_ARTIST, release.artist.name)
		tag.addUserTextFrame(ALBUM_ARTIST_SORTNAME,
			release.artist.sortName)

		tag.addUniqueFileID(FILE_ID, str(extractUuid(track.id)))

		if track.artist is None:
			tag.addUserTextFrame(ARTIST_ID,
				extractUuid(release.artist.id))
		else:
			tag.addUserTextFrame(ARTIST_ID, extractUuid(track.artist.id))

		tag.addUserTextFrame(ALBUM_ID, extractUuid(release.id))
		tag.addUserTextFrame(ALBUM_ARTIST_ID,
			extractUuid(release.artist.id))

		event = release.getEarliestReleaseEvent()
		if event is not None:
			tag.addUserTextFrame(RELEASE_COUNTRY, event.country)
			tag.setDate(event.date[0:4])

		tag.update(eyeD3.ID3_V2_3)
Esempio n. 3
0
def importartist(artistlist):
	for name in artistlist:
		logger.log(u"Querying MusicBrainz for: "+name)
		time.sleep(1)
		artistResults = ws.Query().getArtists(ws.ArtistFilter(string.replace(name, '&', '%38'), limit=1))		
		for result in artistResults:
			if result.artist.name == 'Various Artists':
				logger.log(u"Top result is Various Artists. Skipping.", logger.WARNING)
			else:
				logger.log(u"Found best match: "+result.artist.name+". Gathering album information...")
				time.sleep(1)
				artistid = u.extractUuid(result.artist.id)
				inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), ratings=False, releaseGroups=False)
				artist = ws.Query().getArtistById(artistid, inc)
				conn=sqlite3.connect(database)
				c=conn.cursor()
				c.execute('SELECT ArtistID from artists')
				artistlist = c.fetchall()
				if any(artistid in x for x in artistlist):
					logger.log(result.artist.name + u" is already in the database, skipping")
				else:
					c.execute('INSERT INTO artists VALUES( ?, ?, ?, CURRENT_DATE, ?)', (artistid, artist.name, artist.sortName, 'Active'))
					for release in artist.getReleases():
						time.sleep(1)
						releaseid = u.extractUuid(release.id)
						inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
						results = ws.Query().getReleaseById(releaseid, inc)
						
						for event in results.releaseEvents:
							
							if event.country == 'US':
								
								c.execute('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', (artistid, results.artist.name, results.title, results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id), 'Skipped'))
								conn.commit()
								c.execute('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID="%s"' % u.extractUuid(results.id))
								
								latestrelease = c.fetchall()
								
								if latestrelease[0][0] > latestrelease[0][1]:
									c.execute('UPDATE albums SET Status = "Wanted" WHERE AlbumID="%s"' % u.extractUuid(results.id))
								else:
									pass
								for track in results.tracks:
									c.execute('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', (artistid, results.artist.name, results.title, results.asin, u.extractUuid(results.id), track.title, track.duration, u.extractUuid(track.id)))
								conn.commit()
	
							else:
								logger.log(results.title + u" is not a US release. Skipping for now")
			
				c.close()
Esempio n. 4
0
	def addArtist(self, artistid):
		inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), ratings=False, releaseGroups=False)
		artist = ws.Query().getArtistById(artistid, inc)
		conn=sqlite3.connect(database)
		c=conn.cursor()
		c.execute('CREATE TABLE IF NOT EXISTS artists (ArtistID TEXT UNIQUE, ArtistName TEXT, ArtistSortName TEXT, DateAdded TEXT, Status TEXT)')
		c.execute('CREATE TABLE IF NOT EXISTS albums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, DateAdded TEXT, AlbumID TEXT UNIQUE, Status TEXT)')
		c.execute('CREATE TABLE IF NOT EXISTS tracks (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, AlbumID TEXT, TrackTitle TEXT, TrackDuration, TrackID TEXT)')
		c.execute('SELECT ArtistID from artists')
		artistlist = c.fetchall()
		if any(artistid in x for x in artistlist):
			page = [templates._header]
			page.append('''%s has already been added. Go <a href="/">back</a>.''' % artist.name)
			logger.log(artist.name + u" is already in the database!", logger.WARNING)
			c.close()
			return page
		
		else:
			logger.log(u"Adding " + artist.name + " to the database.")
			c.execute('INSERT INTO artists VALUES( ?, ?, ?, CURRENT_DATE, ?)', (artistid, artist.name, artist.sortName, 'Active'))
			
			for release in artist.getReleases():
				releaseid = u.extractUuid(release.id)
				inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
				results = ws.Query().getReleaseById(releaseid, inc)
				time.sleep(0.6)
				
				for event in results.releaseEvents:
					if event.country == 'US':
						logger.log(u"Now adding album: " + results.title+ " to the database")
						c.execute('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', (artistid, results.artist.name, results.title, results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id), 'Skipped'))
						c.execute('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID="%s"' % u.extractUuid(results.id))
						latestrelease = c.fetchall()
						
						if latestrelease[0][0] > latestrelease[0][1]:
							logger.log(results.title + u" is an upcoming album. Setting its status to 'Wanted'...")
							c.execute('UPDATE albums SET Status = "Wanted" WHERE AlbumID="%s"' % u.extractUuid(results.id))
						else:
							pass
						
						for track in results.tracks:
							c.execute('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', (artistid, results.artist.name, results.title, results.asin, u.extractUuid(results.id), track.title, track.duration, u.extractUuid(track.id)))
					else:
						logger.log(results.title + " is not a US release. Skipping it for now", logger.DEBUG)
			
			conn.commit()
			c.close()
			raise cherrypy.HTTPRedirect("/")
Esempio n. 5
0
	def getUserRating(self, entityUri):
		"""Return the rating a user has applied to an entity.

		The given parameter has to be a fully qualified MusicBrainz
		ID, as returned by other library functions.
		
		Note that this method only works if a valid user name and
		password have been set. Only the rating the authenticated user
		applied to the entity will be returned. If username and/or
		password are incorrect, an AuthenticationError is raised.
		
		This method will return a L{Rating <musicbrainz2.model.Rating>}
		object.
		
		@param entityUri: a string containing an absolute MB ID
		
		@raise ValueError: invalid entityUri
  		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or entity
		@raise AuthenticationError: invalid user name and/or password
		"""
		entity = mbutils.extractEntityType(entityUri)
		uuid = mbutils.extractUuid(entityUri, entity)
		params = { 'entity': entity, 'id': uuid }
		
		stream = self._ws.get('rating', '', filter=params)
		try:
			parser = MbXmlParser()
			result = parser.parse(stream)
		except ParseError, e:
			raise ResponseError(str(e), e)
Esempio n. 6
0
	def submitUserTags(self, entityUri, tags):
		"""Submit folksonomy tags for an entity.

		Note that all previously existing tags from the authenticated
		user are replaced with the ones given to this method. Other
		users' tags are not affected.
		
		@param entityUri: a string containing an absolute MB ID
		@param tags: A list of either L{Tag <musicbrainz2.model.Tag>} objects
		             or strings

		@raise ValueError: invalid entityUri
		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID, entity or tags
		@raise AuthenticationError: invalid user name and/or password
		"""
		entity = mbutils.extractEntityType(entityUri)
		uuid = mbutils.extractUuid(entityUri, entity)
		params = (
			('type', 'xml'),
			('entity', entity),
			('id', uuid),
			('tags', ','.join([unicode(tag).encode('utf-8') for tag in tags]))
		)

		encodedStr = urllib.urlencode(params)

		self._ws.post('tag', '', encodedStr)
Esempio n. 7
0
	def submitUserRating(self, entityUri, rating):
		"""Submit rating for an entity.

		Note that all previously existing rating from the authenticated
		user are replaced with the one given to this method. Other
		users' ratings are not affected.
		
		@param entityUri: a string containing an absolute MB ID
		@param rating: A L{Rating <musicbrainz2.model.Rating>} object
		             or integer

		@raise ValueError: invalid entityUri
		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID, entity or tags
		@raise AuthenticationError: invalid user name and/or password
		"""
		entity = mbutils.extractEntityType(entityUri)
		uuid = mbutils.extractUuid(entityUri, entity)
		params = (
			('type', 'xml'),
			('entity', entity),
			('id', uuid),
			('rating', unicode(rating).encode('utf-8'))
		)

		encodedStr = urllib.urlencode(params)

		self._ws.post('rating', '', encodedStr)
Esempio n. 8
0
	def submitPuids(self, tracks2puids):
		"""Submit track to PUID mappings.

		The C{tracks2puids} parameter has to be a dictionary, with the
		keys being MusicBrainz track IDs (either as absolute URIs or
		in their 36 character ASCII representation) and the values
		being PUIDs (ASCII, 36 characters).

		Note that this method only works if a valid user name and
		password have been set. See the example in L{Query} on how
		to supply authentication data.

		@param tracks2puids: a dictionary mapping track IDs to PUIDs

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid track or PUIDs
		@raise AuthenticationError: invalid user name and/or password
		"""
		assert self._clientId is not None, 'Please supply a client ID'
		params = [ ]
		params.append( ('client', self._clientId.encode('utf-8')) )

		for (trackId, puid) in tracks2puids.iteritems():
			trackId = mbutils.extractUuid(trackId, 'track')
			params.append( ('puid', trackId + ' ' + puid) )

		encodedStr = urllib.urlencode(params, True)

		self._ws.post('track', '', encodedStr)
Esempio n. 9
0
	def _writeTrack(self, xml, track, score=None):
		if track is None:
			return

		xml.start('track', {
			'id': mbutils.extractUuid(track.getId()),
			'ext:score': score,
		})
		
		xml.elem('title', track.getTitle())
		xml.elem('duration', str(track.getDuration()))
		self._writeArtist(xml, track.getArtist())

		if len(track.getReleases()) > 0:
			# TODO: offset + count
			xml.start('release-list')
			for release in track.getReleases():
				self._writeRelease(xml, release)
			xml.end()

		if len(track.getPuids()) > 0:
			xml.start('puid-list')
			for puid in track.getPuids():
				xml.elem('puid', None, { 'id': puid })
			xml.end()

		self._writeRelationList(xml, track)
		# TODO: extensions

		xml.end()
Esempio n. 10
0
	def submitISRCs(self, tracks2isrcs):
		"""Submit track to ISRC mappings.

		The C{tracks2isrcs} parameter has to be a dictionary, with the
		keys being MusicBrainz track IDs (either as absolute URIs or
		in their 36 character ASCII representation) and the values
		being ISRCs (ASCII, 12 characters).

		Note that this method only works if a valid user name and
		password have been set. See the example in L{Query} on how
		to supply authentication data.

		@param tracks2isrcs: a dictionary mapping track IDs to ISRCs

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid track or ISRCs
		@raise AuthenticationError: invalid user name and/or password
		"""
		params = [ ]

		for (trackId, isrc) in tracks2isrcs.iteritems():
			trackId = mbutils.extractUuid(trackId, 'track')
			params.append( ('isrc', trackId + ' ' + isrc) )

		encodedStr = urllib.urlencode(params, True)

		self._ws.post('track', '', encodedStr)
Esempio n. 11
0
def artist_info(artist_name):
    info = dict(members=None, wikipedia=None, homepage=None)
    # short names are bad
    if len(artist_name) < 3:
        return info
    q = ws.Query()
    filt = ws.ArtistFilter(artist_name, limit=10)
    results = q.getArtists(filt)
    results = [x for x in results if x.score >= 99]
    # too many high scoring hits, can't disambiguate automatically
    if len(results) != 1:
        return info
    artist = results[0].artist
    uuid = mbutils.extractUuid(artist.id)
    inc = ws.ArtistIncludes(artistRelations=True, urlRelations=True)
    artist = q.getArtistById(uuid, inc)
    urls = artist.getRelationTargets(m.Relation.TO_URL, m.NS_REL_1+'Wikipedia')
    if len(urls):
        info['wikipedia'] = urllib.unquote(urls[0])
    urls = artist.getRelationTargets(m.Relation.TO_URL, m.NS_REL_1+'OfficialHomepage')
    if len(urls):
        info['homepage'] = urllib.unquote(urls[0])
    if artist.type == m.Artist.TYPE_GROUP:
        members = artist.getRelations(m.Relation.TO_ARTIST, m.NS_REL_1+'MemberOfBand')
        addl_uri = m.NS_REL_1+'Additional'
        coreMembers = [r for r in members if addl_uri not in r.attributes]
        info['members'] = ", ".join([x.target.name for x in coreMembers if not x.endDate])
        if info['members'] == "":
            info['members'] = None
    return info
Esempio n. 12
0
	def findArtist(self, name):
	
		page = [templates._header]
		if len(name) == 0 or name == 'Add an artist':
			raise cherrypy.HTTPRedirect("home")
		else:
			artistResults = ws.Query().getArtists(ws.ArtistFilter(string.replace(name, '&', '%38'), limit=8))
			if len(artistResults) == 0:
				logger.log(u"No results found for " + name)
				page.append('''No results!<a class="blue" href="home">Go back</a>''')
				return page
			elif len(artistResults) > 1:
				page.append('''Search returned multiple artists. Click the artist you want to add:<br /><br />''')
				for result in artistResults:
					artist = result.artist
					detail = artist.getDisambiguation()
					if detail:
						disambiguation = '(%s)' % detail
					else:
						disambiguation = ''
					page.append('''<a href="addArtist?artistid=%s">%s %s</a> (<a class="externalred" href="artistInfo?artistid=%s">more info</a>)<br />''' % (u.extractUuid(artist.id), artist.name, disambiguation, u.extractUuid(artist.id)))
				return page
			else:
				for result in artistResults:
					artist = result.artist
					logger.log(u"Found one artist matching your search term: " + artist.name +" ("+ artist.id+")")			
					raise cherrypy.HTTPRedirect("addArtist?artistid=%s" % u.extractUuid(artist.id))
Esempio n. 13
0
	def _writeRelation(self, xml, rel, targetType):
		relAttrs = ' '.join([mbutils.extractFragment(a) 
				for a in rel.getAttributes()])

		if relAttrs == '':
			relAttrs = None

		attrs = {
			'type': mbutils.extractFragment(rel.getType()),
			'target': mbutils.extractUuid(rel.getTargetId()),
			'direction': rel.getDirection(),
			'begin': rel.getBeginDate(),
			'end': rel.getBeginDate(),
			'attributes': relAttrs,
		}

		if rel.getTarget() is None:
			xml.elem('relation', attrs)
		else:
			xml.start('relation', attrs)
			if targetType == NS_REL_1 + 'Artist':
				self._writeArtist(xml, rel.getTarget())
			elif targetType == NS_REL_1 + 'Release':
				self._writeRelease(xml, rel.getTarget())
			elif targetType == NS_REL_1 + 'Track':
				self._writeTrack(xml, rel.getTarget())
			xml.end()
Esempio n. 14
0
	def _writeLabel(self, xml, label, score=None):
		if label is None:
			return

		xml.start('label', {
			'id': mbutils.extractUuid(label.getId()),
			'type': mbutils.extractFragment(label.getType()),
			'ext:score': score,
		})

		xml.elem('name', label.getName())
		xml.elem('sort-name', label.getSortName())
		xml.elem('disambiguation', label.getDisambiguation())
		xml.elem('life-span', None, {
			'begin': label.getBeginDate(),
			'end': label.getEndDate(),
		})

		if len(label.getAliases()) > 0:
			xml.start('alias-list')
			for alias in label.getAliases():
				xml.elem('alias', alias.getValue(), {
					'type': alias.getType(),
					'script': alias.getScript(),
				})
			xml.end()

		# TODO: releases, artists

		self._writeRelationList(xml, label)
		# TODO: extensions

		xml.end()
Esempio n. 15
0
def uuid_from_soup(soup, type=None):
    uuid_link = soup.find('a', href=MB_PATTERN)
    if uuid_link:
        try:
            return extractUuid(uuid_link['href'], type)
        except ValueError:
            pass  # Not a valid UUID for some reason?
    return None
Esempio n. 16
0
def uuid_from_soup(soup, type = None):
	uuid_link = soup.find('a', href=MB_PATTERN)
	if uuid_link:
		try:
			return extractUuid(uuid_link['href'], type)
		except ValueError:
			pass # Not a valid UUID for some reason?
	return None
Esempio n. 17
0
	def artistInfo(self, artistid):
		page = [templates._header]
		inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
		artist = ws.Query().getArtistById(artistid, inc)
		page.append('''Artist Name: %s </br> ''' % artist.name)
		page.append('''Unique ID: %s </br></br>Albums:<br />''' % u.extractUuid(artist.id))
		for rg in artist.getReleaseGroups():
			page.append('''%s <br />''' % rg.title)
		return page
Esempio n. 18
0
	def __init__(self, title=None, discId=None, releaseTypes=None,
			artistName=None, artistId=None, limit=None,
			offset=None, query=None, trackCount=None):
		"""Constructor.

		If C{discId} or C{artistId} are set, only releases matching
		those IDs are returned. The C{releaseTypes} parameter allows
		to limit the types of the releases returned. You can set it to
		C{(Release.TYPE_ALBUM, Release.TYPE_OFFICIAL)}, for example,
		to only get officially released albums. Note that those values
		are connected using the I{AND} operator. MusicBrainz' support
		is currently very limited, so C{Release.TYPE_LIVE} and
		C{Release.TYPE_COMPILATION} exclude each other (see U{the
		documentation on release attributes
		<http://wiki.musicbrainz.org/AlbumAttribute>} for more
		information and all valid values).

		If both the C{artistName} and the C{artistId} parameter are
		given, the server will ignore C{artistName}.

		The C{query} parameter may contain a query in U{Lucene syntax
		<http://lucene.apache.org/java/docs/queryparsersyntax.html>}.
		Note that C{query} may not be used together with the other
		parameters except for C{limit} and C{offset}.

		@param title: a unicode string containing the release's title
		@param discId: a unicode string containing the DiscID
		@param releaseTypes: a sequence of release type URIs
		@param artistName: a unicode string containing the artist's name
		@param artistId: a unicode string containing the artist's ID
		@param limit: the maximum number of releases to return
		@param offset: start results at this zero-based offset
		@param query: a string containing a query in Lucene syntax
		@param trackCount: the number of tracks in the release

		@see: the constants in L{musicbrainz2.model.Release}
		"""
		if releaseTypes is None or len(releaseTypes) == 0:
			releaseTypesStr = None
		else:
			tmp = [ mbutils.extractFragment(x) for x in releaseTypes ]
			releaseTypesStr = ' '.join(tmp)

		self._params = [
			('title', title),
			('discid', discId),
			('releasetypes', releaseTypesStr),
			('artist', artistName),
			('artistid', mbutils.extractUuid(artistId)),
			('limit', limit),
			('offset', offset),
			('query', query),
			('count', trackCount),
		]

		if not _paramsValid(self._params):
			raise ValueError('invalid combination of parameters')
Esempio n. 19
0
	def testExtractUuid(self):
		artistPrefix = 'http://musicbrainz.org/artist/'
		uuid = 'c0b2500e-0cef-4130-869d-732b23ed9df5'
		mbid = artistPrefix + uuid

		self.assertEquals(u.extractUuid(None), None)
		self.assertEquals(u.extractUuid(uuid), uuid)
		self.assertEquals(u.extractUuid(mbid), uuid)
		self.assertEquals(u.extractUuid(mbid, 'artist'), uuid)

		# not correct, but not enough data to catch this
		self.assertEquals(u.extractUuid(uuid, 'release'), uuid)

		self.assertRaises(ValueError, u.extractUuid, mbid, 'release')
		self.assertRaises(ValueError, u.extractUuid, mbid, 'track')
		self.assertRaises(ValueError, u.extractUuid, mbid+'/xy', 'artist')

		invalidId = 'http://example.invalid/' + uuid
		self.assertRaises(ValueError, u.extractUuid, invalidId)
Esempio n. 20
0
	def __init__(self, title=None, artistName=None, artistId=None,
			releaseTitle=None, releaseId=None,
			duration=None, puid=None, limit=None, offset=None,
			query=None):
		"""Constructor.

		If C{artistId}, C{releaseId} or C{puid} are set, only tracks
		matching those IDs are returned.

		The server will ignore C{artistName} and C{releaseTitle} if
		C{artistId} or ${releaseId} are set respectively.

		The C{query} parameter may contain a query in U{Lucene syntax
		<http://lucene.apache.org/java/docs/queryparsersyntax.html>}.
		Note that C{query} may not be used together with the other
		parameters except for C{limit} and C{offset}.

		@param title: a unicode string containing the track's title
		@param artistName: a unicode string containing the artist's name
		@param artistId: a string containing the artist's ID
		@param releaseTitle: a unicode string containing the release's title
		@param releaseId: a string containing the release's title
		@param duration: the track's length in milliseconds
		@param puid: a string containing a PUID
		@param limit: the maximum number of releases to return
		@param offset: start results at this zero-based offset
		@param query: a string containing a query in Lucene syntax
		"""
		self._params = [
			('title', title),
			('artist', artistName),
			('artistid', mbutils.extractUuid(artistId)),
			('release', releaseTitle),
			('releaseid', mbutils.extractUuid(releaseId)),
			('duration', duration),
			('puid', puid),
			('limit', limit),
			('offset', offset),
			('query', query),
		]

		if not _paramsValid(self._params):
			raise ValueError('invalid combination of parameters')
Esempio n. 21
0
	def removeFromUserCollection(self, releases):
		"""Remove releases from a user's collection.

		The releases parameter must be a list. It can contain either L{Release}
		objects or a string representing a MusicBrainz release ID (either as
		absolute URIs or in their 36 character ASCII representation).

		Removing a release that is not in the collection has no effect.

		@param releases: a list of releases to remove from the user collection

		@raise ConnectionError: couldn't connect to server
		@raise AuthenticationError: invalid user name and/or password
		"""
		rels = []
		for release in releases:
			if isinstance(release, Release):
				rels.append(mbutils.extractUuid(release.id))
			else:
				rels.append(mbutils.extractUuid(release))
		encodedStr = urllib.urlencode({'remove': ",".join(rels)}, True)
		self._ws.post('collection', '', encodedStr)
Esempio n. 22
0
 def __update_result(self, release):
     """Callback for release detail download from result combo."""
     num_results = len(self._resultlist)
     text = ngettext("Found %d result.", "Found %d results.", num_results)
     self.result_label.set_text(text % num_results)
     # issue 973: search can return invalid (or removed) ReleaseIDs
     if release is None:
         return
     self._releasecache.setdefault(extractUuid(release.id), release)
     self.result_treeview.update_remote_album(release.tracks)
     self.current_release = release
     self.release_combo.update(release)
     save_button = self.get_widget_for_response(Gtk.ResponseType.ACCEPT)
     save_button.set_sensitive(True)
Esempio n. 23
0
 def __update_result(self, release):
     """Callback for release detail download from result combo."""
     num_results = len(self._resultlist)
     text = ngettext("Found %d result.", "Found %d results.", num_results)
     self.result_label.set_text(text % num_results)
     # issue 973: search can return invalid (or removed) ReleaseIDs
     if release is None:
         return
     self._releasecache.setdefault(extractUuid(release.id), release)
     self.result_treeview.update_remote_album(release.tracks)
     self.current_release = release
     self.release_combo.update(release)
     save_button = self.get_widget_for_response(Gtk.ResponseType.ACCEPT)
     save_button.set_sensitive(True)
Esempio n. 24
0
	def _writeRelease(self, xml, release, score=None):
		if release is None:
			return

		types = [mbutils.extractFragment(t) for t in release.getTypes()]
		typesStr = None
		if len(types) > 0:
			typesStr = ' '.join(types)

		xml.start('release', {
			'id': mbutils.extractUuid(release.getId()),
			'type': typesStr,
			'ext:score': score,
		})

		xml.elem('title', release.getTitle())
		xml.elem('text-representation', None, {
			'language': release.getTextLanguage(),
			'script': release.getTextScript()
		})
		xml.elem('asin', release.getAsin())

		self._writeArtist(xml, release.getArtist())
		self._writeReleaseGroup(xml, release.getReleaseGroup())

		if len(release.getReleaseEvents()) > 0:
			xml.start('release-event-list')
			for event in release.getReleaseEvents():
				self._writeReleaseEvent(xml, event)
			xml.end()

		if len(release.getDiscs()) > 0:
			xml.start('disc-list')
			for disc in release.getDiscs():
				xml.elem('disc', None, { 'id': disc.getId() })
			xml.end()

		if len(release.getTracks()) > 0:
			# TODO: count attribute
			xml.start('track-list', {
				'offset': release.getTracksOffset()
			})
			for track in release.getTracks():
				self._writeTrack(xml, track)
			xml.end()
		
		self._writeRelationList(xml, release)
		# TODO: extensions

		xml.end()
Esempio n. 25
0
File: search.py Progetto: lidel/mmda
def get_basic_cached_search_result(query_type, query_string):
    """
    Make sure proper CachedSearchResult is present and return its id.

    Method performs local, then optional remote (MusicBrainz) lookup of query result

    @param query_type: a string containing query type
    @param query_string: a string containing query

    @return: a string containing SHA1 hash of a query string (the ID of a CachedSearchResult document)
    """
    query_id        = hashlib.sha1((query_type+query_string).encode('utf-8')).hexdigest()
    search_result   = CachedSearchResult.get_or_create(query_id)
    search_result.query_string  = query_string
    search_result.query_type    = query_type
    if 'mb' not in search_result.cache_state: #TODO: add 14day window check

        try:
            t = mmda_logger('mb','request','search for',query_string)

            if query_type == 'artist':
                filter  = ws.ArtistFilter(name=query_string,limit=RESULTS_LIMIT)
                results = mb_query.getArtists(filter) #TODO: add try, or maybe better in 'create_search' as a global wrapper
                search_result.results = [ {'name':r.artist.name, 'mbid':extractUuid(r.artist.id), 'score':r.score, 'note':r.artist.disambiguation } for r in results ]

            elif query_type == 'release':
                filter  = ws.ReleaseFilter(title=query_string,limit=RESULTS_LIMIT)
                results = mb_query.getReleases(filter) #TODO: add try, or maybe better in 'create_search' as a global wrapper
                search_result.results = [ {'artist':r.release.artist.name, 'title':r.release.title, 'mbid':extractUuid(r.release.id), 'artist_mbid':extractUuid(r.release.artist.id), 'score':r.score, 'tracks_count':r.release.tracksCount, 'year':r.release.getEarliestReleaseEvent().getDate() if r.release.getEarliestReleaseEvent() else None} for r in results ]

            elif query_type == 'tag':
                # TODO: refactor to other packages
                import pylast
                lastfm = pylast.get_lastfm_network(api_key = settings.LASTFM_API_KEY)
                lastfm_similar_tags = lastfm.search_for_tag(query_string).get_next_page()
                search_result.results = [ tag.name for tag in lastfm_similar_tags ]

        except Exception, e:
            # TODO: hard error here
            mmda_logger('search','ERROR',e)
            raise e
        else:
            mmda_logger('mb','result','results',len(search_result.results),t)
            search_result.cache_state['mb'] = [1,datetime.utcnow()]
            search_result.save()
Esempio n. 26
0
	def _writeArtist(self, xml, artist, score=None):
		if artist is None:
			return

		xml.start('artist', {
			'id': mbutils.extractUuid(artist.getId()),
			'type': mbutils.extractFragment(artist.getType()),
			'ext:score': score,
		})

		xml.elem('name', artist.getName())
		xml.elem('sort-name', artist.getSortName())
		xml.elem('disambiguation', artist.getDisambiguation())
		xml.elem('life-span', None, {
			'begin': artist.getBeginDate(),
			'end': artist.getEndDate(),
		})

		if len(artist.getAliases()) > 0:
			xml.start('alias-list')
			for alias in artist.getAliases():
				xml.elem('alias', alias.getValue(), {
					'type': alias.getType(),
					'script': alias.getScript(),
				})
			xml.end()

		if len(artist.getReleases()) > 0:
			xml.start('release-list')
			for release in artist.getReleases():
				self._writeRelease(xml, release)
			xml.end()

		if len(artist.getReleaseGroups()) > 0:
			xml.start('release-group-list')
			for releaseGroup in artist.getReleaseGroups():
				self._writeReleaseGroup(xml, releaseGroup)
			xml.end()

		self._writeRelationList(xml, artist)
		# TODO: extensions

		xml.end()
Esempio n. 27
0
	def _writeReleaseGroup(self, xml, rg, score = None):
		if rg is None:
			return

		xml.start('release-group', {
			'id': mbutils.extractUuid(rg.getId()),
			'type': mbutils.extractFragment(rg.getType()),
			'ext:score': score,
		})

		xml.elem('title', rg.getTitle())
		self._writeArtist(xml, rg.getArtist())

		if len(rg.getReleases()) > 0:
			xml.start('release-list')
			for rel in rg.getReleases():
				self._writeRelease(xml, rel)
			xml.end()

		xml.end()
Esempio n. 28
0
	def findArtist(self, name):
	
		page = [templates._header]
		if len(name) == 0 or name == 'Add an artist':
			raise cherrypy.HTTPRedirect("/")
		else:
			artistResults = ws.Query().getArtists(ws.ArtistFilter(string.replace(name, '&', '%38'), limit=8))
			if len(artistResults) == 0:
				page.append('''No results!<a class="blue" href="/">Go back</a>''')
				
			elif len(artistResults) > 1:
				page.append('''Search returned multiple artists. Click the artist you want to add:<br /><br />''')
				for result in artistResults:
					artist = result.artist
					page.append('''<a href="/addArtist?artistid=%s">%s</a> (<a class="externalred" href="/artistInfo?artistid=%s">more info</a>)<br />''' % (u.extractUuid(artist.id), artist.name, u.extractUuid(artist.id)))
				return page
			else:
				for result in artistResults:
					artist = result.artist
					raise cherrypy.HTTPRedirect("/addArtist?artistid=%s" % u.extractUuid(artist.id))
Esempio n. 29
0
	def getLabelById(self, id_, include=None):
		"""Returns a L{model.Label}
		
		If no label with that ID can be found, or there is a server problem,
		an exception is raised.
		
		@param id_: a string containing the label's ID.

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or include tags
		@raise ResourceNotFoundError: release doesn't exist
		@raise ResponseError: server returned invalid data
		"""
		uuid = mbutils.extractUuid(id_, 'label')
		result = self._getFromWebService('label', uuid, include)
		label = result.getLabel()
		if label is not None:
			return label
		else:
			raise ResponseError("server didn't return a label")
Esempio n. 30
0
def get_basic_release(mbid):
    """
    Make sure release and its dependencies are present and contain required data.

    @param mbid: a string containing a MusicBrainz ID of an artist

    @return:  a CachedReleaseGroup object containing required minimal data set
    """
    release_group   = CachedReleaseGroup.view('artists/releases',include_docs=True, key=mbid).one()
    if not release_group:
        # TODO: optimize? its just one additional request on rare ocassions tho..
        try:
            t = mmda_logger('mb','request','artist mbid of release',mbid)
            mb_release  = mb_query.getReleaseById(mbid, MB_RELEASE_ARTIST)
            artist_mbid = extractUuid(mb_release.artist.id)
            mmda_logger('mb','result','artist mbid',artist_mbid,t)
        except WebServiceError, e:
            # TODO: add error handling here
            mmda_logger('mb-release','ERROR',e)
            raise e
        else:
            get_basic_artist(artist_mbid)
            release_group = CachedReleaseGroup.view('artists/releases',include_docs=True, key=mbid).one()
Esempio n. 31
0
	def getArtistById(self, id_, include=None):
		"""Returns an artist.

		If no artist with that ID can be found, C{include} contains
		invalid tags or there's a server problem, an exception is
		raised.

		@param id_: a string containing the artist's ID
		@param include: an L{ArtistIncludes} object, or None

		@return: an L{Artist <musicbrainz2.model.Artist>} object, or None

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or include tags
		@raise ResourceNotFoundError: artist doesn't exist
		@raise ResponseError: server returned invalid data
		"""
		uuid = mbutils.extractUuid(id_, 'artist')
		result = self._getFromWebService('artist', uuid, include)
		artist = result.getArtist()
		if artist is not None:
			return artist
		else:
			raise ResponseError("server didn't return artist")
Esempio n. 32
0
	def getTrackById(self, id_, include=None):
		"""Returns a track.

		If no track with that ID can be found, C{include} contains
		invalid tags or there's a server problem, an exception is
		raised.

		@param id_: a string containing the track's ID
		@param include: a L{TrackIncludes} object, or None

		@return: a L{Track <musicbrainz2.model.Track>} object, or None

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or include tags
		@raise ResourceNotFoundError: track doesn't exist
		@raise ResponseError: server returned invalid data
		"""
		uuid = mbutils.extractUuid(id_, 'track')
		result = self._getFromWebService('track', uuid, include)
		track = result.getTrack()
		if track is not None:
			return track
		else:
			raise ResponseError("server didn't return track")
Esempio n. 33
0
    if tr:
        tp.releaseTrack(tr)
    
    if status == tunepimp.eError:
        print ("%s:\n\tError: %s\n" % (fileName, tp.getError())).encode('ascii', 'ignore')
        tp.remove(fileId)
                
    if addPUID:
        try:
		fileName, puid, trackId = addPUID
	        print ("%s:\n\t%s - %s" % (fileName, puid, trackId)).encode('ascii', 'ignore')
	        flt = TrackFilter(puid=puid)
	        result = q.getTracks(flt)
	        found = False
	        for res in result:
	            if extractUuid(res.track.id, 'track') == trackId:
	                found = True
	        if not found:
	            toSubmit[trackId] = puid
	            print
	        else:
	            print "\tAlready in MB, skipping.\n"
	except:
		print "EXCEPTION THROWN LOOKING UP TRACK ID"
        tp.remove(fileId)
    
    if len(toSubmit) >= batchSize or (tp.getNumFiles() == 0 and len(toSubmit) > 0):
        print "Submitting %d PUIDs to MusicBrainz...\n" % (len(toSubmit),)
        q.submitPuids(toSubmit) 
        toSubmit = {}
Esempio n. 34
0
def createDiscMetadata(release, cdid, numTracks, toc):
    discMeta = DiscMetadata()

    album = release.title
    albid = extractUuid(release.id, 'release')
    rel_artId = artId = extractUuid(release.artist.id, 'artist')

    rel_artist = artist = release.artist.name
    rel_artistSort = artistSort = release.artist.sortName
    discMeta.variousArtists = (release.artist.id == model.VARIOUS_ARTISTS_ID)

    releaseYear = None

    for event in release.releaseEvents:
        releaseDate = event.date
        releaseCountry = event.country

        thisReleaseYear = int(releaseDate[0:4])
        if releaseYear == None or thisReleaseYear < releaseYear:
            releaseYear = thisReleaseYear

    discNumMatches = DISC_NUM_REGEX.findall(album)
    if discNumMatches:
        discNum = int(discNumMatches[0][0])
    else:
        discNum = 1

    discMeta.title = album
    discMeta.artist = artist
    discMeta.artistSort = artistSort
    discMeta.mbDiscId = cdid
    discMeta.toc = toc
    discMeta.mbAlbumId = albid
    discMeta.mbArtistId = artId
    discMeta.discNumber = (discNum, discNum)
    discMeta.releaseDate = releaseYear

    lastArtist = None
    logging.info("\t%s / %s" % (artist, album))
    trackNum = 0
    for track in release.tracks:
        trackNum += 1
        name = track.title
        artist = track.artist.name if track.artist else rel_artist
        artistSort = track.artist.sortName if track.artist else rel_artistSort
        artId = extractUuid(track.artist.id,
                            'artist') if track.artist else rel_artId
        dura = track.duration if track.duration else 0
        trackURI = track.id
        trackId = extractUuid(trackURI, 'track')
        trackMeta = TrackMetadata()
        trackMeta.title = name
        trackMeta.artist = artist
        if lastArtist and artist <> lastArtist:
            discMeta.variousArtists = True
        lastArtist = artist
        trackMeta.artistSort = artistSort
        trackMeta.number = trackNum
        trackMeta.length = dura
        trackMeta.mbTrackId = trackId
        trackMeta.mbArtistId = artId
        discMeta.tracks.append(trackMeta)
        dura = "%d:%02d" % divmod(int(dura / 1000), 60)

        logging.info("\t%02d - %s - %s (%s)" % (trackNum, artist, name, dura))

    return discMeta
Esempio n. 35
0
    def __save(self, widget=None, response=None):
        """Writes values to Song objects."""
        self._qthread.stop()
        if response != Gtk.ResponseType.ACCEPT:
            self.destroy()
            return

        album = self.current_release
        shared = {}

        shared['album'] = album.title
        if config_get('split_disc', True):
            m = re.match(r'(.*) \(disc (.*?)\)$', album.title)
            if m:
                shared['album'] = m.group(1)
                disc = m.group(2).split(': ', 1)
                shared['discnumber'] = disc[0]
                if len(disc) > 1:
                    shared['discsubtitle'] = disc[1]

        relevt = self.release_combo.get_release_event()
        shared['date'] = relevt and relevt.getDate() or ''
        if shared['date'] and config_get('year_only', False):
            shared['date'] = shared['date'].split('-')[0]

        if config_get('labelid', True):
            if relevt and relevt.getCatalogNumber():
                shared['labelid'] = relevt.getCatalogNumber()

        if not album.isSingleArtistRelease():
            if (config_get('albumartist', True) and
                    extractUuid(album.artist.id) != VARIOUS_ARTISTS_ARTISTID):
                shared['albumartist'] = album.artist.name
                if config_get('artist_sort', False) and \
                        album.artist.sortName != album.artist.name:
                    shared['albumartistsort'] = album.artist.sortName

        if config_get('standard', True):
            shared['musicbrainz_albumartistid'] = extractUuid(album.artist.id)
            shared['musicbrainz_albumid'] = extractUuid(album.id)

        for idx, (song, ) in enumerate(self.result_treeview.model):
            if song is None:
                continue
            song.update(shared)
            if idx >= len(album.tracks):
                continue
            track = album.tracks[idx]
            song['title'] = track.title
            song['tracknumber'] = '%d/%d' % (
                idx + 1, max(len(album.tracks), len(
                    self.result_treeview.model)))
            if config_get('standard', True):
                song['musicbrainz_trackid'] = extractUuid(track.id)
            if album.isSingleArtistRelease() or not track.artist:
                song['artist'] = album.artist.name
                if config_get('artist_sort', False) and \
                        album.artist.sortName != album.artist.name:
                    song['artistsort'] = album.artist.sortName
            else:
                song['artist'] = track.artist.name
                if config_get('artist_sort', False) and \
                        track.artist.sortName != track.artist.name:
                    song['artistsort'] = track.artist.sortName
                if config_get('standard', True):
                    song['musicbrainz_artistid'] = extractUuid(track.artist.id)
            if config_get('split_feat', False):
                feats = re.findall(r' \(feat\. (.*?)\)', track.title)
                if feats:
                    feat = []
                    for value in feats:
                        values = value.split(', ')
                        if len(values) > 1:
                            values += values.pop().split(' & ')
                        feat += values
                    song['performer'] = '\n'.join(feat)
                    song['title'] = re.sub(r' \(feat\. .*?\)', '', track.title)

        self.destroy()