Exemple #1
0
 def read_disc(self):
     try:
         # calculate disc ID from disc
         if self._backend == "libdiscid" and not options.force_submit:
             disc = discid.read(self._device, features=["mcn", "isrc"])
         else:
             disc = discid.read(self._device)
         self._disc = disc
     except DiscError as err:
         print_error("DiscID calculation failed: %s" % err)
         sys.exit(1)
Exemple #2
0
 def read_disc(self):
     try:
         # calculate disc ID from disc
         if self._backend == "libdiscid" and not options.force_submit:
             disc = discid.read(self._device, features=["mcn", "isrc"])
         else:
             disc = discid.read(self._device)
         self._disc = disc
     except DiscError as err:
         print_error("DiscID calculation failed: %s" % err)
         sys.exit(1)
Exemple #3
0
 def get_disk_id(self):
     try:
         disc = discid.read(discid.get_default_device())
         self.id = disc.id
         print(self.id)
     except discid.DiscError:
         logger.warning("No Disc Found")
Exemple #4
0
 def cmd_toc(self, argv):
   ''' Usage: {cmd} [disc_id]
         Print a table of contents for the current disc.
   '''
   disc_id = None
   if argv:
     disc_id = argv.pop(0)
   if argv:
     raise GetoptError("extra arguments: %r" % (argv,))
   options = self.options
   MB = options.mbdb
   if disc_id is None:
     try:
       dev_info = discid.read(device=options.device)
     except discid.disc.DiscError as e:
       error("disc error: %s", e)
       return 1
     disc_id = dev_info.id
   with Pfx("discid %s", disc_id):
     disc = MB.discs[disc_id]
     print(disc.title)
     print(", ".join(disc.artist_names))
     for tracknum, recording in enumerate(disc.recordings(), 1):
       print(
           tracknum, recording.title, '--', ", ".join(recording.artist_names)
       )
   return 0
Exemple #5
0
def read_disc_info():
    while True:
        open_cd_door()
        input("Press enter to close the cd door\n\n")
        close_cd_door()

        print(f"Reading device: {discid.get_default_device()}\n")
        # reads from default device
        try:
            disc = discid.read()
        except discid.disc.DiscError as e:
            print(e)
            print("\n")
            read_disc_info()

        print(f"Disc cddb_id: {disc.freedb_id.upper()}")
        print(f"The number of tracks is {len(disc.tracks)}")
        print(f"The total duration in seconds is: {disc.seconds}")

        enter_shelfmark(disc)

        # https://www.tutorialspoint.com/How-to-get-Python-exception-text

        insert_disc(disc)

        if input("Press enter for the next disc or q to quit: ") == "q":
            break
Exemple #6
0
def read_disc_id():
    try:
        disc = discid.read(CD_DEVICE)
        logger.info('Disc identified as %s', disc.id)
        return disc.id
    except discid.disc.DiscError:
        logger.error('Could not identify disc.')
        return None
Exemple #7
0
def get_disc_id(disc):
    """
    Calculates the identifier of the disc

    return:
    identification object from discid package
    """
    return read(disc.devpath)
Exemple #8
0
def _read_disc():
    try:
        disc = discid.read()
    except discid.DiscError as exception:
        print("[error] %s" % exception)
        sys.exit(1)

    return disc
Exemple #9
0
 def read_cd(self):
     cd_drive = self.wizard.scan_drives_page.combo.currentText()
     self.status_label.setText('Reading CD drive ' + cd_drive)
     try:
         disc = discid.read(str(cd_drive))
     except discid.disc.DiscError:
         self.status_label.setText('Unable to read disc')
         return None
     return disc
Exemple #10
0
def complex_example():
    disc = discid.read("/dev/cdrom", ["mcn", "isrc"])
    print("id:\t%s" % disc.id)
    print("MCN:\t%s" % disc.mcn)
    print("length:\t%s" % _length_str(disc.seconds, disc.sectors))
    for track in disc.tracks:
        length = _length_str(track.seconds, track.sectors)
        print("{num:>2}: {offset:>6} {len}\tISRC: {isrc:13}".format(
            num=track.number, offset=track.offset, len=length, isrc=track.isrc))
 def test_read_put(self):
     # a read followed with a put, which should clear the features
     disc = discid.read(features=["mcn", "isrc"])  # read from default drive
     test_disc = test_discs[0]
     disc = discid.put(test_disc["first"], test_disc["last"],
                       test_disc["sectors"], test_disc["offsets"])
     self.assertTrue(disc.mcn is None)
     for track in disc.tracks:
         self.assertTrue(track.isrc is None)
Exemple #12
0
 def test_read_put(self):
     # a read followed with a put, which should clear the features
     disc = discid.read(features=["mcn", "isrc"]) # read from default drive
     test_disc = test_discs[0]
     disc = discid.put(test_disc["first"], test_disc["last"],
                       test_disc["sectors"], test_disc["offsets"])
     self.assertTrue(disc.mcn is None)
     for track in disc.tracks:
         self.assertTrue(track.isrc is None)
Exemple #13
0
def musicbrainz_lookup():
    """
    Scans a folder for music files with metadata. Collects metadata information
    from all music files and assumes they belong to the same album. Produces a
    simple description of the album that it loads into a KLAP form.
    """
    
    # Help the user
    if len(sys.argv) != 2:
        print "Usage: {} Drive".format(sys.argv[0])
        sys.exit(1)

    tracks = []
    musicbrainzngs.set_useragent("KLAP-CDDBAdd", "0.3", "*****@*****.**")

    disc = discid.read(sys.argv[1])
    try:
        result = musicbrainzngs.get_releases_by_discid(disc.id,
                                                       includes=["artists","recordings","release-groups"])
    except musicbrainzngs.ResponseError:
        print "Couldn't find that disc in the online database, sorry!"
        return None
    else:
        print "Found disc {}".format(disc.id)
        subd = None
        if result.get("disc"):
            if len(result['disc']['release-list']) == 0:
                print "Found the disc id, but it didn't have any releases..."
                return None
            print "Found a musicbrainz release id"
            open_url(KLAP_MB_URL.format(result['disc']['release-list'][0]['id']))
            sys.exit()
        elif result.get("cdstub"):
            artist = normalize(result["cdstub"]["artist"])
            album = normalize(result["cdstub"]["title"])
            subd = result["cdstub"]
            c = 1
            for track in subd['track-list']:
                title = normalize(track['title'])
                tartist = normalize(track['artist'])
                d = {'number': c,
                     'title': title}
                if tartist != artist:
                    d['artist'] = tartist
                tracks.append(d)
                c += 1
    
    # Make sure the info is safe for KLAP
    artist = artist
    album = album
    
    # Make the dict
    obj = {'artist': artist,
           'album': album,
           'tracks': tracks,
          }
    return obj
Exemple #14
0
 def _fetch_disc_info(self):
     disc = discid.read(self._cdplayer.device_name, ['read', 'msn', 'isrc'])
     print("id: %s" % disc.id)
     print("mcn: %s" % disc.mcn)
     print("submission url:\n%s" % disc.submission_url)
     for track in disc.tracks:
         print("{:>2}: {:>4} {:13}".format(track.number, track.seconds,
                                           track.isrc))
     return disc
def com_discid_default_device():
    """
    Determine default rom drive to use and grab the discid from inserted disc
    """
    discid.get_default_device()
    disc = discid.read()
    common_global.es_inst.com_elastic_index('info', {"id": disc.id,
                                                     "submission url": disc.submission_url})
    return discid
    def test_read_simple(self):
        disc = discid.read()  # read from default drive
        self.assertEqual(len(disc.id), 28, "Invalid Disc ID")
        self.assertEqual(len(disc.freedb_id), 8, "Invalid FreeDB Disc ID")
        self.assertTrue(disc.submission_url, "Invalid submission url")
        self.assertTrue(disc.toc_string, "Invalid toc string")
        self.assertEqual(disc.last_track_num, len(disc.tracks),
                         "Wrong amount of tracks")
        self.assertEqual(disc.sectors,
                         disc.tracks[-1].offset + disc.tracks[-1].sectors)

        for track in disc.tracks:
            self.assertTrue(track.offset <= disc.sectors, "Invalid offset")
            if track.number > 1:
                previous_offset = disc.tracks[track.number - 2].offset
                self.assertTrue(track.offset >= previous_offset,
                                "Invalid offset series")

        # additional features should be unset, not empty
        self.assertTrue(disc.mcn is None)
        for track in disc.tracks:
            self.assertTrue(track.isrc is None)

        # check idempotence (use output again as input to put)
        disc_id = disc.id
        freedb_id = disc.freedb_id
        submission_url = disc.submission_url
        toc_string = disc.toc_string
        first = disc.first_track_num
        last = disc.last_track_num
        sectors = disc.sectors
        track_sectors = [track.sectors for track in disc.tracks]
        track_offsets = [track.offset for track in disc.tracks]

        disc = discid.put(first, last, sectors, track_offsets)
        self.assertEqual(disc.id, disc_id, "different id after put")
        self.assertEqual(disc.freedb_id, freedb_id,
                         "different freedb id after put")
        self.assertEqual(disc.submission_url, submission_url,
                         "different submission_url after put")
        self.assertEqual(disc.toc_string, toc_string,
                         "different toc_string after put")
        self.assertEqual(disc.first_track_num, first,
                         "different first track after put")
        self.assertEqual(disc.last_track_num, last,
                         "different last track after put")
        self.assertEqual(disc.sectors, sectors,
                         "different sector count after put")
        new_offsets = [track.offset for track in disc.tracks]
        self.assertEqual(new_offsets, track_offsets,
                         "different offsets after put")
        new_sectors = [track.sectors for track in disc.tracks]
        self.assertEqual(new_sectors, track_sectors,
                         "different lengths after put")
Exemple #17
0
    def test_read_simple(self):
        disc = discid.read()        # read from default drive
        self.assertEqual(len(disc.id), 28, "Invalid Disc ID")
        self.assertEqual(len(disc.freedb_id), 8, "Invalid FreeDB Disc ID")
        self.assertTrue(disc.submission_url, "Invalid submission url")
        self.assertTrue(disc.toc_string, "Invalid toc string")
        self.assertEqual(disc.last_track_num, len(disc.tracks),
                        "Wrong amount of tracks")
        self.assertEqual(disc.sectors,
                         disc.tracks[-1].offset + disc.tracks[-1].sectors)

        for track in disc.tracks:
            self.assertTrue(track.offset <= disc.sectors, "Invalid offset")
            if track.number > 1:
                previous_offset = disc.tracks[track.number-2].offset
                self.assertTrue(track.offset >= previous_offset,
                                "Invalid offset series")

        # additional features should be unset, not empty
        self.assertTrue(disc.mcn is None)
        for track in disc.tracks:
            self.assertTrue(track.isrc is None)

        # check idempotence (use output again as input to put)
        disc_id = disc.id
        freedb_id = disc.freedb_id
        submission_url = disc.submission_url
        toc_string = disc.toc_string
        first = disc.first_track_num
        last = disc.last_track_num
        sectors = disc.sectors
        track_sectors = [track.sectors for track in disc.tracks]
        track_offsets = [track.offset for track in disc.tracks]

        disc = discid.put(first, last, sectors, track_offsets)
        self.assertEqual(disc.id, disc_id, "different id after put")
        self.assertEqual(disc.freedb_id, freedb_id,
                         "different freedb id after put")
        self.assertEqual(disc.submission_url, submission_url,
                         "different submission_url after put")
        self.assertEqual(disc.toc_string, toc_string,
                         "different toc_string after put")
        self.assertEqual(disc.first_track_num, first,
                         "different first track after put")
        self.assertEqual(disc.last_track_num, last,
                         "different last track after put")
        self.assertEqual(disc.sectors, sectors,
                         "different sector count after put")
        new_offsets = [track.offset for track in disc.tracks]
        self.assertEqual(new_offsets, track_offsets,
                         "different offsets after put")
        new_sectors = [track.sectors for track in disc.tracks]
        self.assertEqual(new_sectors, track_sectors,
                         "different lengths after put")
Exemple #18
0
def complex_example():
    device_name = discid.get_default_device()
    disc = discid.read(device_name, ["mcn", "isrc"])
    print("device:\t%s" % device_name)
    print("id:\t%s" % disc.id)
    print("MCN:\t%s" % disc.mcn)
    print("length:\t%s" % _length_str(disc.seconds, disc.sectors))
    for track in disc.tracks:
        length = _length_str(track.seconds, track.sectors)
        print("{num:>2}: {offset:>6} {len}\tISRC: {isrc:13}".format(
            num=track.number, offset=track.offset, len=length,
            isrc=track.isrc))
Exemple #19
0
    def test_read_features(self):
        disc = discid.read(features=["mcn", "isrc"]) # read from default drive
        self.assertEqual(len(disc.id), 28, "Invalid Disc ID")
        self.assertTrue(disc.submission_url, "Invalid submission url")

        if "mcn" in discid.FEATURES:
            self.assertTrue(disc.mcn is not None)
        else:
            self.assertTrue(disc.mcn is None)

        for track in disc.tracks:
            if "isrc" in discid.FEATURES:
                self.assertTrue(track.isrc is not None)
            else:
                self.assertTrue(track.isrc is None)
Exemple #20
0
 def refresh(self):
     self.tracks=[]
     try:
         self.disc = discid.read()
     except:
         logger.debug("Cdrom: Unable to read cd")
         return
     logger.debug("Cdrom: reading cd")
     self.n = len(self.disc.tracks)
     logger.debug('Cdrom: %d tracks found',self.n)
     for track in self.disc.tracks:
         number = track.number
         duration = track.seconds
         name = 'Cdrom Track %s (%s)' % (number, time.strftime('%H:%M:%S', time.gmtime (duration)))
         self.tracks.append((number,name,duration))
    def test_read_features(self):
        disc = discid.read(features=["mcn", "isrc"])  # read from default drive
        self.assertEqual(len(disc.id), 28, "Invalid Disc ID")
        self.assertTrue(disc.submission_url, "Invalid submission url")
        self.assertTrue(disc.toc_string, "Invalid toc string")

        if "mcn" in discid.FEATURES:
            self.assertTrue(disc.mcn is not None)
        else:
            self.assertTrue(disc.mcn is None)

        for track in disc.tracks:
            if "isrc" in discid.FEATURES:
                self.assertTrue(track.isrc is not None)
            else:
                self.assertTrue(track.isrc is None)
Exemple #22
0
 def refresh(self):
     self.tracks = []
     try:
         self.disc = discid.read()
     except:
         logger.debug("Cdrom: Unable to read cd")
         return
     logger.debug("Cdrom: reading cd")
     self.n = len(self.disc.tracks)
     logger.debug('Cdrom: %d tracks found', self.n)
     for track in self.disc.tracks:
         number = track.number
         duration = track.seconds
         name = 'Cdrom Track %s (%s)' % (
             number, time.strftime('%H:%M:%S', time.gmtime(duration)))
         self.tracks.append((number, name, duration))
Exemple #23
0
    def read(self):
        try:
            disc_id = discid.read()
            logger.debug(
                'Read disc: MusicBrainz DiscID %s, FreeDB ID %s, %d tracks',
                disc_id.id, disc_id.freedb_id, len(disc_id.tracks))
        except (discid.DiscError, NotImplementedError) as e:
            logger.info('Error identifying disc: %s', e)
            self.disc = UNKNOWN_DISC
            return

        # use cached disc info if possible
        if self.disc.discid == disc_id.id:
            return

        try:
            mbrainz_info = musicbrainzngs.get_releases_by_discid(
                id=disc_id.id,
                toc=disc_id.toc_string,
                includes=['artist-credits', 'recordings'],
                cdstubs=False)
            # mbrainz_info is either
            # a {disc: {release-list: [...]}, ...} dict or
            # a {release-list: [...]} dict when matched by ToC
            release = mbrainz_info.get('disc', mbrainz_info)['release-list'][0]
            try:
                images = musicbrainzngs.get_image_list(release['id'])
            except musicbrainzngs.ResponseError as e:
                logger.debug('Error getting CD images from MusicBrainz: %s', e)
                images = {'images': ()}

            self.disc = Disc(
                id=release['id'],
                discid=disc_id.id,
                title=release['title'],
                discs=release['medium-count'],
                year=release['date'],
                images=CdRom._extract_images(images['images']),
                artists=CdRom._extract_artists(release['artist-credit']),
                tracks=CdRom._extract_tracks(disc_id, release['medium-list']))
        except (LookupError, musicbrainzngs.WebServiceError) as e:
            logger.info('Error accessing MusicBrainz: %s', e)
            self.disc = UNKNOWN_DISC._replace(
                discid=disc_id.id, tracks=CdRom._extract_tracks(disc_id))
Exemple #24
0
    def loadTreeFromCD(self) -> Tree:
        self.log.info('Loading CD')
        disc = discid.read(config.DEV_CDROM)
        discName, trackNamesByPosition = self.__readNamesFromMB(disc)

        tree = Tree()
        rootID = self._idProvider.getNextID()
        tree.create_node(identifier=rootID, parent=None, data=RootItem(discName))
        startsAtSecs = 0
        for track in disc.tracks:  # type: Track
            nodeID = self._idProvider.getNextID()
            position = track.number
            trackName = self.__getTrackName(position, trackNamesByPosition)
            lengthInSecs = track.seconds
            tree.create_node(identifier=nodeID, parent=rootID,
                             data=TrackItem(trackName, position, lengthInSecs, startsAtSecs))
            # startAtSecs for next track
            startsAtSecs += lengthInSecs
        return tree
Exemple #25
0
 def refresh(self):
     self.tracks = []
     try:
         self.disc = discid.read()
     except:
         logger.debug("Cdrom: Unable to read cd")
         return
     logger.debug("Cdrom: reading cd")
     self.n = len(self.disc.tracks)
     logger.debug('Cdrom: %d tracks found', self.n)
     read_info = {}
     try:
         self.disc_id = DiscID.disc_id(DiscID.open())
         (query_status, query_info) = CDDB.query(self.disc_id)
         (read_status, read_info) = CDDB.read(query_info['category'],
                                              query_info['disc_id'])
     except:
         pass
     if 'DYEAR' in read_info:
         self.year = read_info['DYEAR']
     else:
         self.year = ''
     if 'DGENRE' in read_info:
         self.genre = read_info['DGENRE']
     else:
         self.genre = 'unknown'
     if 'DTITLE' in read_info:
         self.albumtitle = self.sanitizeString(read_info['DTITLE'])
     else:
         self.albumtitle = 'CD'
     for track in self.disc.tracks:
         number = track.number
         duration = track.seconds
         key = 'TTITLE' + repr((track.number - 1))
         if key in read_info:
             name = self.sanitizeString(read_info[key])
         else:
             name = 'Cdrom Track %s (%s)' % (
                 number, time.strftime('%H:%M:%S', time.gmtime(duration)))
         self.tracks.append((number, name, duration, self.albumtitle,
                             self.genre, self.year))
Exemple #26
0
    def askForDiscId():
        """Asks the user for a CD-ROM device to use.
        :returns: Three-tuple of the *device*, *disc id*, and number of tracks.
        """
        import discid

        device, ok = QtWidgets.QInputDialog.getText(
            mainwindow.mainWindow,
            translate('AudioCD Plugin', 'Select device'),
            translate('AudioCD Plugin', 'CDROM device:'),
            QtWidgets.QLineEdit.Normal,
            discid.get_default_device())
        if not ok:
            return None
        try:
            with discid.read(device) as disc:
                disc.read()
        except discid.disc.DiscError as e:
                dialogs.warning(translate("AudioCD Plugin", "CDROM drive is empty"), str(e))
                return None
        return device, disc.id, len(disc.tracks)
Exemple #27
0
def main():
    result = None
    musicbrainzngs.set_hostname(MUSICBRAINZ_HOST)
    musicbrainzngs.set_useragent('freedb2musicbrainz.py',
                                 __version__,
                                 contact='Freso')

    try:
        disc = discid.read(features=['mcn'])
    except discid.disc.DiscError as err:
        print("Error reading disc: %s" % (err))
        exit(1)

    try:
        result = musicbrainzngs.get_releases_by_discid(disc.id)
    except musicbrainzngs.ResponseError as err:
        print('Disc not currently in MusicBrainz (or bad response): %s' %
              (err))

    if result:
        if result.get('disc'):
            print('This release seems to already be in MusicBrainz.')
            print(
                'Check %s to verify that it is the same or submit your specific copy'
                % (disc.submission_url))
        elif result.get("cdstub"):
            print('There seems to be a CD stub of your disc.')
            print('Go to %s to add the stub fully into the database.' %
                  (disc.submission_url))
    else:
        print('The release seems to not be in MusicBrainz. Let’s try FreeDB…')
        freedb = Cddb.CddbServer()
        print(cddb_lookup_string(disc))
        result = freedb.getDiscs(cddb_lookup_string(disc))
        if result:
            for r in result:
                print(r.artist, "-", r.title)
        else:
            print('This release is non-existant! Add it to MB!!')
            print(disc.submission_url)
Exemple #28
0
 def read(self, path):
     if path != 'cdda://': return None
     try:
         import discid
     except:
         raise RuntimeError('Cannot import discid. Is it installed?')
     device_name = discid.get_default_device()
     disc = discid.read(device_name)
     tracks = []
     for cdda_track in disc.tracks:
         track = Track()
         track.path = path
         track.title = 'CD Audio track'  # TODO: read tags from FreeDB
         track.index = cdda_track.number
         track.length = cdda_track.seconds
         track.length_string, track.time_format = self._format_seconds_and_get_format_string(
             track.length)
         try:
             track.offset = tracks[-1].offset + tracks[-1].length
         except:
             pass
         tracks.append(track)
     return tracks
Exemple #29
0
def rip(
    device,
    mbdb,
    *,
    output_dirpath,
    disc_id=None,
    fstags=None,
    no_action=False
):
  ''' Pull audio from `device` and save in `output_dirpath`.
  '''
  if disc_id is None:
    dev_info = discid.read(device=device)
    disc_id = dev_info.id
  if fstags is None:
    fstags = FSTags()
  with Pfx("MB: discid %s", disc_id, print=True):
    disc = mbdb.discs[disc_id]
  level1 = ", ".join(disc.artist_names).replace(os.sep, '_') or "NO_ARTISTS"
  level2 = disc.title or "UNTITLED"
  if disc.medium_count > 1:
    level2 += f" ({disc.medium_position} of {disc.medium_count})"
  subdir = joinpath(output_dirpath, level1, level2)
  if not isdirpath(subdir):
    with Pfx("makedirs(%r)", subdir, print=True):
      os.makedirs(subdir)
  fstags[subdir].update(
      TagSet(discid=disc.id, title=disc.title, artists=disc.artist_names)
  )
  for tracknum, recording_id in enumerate(disc.recordings, 1):
    recording = disc.ontology.metadata('recording', recording_id)
    track_fstags = TagSet(
        discid=disc.mbkey,
        artists=recording.artist_names,
        title=recording.title,
        track=tracknum
    )
    track_artists = ", ".join(recording.artist_names)
    track_base = f"{tracknum:02} - {recording.title} -- {track_artists}".replace(
        os.sep, '-'
    )
    wav_filename = joinpath(subdir, track_base + '.wav')
    mp3_filename = joinpath(subdir, track_base + '.mp3')
    if existspath(mp3_filename):
      warning("MP3 file already exists, skipping track: %r", mp3_filename)
    else:
      with NamedTemporaryFile(dir=subdir,
                              prefix=f"cdparanoia--track{tracknum}--",
                              suffix='.wav') as T:
        if existspath(wav_filename):
          info("using existing WAV file: %r", wav_filename)
        else:
          argv = ['cdparanoia', '-d', '1', '-w', str(tracknum), T.name]
          if no_action:
            print(*argv)
          else:
            with Pfx("+ %r", argv, print=True):
              subprocess.run(argv, stdin=subprocess.DEVNULL, check=True)
            with Pfx("%r => %r", T.name, wav_filename, print=True):
              os.link(T.name, wav_filename)
      if no_action:
        print("fstags[%r].update(%s)" % (wav_filename, track_fstags))
      else:
        fstags[wav_filename].update(track_fstags)
        fstags[wav_filename].rip_command = argv
      argv = [
          'lame',
          '-q',
          '7',
          '-V',
          '0',
          '--tt',
          recording.title or "UNTITLED",
          '--ta',
          track_artists or "NO ARTISTS",
          '--tl',
          level2,
          ## '--ty',recording year
          '--tn',
          str(tracknum),
          ## '--tg', recording genre
          ## '--ti', album cover filename
          wav_filename,
          mp3_filename
      ]
      if no_action:
        print(*argv)
      else:
        with Pfx("+ %r", argv, print=True):
          subprocess.run(argv, stdin=subprocess.DEVNULL, check=True)
      fstags[mp3_filename].conversion_command = argv
    if no_action:
      print("fstags[%r].update(%s)" % (mp3_filename, track_fstags))
    else:
      fstags[mp3_filename].update(track_fstags)
  if not no_action:
    subprocess.run(['ls', '-la', subdir])
    os.system("eject")
Exemple #30
0
def simple_example():
    disc = discid.read()  # use default device
    print("id: %s" % disc.id)
    print("used %s as device" % discid.get_default_device())
    print("submit with:\n%s" % disc.submission_url)
import discid
import pymysql
import getpass

db = pymysql.connect(host="localhost",
                     user="******",
                     passwd="nopassforyou",
                     db="CD_Database",
                     autocommit=True)
cur = db.cursor()

disc = discid.read("/dev/cdrom", features=["mcn"])
mcn = disc.mcn
if mcn == "":
    print("DISC UPC NOT FOUND. MANUALLY ENTER")
else:
    print("DISC UPC: %s" % mcn)

user = getpass.getuser()

sql = "INSERT INTO WeHave(UPC,AddedBy) VALUES ('" + str(mcn) + "','" + str(
    user) + "');"
cur.execute(sql)
Exemple #32
0
def main():
    parser = optparse.OptionParser()
    parser.add_option("-u", "--user", type=str, help="Username")
    parser.add_option("-p", "--password", type=str, help="Password")
    parser.add_option("-d", "--device", type=str,
            default=discid.get_default_device(),
            help="Device name, the default is %s" % discid.get_default_device())
    (args, options) = parser.parse_args()

    if not args.user:
        exit("No username given")

    if not args.password:
        password = getpass.getpass()
    else:
        password = args.password

    try:
        disc = discid.read(args.device)
    except discid.DiscError:
        exit("No discid could be calculated")

    musicbrainzngs.auth(args.user, password)
    musicbrainzngs.set_useragent("isrcsubmit-cdrdao", "0.2", "Mineo@Freenode")

    results = musicbrainzngs.get_releases_by_discid(
            disc.id, includes=["recordings", "isrcs",
            "artist-credits"])["disc"]["release-list"]

    if len(results) == 0:
        print "The disc is not in the database"
        print "Please submit it with: %s" % disc.submission_url
        exit(1)
    elif len(results) > 1:
        print "This Disc ID is ambiguous:"
        for i, release in enumerate(results):
            print str(i)+":", release["artist-credit-phrase"]
            print "-", release["title"]
            print release["id"]
        num = -1
        while True:
            try:
                num =  raw_input("Which one do you want? [0-%d] " % i)
                release = results[int(num)]
            except (IndexError, ValueError):
                continue
            break
    else:
        release = results[0]

    print 'Artist: %s' % release["artist-credit-phrase"]
    print 'Release: %s' % release["title"]

    real_medium = None
    for medium in release["medium-list"]:
        for mdisc in medium["disc-list"]:
            print mdisc
            if mdisc["id"] == disc.id:
                real_medium = medium
                break

    filename = "/tmp/cdrdao-%s.toc" % datetime.now()
    try:
        proc = subprocess.Popen(["cdrdao", "read-toc", "--fast-toc", "--device",
                args.device, "-v", "0", filename], stderr=subprocess.PIPE,
                stdout=subprocess.PIPE)
        proc.wait()
    except Exception, e:
        exit("Exception while calling cdrdao: %s" % str(e))
Exemple #33
0
def find_disc(cddrive):
    import discid
    from lxml import etree

    root = etree.XML(u'<finddisc></finddisc>')

    try:
        disc = discid.read(cddrive, ["mcn", "isrc"])
        id = disc.id
        toc = disc.toc_string
    except discid.DiscError as err:
        etree.SubElement(root, "error").text = "Failed to get discid ({})".format(str(err))
        log(True, etree.tostring(root, encoding='UTF-8', pretty_print=True, xml_declaration=True))
        sys.exit(1)

    etree.SubElement(root, "discid").text = id
    etree.SubElement(root, "toc").text = toc

    try:
        # the "labels" include enables the cat#s we display
        result = musicbrainzngs.get_releases_by_discid(id, includes=["labels"], toc=toc, cdstubs=False)
    except musicbrainzngs.ResponseError as err:
        if err.cause.code == 404:
            etree.SubElement(root, "error").text = "Disc not found"
            log(True, etree.tostring(root, encoding='UTF-8', pretty_print=True, xml_declaration=True))
            sys.exit(1)
        else:
            etree.SubElement(root, "error").text = "Received bad response from the MB server"
            log(True, etree.tostring(root, encoding='UTF-8', pretty_print=True, xml_declaration=True))
            sys.exit(1)

    # The result can either be a "disc" or a "cdstub"
    if result.get('disc'):
        discnode = etree.SubElement(root, "disc")

        etree.SubElement(discnode, "sectors").text = result['disc']['sectors']

        if "offset-list" in result['disc']:
            offsets = None
            for offset in result['disc']['offset-list']:
                if offsets == None:
                    offsets = str(offset)
                else:
                    offsets += " " + str(offset)

            etree.SubElement(discnode, "offsets").text = offsets
            etree.SubElement(discnode, "tracks").text = str(result['disc']['offset-count'])

        for release in result['disc']['release-list']:
            relnode = etree.SubElement(discnode, "release")

            etree.SubElement(relnode, "title").text = release['title']
            etree.SubElement(relnode, "musicbrainzid").text = release['id']

            if release.get('barcode'):
                etree.SubElement(relnode, "barcode").text = release['barcode']
            for info in release['label-info-list']:
                if info.get('catalog-number'):
                    etree.SubElement(relnode, "catalog-number").text = info['catalog-number']
    elif result.get('cdstub'):
        stubnode = etree.SubElement(root, "cdstub")

        etree.SubElement(stubnode, "artist").text = result['cdstub']['artist']
        etree.SubElement(stubnode, "title").text = result['cdstub']['title']

        if result['cdstub'].get('barcode'):
            etree.SubElement(stubnode, "barcode").text = result['cdstub']['barcode']
    else:
        etree.SubElement(root, "error").text = "No valid results"
        log(True, etree.tostring(root, encoding='UTF-8', pretty_print=True, xml_declaration=True))
        sys.exit(1)

    log(True, etree.tostring(root, encoding='UTF-8', pretty_print=True, xml_declaration=True))
    sys.exit(0)
Exemple #34
0
def find_disc(cddrive):
    import discid
    from lxml import etree

    root = etree.XML(u'<finddisc></finddisc>')

    try:
        disc = discid.read(cddrive, ["mcn", "isrc"])
        id = disc.id
        toc = disc.toc_string
    except discid.DiscError as err:
        etree.SubElement(root,
                         "error").text = "Failed to get discid ({})".format(
                             str(err))
        log(
            True,
            convert_etree(
                etree.tostring(root,
                               encoding='UTF-8',
                               pretty_print=True,
                               xml_declaration=True)))
        sys.exit(1)

    etree.SubElement(root, "discid").text = id
    etree.SubElement(root, "toc").text = toc

    try:
        # the "labels" include enables the cat#s we display
        result = musicbrainzngs.get_releases_by_discid(id,
                                                       includes=["labels"],
                                                       toc=toc,
                                                       cdstubs=False)
    except musicbrainzngs.ResponseError as err:
        if err.cause.code == 404:
            etree.SubElement(root, "error").text = "Disc not found"
            log(
                True,
                convert_etree(
                    etree.tostring(root,
                                   encoding='UTF-8',
                                   pretty_print=True,
                                   xml_declaration=True)))
            sys.exit(1)
        else:
            etree.SubElement(
                root,
                "error").text = "Received bad response from the MB server"
            log(
                True,
                convert_etree(
                    etree.tostring(root,
                                   encoding='UTF-8',
                                   pretty_print=True,
                                   xml_declaration=True)))
            sys.exit(1)

    # The result can either be a "disc" or a "cdstub"
    if result.get('disc'):
        discnode = etree.SubElement(root, "disc")

        etree.SubElement(discnode, "sectors").text = result['disc']['sectors']

        if "offset-list" in result['disc']:
            offsets = None
            for offset in result['disc']['offset-list']:
                if offsets is None:
                    offsets = str(offset)
                else:
                    offsets += " " + str(offset)

            etree.SubElement(discnode, "offsets").text = offsets
            etree.SubElement(discnode, "tracks").text = str(
                result['disc']['offset-count'])

        for release in result['disc']['release-list']:
            relnode = etree.SubElement(discnode, "release")

            etree.SubElement(relnode, "title").text = release['title']
            etree.SubElement(relnode, "musicbrainzid").text = release['id']

            if release.get('barcode'):
                etree.SubElement(relnode, "barcode").text = release['barcode']
            for info in release['label-info-list']:
                if info.get('catalog-number'):
                    etree.SubElement(
                        relnode,
                        "catalog-number").text = info['catalog-number']
    elif result.get('cdstub'):
        stubnode = etree.SubElement(root, "cdstub")

        etree.SubElement(stubnode, "artist").text = result['cdstub']['artist']
        etree.SubElement(stubnode, "title").text = result['cdstub']['title']

        if result['cdstub'].get('barcode'):
            etree.SubElement(stubnode,
                             "barcode").text = result['cdstub']['barcode']
    else:
        etree.SubElement(root, "error").text = "No valid results"
        log(
            True,
            convert_etree(
                etree.tostring(root,
                               encoding='UTF-8',
                               pretty_print=True,
                               xml_declaration=True)))
        sys.exit(1)

    log(
        True,
        convert_etree(
            etree.tostring(root,
                           encoding='UTF-8',
                           pretty_print=True,
                           xml_declaration=True)))
    sys.exit(0)
Exemple #35
0
    def identify(self):
        """Drrn drrn
        """

        try:
            disc = discid.read(DEVICE)
        except discid.disc.DiscError as e:
            logger.error('[FAIL] %s' % e)
            logger.error(''.join(traceback.format_exception(*sys.exc_info())))
            self.interface.queue_to_identify_interface.send('FAILED_IDENTIFY')
            return

        logger.info('[URL] %s' % disc.submission_url)

        logger.info('[SUCCESS] Identified disc as: %s' % disc.id)

        ## XXX: The library doesn't understand a tuple here
        includes = ['artist-credits', 'labels', 'release-rels', 'recordings']
        try:
            data = musicbrainzngs.get_releases_by_discid(disc.id, includes=includes)
        except musicbrainzngs.ResponseError as e:
            ## Fake response to make flow easier
            if e.cause.code == 404:
                data = {
                    'disc': {
                        'id': disc.id,
                        'release-list': []
                    }
                }
            else:
                raise
        except Exception as e:
            logger.error('[FAIL] %s' % e)
            logger.error(''.join(traceback.format_exception(*sys.exc_info())))
            self.interface.queue_to_identify_interface.send('FAILED_IDENTIFY')

            return
        else:
            if not data:
                logger.error('[FAIL] No data returned. Check submission url')
                return

        try:
            releases = data['disc']['release-list']
        except KeyError:
            if 'cdstub' in data:
                logger.warn('[DISC] This release is only a stub, fill it in at MusicBrainz')
                self.interface.queue_to_identify_interface.send('NO_DATA')
                return

        logger.info('[SUCCESS] Got %d releases' % len(releases))

        if len(releases) == 0:
            self.interface.queue_to_identify_interface.send('NO_DATA')

            self.interface.queue_to_identify_interface.send(disc.submission_url)

            return
        elif len(releases) > 1:
            self.interface.queue_to_identify_interface.send('MULTIPLE_RELEASES')
            self.interface.queue_to_identify_interface.send(releases)

            rel_num = self.interface.queue_to_identify_interface.recv()
        else:
            rel_num = 0

        ## Which release do we want?
        release = releases[rel_num]

        ## Disc title
        title = release['title']
        disambiguation = release.get('disambiguation', None)
        is_remaster = False
        for rel_release in release.get('release-relation-list', ()):
            if rel_release.get('type', None) == 'remaster':
                is_remaster = True
                break

        extra_str = ''
        if disambiguation:
            extra_str = '%s' % disambiguation
        if is_remaster:
            extra_str = '%s remaster' % extra_str

        extra_str = extra_str.strip()

        if extra_str:
            title = '%s (%s)' % (title, extra_str)

        ## Require release date
        date = release['date']
        if not date:
            self.interface.queue_to_identify_interface.send('NO_DATE')

            return

        year = date.split('-', 1)[0]

        ## 0th artist...
        if len(release['artist-credit']) > 1:
            self.interface.queue_to_identify_interface.send('TOO_MANY_ARTISTS')

            return

        artist_sort_name = release['artist-credit'][0]['artist']['sort-name']
        artist_sort_name = artist_sort_name

        ## Media count and name
        disc_num = 1
        if 'medium-count' not in release:
            disc_count = len(release['medium-list'])
        else:
            disc_count = release['medium-count']

        medium_n = 0
        media_name = None
        if disc_count > 1:
            for medium_n, medium in enumerate(release['medium-list']):
                if 'title' in medium:
                    media_name = medium['title']
                else:
                    media_name = None
                if disc.id in [d['id'] for d in medium['disc-list']]:
                    disc_num = medium_n + 1
                    break

        # Pass the media_name along if required, otherwise it's None
        if media_name is not None and media_name == title:
            media_name = None

        ## Unlike the mb example code, disregard different track artists
        track_tuples = []
        for track in release['medium-list'][medium_n]['track-list']:
            formatted_track_num = '%02d' % int(track['number'])

            track_title = track['recording']['title']
            track_tuple = TrackTuple(
                disc_id=disc.id,
                release_id=release['id'],
                artist=artist_sort_name,
                year=year,
                title=title,
                formatted_track_num=formatted_track_num,
                track_title=track_title,
                disc_num=disc_num,
                disc_count=disc_count,
                media_name=media_name)

            track_tuples.append(track_tuple)

        self.interface.queue_to_identify_interface.send('FINISHED_IDENTIFY')
        self.interface.queue_to_identify_interface.send(tuple(track_tuples))
    def _do_disc(self, spec_device=None):
        """Read table of contents from a CD-ROM, search for a release, and
        optionally add to the catalog"""

        try:
            import discid
        except ImportError as e:
            raise Exception('Could not import discid')
        default_device = discid.get_default_device()
        if not spec_device:
            spec_device = raw_input('Device to read [empty for \'%s\']: ' %
                                    default_device)
        if not spec_device:
            spec_device = default_device

        try:
            disc = discid.read(spec_device)
        except discid.DiscError as e:
            raise Exception("DiscID calculation failed: " + str(e))
        print('DiscID: %s' % disc.id)
        print('Submisson URL: %s' % disc.submission_url)

        try:
            print("Querying MusicBrainz...")
            result = mb.get_releases_by_discid(disc.id, includes=["artists"])
            print('OK')
        except mb.ResponseError:
            _log.warning('Disc not found or bad MusicBrainz response.')
            self.askBrowseSubmission(disc.submission_url)
            return

        else:
            if result.get("disc"):
                oneInCatalog = self.printDiscQueryResults(result)
            elif result.get("cdstub"):
                for label, key in [('CD Stub', 'id'), ('Artist', 'artist'),
                                   ('Title', 'title'), ('Barcode', 'barcode')]:
                    if key in result['cdstub']:
                        print('%10s: %s' % (label, result['cdstub'][key]))
                # TODO this is broken, needs argument
                self.askBrowseSubmission()

                raise Exception('There was only a CD stub.')

        if len(result['disc']['release-list']) == 0:
            raise Exception("There were no matches for disc ID: %s" % disc.id)
        elif len(result['disc']['release-list']) == 1:
            print("There was one match. " +
                  ('It is already in the catalog. ' if oneInCatalog else ''))
            if not oneInCatalog:
                return self.addResultToCatalog(result, 0)
            else:
                return oneInCatalog[0]
        else:
            print("There were %d matches." %
                  len(result['disc']['release-list']))
            choice = raw_input('Choose one result to add (empty for none): ')
            if not choice.isdigit():
                raise Exception('Input was not a number')
            choice = int(choice)
            if choice < 0 or choice >= len(result['disc']['release-list']):
                raise Exception('Input was out of range')
            return self.addResultToCatalog(result, choice)
 def __init__(self, drive):
     self.disc = discid.read(drive)
Exemple #38
0
def simple_example():
    disc = discid.read()       # use default device
    print("id: %s" % disc.id)
    print("used %s as device" % discid.get_default_device())
    print("submit with:\n%s" % disc.submission_url)
Exemple #39
0
def musicbrainz_info():
    try:
        # Read the disc
        disc_read = discid.read()
        # Get the disc ID from the read object
        disc_id = disc_read.id
        # Also get the submission URL in case of an accident
        disc_submission = disc_read.submission_url
    except:
        print("Please insert a compact disc")
        sys.exit(0)

    musicbrainzngs.set_useragent("Tedm ripper", "0.0.1", "*****@*****.**")

    try:
        result = musicbrainzngs.get_releases_by_discid(disc_id,
                                                       includes=['artists',
                                                                 'labels',
                                                                 'recordings'])
        release_list = result['disc']['release-list'][0]
        number_of_discs = release_list['medium-count']
        disc_number_list = list(range(1, (number_of_discs + 1)))
        disc_string = ', '.join(map(str, disc_number_list))
        if number_of_discs > 1:
            print('This disc is part of a set. You can choose from %s' % disc_string)

            choice = input('Please enter the proper disc number: ')
            if not int(choice) in disc_number_list:
                print("Invalid disc number")
                sys.exit(0)
            pretty_disc_number = choice
            raw_disc_number = int(pretty_disc_number) - 1
        else:
            pretty_disc_number = '1'
            raw_disc_number = 0

    except musicbrainzngs.ResponseError:
        print("Disc was not found in database, check if available on musicbrainz.org")
        print(disc_submission)
        sys.exit(0)
    except musicbrainzngs.musicbrainz.NetworkError:
        print("You do not seem to be connected to the internet")
        sys.exit(0)
    else:
        # Define metadata for the entire album
        album_info_dict = {
            'album': release_list['title'],
            'album_artist': release_list['artist-credit'][0]['artist']['name'],
            'artist': release_list['artist-credit'][0]['artist']['name'],
            'date': release_list['date'],
            'disc': pretty_disc_number,
            'disc_id': result['disc']['id'],
            'total_discs': str(number_of_discs),
            'total_tracks': release_list['medium-list'][raw_disc_number]['track-count'],
        }
        try:
            album_info_dict['label'] = release_list['label-info-list'][0]['label']['name']
        except IndexError:
            album_info_dict['label'] = ''

        track_dict = {}

        for track in release_list['medium-list'][raw_disc_number]['track-list']:

            title = track['recording']['title']
            track_number = track['position']

            track_dict[track_number] = title

        return album_info_dict, track_dict
Exemple #40
0
        return data['key']
    except KeyError:
        return default
        
def printIfSet (prefix, key, data, default):
    "Print the line only if the data is not null"
    data = getIfSet(key, data, default)
    
    if data != default:
        print prefix, data



# get Audio CD details
try:
    disc = discid.read()        # reads from default device
except discid.DiscError, e:
    if str(e) == u'cannot read table of contents':
        print 'Could not read CD.'
    sys.exit(1)



# try to find Audio CD match on MusicBrainz
print "\nFetching release data for CD ..."
musicbrainzngs.set_useragent(scriptName, scriptVersion, scriptURL)

try:
    discReleases = musicbrainzngs.get_releases_by_discid(disc.id, ['artist-credits', 'recordings'], disc.toc_string, False)
except:
    print sys.exc_info()
#!/usr/bin/env python3

import sys

try:
    import discid
except ImportError:
    print("You have to install discid")
    print("Maybe run 'pip install discid'?")
    sys.exit(1)

import cddb

if __name__ == "__main__":
    c = cddb.CDDBClient(discid.read())
    r = c.query()

    print(r)
    for i in r.tracks:
        print(i)
Exemple #42
0
    "https://github.com/rlhelinski/musicbrainz-catalog/",
)

c = Catalog()

io = InputSplitter()

while not io.nextLine('Press enter to read the disc or \'q\' to quit... ').startswith('q'):

    try:
        # Read the disc in the default disc drive. If necessary, you can pass
        # the 'deviceName' parameter to select a different drive.
        #
        dev = sys.argv[1] if len(sys.argv) > 1 else discid.get_default_device()
        io.write ('Reading from %s\n' % dev)
        disc = discid.read(dev)
    except discid.DiscError as e:
        print ("DiscID calculation failed: " + str(e))
        continue

    if (not os.path.isdir('disc-id')):
        os.mkdir('disc-id')
    if (not os.path.isdir(os.path.join('disc-id', disc.id))):
        os.mkdir(os.path.join('disc-id', disc.id))

    with open(os.path.join('disc-id', disc.id, 'toc.txt'), 'a') as tocf:
        print ('DiscID      :', disc.id, file=tocf)
        print ('First Track :', disc.first_track_num, file=tocf)
        print ('Last Track  :', disc.last_track_num, file=tocf)
        print ('Length      :', disc.sectors, 'sectors', file=tocf)
Exemple #43
0
cdda2wav_args = []
if parser.has_option('ripper', 'cdda2wavArgs'):
    cdda2wav_args = parser.get('ripper', 'cdda2wavArgs').split()
ffmpeg_path = parser.get('ripper', 'ffmpegPath')

print('Music dir: %s' % music_dir)
print('cdda2wav: %s' % cdda2wav_path)
print('cdda2wav args: %s' % cdda2wav_args)
print('ffmpeg: %s' % ffmpeg_path)

# Retrieve information from Musicbrainz
print('-' * 79)
print('Searching Musicbrainz...')

try:
    disc_id = discid.read().id
except Exception as ex:
    print('Error while searching Musicbrainz: %s' % str(ex))
    sys.exit(1)

print('Disc id: %s' % disc_id)

#call([internet_program_path, mbdisc.getSubmissionUrl(disc)])
#sys.exit(1)
try:
    release = get_release(disc_id)
except Exception as ex:
    print(ex)
    sys.exit(1)

# Release information
Exemple #44
0
def read_disc_metadata(device=CDROM_DEVICE):
    def simple_md(disc):
        """ For disc not found, we can derive the tracks and tracks length
            from the 'disc' object properties.
        """
        print(
            f'(cdda.py) {disc.last_track_num} tracks found on discid \'{disc.id}\''
        )
        # https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2#discid
        # The toc consists of the following:
        #   First track (always 1)
        #   total number of tracks
        #   sector offset of the leadout (end of the disc
        #   a list of sector offsets for each track, beginning with track 1 (generally 150 sectors)
        #
        # Example of TOC for a 7 tracks disc:
        # disc.toc_string: '1 7 235745 150 40742 77847 108042 118682 154277 191952'
        toc = disc.toc_string.split()

        # A second of CD-AUDIO has 75 frames (or sectors) -wikipedia-
        track_sectors = toc[3:] + [toc[2]]
        track_sectors = [int(x) for x in track_sectors]
        for i in range(len(track_sectors)):
            if i == 0:
                continue
            trackNum = i
            trackLen = (track_sectors[i] - track_sectors[i - 1]) / 75
            md[str(trackNum)] = {
                'title': 'track ' + f'{trackNum}'.zfill(2),
                'length': msec2string(trackLen * 1e3)
            }

        return md

    # will complete md with info retrieved from musicbrainz
    md = CDDA_INFO_TEMPLATE.copy()

    mz.set_useragent('tmp', '0.1', 'dummy@mail')

    try:
        disc = discid.read(device)
        md['discid'] = disc.id
        global CDDA_DISCID
        CDDA_DISCID = disc.id
    except:
        print('(cdaa.py) not CDDA found')
        return md

    try:
        result = mz.get_releases_by_discid(disc.id,
                                           includes=['artists', 'recordings'])
    except mz.ResponseError:
        print('(cdda.py) disc not found or bad response')
        return simple_md(disc)

    # most of discs are 'disc' musicbrainz kinf of
    if result.get('disc'):

        print(f'(cdda.py) musicbrainz got \'disc\': {disc.id}')

        mz_md = result['disc']['release-list'][0]

        md['artist'] = mz_md['artist-credit-phrase']

        md['album'] = mz_md['title']

        track_list = mz_md['medium-list'][0]['track-list']

    # but somo are 'cdstub' musicbrainz kind of
    elif result.get('cdstub'):

        print(f'(cdda.py) musicbrainz got \'cdstub\': {disc.id}')

        mz_md = result['cdstub']

        if 'artist' in mz_md:
            md['artist'] = mz_md['artist']
        elif 'artist-credit-phrase' in mz_md:
            md['artist'] = mz_md['artist-credit-phrase']

        if 'title' in mz_md:
            md['album'] = mz_md['title']

        # (!) pending on investigate more on tracks under 'cdstub'
        if 'track-list' in mz_md:
            track_list = mz_md['track-list']
        else:
            track_list = []

    # Lets complete our track list structure inside the 'md' template
    for pos, track in enumerate(track_list):

        # Retrieve track length
        # from normal 'disc':
        if 'recording' in track and 'length' in track['recording']:
            lengthStr = msec2string(float(track['recording']['length']))
        # from some 'cdstub':
        elif 'length' in track:
            lengthStr = msec2string(float(track['length']))
        # from some 'cdstub':
        elif 'track_or_recording_length' in track:
            lengthStr = msec2string(float(track['track_or_recording_length']))
        else:
            lengthStr = msec2string(0.0)

        # Retrieve track title
        if 'recording' in track and 'title' in track['recording']:
            track_title = track['recording']['title']
        elif 'title' in track:
            track_title = track['title']

        # adding to our metadata disc structure
        md[str(pos + 1)] = {'title': track_title, 'length': lengthStr}

    return md
    def _do_disc(self, spec_device=None):
        """Read table of contents from a CD-ROM, search for a release, and
        optionally add to the catalog"""

        try:
            import discid
        except ImportError as e:
            raise Exception('Could not import discid')
        default_device = discid.get_default_device()
        if not spec_device:
            spec_device = raw_input('Device to read [empty for \'%s\']: ' %
                                          default_device)
        if not spec_device:
            spec_device = default_device

        try:
            disc = discid.read(spec_device)
        except discid.DiscError as e:
            raise Exception("DiscID calculation failed: " + str(e))
        print('DiscID: %s' % disc.id)
        print('Submisson URL: %s' % disc.submission_url)

        try:
            print("Querying MusicBrainz...")
            result = mb.get_releases_by_discid(disc.id,
                                               includes=["artists"])
            print('OK')
        except mb.ResponseError:
            _log.warning('Disc not found or bad MusicBrainz response.')
            self.askBrowseSubmission(disc.submission_url)
            return

        else:
            if result.get("disc"):
                oneInCatalog = self.printDiscQueryResults(result)
            elif result.get("cdstub"):
                for label, key in [
                        ('CD Stub', 'id'),
                        ('Artist', 'artist'),
                        ('Title', 'title'),
                        ('Barcode', 'barcode')]:
                    if key in result['cdstub']:
                        print('%10s: %s' %
                                     (label, result['cdstub'][key]))
                # TODO this is broken, needs argument
                self.askBrowseSubmission()

                raise Exception('There was only a CD stub.')

        if len(result['disc']['release-list']) == 0:
            raise Exception("There were no matches for disc ID: %s" % disc.id)
        elif len(result['disc']['release-list']) == 1:
            print("There was one match. " +
                         ('It is already in the catalog. ' if oneInCatalog else ''))
            if not oneInCatalog:
                return self.addResultToCatalog(result, 0)
            else:
                return oneInCatalog[0]
        else:
            print("There were %d matches." %
                         len(result['disc']['release-list']))
            choice = raw_input(
                'Choose one result to add (empty for none): ')
            if not choice.isdigit():
                raise Exception('Input was not a number')
            choice = int(choice)
            if choice < 0 or choice >= len(result['disc']['release-list']):
                raise Exception('Input was out of range')
            return self.addResultToCatalog(result, choice)