Пример #1
0
 def __init__(self, name):
     Con.Adapter.__init__(
         self,
         Con.RepeatUntil(lambda obj, ctx: (obj & 0x80) == 0x00,
                         Con.UBInt8(name)))
Пример #2
0
class DiscID:
    """An object representing a 32 bit FreeDB disc ID value."""

    DISCID = Con.Struct('discid', Con.UBInt8('digit_sum'),
                        Con.UBInt16('length'), Con.UBInt8('track_count'))

    def __init__(self, tracks=[], offsets=None, length=None, lead_in=150):
        """Fields are as follows:

        tracks  - a list of track lengths in CD frames
        offsets - a list of track offsets in CD frames
        length  - the length of the entire disc in CD frames
        lead_in - the location of the first track on the CD, in frames

        These fields are all optional.
        One will presumably fill them with data later in that event.
        """

        self.tracks = tracks
        self.__offsets__ = offsets
        self.__length__ = length
        self.__lead_in__ = lead_in

    @classmethod
    def from_cdda(cls, cdda):
        """Given a CDDA object, returns a populated DiscID.

        May raise ValueError if there are no audio tracks on the CD."""

        tracks = list(cdda)
        if (len(tracks) < 1):
            raise ValueError(_(u"no audio tracks in CDDA object"))

        return cls(tracks=[t.length() for t in tracks],
                   offsets=[t.offset() for t in tracks],
                   length=cdda.length(),
                   lead_in=tracks[0].offset())

    def add(self, track):
        """Adds a new track length, in CD frames."""

        self.tracks.append(track)

    def offsets(self):
        """Returns a list of calculated offset integers, from track lengths."""

        if (self.__offsets__ is None):
            offsets = [self.__lead_in__]

            for track in self.tracks[0:-1]:
                offsets.append(track + offsets[-1])

            return offsets
        else:
            return self.__offsets__

    def length(self):
        """Returns the total length of the disc, in seconds."""

        if (self.__length__ is None):
            return sum(self.tracks)
        else:
            return self.__length__

    def idsuffix(self):
        """Returns a FreeDB disc ID suffix string.

        This is for making server queries."""

        return str(len(self.tracks)) + " " + \
               " ".join([str(offset) for offset in self.offsets()]) + \
               " " + str((self.length() + self.__lead_in__) / 75)

    def __str__(self):
        def __count_digits__(i):
            if (i == 0):
                return 0
            else:
                return (i % 10) + __count_digits__(i / 10)

        disc_id = Con.Container()

        disc_id.track_count = len(self.tracks)
        disc_id.length = self.length() / 75
        disc_id.digit_sum = sum(
            [__count_digits__(o / 75) for o in self.offsets()]) % 0xFF

        return DiscID.DISCID.build(disc_id).encode('hex')

    def freedb_id(self):
        """Returns the entire FreeDB disc ID, including suffix."""

        return str(self) + " " + self.idsuffix()

    def toxmcd(self, output):
        """Writes a newly created XMCD file to output.

        Its values are populated from this DiscID's fields."""

        output.write(
            XMCD.from_tracks([
                DummyAudioFile(length, None, i + 1)
                for (i, length) in enumerate(self.tracks)
            ]).to_string())