diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..1a0ae91 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,44 @@ +# Description + +Please include a summary of the change and which issue is fixed. +List any dependencies that are required for this change. + + + + + + +**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 +- [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 diff --git a/README.md b/README.md index d852172..d89bc8c 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,41 @@ +### [](https://www.minepi.com/AlexKent) Support me joining PI Network app with invitation code [AlexKent](https://www.minepi.com/AlexKent) [](https://www.minepi.com/AlexKent) + +--- + +
+🎶 +
++ +Java Audio Controller Library with (skip,skipTo,start,stop,pause,play,restart) + This is the next version of JavaZoom BasicPlayer + +
+ +--- + [](https://github.com/goxr3plus/java-stream-player/releases) [](http://hits.dwyl.io/goxr3plus/java-stream-player)+ * 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(); } 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..4a6c452 --- /dev/null +++ b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java @@ -0,0 +1,73 @@ +package com.goxr3plus.streamplayer.stream; + +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; +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"); + } + + + @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 4cfbc5b..1c247e4 100644 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java +++ b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java @@ -3,13 +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.SourceDataLine; +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. @@ -85,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; @@ -95,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(); @@ -104,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. } /** @@ -127,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 @@ -183,17 +191,26 @@ 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 void stopped() { - player.isStopped(); - fail("Test not done"); + assertFalse(player.isStopped()); + + player.stop(); + assertTrue(player.isStopped()); } @Test @@ -209,92 +226,195 @@ void sourceDataLine() throws StreamPlayerException { } @Test - void playing() { - final boolean playing = player.isPlaying(); + void playing() throws StreamPlayerException { - assertFalse(playing); + assertFalse(player.isPlaying()); - fail("Test not done"); - } + player.open(audioFile); + assertFalse(player.isPlaying()); - @Test - void pausedOrPlaying() { - player.isPausedOrPlaying(); + player.play(); + assertTrue(player.isPlaying()); - fail("Test not done"); + player.pause(); + assertFalse(player.isPlaying()); } @Test - void paused() { - player.isPaused(); + 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 - void addStreamPlayerListener_dontAcceptNull() { - assertThrows(Exception.class, () -> player.addStreamPlayerListener(null)); + 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 - void addStreamPlayerListener() { + void addStreamPlayerListener() throws StreamPlayerException, InterruptedException { + // Setup final StreamPlayerListener listener = mock(StreamPlayerListener.class); + + ArgumentCaptor