Skip to content

Commit fd27f0b

Browse files
HelgeStenstromgoxr3plus
authored andcommitted
Data source (#44)
Data source
1 parent 634c991 commit fd27f0b

File tree

5 files changed

+258
-56
lines changed

5 files changed

+258
-56
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.goxr3plus.streamplayer.stream;
2+
3+
import javax.naming.OperationNotSupportedException;
4+
import javax.sound.sampled.AudioFileFormat;
5+
import javax.sound.sampled.AudioInputStream;
6+
import javax.sound.sampled.UnsupportedAudioFileException;
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.io.InputStream;
10+
import java.net.URL;
11+
12+
public interface DataSource {
13+
static DataSource newDataSource(Object source) throws OperationNotSupportedException {
14+
if (source instanceof File) {
15+
return new FileDataSource((File) source);
16+
}
17+
if (source instanceof URL) {
18+
return new UrlDataSource((URL) source);
19+
}
20+
if (source instanceof InputStream) {
21+
return new StreamDataSource((InputStream) source);
22+
}
23+
throw new OperationNotSupportedException();
24+
}
25+
26+
Object getSource(); // TODO: Try to make this method not needed.
27+
28+
/**
29+
* Returns a string representation of the object. In general, the
30+
* {@code toString} method returns a string that
31+
* "textually represents" this object. The result should
32+
* be a concise but informative representation that is easy for a
33+
* person to read.
34+
* It is recommended that all subclasses override this method.
35+
* <p>
36+
* The {@code toString} method for class {@code Object}
37+
* returns a string consisting of the name of the class of which the
38+
* object is an instance, the at-sign character `{@code @}', and
39+
* the unsigned hexadecimal representation of the hash code of the
40+
* object. In other words, this method returns a string equal to the
41+
* value of:
42+
* <blockquote>
43+
* <pre>
44+
* getClass().getName() + '@' + Integer.toHexString(hashCode())
45+
* </pre></blockquote>
46+
*
47+
* @return a string representation of the object.
48+
*/
49+
@Override
50+
String toString();
51+
52+
/**
53+
* @return the format of the source data
54+
* @throws UnsupportedAudioFileException if the file type is unsupported
55+
* @throws IOException if there is a runtime problem with IO.
56+
*/
57+
AudioFileFormat getAudioFileFormat() throws UnsupportedAudioFileException, IOException;
58+
59+
/**
60+
* @return a stream representing the input data, regardless of source.
61+
* @throws UnsupportedAudioFileException if the file type is unsupported
62+
* @throws IOException if there is a runtime problem with IO.
63+
*/
64+
AudioInputStream getAudioInputStream() throws UnsupportedAudioFileException, IOException;
65+
66+
/**
67+
* @return The duration of the source data in seconds, or -1 if duration is unavailable.
68+
*/
69+
int getDurationInSeconds();
70+
71+
/**
72+
* @return true if the DataSource is a FileDataSource,
73+
* which happens if the source used to create it is a File
74+
*/
75+
boolean isFile();
76+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.goxr3plus.streamplayer.stream;
2+
3+
import com.goxr3plus.streamplayer.enums.AudioType;
4+
import com.goxr3plus.streamplayer.tools.TimeTool;
5+
6+
import javax.sound.sampled.AudioFileFormat;
7+
import javax.sound.sampled.AudioInputStream;
8+
import javax.sound.sampled.AudioSystem;
9+
import javax.sound.sampled.UnsupportedAudioFileException;
10+
import java.io.File;
11+
import java.io.IOException;
12+
13+
public class FileDataSource implements DataSource {
14+
15+
private File source;
16+
17+
FileDataSource(File source) {
18+
this.source = source;
19+
}
20+
21+
@Override
22+
public AudioFileFormat getAudioFileFormat() throws UnsupportedAudioFileException, IOException {
23+
return AudioSystem.getAudioFileFormat(this.source);
24+
}
25+
26+
@Override
27+
public AudioInputStream getAudioInputStream() throws UnsupportedAudioFileException, IOException {
28+
return AudioSystem.getAudioInputStream(source);
29+
}
30+
31+
@Override
32+
public int getDurationInSeconds() {
33+
return TimeTool.durationInSeconds(source.getAbsolutePath(), AudioType.FILE);
34+
}
35+
36+
@Override
37+
public Object getSource() {
38+
return source;
39+
}
40+
41+
@Override
42+
public String toString() {
43+
return "FileDataSource with " + source.toString();
44+
}
45+
46+
@Override
47+
public boolean isFile() {
48+
return true;
49+
}
50+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.goxr3plus.streamplayer.stream;
2+
3+
import javax.sound.sampled.AudioFileFormat;
4+
import javax.sound.sampled.AudioInputStream;
5+
import javax.sound.sampled.AudioSystem;
6+
import javax.sound.sampled.UnsupportedAudioFileException;
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
10+
public class StreamDataSource implements DataSource {
11+
12+
private InputStream source;
13+
14+
StreamDataSource(InputStream source) {
15+
this.source = source;
16+
}
17+
18+
@Override
19+
public AudioFileFormat getAudioFileFormat() throws UnsupportedAudioFileException, IOException {
20+
return AudioSystem.getAudioFileFormat(source);
21+
}
22+
23+
@Override
24+
public AudioInputStream getAudioInputStream() throws UnsupportedAudioFileException, IOException {
25+
return AudioSystem.getAudioInputStream(source);
26+
}
27+
28+
@Override
29+
public int getDurationInSeconds() {
30+
return -1;
31+
}
32+
33+
@Override
34+
public Object getSource() {
35+
return source;
36+
}
37+
38+
@Override
39+
public String toString() {
40+
return "StreamDataSource with " + source.toString();
41+
}
42+
43+
@Override
44+
public boolean isFile() {
45+
return false;
46+
}
47+
}

src/main/java/com/goxr3plus/streamplayer/stream/StreamPlayer.java

Lines changed: 38 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,26 @@
1010

1111
package com.goxr3plus.streamplayer.stream;
1212

13-
import java.io.File;
13+
import com.goxr3plus.streamplayer.enums.Status;
14+
import com.goxr3plus.streamplayer.stream.StreamPlayerException.PlayerException;
15+
import javazoom.spi.PropertiesContainer;
16+
import org.tritonus.share.sampled.TAudioFormat;
17+
import org.tritonus.share.sampled.file.TAudioFileFormat;
18+
19+
import javax.naming.OperationNotSupportedException;
20+
import javax.sound.sampled.AudioFileFormat;
21+
import javax.sound.sampled.AudioFormat;
22+
import javax.sound.sampled.AudioInputStream;
23+
import javax.sound.sampled.AudioSystem;
24+
import javax.sound.sampled.BooleanControl;
25+
import javax.sound.sampled.DataLine;
26+
import javax.sound.sampled.FloatControl;
27+
import javax.sound.sampled.Line;
28+
import javax.sound.sampled.LineUnavailableException;
29+
import javax.sound.sampled.Mixer;
30+
import javax.sound.sampled.SourceDataLine;
31+
import javax.sound.sampled.UnsupportedAudioFileException;
1432
import java.io.IOException;
15-
import java.io.InputStream;
16-
import java.net.URL;
1733
import java.nio.ByteBuffer;
1834
import java.nio.ByteOrder;
1935
import java.util.ArrayList;
@@ -29,29 +45,6 @@
2945
import java.util.logging.Level;
3046
import java.util.logging.Logger;
3147

32-
import javax.sound.sampled.AudioFileFormat;
33-
import javax.sound.sampled.AudioFormat;
34-
import javax.sound.sampled.AudioInputStream;
35-
import javax.sound.sampled.AudioSystem;
36-
import javax.sound.sampled.BooleanControl;
37-
import javax.sound.sampled.DataLine;
38-
import javax.sound.sampled.FloatControl;
39-
import javax.sound.sampled.Line;
40-
import javax.sound.sampled.LineUnavailableException;
41-
import javax.sound.sampled.Mixer;
42-
import javax.sound.sampled.SourceDataLine;
43-
import javax.sound.sampled.UnsupportedAudioFileException;
44-
45-
import org.tritonus.share.sampled.TAudioFormat;
46-
import org.tritonus.share.sampled.file.TAudioFileFormat;
47-
48-
import com.goxr3plus.streamplayer.enums.AudioType;
49-
import com.goxr3plus.streamplayer.enums.Status;
50-
import com.goxr3plus.streamplayer.stream.StreamPlayerException.PlayerException;
51-
import com.goxr3plus.streamplayer.tools.TimeTool;
52-
53-
import javazoom.spi.PropertiesContainer;
54-
5548
/**
5649
* StreamPlayer is a class based on JavaSound API. It has been successfully tested under Java 10
5750
*
@@ -69,8 +62,10 @@ public class StreamPlayer implements StreamPlayerInterface, Callable<Void> {
6962

7063
private volatile Status status = Status.NOT_SPECIFIED;
7164

72-
/** The data source. */
73-
private Object dataSource;
65+
/**
66+
* The data source
67+
*/
68+
private DataSource source;
7469

7570
/** The audio input stream. */
7671
private volatile AudioInputStream audioInputStream;
@@ -261,7 +256,12 @@ public void open(final Object object) throws StreamPlayerException {
261256
if (object == null)
262257
return;
263258

264-
dataSource = object;
259+
//source = new DataSource(object);
260+
try {
261+
source = DataSource.newDataSource(object);
262+
} catch (OperationNotSupportedException e) {
263+
e.printStackTrace();
264+
}
265265
initAudioInputStream();
266266
}
267267

@@ -280,21 +280,13 @@ private void initAudioInputStream() throws StreamPlayerException {
280280

281281
// Notify Status
282282
status = Status.OPENING;
283-
generateEvent(Status.OPENING, getEncodedStreamPosition(), dataSource);
283+
generateEvent(Status.OPENING, getEncodedStreamPosition(), source);
284284

285285
// Audio resources from file||URL||inputStream.
286-
if (dataSource instanceof URL) {
287-
audioInputStream = AudioSystem.getAudioInputStream((URL) dataSource);
288-
audioFileFormat = AudioSystem.getAudioFileFormat((URL) dataSource);
289-
290-
} else if (dataSource instanceof File) {
291-
audioInputStream = AudioSystem.getAudioInputStream((File) dataSource);
292-
audioFileFormat = AudioSystem.getAudioFileFormat((File) dataSource);
286+
audioInputStream = source.getAudioInputStream();
293287

294-
} else if (dataSource instanceof InputStream) {
295-
audioInputStream = AudioSystem.getAudioInputStream((InputStream) dataSource);
296-
audioFileFormat = AudioSystem.getAudioFileFormat((InputStream) dataSource);
297-
}
288+
// Audio resources from file||URL||inputStream.
289+
audioFileFormat = source.getAudioFileFormat();
298290

299291
// Create the Line
300292
createLine();
@@ -314,6 +306,7 @@ private void initAudioInputStream() throws StreamPlayerException {
314306
logger.info("Exited initAudioInputStream\n");
315307
}
316308

309+
317310
/**
318311
* Determines Properties when the File/URL/InputStream is opened.
319312
*/
@@ -367,7 +360,7 @@ private void determineProperties() {
367360
final Map<String, Object> audioPropertiesCopy = audioProperties; // TODO: Remove, it's meaningless.
368361

369362
// Notify all registered StreamPlayerListeners
370-
listeners.forEach(listener -> listener.opened(dataSource, audioPropertiesCopy));
363+
listeners.forEach(listener -> listener.opened(source.getSource(), audioPropertiesCopy));
371364

372365
logger.info("Exited determineProperties()!\n");
373366

@@ -652,7 +645,7 @@ public long seekBytes(final long bytes) throws StreamPlayerException {
652645
long totalSkipped = 0;
653646

654647
// If it is File
655-
if (dataSource instanceof File) {
648+
if (source.isFile()) {
656649

657650
// Check if the requested bytes are more than totalBytes of Audio
658651
final long bytesLength = getTotalBytes();
@@ -771,18 +764,7 @@ private void validateSeconds(int seconds, int durationInSeconds) {
771764

772765
@Override
773766
public int getDurationInSeconds() {
774-
775-
// Audio resources from file||URL||inputStream.
776-
if (dataSource instanceof File) {
777-
return TimeTool.durationInSeconds(((File) dataSource).getAbsolutePath(), AudioType.FILE);
778-
} else if (dataSource instanceof URL) { //todo
779-
return -1;
780-
} else if (dataSource instanceof InputStream) { //todo
781-
return -1;
782-
}
783-
784-
return -1;
785-
767+
return source.getDurationInSeconds();
786768
}
787769

788770
/**
@@ -910,7 +892,7 @@ private void goOutOfPause() {
910892
@Override
911893
public int getEncodedStreamPosition() {
912894
int position = -1;
913-
if (dataSource instanceof File && encodedAudioInputStream != null)
895+
if (source.isFile() && encodedAudioInputStream != null)
914896
try {
915897
position = encodedAudioLength - encodedAudioInputStream.available();
916898
} catch (final IOException ex) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.goxr3plus.streamplayer.stream;
2+
3+
import javax.sound.sampled.AudioFileFormat;
4+
import javax.sound.sampled.AudioInputStream;
5+
import javax.sound.sampled.AudioSystem;
6+
import javax.sound.sampled.UnsupportedAudioFileException;
7+
import java.io.IOException;
8+
import java.net.URL;
9+
10+
public class UrlDataSource implements DataSource {
11+
12+
private URL source;
13+
14+
UrlDataSource(URL source) {
15+
this.source = source;
16+
}
17+
18+
@Override
19+
public AudioFileFormat getAudioFileFormat() throws UnsupportedAudioFileException, IOException {
20+
return AudioSystem.getAudioFileFormat((URL) source);
21+
}
22+
23+
@Override
24+
public AudioInputStream getAudioInputStream() throws UnsupportedAudioFileException, IOException {
25+
return AudioSystem.getAudioInputStream(source);
26+
}
27+
28+
@Override
29+
public int getDurationInSeconds() {
30+
return -1;
31+
}
32+
33+
@Override
34+
public Object getSource() {
35+
return source;
36+
}
37+
38+
@Override
39+
public String toString() {
40+
return "UrlDataSource with " + source.toString();
41+
}
42+
43+
@Override
44+
public boolean isFile() {
45+
return false;
46+
}
47+
}

0 commit comments

Comments
 (0)