Jason94
Jason94

Reputation: 13620

How can I stream MP3 with AudioTrackStreamer?

I'm trying to create a mp3 streamer, but I'm failing miserably :-)

I've got the following in my AudioTrackStreamer:

        protected override void OnBeginStreaming(AudioTrack track, AudioStreamer streamer)
        {
            //TODO: Set the SetSource property of streamer to a MSS source
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://api.soundcloud.com/tracks/85085126/stream?consumer_key=db840ada2477a93d5fdbcc96a46b37c1");
            req.ContentType = "application/octet-stream";

            try
            {
                req.BeginGetRequestStream((callback) =>
                    {
                        HttpWebRequest request = (HttpWebRequest)callback.AsyncState;
                        Stream stream = request.EndGetRequestStream(callback);
                        Mp3MediaStreamSource src = new Mp3MediaStreamSource(stream, 1000);

                        streamer.SetSource(src);

                        NotifyComplete();

                    }, req);
            }
            catch { }

And it fails, catching ProtocolIViolationException with the message:

[Arg_InvalidOperationException]
Arguments: 
Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.50829.0&File=mscorlib.dll&Key=Arg_InvalidOperationException

The url to the file is something I found while googling free Music, and if you open it you get to download a mp3 file... so the source should be legit?

Upvotes: 0

Views: 277

Answers (1)

Soonts
Soonts

Reputation: 21956

  1. You're using the wrong stream for the data source. Replace [Begin/End]GetRequestStream with [Begin/End]GetResponse, in the completion handler call WebResponse.GetResponseStream to access the correct stream.
  2. Don't call NotifyComplete from OnBeginStreaming. Instead, call NotifyComplete when the track is played to the end.
  3. Before BeginGetResponse, you should set req.AllowReadStreamBuffering = false; otherwise your MP3s will download completely before playback.

Update - my while() loop looks like this:

while( true )
{
    if( cancel.IsCancellationRequested )
        return;

    if( buffer.hasFreeSpace() )
    {
        int cb = await this.downloadAsync().ConfigureAwait( false );
        var buffWaiter = m_bufferAwaiter;
        if( 0 == cb )
        {
            Exception ex = new Exception( "runBackgroundAsync: connection dropped" );;
            if( null != buffWaiter )
                buffWaiter.Fail( ex );
            throw ex;
        }

        if( null != buffWaiter )
        {
            // The client is waiting for the data to be pre-buffered
            if( buffWaiter.haveBuffer( buffer.cbLength ) )
            {
                // Sufficient data has been downloaded, so playback is going to resume after this haveBuffer() call.
                m_bufferAwaiter = null;
            }
        }
        continue;   //< Continuing to while(true) without a single sleep.
    }
    await TaskEx.Delay( this.tsSleepTimeWhenBufferFull, cancel ).ConfigureAwait( false );
}

Upvotes: 1

Related Questions