parseTagsSync method

bool parseTagsSync()

Implementation

bool parseTagsSync() {
  List<int> _tag;
  _tag = mp3Bytes.sublist(0, 3);

  if (latin1.decode(_tag) == 'ID3') {
    final int major_v = mp3Bytes[3];
    final int revision_v = mp3Bytes[4];
    final int flag = mp3Bytes[5];

    final bool unsync = (0x40 & flag != 0);
    final bool extended = (0x20 & flag != 0);
    final bool experimental = (0x10 & flag != 0);

    metaTags['Version'] = 'v2.$major_v.$revision_v';

    if (extended) {
      print('Extended id3v2 tags are not supported yet!');
    } else if (unsync) {
      print('Unsync id3v2 tags are not supported yet!');
    } else if (experimental) {
      print('Experimental id3v2 tag');
    }

    int cb = 10;

    Map<String, String> frames_db = FRAMESv2_3;
    int frameNameLength = 4;
    int frameSizeLength = 4;
    int frameTagLength = 2;
    if (major_v == 2) {
      frames_db = FRAMESv2_2;
      frameNameLength = 3;
      frameSizeLength = 3;
      frameTagLength = 0;
    }
    final int frameHeaderLength =
        frameNameLength + frameSizeLength + frameTagLength;

    while (true) {
      final List<int> frameHeader =
          mp3Bytes.sublist(cb, cb + frameHeaderLength);
      final List<int> frameName = frameHeader.sublist(0, frameNameLength);

      final RegExp exp = RegExp(r'[A-Z0-9]+');
      if (latin1.decode(frameName) !=
          exp.stringMatch(latin1.decode(frameName))) {
        break;
      }

      final int frameSize = parseSize(
          frameHeader.sublist(
              frameNameLength, frameNameLength + frameSizeLength),
          major_v);
      final List<int> frameContent = mp3Bytes.sublist(
          cb + frameHeaderLength, cb + frameHeaderLength + frameSize);

      if (frames_db[latin1.decode(frameName)] == FRAMESv2_3['APIC']) {
        final Map<String, String> apic = {
          'mime': '',
          'textEncoding': frameContent[0].toString(),
          'picType': '',
          'description': '',
          'base64': ''
        };

        final frame = _MP3FrameParser(frameContent);
        frame.readEncoding();
        // In ID3v2.2 the MIME type is always 3 characters
        if (major_v == 2) {
          apic['mime'] = latin1.decode(frame.readBytes(3));
        } else {
          apic['mime'] = frame.readLatin1String();
        }
        apic['picType'] = PICTYPE[frame.readBytes(1).first] ?? 'Unknown';
        apic['description'] = frame.readString(checkEncoding: false);
        apic['base64'] = base64.encode(frame.readRemainingBytes());
        metaTags['APIC'] = apic;
      } else if (frames_db[latin1.decode(frameName)] == FRAMESv2_3['USLT']) {
        final frame = _MP3FrameParser(frameContent);
        frame.readEncoding();
        final language = latin1.decode(frame.readBytes(3));
        String contentDescriptor;
        contentDescriptor = frame.readString(checkEncoding: false);
        final lyrics = (frame.remainingBytes > 0)
            ? frame.readString(checkEncoding: false, terminator: false)
            : contentDescriptor;
        if (frame.remainingBytes == 0) {
          contentDescriptor = '';
        }
        metaTags['USLT'] = {
          'language': language,
          'contentDescriptor': contentDescriptor,
          'lyrics': lyrics
        };
      } else if (frames_db[latin1.decode(frameName)] == FRAMESv2_3['WXXX']) {
        final frame = _MP3FrameParser(frameContent);
        metaTags['WXXX'] = {
          'description': frame.readString(),
          'url': frame.readLatin1String(terminator: false)
        };
      } else if (frames_db[latin1.decode(frameName)] == FRAMESv2_3['COMM']) {
        final frame = _MP3FrameParser(frameContent);
        frame.readEncoding();
        final language = latin1.decode(frame.readBytes(3));
        final shortDescription = frame.readString(checkEncoding: false);
        final text =
            frame.readString(terminator: false, checkEncoding: false);
        if (metaTags['COMM'] == null) {
          metaTags['COMM'] = {};
          if (metaTags['COMM'][language] == null) {
            metaTags['COMM'][language] = {};
          }
        }
        metaTags['COMM'][language][shortDescription] = text;
      } else if (frames_db[latin1.decode(frameName)] == FRAMESv2_3['MCDI'] ||
          frames_db[latin1.decode(frameName)] == FRAMESv2_3['RVAD']) {
        // Binary data
        metaTags[frames_db[latin1.decode(frameName)] ??
            latin1.decode(frameName)] = frameContent;
      } else {
        final String tag =
            frames_db[latin1.decode(frameName)] ?? latin1.decode(frameName);
        metaTags[tag] =
            _MP3FrameParser(frameContent).readString(terminator: false);
      }

      cb += frameHeaderLength + frameSize;
    }

    return true;
  }

  final List<int> _header =
      mp3Bytes.sublist(mp3Bytes.length - 128, mp3Bytes.length);
  _tag = _header.sublist(0, 3);

  if (latin1.decode(_tag).toLowerCase() == 'tag') {
    metaTags['Version'] = '1.0';

    final List<int> _title = _header.sublist(3, 33);
    final List<int> _artist = _header.sublist(33, 63);
    final List<int> _album = _header.sublist(63, 93);
    final List<int> _year = _header.sublist(93, 97);
    final List<int> _comment = _header.sublist(97, 127);
    final int _genre = _header[127];

    metaTags['Title'] = latin1.decode(_title).trim();
    metaTags['Artist'] = latin1.decode(_artist).trim();
    metaTags['Album'] = latin1.decode(_album).trim();
    metaTags['Year'] = latin1.decode(_year).trim();
    metaTags['Comment'] = latin1.decode(_comment).trim();
    metaTags['Genre'] = GENREv1[_genre];

    return true;
  }

  return false;
}