Skip to content

Commit

Permalink
Merge branch 'release/0.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
NiKoTron committed Aug 9, 2020
2 parents 91a5397 + 9390aed commit 9cb14ad
Show file tree
Hide file tree
Showing 28 changed files with 670 additions and 235 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,15 @@
## 0.3.0 (BREAKING CHANGES)

- COMM, APIC, USLT, WXXX tags returns as a map
- WXXX frame returns WURL object
- various fixes
- added USLT tag
- added possibility to pass many COMM, APIC, USLT tags
- APIC processing was refactored
- hex encoder
- unrecognized encoding falls to hex encoder (removed unsupported encoding error)
- unsupported tags like PRIV will be printed just like raw binary data

## 0.2.3

- Fixed issue [issue #13](https://github.com/NiKoTron/dart-tags/issues/13))
Expand Down
22 changes: 15 additions & 7 deletions README.md
Expand Up @@ -16,22 +16,30 @@ project under MIT [license][license]

[full changelog][changelog]

## 0.2.3
## 0.3.0 (BREAKING CHANGES)

- Fixed wrong utf16 decoding. issue [issue #13](https://github.com/NiKoTron/dart-tags/issues/13))
- COMM, APIC, USLT, WXXX tags returns as a map
- WXXX frame returns WURL object
- various fixes
- added USLT tag
- added possibility to pass many COMM, APIC, USLT tags
- APIC processing was refactored
- hex encoder
- unrecognized encoding falls to hex encoder (removed unsupported encoding error)
- unsupported tags like PRIV will be printed just like raw binary data

## 0.2.2

- fixed an issue with wrong header calculation thanx [@frankdenouter](https://github.com/frankdenouter) and his [PR](https://github.com/NiKoTron/dart-tags/pull/10)
- added test assets v23 for reader
## 0.2.3

- Fixed wrong utf16 decoding. issue [issue #13](https://github.com/NiKoTron/dart-tags/issues/13))

## Instalation

add dependency in pubsec.yaml

```yaml
dependencies:
dart_tags: ^0.2.2
dart_tags: ^0.3.0
```

## Usage
Expand Down Expand Up @@ -66,7 +74,7 @@ Thanx for contributing [@magodo](https://github.com/magodo), [@frankdenouter](ht

Thanx for the [Photo][photo] by [Mink Mingle][mink_mingle] on [Unsplash][unsplash] that we using in unit tests.

[id3org]: http://id3.org/Home
[id3org]: https://id3.org/Home
[tracker]: https://github.com/NiKoTron/dart-tags/issues
[changelog]: CHANGELOG.md
[license]: LICENSE
Expand Down
23 changes: 23 additions & 0 deletions lib/src/convert/hex_encoding.dart
@@ -0,0 +1,23 @@
import 'dart:convert';

import 'package:convert/convert.dart';

class HEXEncoding extends Encoding {
@override
Converter<List<int>, String> get decoder => _HEXDecoder();
@override
Converter<String, List<int>> get encoder => _HEXEnoder();

@override
String get name => 'hex';
}

class _HEXDecoder extends Converter<List<int>, String> {
@override
String convert(List<int> input) => hex.encode(input);
}

class _HEXEnoder extends Converter<String, List<int>> {
@override
List<int> convert(String input) => hex.decode(input);
}
68 changes: 59 additions & 9 deletions lib/src/convert/utf16.dart
@@ -1,28 +1,78 @@
import 'dart:convert';
import 'dart:core';

import 'package:utf/utf.dart';
import 'package:utf/utf.dart' as utf;

abstract class UTF16 extends Encoding {
List<int> get bom;

static const le = [0xff, 0xfe];
static const be = [0xfe, 0xff];

@override
Converter<List<int>, String> get decoder;

@override
Converter<String, List<int>> get encoder;

@override
String get name; // => 'utf16';
}

class UTF16LE extends UTF16 {
@override
List<int> get bom => UTF16.le;

@override
Converter<List<int>, String> get decoder => _UTF16LEDecoder();

@override
Converter<String, List<int>> get encoder => _UTF16LEEnoder();

@override
String get name => 'utf16le';
}

class _UTF16LEDecoder extends Converter<List<int>, String> {
@override
String convert(List<int> input) {
final decoder = utf.Utf16leBytesToCodeUnitsDecoder(input);
return String.fromCharCodes(decoder.decodeRest());
}
}

class _UTF16LEEnoder extends Converter<String, List<int>> {
@override
List<int> convert(String input) {
return utf.encodeUtf16le(input, true);
}
}

class UTF16BE extends UTF16 {
@override
List<int> get bom => UTF16.be;

class UTF16 extends Encoding {
@override
Converter<List<int>, String> get decoder => _UTF16Decoder();
Converter<List<int>, String> get decoder => _UTF16BEDecoder();

@override
Converter<String, List<int>> get encoder => _UTF16Enoder();
Converter<String, List<int>> get encoder => _UTF16BEEnoder();

@override
String get name => 'utf16';
String get name => 'utf16be';
}

class _UTF16Decoder extends Converter<List<int>, String> {
class _UTF16BEDecoder extends Converter<List<int>, String> {
@override
String convert(List<int> input) {
return decodeUtf16(input);
final decoder = utf.Utf16beBytesToCodeUnitsDecoder(input);
return String.fromCharCodes(decoder.decodeRest());
}
}

class _UTF16Enoder extends Converter<String, List<int>> {
class _UTF16BEEnoder extends Converter<String, List<int>> {
@override
List<int> convert(String input) {
return input.runes.toList();
return utf.encodeUtf16be(input, true);
}
}
8 changes: 5 additions & 3 deletions lib/src/frames/frame.dart
Expand Up @@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:dart_tags/src/frames/id3v2/apic_frame.dart';
import 'package:dart_tags/src/frames/id3v2/comm_frame.dart';
import 'package:dart_tags/src/frames/id3v2/txxx_frame.dart';
import 'package:dart_tags/src/frames/id3v2/uslt_frame.dart';
import 'package:dart_tags/src/frames/id3v2/wxxx_frame.dart';
import 'package:dart_tags/src/model/consts.dart' as consts;

Expand All @@ -17,7 +18,7 @@ abstract class Frame<T> {
MapEntry<String, T> decode(List<int> data);
}

class FrameFactory {
class FrameFactory<T extends Frame> {
String version;

// ignore: avoid_annotating_with_dynamic
Expand All @@ -36,15 +37,16 @@ class FrameFactory {
return FrameFactory._internal('0', (v) => null);
}

T getFrame<T extends Frame>(entry) => _frameGetter(entry);
T getFrame(entry) => _frameGetter(entry);
}

class FramesID3V24 {
final Map<String, Frame> _frames = {
'APIC': ApicFrame(),
'TXXX': TXXXFrame(),
'WXXX': WXXXFrame(),
'COMM': COMMFrame()
'COMM': COMMFrame(),
'USLT': USLTFrame(),
};

Frame<T> _getFrame<T>(String tag) {
Expand Down
62 changes: 31 additions & 31 deletions lib/src/frames/id3v2/apic_frame.dart
@@ -1,7 +1,10 @@
import 'dart:convert';

import 'package:dart_tags/src/frames/id3v2/id3v2_frame.dart';
import 'package:dart_tags/src/model/attached_picture.dart';
import 'package:dart_tags/src/convert/utf16.dart';
import 'package:dart_tags/src/utils/image_extractor.dart';

import '../../frames/id3v2/id3v2_frame.dart';
import '../../model/attached_picture.dart';

/* http://id3.org/id3v2.4.0-frames
4.14. Attached picture
Expand Down Expand Up @@ -53,43 +56,39 @@ import 'package:dart_tags/src/model/attached_picture.dart';
*/

class ApicFrame with ID3V2Frame<AttachedPicture> {
final _imageExtractors = {
'image/jpg': () => JPEGImageExtractor(),
'image/jpeg': () => JPEGImageExtractor(),
'image/png': () => PNGImageExtractor(),
};

@override
AttachedPicture decodeBody(List<int> data, Encoding enc) {
final iterator = data.iterator;
var buff = <int>[];

final attachedPicture = AttachedPicture();

var cont = 0;

while (iterator.moveNext() && cont < 4) {
final crnt = iterator.current;
if (crnt == 0x00 && cont < 3) {
if (cont == 1 && buff.isNotEmpty) {
attachedPicture.imageTypeCode = buff[0];
cont++;
attachedPicture.description = enc.decode(buff.sublist(1));
} else {
attachedPicture.mime = enc.decode(buff);
}
buff = [];
cont++;
continue;
}
buff.add(crnt);
}

attachedPicture.imageData = buff;

return attachedPicture;
final splitIndex1 = data.indexOf(0x00);

final mime = latin1.decode(data.sublist(0, splitIndex1));
final imageType = data[splitIndex1 + 1];

final splitIndex2 = enc is UTF16
? indexOfSplitPattern(
data.sublist(splitIndex1 + 1), [0x00, 0x00], splitIndex1)
: data.sublist(splitIndex1 + 1).indexOf(0x00) + splitIndex1 + 1;

final description = enc.decode(data.sublist(splitIndex1 + 2, splitIndex2));

final imageData = _imageExtractors.containsKey(mime)
? _imageExtractors[mime]().parse(data.sublist(splitIndex2))
: data.sublist(splitIndex2);

return AttachedPicture(mime, imageType, description, imageData);
}

@override
List<int> encode(AttachedPicture value, [String key]) {
final mimeEncoded = utf8.encode(value.mime);
final mimeEncoded = latin1.encode(value.mime);
final descEncoded = utf8.encode(value.description);

return [
final b = [
...utf8.encode(frameTag),
...frameSizeInBytes(
mimeEncoded.length + descEncoded.length + value.imageData.length + 4),
Expand All @@ -101,6 +100,7 @@ class ApicFrame with ID3V2Frame<AttachedPicture> {
0x00,
...value.imageData
];
return b;
}

@override
Expand Down
20 changes: 13 additions & 7 deletions lib/src/frames/id3v2/comm_frame.dart
@@ -1,7 +1,7 @@
import 'dart:convert';

import 'package:dart_tags/src/model/comment.dart';

import '../../convert/utf16.dart';
import '../../model/comment.dart';
import 'id3v2_frame.dart';

/* http://id3.org/id3v2.4.0-frames
Expand All @@ -25,10 +25,16 @@ import 'id3v2_frame.dart';
class COMMFrame extends ID3V2Frame<Comment> {
@override
Comment decodeBody(List<int> data, Encoding enc) {
final lang = enc.decode(data.sublist(0, 3));
final splitIndex = data.indexOf(0x00);
final description = enc.decode(data.sublist(3, splitIndex));
final body = enc.decode(data.sublist(splitIndex + 1));
final lang = latin1.decode(data.sublist(0, 3));
final splitIndex = enc is UTF16
? indexOfSplitPattern(data, [0x00, 0x00], 3)
: data.indexOf(0x00);
final description =
splitIndex < 0 ? '' : enc.decode(data.sublist(3, splitIndex));
final offset = splitIndex + (enc is UTF16 ? 2 : 1);
final bodyBytes = data.sublist(offset);

final body = enc.decode(bodyBytes);

return Comment(lang, description, body);
}
Expand All @@ -38,7 +44,7 @@ class COMMFrame extends ID3V2Frame<Comment> {
final enc = header?.encoding ?? utf8;

return [
...enc.encode(frameTag),
...latin1.encode(frameTag),
...frameSizeInBytes(value.lang.length +
value.description.length +
1 +
Expand Down
2 changes: 1 addition & 1 deletion lib/src/frames/id3v2/default_frame.dart
@@ -1,6 +1,6 @@
import 'dart:convert';

import 'package:dart_tags/src/frames/id3v2/id3v2_frame.dart';
import '../../frames/id3v2/id3v2_frame.dart';

class DefaultFrame with ID3V2Frame<String> {
final String _tag;
Expand Down

0 comments on commit 9cb14ad

Please sign in to comment.