From e0230718598e3c6f0999be49a95ca71dec26d5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Tue, 24 Sep 2019 22:58:24 +0200 Subject: [PATCH 01/23] Update StreamPlayer.java Slight reformatting --- .../com/goxr3plus/streamplayer/stream/StreamPlayer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java index f0ee979..d932ef3 100644 --- a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java +++ b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java @@ -214,9 +214,9 @@ public void reset() { */ private String generateEvent(final Status status, final int encodedStreamPosition, final Object description) { try { - return eventsExecutorService - .submit(new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners)) - .get(); + StreamPlayerEventLauncher task = new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners); + Future submit = eventsExecutorService.submit(task); + return submit.get(); } catch (InterruptedException | ExecutionException ex) { logger.log(Level.WARNING, "Problem in StreamPlayer generateEvent() method", ex); } @@ -574,7 +574,7 @@ public void play() throws StreamPlayerException { // Proceed only if we have not problems logger.info("Submitting new StreamPlayer Thread"); - streamPlayerExecutorService.submit(this); + Future submit = streamPlayerExecutorService.submit(this); // Update the status status = Status.PLAYING; From dfd34cd2d199e22bbe112cc9066af2bdf2d8ca48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Tue, 24 Sep 2019 23:16:37 +0200 Subject: [PATCH 02/23] Remove unneeded thread Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayerEvent"))); is not needed --- .../streamplayer/stream/StreamPlayer.java | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java index d932ef3..cee6f22 100644 --- a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java +++ b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java @@ -41,7 +41,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -120,11 +119,6 @@ public class StreamPlayer implements StreamPlayerInterface, Callable { private final ExecutorService streamPlayerExecutorService; private Future future; - /** - * This executor service is used in order the playerState events to be executed - * in an order - */ - private final ExecutorService eventsExecutorService; /** Holds a list of Linteners to be notified about Stream PlayerEvents */ private final ArrayList listeners; @@ -154,20 +148,17 @@ public StreamPlayer() { */ public StreamPlayer(Logger logger) { this(logger, - Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayer")), - Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayerEvent"))); + Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayer"))); } /** * Constructor with settable logger and executor services. * @param logger The logger that will be used by the player * @param streamPlayerExecutorService Executor service for the stream player - * @param eventsExecutorService Executor service for events. */ - public StreamPlayer(Logger logger, ExecutorService streamPlayerExecutorService, ExecutorService eventsExecutorService) { + public StreamPlayer(Logger logger, ExecutorService streamPlayerExecutorService) { this.logger = logger; this.streamPlayerExecutorService = streamPlayerExecutorService; - this.eventsExecutorService = eventsExecutorService; listeners = new ArrayList<>(); outlet = new Outlet(logger); reset(); @@ -210,17 +201,10 @@ public void reset() { * @param encodedStreamPosition in the stream when the event occurs. * @param description the description * - * @return A String Describing if any problem occurred */ - private String generateEvent(final Status status, final int encodedStreamPosition, final Object description) { - try { - StreamPlayerEventLauncher task = new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners); - Future submit = eventsExecutorService.submit(task); - return submit.get(); - } catch (InterruptedException | ExecutionException ex) { - logger.log(Level.WARNING, "Problem in StreamPlayer generateEvent() method", ex); - } - return "Problem in StreamPlayer generateEvent() method"; + private void generateEvent(final Status status, final int encodedStreamPosition, final Object description) { + new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners).call(); + } /** From 664fa3be5ebd1a14126f81cb520423e73484d5e9 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Wed, 25 Sep 2019 10:52:17 +0300 Subject: [PATCH 03/23] Create PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 PULL_REQUEST_TEMPLATE.md diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..2cbedd9 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,28 @@ +# Description + +Please include a summary of the change and which issue is fixed. +List any dependencies that are required for this change. + +Fixes # (issue) + +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +# Has This Been Tested? + +# Checklist: + +- [X] My code follows the style guidelines of this project +- [X] I have performed a self-review of my own code +- [X] I have commented my code, particularly in hard-to-understand areas +- [X] I have made corresponding changes to the documentation +- [X] My changes generate no new warnings +- [X] I have added tests that prove my fix is effective or that my feature works +- [X] New and existing unit tests pass locally with my changes +- [X] Any dependent changes have been merged and published in downstream modules From 87f0f5955bb9889add3ed1ea235f5c927df962e6 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Wed, 25 Sep 2019 10:57:16 +0300 Subject: [PATCH 04/23] Update PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 2cbedd9..1a0ae91 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -3,19 +3,35 @@ Please include a summary of the change and which issue is fixed. List any dependencies that are required for this change. -Fixes # (issue) + -## Type of change + + -Please delete options that are not relevant. +**What kind of change does this PR introduce?** (check at least one) - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Code style update +- [ ] Refactor +- [ ] Build-related changes - [ ] This change requires a documentation update +- [ ] Other, please describe: + +**Does this PR introduce a breaking change?** (check one) + +- [ ] Yes +- [ ] No # Has This Been Tested? +- [ ] Yes +- [ ] No + # Checklist: - [X] My code follows the style guidelines of this project From 75f289a964a5f590b4a3569b3b3b9ca95c7c2d8f Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Tue, 26 Nov 2019 09:40:03 +0200 Subject: [PATCH 05/23] Update README.md --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d852172..e222bcc 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,19 @@ +

Java Stream Player

+

+🎶 +

+

+ +Java Audio Controller Library with (skip,skipTo,start,stop,pause,play,restart features) +This is the next version of [JavaZoom BasicPlayer](http://www.javazoom.net/jlgui/api.html)" target="_blank">Download + +

+ [![Latest Version](https://img.shields.io/github/release/goxr3plus/java-stream-player.svg?style=flat-square)](https://github.com/goxr3plus/java-stream-player/releases) [![HitCount](http://hits.dwyl.io/goxr3plus/java-stream-player.svg)](http://hits.dwyl.io/goxr3plus/java-stream-player) Patreon donate button PayPal donate button - -# Java-stream-player -Java Audio Controller Library with (skip,skipTo,start,stop,pause,play,restart features) -This is the next version of [JavaZoom BasicPlayer](http://www.javazoom.net/jlgui/api.html) - ### What audio formats it supports? It supports **WAV, AU, AIFF, MP3, OGG VORBIS, FLAC, MONKEY's AUDIO and SPEEX audio formats** , using some external libraries . Although more will be added in future releases. From b1e1fbe252be5073e74486d5ee9c53b75963a070 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Tue, 26 Nov 2019 09:40:55 +0200 Subject: [PATCH 06/23] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e222bcc..4234c41 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +---

Java Stream Player

🎶 @@ -9,6 +10,8 @@ This is the next version of [JavaZoom BasicPlayer](http://www.javazoom.net/jlgui

+ + [![Latest Version](https://img.shields.io/github/release/goxr3plus/java-stream-player.svg?style=flat-square)](https://github.com/goxr3plus/java-stream-player/releases) [![HitCount](http://hits.dwyl.io/goxr3plus/java-stream-player.svg)](http://hits.dwyl.io/goxr3plus/java-stream-player) Patreon donate button From 06b357ca35d2a3d6854fe2bef70c3bbae206cf21 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Tue, 26 Nov 2019 09:41:10 +0200 Subject: [PATCH 07/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4234c41..4fde380 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This is the next version of [JavaZoom BasicPlayer](http://www.javazoom.net/jlgui

- +--- [![Latest Version](https://img.shields.io/github/release/goxr3plus/java-stream-player.svg?style=flat-square)](https://github.com/goxr3plus/java-stream-player/releases) [![HitCount](http://hits.dwyl.io/goxr3plus/java-stream-player.svg)](http://hits.dwyl.io/goxr3plus/java-stream-player) From 75b9f0dec48e3c30ff5b4d45494e4f85dfe8c10d Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Tue, 26 Nov 2019 09:44:42 +0200 Subject: [PATCH 08/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4fde380..4208303 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ --- -

Java Stream Player

+

Java Stream Player ( Library )

🎶

From 416401070c58f976ab4cb827e9c8d9fae64f4fa2 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Tue, 26 Nov 2019 09:49:47 +0200 Subject: [PATCH 09/23] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4208303..ba0ae3c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ --- +

Java Stream Player ( Library )

🎶 From 9da15812d70f6839f73e3641098be0f26c423e9c Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Tue, 26 Nov 2019 09:53:20 +0200 Subject: [PATCH 10/23] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ba0ae3c..8862c83 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@

-Java Audio Controller Library with (skip,skipTo,start,stop,pause,play,restart features) -This is the next version of [JavaZoom BasicPlayer](http://www.javazoom.net/jlgui/api.html)" target="_blank">Download +Java Audio Controller Library with (skip,skipTo,start,stop,pause,play,restart) + This is the next version of JavaZoom BasicPlayer

From fb6651f1a05748a4c44345c55a2fceaeaaeaf1c4 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Tue, 26 Nov 2019 10:14:38 +0200 Subject: [PATCH 11/23] Update README.md --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8862c83..fb81e54 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,18 @@ PayPal donate button ### What audio formats it supports? -It supports **WAV, AU, AIFF, MP3, OGG VORBIS, FLAC, MONKEY's AUDIO and SPEEX audio formats** , using some external libraries . Although more will be added in future releases. +- **Fully Supported ✔️** + - WAV + - MP3 +- **Partially not full tested 🚧** + - OGG VORBIS + - FLAC + - MONKEY's AUDIO + - SPEEX +- **Not Supported Yet ❌** + - AAC + - THEORA + - ... all the others ### Step 1. Add the JitPack repository to your build file From 987d0cddcb394fa5d3a430ee79dd4c7f7b8cb142 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Fri, 29 Nov 2019 21:43:54 +0200 Subject: [PATCH 12/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fb81e54..8860bd0 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ - ... all the others -### Step 1. Add the JitPack repository to your build file +### Step 1. Add the JitPack repository to your build file https://jitpack.io/private#goxr3plus/java-stream-player ``` XML From 6a00a79f32bf324f7d6232182d93745da64bee0b Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Mon, 9 Dec 2019 10:30:02 +0200 Subject: [PATCH 13/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8860bd0..f780dc1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ --- -

Java Stream Player ( Library )

+

Java Stream Player ( Library )

🎶

From 719d370aac524836099cf093c7f96e1f135eee71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Wed, 18 Dec 2019 22:43:22 +0100 Subject: [PATCH 14/23] minor JavaDoc and readability improvement --- .../goxr3plus/streamplayer/stream/StreamPlayer.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java index f0ee979..3cbf3e3 100644 --- a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java +++ b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java @@ -1067,12 +1067,18 @@ public float getMinimumGain() { /** * Returns Pan precision. + *

+ * Obtains the resolution or granularity of the control, in the units that the control measures. + * The precision is the size of the increment between discrete valid values for this control, + * over the set of supported floating-point values. * - * @return The Precision Value + * @return The Precision Value for the pan control, if it exists, otherwise 0.0. */ @Override public float getPrecision() { - return !outlet.hasControl(FloatControl.Type.PAN, outlet.getPanControl()) ? 0.0F : outlet.getPanControl().getPrecision(); + return !outlet.hasControl(FloatControl.Type.PAN, outlet.getPanControl()) + ? 0 + : outlet.getPanControl().getPrecision(); } From 0ef3d2ff7dea0712edeba317de0ad6d73a85a261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Wed, 18 Dec 2019 22:43:48 +0100 Subject: [PATCH 15/23] Update StreamPlayerMethodsTest.java Some unit tests are improved, but there are more to be done. --- .../stream/StreamPlayerMethodsTest.java | 96 +++++++++++++++---- 1 file changed, 75 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java index 4cfbc5b..ba43454 100644 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java +++ b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java @@ -4,8 +4,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.*; import java.io.File; +import java.io.IOException; +import java.util.List; import java.util.logging.Logger; import static org.junit.jupiter.api.Assertions.*; @@ -191,9 +193,11 @@ void totalBytes() { @Test void stopped() { - player.isStopped(); - fail("Test not done"); + assertFalse(player.isStopped()); + + player.stop(); + assertTrue(player.isStopped()); } @Test @@ -225,10 +229,17 @@ void pausedOrPlaying() { } @Test - void paused() { - player.isPaused(); + void paused() throws StreamPlayerException { + assertFalse(player.isPaused()); - fail("Test not done"); + player.open(audioFile); + assertFalse(player.isPaused()); + + player.play(); + assertFalse(player.isPaused()); + + player.pause(); + assertTrue(player.isPaused()); } @Test @@ -277,10 +288,21 @@ void play() throws StreamPlayerException { } @Test - void resume() { - player.resume(); + void resume() throws StreamPlayerException { + assertFalse(player.isPlaying()); - fail("Test not done"); + player.open(audioFile); + assertFalse(player.isPlaying()); + + player.play(); + assertTrue(player.isPlaying()); + + player.pause(); + assertFalse(player.isPlaying()); + + + player.resume(); + assertTrue(player.isPlaying()); } @Test @@ -310,9 +332,15 @@ void pan() throws StreamPlayerException { player.setPan(pan); assertEquals(pan, player.getPan(), delta); + // If we set the pan outside the permitted range, it will not change + // The permitted range is undefined. double outsideRange = 1.1; player.setPan(outsideRange); assertEquals(pan, player.getPan(), delta); + + float precision = player.getPrecision(); + assertNotEquals(0, precision); + assertEquals(3f, 1.0/precision); } @Test @@ -332,14 +360,18 @@ void open() throws StreamPlayerException { @Test void mixers() { - player.getMixers(); - - fail("Test not done"); + List mixers = player.getMixers(); + // TODO: Make this method player.getMixers() private, remove it from the interface. + // There is nothing that can be done with the information outside the private scope. } @Test void seekBytes() throws StreamPlayerException { - player.seekBytes(0); + player.open(audioFile); + int positionByte1 = player.getPositionByte(); + + player.seekBytes(100); + int positionByte2 = player.getPositionByte(); fail("Test not done"); } @@ -376,17 +408,22 @@ void positionByte() { } @Test - void precision() { - player.getPrecision(); + void precision() throws StreamPlayerException { + assertEquals(0f, player.getPrecision()); - fail("Test not done"); + player.open(audioFile); + player.play(); + + assertNotEquals(0f, player.getPrecision()); + // On one computer the precision = 1/128. There are no guarantees. } @Test - void opened() { - player.isOpened(); + void opened() throws StreamPlayerException { + assertFalse(player.isOpened()); - fail("Test not done"); + player.open(audioFile); + assertTrue(player.isOpened()); } @Test @@ -404,8 +441,25 @@ void removeStreamPlayerListener() { } @Test - void seekTo() throws StreamPlayerException { - player.seekTo(1000); + void seekTo() throws StreamPlayerException, IOException, UnsupportedAudioFileException { + + // Some tests before we do the real tests + AudioFileFormat audioFileFormat = AudioSystem.getAudioFileFormat(audioFile); + + + // Setup + player.open(audioFile); + player.play(); + player.pause(); + int positionByte1 = player.getPositionByte(); + assertNotEquals(AudioSystem.NOT_SPECIFIED, positionByte1, "If we cannot check the position, how can we verify seek?"); + + // Execute + player.seekTo(10); + + // Verify + int positionByte2 = player.getPositionByte(); + assertNotEquals(positionByte2, positionByte1); fail("Test not done"); } From afb30bc1a818ec3f74f0746983ac259858433434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Thu, 19 Dec 2019 08:08:50 +0100 Subject: [PATCH 16/23] AudioSystem.getMixerInfo() will not return null, so we don't have to check for it. --- .../streamplayer/stream/StreamPlayer.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java index f0ee979..e6b26f4 100644 --- a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java +++ b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java @@ -35,11 +35,7 @@ import java.net.URL; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -994,17 +990,16 @@ public List getMixers() { // audio mixers that are currently installed on the system. final Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo(); - if (mixerInfos != null) - Arrays.stream(mixerInfos).forEach(mInfo -> { - // line info - final Line.Info lineInfo = new Line.Info(SourceDataLine.class); - final Mixer mixer = AudioSystem.getMixer(mInfo); + Arrays.stream(mixerInfos).forEach(mInfo -> { + // line info + final Line.Info lineInfo = new Line.Info(SourceDataLine.class); + final Mixer mixer = AudioSystem.getMixer(mInfo); - // if line supported - if (mixer.isLineSupported(lineInfo)) - mixers.add(mInfo.getName()); + // if line supported + if (mixer.isLineSupported(lineInfo)) + mixers.add(mInfo.getName()); - }); + }); return mixers; } @@ -1023,7 +1018,7 @@ private Mixer getMixer(final String name) { // audio mixers that are currently installed on the system. final Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo(); - if (name != null && mixerInfos != null) + if (name != null) for (Mixer.Info mixerInfo : mixerInfos) if (mixerInfo.getName().equals(name)) { mixer = AudioSystem.getMixer(mixerInfo); From 68c67ca20e6d025a89d4dbc02931331e126c6c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Fri, 20 Dec 2019 23:17:22 +0100 Subject: [PATCH 17/23] Improved and re-structured unit tests --- .../StreamPlayerFutureImprovementTest.java | 47 +++++ .../stream/StreamPlayerMethodsTest.java | 166 +++++++++++++----- 2 files changed, 172 insertions(+), 41 deletions(-) create mode 100644 src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java new file mode 100644 index 0000000..807c4d9 --- /dev/null +++ b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java @@ -0,0 +1,47 @@ +package com.goxr3plus.streamplayer.stream; + +import com.goxr3plus.streamplayer.enums.Status; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.logging.Logger; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; + +/** + * Tests of all or most of the public methods of StreamPlayer. + * These unit tests are written primarily as documentation of the behavior and as example use case, + * not as a part of test driven development. + */ +public class StreamPlayerFutureImprovementTest { + StreamPlayer player; + private File audioFile; + + @BeforeEach + void setup() { + final Logger logger = mock(Logger.class); + player = new StreamPlayer(logger); + audioFile = new File("Logic - Ballin [Bass Boosted].mp3"); + } + + /** + * This test fails if it's permitted to add a null to the StreamPlayer listener list. + */ + @Test + void addStreamPlayerListener_dontAcceptNull() { + // Currently, we can add a null to the list of stream player listeners. + // Should that really be allowed? + assertThrows(Exception.class, () -> player.addStreamPlayerListener(null)); + + fail("Test not done"); + } + +} diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java index ba43454..98dcab0 100644 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java +++ b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java @@ -3,15 +3,18 @@ import com.goxr3plus.streamplayer.enums.Status; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import javax.sound.sampled.*; import java.io.File; import java.io.IOException; import java.util.List; +import java.util.Map; import java.util.logging.Logger; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.*; /** * Tests of all or most of the public methods of StreamPlayer. @@ -87,7 +90,7 @@ void status() throws StreamPlayerException { @Test void gain() throws StreamPlayerException, InterruptedException { // Setup - final double gain1 = 0.99; + final double gain1_dB = 0.5; final double gain2 = 0.2; final double delta = 0.05; final boolean listen = false; @@ -97,8 +100,8 @@ void gain() throws StreamPlayerException, InterruptedException { player.open(audioFile); player.seekTo(30); player.play(); - player.setGain(gain1); - final float actualGain1First = player.getGainValue(); + player.setGain(gain1_dB); + final float actualGain0 = player.getGainValue(); if (listen) Thread.sleep(2000); final float actualGain1 = player.getGainValue(); @@ -106,16 +109,19 @@ void gain() throws StreamPlayerException, InterruptedException { if (listen) Thread.sleep(2000); final float actualGain2 = player.getGainValue(); - player.setGain(gain1); + player.setGain(gain1_dB); if (listen) Thread.sleep(2000); player.stop(); // Verify assertEquals(0, initialGain); - assertEquals(actualGain1First, actualGain1); - assertEquals(gain1, actualGain1, delta); // TODO: Investigate probable bug. - // fail("Test not done"); + assertEquals(actualGain0, actualGain1); + assertEquals(20.0 * Math.log10(gain1_dB), actualGain1, delta); + + // TODO: Consider changing the API. setGain() and getGainValue() have different scales. + // setGain(linear scale), + // whereas getGainValue() returns a logarithmic dB scale value. This is inconsistent. } /** @@ -185,10 +191,17 @@ void maximumGain() throws StreamPlayerException { } @Test - void totalBytes() { - player.getTotalBytes(); + void totalBytes() throws StreamPlayerException, InterruptedException { + int expectedLengthOfExampleAudioFile = 5877062; - fail("Test not done"); + + assertEquals(-1, player.getTotalBytes()); + + player.open(audioFile); + assertEquals(expectedLengthOfExampleAudioFile, player.getTotalBytes()); + + player.play(); + assertEquals(expectedLengthOfExampleAudioFile, player.getTotalBytes()); } @Test @@ -213,19 +226,36 @@ void sourceDataLine() throws StreamPlayerException { } @Test - void playing() { - final boolean playing = player.isPlaying(); + void playing() throws StreamPlayerException { + + assertFalse(player.isPlaying()); - assertFalse(playing); + player.open(audioFile); + assertFalse(player.isPlaying()); - fail("Test not done"); + player.play(); + assertTrue(player.isPlaying()); + + player.pause(); + assertFalse(player.isPlaying()); } @Test - void pausedOrPlaying() { - player.isPausedOrPlaying(); + void pausedOrPlaying() throws StreamPlayerException { - fail("Test not done"); + assertFalse(player.isPausedOrPlaying()); + + player.open(audioFile); + assertFalse(player.isPausedOrPlaying()); + + player.play(); + assertTrue(player.isPausedOrPlaying()); + + player.pause(); + assertTrue(player.isPausedOrPlaying()); + + player.stop(); + assertFalse(player.isPausedOrPlaying()); } @Test @@ -243,34 +273,76 @@ void paused() throws StreamPlayerException { } @Test - void addStreamPlayerListener_dontAcceptNull() { - assertThrows(Exception.class, () -> player.addStreamPlayerListener(null)); + void addStreamPlayerListener() throws StreamPlayerException, InterruptedException { + // Setup + final StreamPlayerListener listener = mock(StreamPlayerListener.class); - fail("Test not done"); - } + ArgumentCaptor dataSourceCaptor = ArgumentCaptor.forClass(Object.class); + ArgumentCaptor propertiesCaptor1 = ArgumentCaptor.forClass(Map.class); - @Test - void addStreamPlayerListener() { - final StreamPlayerListener listener = mock(StreamPlayerListener.class); + // Execute player.addStreamPlayerListener(listener); + player.open(audioFile); + player.play(); + Thread.sleep(30); + + // Verify + verify(listener).opened(dataSourceCaptor.capture(), propertiesCaptor1.capture()); + Object value = dataSourceCaptor.getValue(); + assertTrue(value instanceof File); + + Map value11 = propertiesCaptor1.getValue(); + + assertTrue(value11.containsKey("basicplayer.sourcedataline")); + + verify(listener, times(4)).statusUpdated(any()); + + verify(listener, times(1)).opened(any(), any()); + + verify(listener, atLeast(5)).progress(anyInt(), anyLong(), any(), any()); + verify(listener, atMost(10)).progress(anyInt(), anyLong(), any(), any()); + + // TODO: Make separate tests for the different calls made to the listener + // TODO: Do we need to test the values passed to these methods? - fail("Test not done"); // TODO: CHeck that the listener is actually added } @Test - void mute() { - player.getMute(); + void mute() throws StreamPlayerException { + // TODO: How can mute be tested, without too much assumptions about the actual implementation? + // A manual test would involve listening. + + + assertFalse(player.getMute()); + player.open(audioFile); + player.play(); + player.setMute(true); + assertTrue(player.getMute()); player.setMute(false); + assertFalse(player.getMute()); - fail("Test not done"); } @Test - void speedFactor() { - player.getSpeedFactor(); - player.setSpeedFactor(1000); + void speedFactor() throws StreamPlayerException, InterruptedException { + assertEquals(player.getSpeedFactor(), 1); + + double fast = 1; + player.setSpeedFactor(fast); + assertEquals(fast, player.getSpeedFactor()); + + double slow = 0.5; + player.open(audioFile); + player.play(); + player.setSpeedFactor(slow); + Thread.sleep(50); + assertEquals(slow, player.getSpeedFactor()); + + // TODO: Find a way to verify that the speed factor actually works. That it can be read back is no proof. + // I might be possible to play a short sequence of known length, and measure the time it takes. + // But things that take time are generally not advisable in unit tests. + - fail("Test not done"); } @Test @@ -387,10 +459,18 @@ void lineBufferSize() { } @Test - void lineCurrentBufferSize() { - player.getLineCurrentBufferSize(); + void lineCurrentBufferSize() throws StreamPlayerException { + // TODO: Document the purpose of getLineCurrentBufferSize(). What is it good for? + // Can it be removed? The method doesn't really return the current line buffer size, + // but a cached value, which might be the same thing. Hard to say. - fail("Test not done"); + assertEquals(-1, player.getLineCurrentBufferSize(), "Initially, the buffer size is undefined, coded as -1."); + + player.open(audioFile); + assertEquals(-1, player.getLineCurrentBufferSize(), "After the player is opened, the buffer size is undefined"); + + player.play(); + assertEquals(2 * 44100, player.getLineCurrentBufferSize(), "After the play starts, the buffer size 1 second at CD sampling rate"); } @Test @@ -451,17 +531,21 @@ void seekTo() throws StreamPlayerException, IOException, UnsupportedAudioFileExc player.open(audioFile); player.play(); player.pause(); - int positionByte1 = player.getPositionByte(); - assertNotEquals(AudioSystem.NOT_SPECIFIED, positionByte1, "If we cannot check the position, how can we verify seek?"); + int encodedStreamPosition1 = player.getEncodedStreamPosition(); // Execute player.seekTo(10); // Verify - int positionByte2 = player.getPositionByte(); - assertNotEquals(positionByte2, positionByte1); + int encodedStreamPosition2 = player.getEncodedStreamPosition(); + assertTrue(encodedStreamPosition2 > encodedStreamPosition1); - fail("Test not done"); + // Execute: go backwards + player.seekTo(5); + + // Verify: position goes backwards + int encodedStreamPosition3 = player.getEncodedStreamPosition(); + assertTrue(encodedStreamPosition3 < encodedStreamPosition2); } @Test From dca8c7a8e3ae6c1e4136358b810df3377136c526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Sun, 22 Dec 2019 11:09:10 +0100 Subject: [PATCH 18/23] Improved and more complete unit tests. StreamPlayerMethodsTest still contains tests that don't pass. The tested methods are candidates for removal from StreamPlayer. All tests in StreamPlayerMethodsTest must be reviewed: Do they actually verify anything that need to be verified? Or are they too coupled with the current implementation? StreamPlayerFutureImprovementTest contains tests that currently fail. Failures are caused by behavior in StreamPlayer which I think is wrong or bad. But I may have misinterpreted the intended behavior. --- .../StreamPlayerFutureImprovementTest.java | 26 +++++++ .../stream/StreamPlayerMethodsTest.java | 71 ++++++++++++------- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java index 807c4d9..4a6c452 100644 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java +++ b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java @@ -2,6 +2,7 @@ import com.goxr3plus.streamplayer.enums.Status; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import javax.sound.sampled.AudioFileFormat; @@ -44,4 +45,29 @@ void addStreamPlayerListener_dontAcceptNull() { fail("Test not done"); } + + @Test + @DisplayName("When play() is called without first calling open(), an exception is thrown") + void playingUnopenedSourceThrowsException() { + + assertThrows(Exception.class, () -> player.play()); + } + + @Test + void seekBytes() throws StreamPlayerException { + player.open(audioFile); + player.play(); + int positionByte1 = player.getPositionByte(); + + player.seekBytes(100); + int positionByte2 = player.getPositionByte(); + + assertTrue( positionByte2 > positionByte1); + + // TODO: It seems that getPositionByte doesn't work. + // It isn't called from within this project, except for in this test. + // It is however called by XR3Player. If XR3Player needs this method, it must be tested + // within this project. The method relies on a map, which doesn't seem to be updated by play() + } + } diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java index 98dcab0..1c247e4 100644 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java +++ b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java @@ -135,7 +135,7 @@ void gain() throws StreamPlayerException, InterruptedException { @Test void logScaleGain() throws StreamPlayerException, InterruptedException { // Setup - final boolean listen = true; + final boolean listen = false; // Set to true to listen to the test. // Exercise @@ -299,8 +299,8 @@ void addStreamPlayerListener() throws StreamPlayerException, InterruptedExceptio verify(listener, times(1)).opened(any(), any()); - verify(listener, atLeast(5)).progress(anyInt(), anyLong(), any(), any()); - verify(listener, atMost(10)).progress(anyInt(), anyLong(), any(), any()); + verify(listener, atLeast(4)).progress(anyInt(), anyLong(), any(), any()); + verify(listener, atMost(30)).progress(anyInt(), anyLong(), any(), any()); // TODO: Make separate tests for the different calls made to the listener // TODO: Do we need to test the values passed to these methods? @@ -348,15 +348,25 @@ void speedFactor() throws StreamPlayerException, InterruptedException { @Test void equalizer() { player.setEqualizer(null, 0); - - fail("Test not done"); + // TODO: Find out what the intention of setEqualizer() is, and make a test for that assumption. } @Test - void play() throws StreamPlayerException { + void play() throws StreamPlayerException, InterruptedException { + // Setup + player.open(audioFile); + + // Pre-validate + assertFalse(player.isPlaying()); + + // Execute player.play(); - fail("Test not done"); + // Verify + assertTrue(player.isPlaying()); + + // TODO: Find way to verify that the player is actually playing, that doesn't need listening. + // The method might look at the playing position, but it must be fairly quick. } @Test @@ -378,17 +388,33 @@ void resume() throws StreamPlayerException { } @Test - void pause() { + void pause() throws StreamPlayerException { + + // Setup + player.open(audioFile); + player.play(); + // Pre-validate + assertFalse(player.isPaused()); + + // Execute player.pause(); - fail("Test not done"); + // Verify + assertTrue(player.isPaused()); + } @Test void stop() { + + assertFalse(player.isStopped()); + player.stop(); - fail("Test not done"); + assertTrue(player.isStopped()); + + // TODO: Find a way to verify that playback is stopped by running the stop method. + // The isStopped() method is not enough. } @Test @@ -412,22 +438,27 @@ void pan() throws StreamPlayerException { float precision = player.getPrecision(); assertNotEquals(0, precision); - assertEquals(3f, 1.0/precision); + double expected = 128.0; // Possibly platform dependent. Tested on a Mac with Intellij. + assertEquals(expected, 1.0/precision, 2.0); } @Test void unknown() { player.isUnknown(); - - fail("Test not done"); + // This is a useless test of a useless method. + // TODO: Remove player.isUnknown(). It's not used, and it's useless. + // There is already getStatus(). } @Test void open() throws StreamPlayerException { - File file = null; + File file = spy(audioFile); player.open(file); + verify(file, atLeast(1)).getPath(); - fail("Test not done"); + // It's unclear what the contract of open() is; what we need it to do. + // It's a pre-requisite for play(), but play() doesn't throw an + // exception if open() is missing. } @Test @@ -437,19 +468,11 @@ void mixers() { // There is nothing that can be done with the information outside the private scope. } - @Test - void seekBytes() throws StreamPlayerException { - player.open(audioFile); - int positionByte1 = player.getPositionByte(); - - player.seekBytes(100); - int positionByte2 = player.getPositionByte(); - fail("Test not done"); - } // The methods tested below aren't used elsewhere in this project, nor in XR3Player + // TODO: Consider each of the tested methods below, to see if they can be removed from StreamPlayer. @Test void lineBufferSize() { From 8463821490568671590402fecdf2c346b78c6c97 Mon Sep 17 00:00:00 2001 From: GOXR3PLUS STUDIO Date: Wed, 1 Jan 2020 20:29:53 +0200 Subject: [PATCH 19/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f780dc1..9075944 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ - FLAC - MONKEY's AUDIO - SPEEX -- **Not Supported Yet ❌** +- **Not Supported Yet ❌** - AAC - THEORA - ... all the others From 074a81bd7a7678e5583559e4501c77a484fcc9db Mon Sep 17 00:00:00 2001 From: Alexander Kentros Date: Thu, 27 Feb 2020 12:02:46 +0200 Subject: [PATCH 20/23] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9075944..d89bc8c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +### [![AlexKent](https://user-images.githubusercontent.com/20374208/75432997-f5422100-5957-11ea-87a2-164eb98d83ef.png)](https://www.minepi.com/AlexKent) Support me joining PI Network app with invitation code [AlexKent](https://www.minepi.com/AlexKent) [![AlexKent](https://user-images.githubusercontent.com/20374208/75432997-f5422100-5957-11ea-87a2-164eb98d83ef.png)](https://www.minepi.com/AlexKent) + ---

Java Stream Player ( Library )

From 1ec869bcd8fb4bc47c61ab4f3d8f369ad1e97703 Mon Sep 17 00:00:00 2001 From: Alexander Kentros Date: Tue, 31 Mar 2020 14:49:29 +0300 Subject: [PATCH 21/23] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fc849b0..b85c184 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.goxr3plus java-stream-player - 9.0.5 + 10.0.0 From b1af6cb894442adc06e1bdb4dae399fb6d148dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Tue, 24 Sep 2019 22:58:24 +0200 Subject: [PATCH 22/23] Update StreamPlayer.java Slight reformatting --- .../com/goxr3plus/streamplayer/stream/StreamPlayer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java index 8756aca..0b90179 100644 --- a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java +++ b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java @@ -210,9 +210,9 @@ public void reset() { */ private String generateEvent(final Status status, final int encodedStreamPosition, final Object description) { try { - return eventsExecutorService - .submit(new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners)) - .get(); + StreamPlayerEventLauncher task = new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners); + Future submit = eventsExecutorService.submit(task); + return submit.get(); } catch (InterruptedException | ExecutionException ex) { logger.log(Level.WARNING, "Problem in StreamPlayer generateEvent() method", ex); } @@ -570,7 +570,7 @@ public void play() throws StreamPlayerException { // Proceed only if we have not problems logger.info("Submitting new StreamPlayer Thread"); - streamPlayerExecutorService.submit(this); + Future submit = streamPlayerExecutorService.submit(this); // Update the status status = Status.PLAYING; From 439b43348fa992835c47824f8eb0caa9e19c5d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20Stenstr=C3=B6m?= Date: Tue, 24 Sep 2019 23:16:37 +0200 Subject: [PATCH 23/23] Remove unneeded thread Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayerEvent"))); is not needed --- .../streamplayer/stream/StreamPlayer.java | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java index 0b90179..3c2c278 100644 --- a/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java +++ b/src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java @@ -37,7 +37,6 @@ import java.nio.ByteOrder; import java.util.*; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -116,11 +115,6 @@ public class StreamPlayer implements StreamPlayerInterface, Callable { private final ExecutorService streamPlayerExecutorService; private Future future; - /** - * This executor service is used in order the playerState events to be executed - * in an order - */ - private final ExecutorService eventsExecutorService; /** Holds a list of Linteners to be notified about Stream PlayerEvents */ private final ArrayList listeners; @@ -150,20 +144,17 @@ public StreamPlayer() { */ public StreamPlayer(Logger logger) { this(logger, - Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayer")), - Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayerEvent"))); + Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("StreamPlayer"))); } /** * Constructor with settable logger and executor services. * @param logger The logger that will be used by the player * @param streamPlayerExecutorService Executor service for the stream player - * @param eventsExecutorService Executor service for events. */ - public StreamPlayer(Logger logger, ExecutorService streamPlayerExecutorService, ExecutorService eventsExecutorService) { + public StreamPlayer(Logger logger, ExecutorService streamPlayerExecutorService) { this.logger = logger; this.streamPlayerExecutorService = streamPlayerExecutorService; - this.eventsExecutorService = eventsExecutorService; listeners = new ArrayList<>(); outlet = new Outlet(logger); reset(); @@ -206,17 +197,10 @@ public void reset() { * @param encodedStreamPosition in the stream when the event occurs. * @param description the description * - * @return A String Describing if any problem occurred */ - private String generateEvent(final Status status, final int encodedStreamPosition, final Object description) { - try { - StreamPlayerEventLauncher task = new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners); - Future submit = eventsExecutorService.submit(task); - return submit.get(); - } catch (InterruptedException | ExecutionException ex) { - logger.log(Level.WARNING, "Problem in StreamPlayer generateEvent() method", ex); - } - return "Problem in StreamPlayer generateEvent() method"; + private void generateEvent(final Status status, final int encodedStreamPosition, final Object description) { + new StreamPlayerEventLauncher(this, status, encodedStreamPosition, description, listeners).call(); + } /**