Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Getting the size of a stream  RSS feed

 
olze oli
Ranch Hand
Posts: 174
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

following problem:
I have an InputStream which is a media file from a webserver (mp3) which plays fine. I have a JSlider to display the position in the song, that works also fine. But now i want to add a second value over the original slider which represents how many bytes have been downloaded into the buffer for playback.

m_audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(SomeUrlsInputStream));

i tried to add another thread which reads from m_audioInputStream until -1 is returned but that leads to strange effects in the playback. Do i have to create another BufferedInputStream? Is the file then downloaded twice? Or does anyone have a better idea? Thanks!
 
Rob Spoor
Sheriff
Posts: 21092
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you use URL and URLConnection to get the InputStream you can probably use the content length:
 
olze oli
Ranch Hand
Posts: 174
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i get the content length from the server header, this is the maximum of my slider and i set the value always when i read in (n) byte

i dont know how to explain that correctly in english (my english is not the best) so i will try it with an example, youtube ;)
if you watch any video, you see 2 red bars and one knob for playing forward/backward
the first and more red painted line is whats your current position in the video <---- thats what i already have
the second and less red painted line is whats already downloaded <--- thats what i want to implement
 
Rob Spoor
Sheriff
Posts: 21092
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You'll need to create your own buffering input stream, as BufferedInputStream doesn't let you query what's already been read. Also, the reading must be done in multiple threads: one thread must fill your buffer, the other will be used for displaying the data.

I think the best way is to extend InputStream. Your subclass then has a buffer of bytes; perhaps a Deque<Byte> is best so 1) it's resizable, and 2) you can add to the end and remove from the start. It has one thread that reads from the InputStream passed in the constructor, and fills the buffer. The read methods then read from the buffer. Make sure to synchronize on the buffer to prevent any problems.

As an extra feature you can perhaps limit the buffer size so it won't fill up indefinitely.
 
olze oli
Ranch Hand
Posts: 174
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you tell me what you mean with: Deque<Byte> ?
Just writing the class... thanks for that hint ;)

edit: ok found that Deque thing... which class would you use? BlockingDeque?
 
olze oli
Ranch Hand
Posts: 174
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

unfortunatly this throws a exception:
java.io.IOException: Resetting to invalid mark
at java.io.BufferedInputStream.reset(BufferedInputStream.java:416)
at org.tritonus.share.sampled.file.TAudioFileReader.getAudioInputStream(TAudioFileReader.java:325)
at javazoom.spi.mpeg.sampled.file.MpegAudioFileReader.getAudioInputStream(Unknown Source)
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1094)
at playbox.player.PlayThread.run(PlayThread.java:276)


in my application i use the HttpClient library for accessing the http stream, but as i needed the raw InputStream i modified the source a little bit to get the original stream


becomes a little bit too complex...
 
Rob Spoor
Sheriff
Posts: 21092
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A BlockingDeque could be used, but you'd need a special end-of-stream value. InputStream uses primitives so they've solved it by returning a value between 0 and 255 for proper values and -1 for end-of-stream. Since your Deque will contain Byte (the wrapper class) instances you can add null as a last element when all data is read. That way the Deque won't block when no more data is available but null is its only element instead.
 
Rob Spoor
Sheriff
Posts: 21092
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You'll also need to implement marking and resetting, possibly with a separate collection of bytes - those that were read since marking. Upon a reset you add those back to the start of the Deque.
 
olze oli
Ranch Hand
Posts: 174
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ok thanks, i think this will take days or even weeks because i never handled that detailed with streams...

edit: isn't there any other way to do this for not so advanced java programmer?
 
Rob Spoor
Sheriff
Posts: 21092
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not that I know of.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!