Merge "Address API feedback on setOnRtpRxNoticeListener"
This commit is contained in:
committed by
Android (Google) Code Review
commit
c45ddb6938
@@ -4424,11 +4424,11 @@ package android.media {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
|
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
|
||||||
method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler);
|
method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface MediaPlayer.OnImsRxNoticeListener {
|
public static interface MediaPlayer.OnRtpRxNoticeListener {
|
||||||
method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]);
|
method public void onRtpRxNotice(@NonNull android.media.MediaPlayer, int, @NonNull int[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class MediaRecorder.AudioSource {
|
public final class MediaRecorder.AudioSource {
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(jav
|
|||||||
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
|
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
|
||||||
|
|
||||||
|
|
||||||
ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
|
ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
|
||||||
Registration methods should have overload that accepts delivery Executor: `setOnImsRxNoticeListener`
|
Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener`
|
||||||
ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#deletePersistentGroup(android.net.wifi.p2p.WifiP2pManager.Channel, int, android.net.wifi.p2p.WifiP2pManager.ActionListener):
|
ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#deletePersistentGroup(android.net.wifi.p2p.WifiP2pManager.Channel, int, android.net.wifi.p2p.WifiP2pManager.ActionListener):
|
||||||
|
|
||||||
ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#factoryReset(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener):
|
ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#factoryReset(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener):
|
||||||
@@ -377,8 +377,8 @@ SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.
|
|||||||
|
|
||||||
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
||||||
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
||||||
SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
|
SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
|
||||||
SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnImsRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
||||||
SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
||||||
|
|
||||||
SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
|
SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
|
||||||
|
|||||||
@@ -4364,11 +4364,11 @@ package android.media {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
|
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
|
||||||
method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler);
|
method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface MediaPlayer.OnImsRxNoticeListener {
|
public static interface MediaPlayer.OnRtpRxNoticeListener {
|
||||||
method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]);
|
method public void onRtpRxNotice(@NonNull android.media.MediaPlayer, int, @NonNull int[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class MediaRecorder.AudioSource {
|
public final class MediaRecorder.AudioSource {
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
|
|||||||
BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
|
BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
|
||||||
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
|
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
|
||||||
|
|
||||||
ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
|
ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
|
||||||
|
Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener`
|
||||||
|
|
||||||
GenericException: android.app.prediction.AppPredictor#finalize():
|
GenericException: android.app.prediction.AppPredictor#finalize():
|
||||||
|
|
||||||
@@ -182,7 +183,8 @@ SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallb
|
|||||||
|
|
||||||
SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
||||||
|
|
||||||
SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
|
SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
|
||||||
|
SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
||||||
|
|
||||||
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package android.media;
|
package android.media;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.BIND_IMS_SERVICE;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -83,6 +86,7 @@ import java.util.BitSet;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -2109,8 +2113,8 @@ public class MediaPlayer extends PlayerBase
|
|||||||
mOnInfoListener = null;
|
mOnInfoListener = null;
|
||||||
mOnVideoSizeChangedListener = null;
|
mOnVideoSizeChangedListener = null;
|
||||||
mOnTimedTextListener = null;
|
mOnTimedTextListener = null;
|
||||||
mOnImsRxNoticeListener = null;
|
mOnRtpRxNoticeListener = null;
|
||||||
mOnImsRxNoticeHandler = null;
|
mOnRtpRxNoticeHandler = null;
|
||||||
synchronized (mTimeProviderLock) {
|
synchronized (mTimeProviderLock) {
|
||||||
if (mTimeProvider != null) {
|
if (mTimeProvider != null) {
|
||||||
mTimeProvider.close();
|
mTimeProvider.close();
|
||||||
@@ -3323,7 +3327,7 @@ public class MediaPlayer extends PlayerBase
|
|||||||
private static final int MEDIA_META_DATA = 202;
|
private static final int MEDIA_META_DATA = 202;
|
||||||
private static final int MEDIA_DRM_INFO = 210;
|
private static final int MEDIA_DRM_INFO = 210;
|
||||||
private static final int MEDIA_TIME_DISCONTINUITY = 211;
|
private static final int MEDIA_TIME_DISCONTINUITY = 211;
|
||||||
private static final int MEDIA_IMS_RX_NOTICE = 300;
|
private static final int MEDIA_RTP_RX_NOTICE = 300;
|
||||||
private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;
|
private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;
|
||||||
|
|
||||||
private TimeProvider mTimeProvider;
|
private TimeProvider mTimeProvider;
|
||||||
@@ -3633,31 +3637,34 @@ public class MediaPlayer extends PlayerBase
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case MEDIA_IMS_RX_NOTICE:
|
case MEDIA_RTP_RX_NOTICE:
|
||||||
final OnImsRxNoticeListener imsRxNoticeListener;
|
final OnRtpRxNoticeListener rtpRxNoticeListener = mOnRtpRxNoticeListener;
|
||||||
final Handler imsRxNoticeHandler;
|
final Handler rtpRxNoticeHandler = mOnRtpRxNoticeHandler;
|
||||||
imsRxNoticeListener = mOnImsRxNoticeListener;
|
if (rtpRxNoticeListener == null) {
|
||||||
imsRxNoticeHandler = mOnImsRxNoticeHandler;
|
|
||||||
if (imsRxNoticeListener == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg.obj instanceof Parcel) {
|
if (msg.obj instanceof Parcel) {
|
||||||
Parcel parcel = (Parcel) msg.obj;
|
Parcel parcel = (Parcel) msg.obj;
|
||||||
byte[] event;
|
parcel.setDataPosition(0);
|
||||||
|
int noticeType;
|
||||||
|
int[] data;
|
||||||
try {
|
try {
|
||||||
event = parcel.marshall();
|
noticeType = parcel.readInt();
|
||||||
|
int numOfArgs = parcel.dataAvail() / 4;
|
||||||
|
data = new int[numOfArgs];
|
||||||
|
for (int i = 0; i < numOfArgs; i++) {
|
||||||
|
data[i] = parcel.readInt();
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
parcel.recycle();
|
parcel.recycle();
|
||||||
}
|
}
|
||||||
if (imsRxNoticeHandler == null) {
|
if (rtpRxNoticeHandler == null) {
|
||||||
imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event);
|
rtpRxNoticeListener.onRtpRxNotice(mMediaPlayer, noticeType, data);
|
||||||
} else {
|
} else {
|
||||||
imsRxNoticeHandler.post(new Runnable() {
|
rtpRxNoticeHandler.post(
|
||||||
@Override
|
() ->
|
||||||
public void run() {
|
rtpRxNoticeListener
|
||||||
imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event);
|
.onRtpRxNotice(mMediaPlayer, noticeType, data));
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -4103,18 +4110,18 @@ public class MediaPlayer extends PlayerBase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface definition of a callback to be invoked when
|
* Interface definition of a callback to be invoked when
|
||||||
* IMS Rx connection has a notice.
|
* RTP Rx connection has a notice.
|
||||||
*
|
*
|
||||||
* @see MediaPlayer.setOnImsRxNoticeListener
|
* @see #setOnRtpRxNoticeListener
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
public interface OnImsRxNoticeListener
|
public interface OnRtpRxNoticeListener
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Called to indicate an IMS event noticed from native media frameworks.
|
* Called when an RTP Rx connection has a notice.
|
||||||
* <p></p>
|
* <p>
|
||||||
* Basic format. All TYPE and ARG are 4 bytes unsigned integer in native byte order.
|
* Basic format. All TYPE and ARG are 4 bytes unsigned integer in native byte order.
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* 0 4 8 12
|
* 0 4 8 12
|
||||||
@@ -4169,14 +4176,14 @@ public class MediaPlayer extends PlayerBase
|
|||||||
* TYPE 205 - Transport layer Feedback message. (RFC-5104 Sec.4.2)
|
* TYPE 205 - Transport layer Feedback message. (RFC-5104 Sec.4.2)
|
||||||
* 0 4 8 12
|
* 0 4 8 12
|
||||||
* +----------------+---------------+----------------+----------------+
|
* +----------------+---------------+----------------+----------------+
|
||||||
* | 205 | SSRC | FB type(1 or 3)| value |
|
* | 205 |FB type(1 or 3)| SSRC | Value |
|
||||||
* +----------------+---------------+----------------+----------------+
|
* +----------------+---------------+----------------+----------------+
|
||||||
* SSRC
|
|
||||||
* - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
|
|
||||||
* Feedback (FB) type: determines the type of the event.
|
* Feedback (FB) type: determines the type of the event.
|
||||||
* - if 1, we received a NACK request from the remote side.
|
* - if 1, we received a NACK request from the remote side.
|
||||||
* - if 3, we received a TMMBR (Temporary Maximum Media Stream Bit Rate Request) from
|
* - if 3, we received a TMMBR (Temporary Maximum Media Stream Bit Rate Request) from
|
||||||
* the remote side.
|
* the remote side.
|
||||||
|
* SSRC
|
||||||
|
* - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
|
||||||
* Value: the FCI (Feedback Control Information) depending on the value of FB type
|
* Value: the FCI (Feedback Control Information) depending on the value of FB type
|
||||||
* - if FB type is 1, the Generic NACK as specified in RFC-4585 Sec.6.2.1
|
* - if FB type is 1, the Generic NACK as specified in RFC-4585 Sec.6.2.1
|
||||||
* - if FB type is 3, the TMMBR as specified in RFC-5104 Sec.4.2.1.1
|
* - if FB type is 3, the TMMBR as specified in RFC-5104 Sec.4.2.1.1
|
||||||
@@ -4185,13 +4192,13 @@ public class MediaPlayer extends PlayerBase
|
|||||||
* TYPE 206 - Payload-specific Feedback message. (RFC-5104 Sec.4.3)
|
* TYPE 206 - Payload-specific Feedback message. (RFC-5104 Sec.4.3)
|
||||||
* 0 4 8
|
* 0 4 8
|
||||||
* +----------------+---------------+----------------+
|
* +----------------+---------------+----------------+
|
||||||
* | 206 | SSRC | FB type(1 or 4)|
|
* | 206 |FB type(1 or 4)| SSRC |
|
||||||
* +----------------+---------------+----------------+
|
* +----------------+---------------+----------------+
|
||||||
* SSRC
|
|
||||||
* - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
|
|
||||||
* Feedback (FB) type: determines the type of the event.
|
* Feedback (FB) type: determines the type of the event.
|
||||||
* - if 1, we received a PLI request from the remote side.
|
* - if 1, we received a PLI request from the remote side.
|
||||||
* - if 4, we received a FIR request from the remote side.
|
* - if 4, we received a FIR request from the remote side.
|
||||||
|
* SSRC
|
||||||
|
* - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* TYPE 300 - CVO (RTP Extension) message.
|
* TYPE 300 - CVO (RTP Extension) message.
|
||||||
@@ -4212,34 +4219,39 @@ public class MediaPlayer extends PlayerBase
|
|||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param mp the {@code MediaPlayer} associated with this callback.
|
* @param mp the {@code MediaPlayer} associated with this callback.
|
||||||
* @param event an IMS media event serialized as byte[] array.
|
* @param noticeType TYPE of the event.
|
||||||
|
* @param params RTP Rx media data serialized as int[] array.
|
||||||
*/
|
*/
|
||||||
void onImsRxNotice(@NonNull MediaPlayer mp, @NonNull byte[] event);
|
void onRtpRxNotice(@NonNull MediaPlayer mp, int noticeType, @NonNull int[] params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a callback to be invoked when IMS Rx connection has a notice.
|
* Sets the listener to be invoked when an RTP Rx connection has a notice.
|
||||||
* The callback required if mediaplayer configured for RTPSource by
|
* The listener is required if MediaPlayer is configured for RTPSource by
|
||||||
* MediaPlayer.setDataSource(String8 rtpParams) of mediaplayer.h
|
* MediaPlayer.setDataSource(String8 rtpParams) of mediaplayer.h.
|
||||||
*
|
*
|
||||||
* @see MediaPlayer.OnImsRxNoticeListener
|
* @see OnRtpRxNoticeListener
|
||||||
*
|
*
|
||||||
* @param listener the callback that will be run
|
* @param listener the listener called after a notice from RTP Rx
|
||||||
* @param handler Specifies Handler object for the thread on which to execute
|
* @param handler the {@link Handler} that receives RTP Tx events
|
||||||
* the callback. If null, the handler on the main looper will be used.
|
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
@RequiresPermission("android.permission.BIND_IMS_SERVICE")
|
@RequiresPermission("android.permission.BIND_IMS_SERVICE")
|
||||||
public void setOnImsRxNoticeListener(
|
public void setOnRtpRxNoticeListener(
|
||||||
@Nullable OnImsRxNoticeListener listener, @Nullable Handler handler) {
|
@NonNull Context context,
|
||||||
mOnImsRxNoticeListener = listener;
|
@NonNull OnRtpRxNoticeListener listener, @Nullable Handler handler) {
|
||||||
mOnImsRxNoticeHandler = handler;
|
Objects.requireNonNull(context);
|
||||||
|
Preconditions.checkArgument(
|
||||||
|
context.checkSelfPermission(BIND_IMS_SERVICE) == PERMISSION_GRANTED,
|
||||||
|
"android.permission.BIND_IMS_SERVICE permission not granted.");
|
||||||
|
mOnRtpRxNoticeListener = Objects.requireNonNull(listener);
|
||||||
|
mOnRtpRxNoticeHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OnImsRxNoticeListener mOnImsRxNoticeListener;
|
private OnRtpRxNoticeListener mOnRtpRxNoticeListener;
|
||||||
private Handler mOnImsRxNoticeHandler;
|
private Handler mOnRtpRxNoticeHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a callback to be invoked when a selected track has timed metadata available.
|
* Register a callback to be invoked when a selected track has timed metadata available.
|
||||||
|
|||||||
Reference in New Issue
Block a user