Skip to content

Commit

Permalink
Merge branch 'release/v0.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
NiKoTron committed Sep 23, 2019
2 parents 589837d + 80c8cce commit cc755f7
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 25 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,6 @@ fabric.properties
*.tmp
*.bak

test/output/*
test/output/*

.idea
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,8 @@
- fixed empty tag exception for id3v1
- added [CoC](CODE_OF_CONDUCT.md)
- fixed writing APIC tag [issue #3](https://github.com/NiKoTron/dart-tags/issues/3)

## 0.2.1

- fixed an issue with wrong utf16 decoding thanx [@magodo](https://github.com/magodo) and his [PR](https://github.com/NiKoTron/dart-tags/pull/9)
- wrote some additional tests
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@ linter:

- prefer_single_quotes
- package_api_docs
# - public_member_api_docs

4 changes: 3 additions & 1 deletion lib/src/convert/utf16.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'dart:convert';

import 'package:utf/utf.dart';

class UTF16 extends Encoding {
@override
Converter<List<int>, String> get decoder => _UTF16Decoder();
Expand All @@ -14,7 +16,7 @@ class UTF16 extends Encoding {
class _UTF16Decoder extends Converter<List<int>, String> {
@override
String convert(List<int> input) {
return String.fromCharCodes(input);
return decodeUtf16le(input, 0, input.length);
}
}

Expand Down
13 changes: 8 additions & 5 deletions lib/src/frames/frame.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
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/wxxx_frame.dart';
import 'package:dart_tags/src/model/consts.dart' as consts;

import 'id3v2/default_frame.dart';
import 'id3v2/id3v2_frame.dart';

import 'package:dart_tags/src/model/consts.dart' as consts;

/// Abstract implementation of id3v2 frame
abstract class Frame<T> {
/// Encode [key] tag with [value] to bytearray
List<int> encode(T value, [String key]);

/// Decode byte [data] to frame data map
MapEntry<String, T> decode(List<int> data);
}

Expand Down Expand Up @@ -57,8 +61,7 @@ class FramesID3V24 {
assert(data is List<int> || data is String);

if (data is List<int>) {
final encoding = ID3V2Frame.getEncoding(data[ID3V2Frame.headerLength]);
final tag = encoding.decode(data.sublist(0, 4));
final tag = latin1.decode(data.sublist(0, 4));
return _getFrame(consts.framesV23_V24[tag] ?? tag);
} else if (data is String) {
return _getFrame(getTagByPseudonym(data));
Expand Down
4 changes: 2 additions & 2 deletions lib/src/frames/id3v2/id3v2_frame.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ abstract class ID3V2Frame<T> implements Frame<T> {

@override
MapEntry<String, T> decode(List<int> data) {
final encoding = getEncoding(data[headerLength]);
final tag = encoding.decode(data.sublist(0, 4));
final tag = latin1.decode(data.sublist(0, 4));
if (!consts.framesHeaders.keys.contains(tag)) {
print('$tag unknown tag');
return null;
Expand All @@ -37,6 +36,7 @@ abstract class ID3V2Frame<T> implements Frame<T> {
return null;
}

final encoding = getEncoding(data[headerLength]);
_header = ID3V2FrameHeader(tag, encoding, size);

print('${data.length}, ${headerLength}, ${_header.length}');
Expand Down
4 changes: 2 additions & 2 deletions lib/src/tag_processor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class TagProcessor {
/// Returns the tags from the byte array
Future<List<Tag>> getTagsFromByteArray(Future<List<int>> bytes,
[List<TagType> types]) async {
if (bytes == null) {
if (await bytes == null) {
throw ParsingException(ParsingException.byteArrayNull);
}

Expand Down Expand Up @@ -88,7 +88,7 @@ class TagProcessor {

Future<List<int>> putTagsToByteArray(Future<List<int>> bytes,
[List<Tag> tags]) async {
if (bytes == null) {
if (await bytes == null) {
throw ParsingException(ParsingException.byteArrayNull);
}
var b = await bytes;
Expand Down
1 change: 1 addition & 0 deletions lib/src/writers/id3v2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ID3V2Writer extends Writer {
return c.future;
}

/// Returns size of frame in bytes
static List<int> frameSizeInBytes(int value) {
assert(value <= 16777216);

Expand Down
5 changes: 4 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
name: dart_tags
description: The library for work with music tags like ID3. Written on pure Dart. It can be used in flutter, web, and vm projects.
version: 0.2.0
version: 0.2.1
homepage: https://github.com/NiKoTron/dart-tags
author: NiKoTron <nickolay.simonov@gmail.com>

environment:
sdk: '>=2.3.0 <3.0.0'

dependencies:
utf: ^0.9.0+5

dev_dependencies:
pedantic: ^1.8.0+1
test: ^1.6.5
117 changes: 109 additions & 8 deletions test/dart_tags_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@TestOn('vm')
import 'dart:io';
import 'dart:typed_data';

import 'package:dart_tags/dart_tags.dart';
import 'package:dart_tags/src/frames/id3v2/comm_frame.dart';
Expand All @@ -23,6 +24,15 @@ void main() {
picture = File('test/test_assets/mink-mingle-109837-unsplash.jpg');
});

group('Parsing exception Tests', () {
test('Exception cause should be correct', () {
final ex1 = ParsingException(ParsingException.byteArrayNull);
final ex2 = ParsingException(ParsingException.byteDataNull);
expect(ex1.cause, ParsingException.byteArrayNull);
expect(ex2.cause, ParsingException.byteDataNull);
});
});

group('V2 Frame Tests', () {
test('COMM encode', () {
final expected = [
Expand Down Expand Up @@ -192,10 +202,21 @@ void main() {
..type = 'ID3'
..version = '2.4';

final _av = () async =>
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

final foo = await TagProcessor().putTagsToByteArray(_av(), [tag1, tag2]);
final foo = await TagProcessor().putTagsToByteArray(
Future.value([
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
]),
[tag1, tag2]);

final _fr = () async => foo;

Expand All @@ -207,9 +228,58 @@ void main() {
final t2 = await rdr2.read(_fr());
expect(t2.tags, equals(tag2.tags));
});

test('put null block', () async {
final tag1 = Tag()
..tags = {
'title': 'foo',
'artist': 'bar',
'album': 'baz',
'year': '2010',
'comment': 'lol it is a comment',
'track': '6',
'genre': 'Dream'
}
..type = 'ID3'
..version = '1.1';

final tag2 = Tag()
..tags = {
'title': 'foo',
'artist': 'bar',
'album': 'baz',
'year': '2010',
'comment': Comment('eng', 'desc', 'lol it is a comment'),
'track': '6',
'genre': 'Dream',
'Custom': 'Just tag'
}
..type = 'ID3'
..version = '2.4';

expect(
() async => await TagProcessor()
.putTagsToByteArray(Future.value(null), [tag1, tag2]),
throwsA(predicate<Exception>((e) =>
e is ParsingException &&
e.cause == ParsingException.byteArrayNull)));
});
});

group('Reader Tests', () {
test('Test with file unspecified', () async {
final foo =
await TagProcessor().getTagsFromByteArray(file2.readAsBytes());

expect(foo.length, equals(2));

expect(foo[0].type, equals('ID3'));
expect(foo[0].version, equals('1.1'));

expect(foo[1].type, equals('ID3'));
expect(foo[1].version, equals('2.4.0'));
});

test('Test with file 1.1', () async {
final foo = await TagProcessor()
.getTagsFromByteArray(file1.readAsBytes(), [TagType.id3v1]);
Expand All @@ -230,6 +300,26 @@ void main() {
expect(foo[0].version, equals('2.4.0'));
});

test('Test with file 1.1 ByteData', () async {
final foo = await TagProcessor().getTagsFromByteData(
ByteData.view(file1.readAsBytesSync().buffer), [TagType.id3v1]);

expect(foo.length, equals(1));

expect(foo[0].type, equals('ID3'));
expect(foo[0].version, equals('1.1'));
});

test('Test with file 2.4 ByteData', () async {
final foo = await TagProcessor().getTagsFromByteData(
ByteData.view(file2.readAsBytesSync().buffer), [TagType.id3v2]);

expect(foo.length, equals(1));

expect(foo[0].type, equals('ID3'));
expect(foo[0].version, equals('2.4.0'));
});

test('Test on Failure', () async {
expect(
() async => await TagProcessor().getTagsFromByteArray(null),
Expand All @@ -256,10 +346,21 @@ void main() {
..type = 'ID3'
..version = '2.4';

final _av = () async =>
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

final foo = await TagProcessor().putTagsToByteArray(_av(), [tag2]);
final foo = await TagProcessor().putTagsToByteArray(
Future.value([
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
]),
[tag2]);

final _fr = () async => foo;

Expand Down
7 changes: 2 additions & 5 deletions tool/travis/cov.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
#! /bin/sh

export REPO_TOKEN=RltkmM2Z4YjS0yAjabbeiuWHOy4b6sv32

# Install dart_coveralls; gather and send coverage data.
if [ "$REPO_TOKEN" ]; then
if [ "$COVERALLS_TOKEN" ]; then
pub global activate dart_coveralls
pub global run dart_coveralls report \
--token $REPO_TOKEN \
--token $COVERALLS_TOKEN \
--retry 2 \
--exclude-test-files \
test/dart_tags_test.dart
Expand Down

0 comments on commit cc755f7

Please sign in to comment.