Skip to content

Commit

Permalink
Added an event that triggers when metadata is received from the track…
Browse files Browse the repository at this point in the history
… source (#552)

* Added the playback-metadata-received event

The event supports ID3 tags and ICY Metadata. Closes #192
  • Loading branch information
Guichaguri authored May 1, 2019
1 parent 4f491e0 commit 61f7a8e
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,20 @@ public void onEnd(Track previous, long prevPos) {
service.emit(MusicEvents.PLAYBACK_QUEUE_ENDED, bundle);
}

public void onMetadataReceived(String source, String title, String url, String artist, String album, String date, String genre) {
Log.d(Utils.LOG, "onMetadataReceived: " + source);

Bundle bundle = new Bundle();
bundle.putString("source", source);
bundle.putString("title", title);
bundle.putString("url", url);
bundle.putString("artist", artist);
bundle.putString("album", album);
bundle.putString("date", date);
bundle.putString("genre", genre);
service.emit(MusicEvents.PLAYBACK_METADATA, bundle);
}

public void onError(String code, String error) {
Log.d(Utils.LOG, "onError");
Log.e(Utils.LOG, "Playback error: " + code + " - " + error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.*;
import com.google.android.exoplayer2.Player.EventListener;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataOutput;
import com.google.android.exoplayer2.metadata.icy.IcyHeaders;
import com.google.android.exoplayer2.metadata.icy.IcyInfo;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.metadata.id3.UrlLinkFrame;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.guichaguri.trackplayer.service.MusicManager;
Expand All @@ -24,7 +27,7 @@
/**
* @author Guichaguri
*/
public abstract class ExoPlayback<T extends Player> implements EventListener {
public abstract class ExoPlayback<T extends Player> implements EventListener, MetadataOutput {

protected final Context context;
protected final MusicManager manager;
Expand All @@ -41,6 +44,9 @@ public ExoPlayback(Context context, MusicManager manager, T player) {
this.context = context;
this.manager = manager;
this.player = player;

Player.MetadataComponent component = player.getMetadataComponent();
if(component != null) component.addMetadataOutput(this);
}

public void initialize() {
Expand Down Expand Up @@ -242,7 +248,21 @@ public void onPositionDiscontinuity(int reason) {

@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

for(int i = 0; i < trackGroups.length; i++) {
// Loop through all track groups.
// As for the current implementation, there should be only one
TrackGroup group = trackGroups.get(i);

for(int f = 0; f < group.length; f++) {
// Loop through all formats inside the track group
Format format = group.getFormat(f);

// Parse the metadata if it is present
if (format.metadata != null) {
onMetadata(format.metadata);
}
}
}
}

@Override
Expand Down Expand Up @@ -306,4 +326,81 @@ public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
public void onSeekProcessed() {
// Finished seeking
}

private void handleId3Metadata(Metadata metadata) {
String title = null, url = null, artist = null, album = null, date = null, genre = null;

for(int i = 0; i < metadata.length(); i++) {
Metadata.Entry entry = metadata.get(i);

if (entry instanceof TextInformationFrame) {
// ID3 text tag
TextInformationFrame id3 = (TextInformationFrame) entry;
String id = id3.id.toUpperCase();

if (id.equals("TIT2") || id.equals("TT2")) {
title = id3.value;
} else if (id.equals("TALB") || id.equals("TOAL") || id.equals("TAL")) {
album = id3.value;
} else if (id.equals("TOPE") || id.equals("TPE1") || id.equals("TP1")) {
artist = id3.value;
} else if (id.equals("TDRC") || id.equals("TOR")) {
date = id3.value;
} else if (id.equals("TCON") || id.equals("TCO")) {
genre = id3.value;
}

} else if (entry instanceof UrlLinkFrame) {
// ID3 URL tag
UrlLinkFrame id3 = (UrlLinkFrame) entry;
String id = id3.id.toUpperCase();

if (id.equals("WOAS") || id.equals("WOAF") || id.equals("WOAR") || id.equals("WAR")) {
url = id3.url;
}

}
}

if (title != null || url != null || artist != null || album != null || date != null || genre != null) {
manager.onMetadataReceived("id3", title, url, artist, album, date, genre);
}
}

private void handleIcyMetadata(Metadata metadata) {
for (int i = 0; i < metadata.length(); i++) {
Metadata.Entry entry = metadata.get(i);

if(entry instanceof IcyHeaders) {
// ICY headers
IcyHeaders icy = (IcyHeaders)entry;

manager.onMetadataReceived("icy-headers", icy.name, icy.url, null, null, null, icy.genre);

} else if(entry instanceof IcyInfo) {
// ICY data
IcyInfo icy = (IcyInfo)entry;

String artist, title;
int index = icy.title == null ? -1 : icy.title.indexOf(" - ");

if (index != -1) {
artist = icy.title.substring(0, index);
title = icy.title.substring(index + 3);
} else {
artist = null;
title = icy.title;
}

manager.onMetadataReceived("icy", title, icy.url, artist, null, null, null);

}
}
}

@Override
public void onMetadata(Metadata metadata) {
handleId3Metadata(metadata);
handleIcyMetadata(metadata);
}
}
13 changes: 13 additions & 0 deletions docs/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,19 @@ Fired when the queue reaches the end.
| track | `string` | The previous track id. Might be null |
| position | `number` | The previous track position in seconds |

#### `playback-metadata-received`
Fired when the current track receives metadata encoded in. (e.g. ID3 tags or Icy Metadata).

| Param | Type | Description |
| -------- | -------- | --------------------------------------------------- |
| source | `string` | The metadata source (`id3`, `icy` or `icy-headers`) |
| title | `string` | The track title. Might be null |
| url | `string` | The track url. Might be null |
| artist | `string` | The track artist. Might be null |
| album | `string` | The track album. Might be null |
| date | `string` | The track date. Might be null |
| genre | `string` | The track genre. Might be null |

#### `playback-error`
Fired when an error occurs.

Expand Down

0 comments on commit 61f7a8e

Please sign in to comment.