I have a thread (in VB.NET 4.0) that is designed to play audio. This thread is part of a Windows Service. I'm trying to do real simple play the wav file, then go on and play the next one in the queue sort of thing if there is one. I've used the Wave.IWavePlayer object to do this.
The problem I am having is it will work for a while then either get in a state where it says it is playing but stays at position 0. Or alternatively it will crash my entire service. I'm using 1.5.4. Obviously it is a Windows Service so lacks in the user interface department which might be causing its own issues. Any help you can provide would be greatly appreciated. As a side note, I have starting using NAudio instead of the standard My.Computer.Audio.Play() because Windows 7 has somehow prevented Windows Services from playing audio (worked fine on XP), but the NAudio library seems to get me around that restriction.
Here is the relevant parts of the class:
Private WithEvents _Player As NAudio.Wave.IWavePlayer
Public Sub New()
_Player = New NAudio.Wave.DirectSoundOut(100)
End Sub
Private Sub PlayWAV(byval wavFile as String)
Try
Dim stream As NAudio.Wave.WaveChannel32
Dim mp3Reader As NAudio.Wave.WaveStream = Nothing
Dim wavReader As NAudio.Wave.WaveStream = Nothing
If (wfile.EndsWith(".mp3")) Then
mp3Reader = New NAudio.Wave.Mp3FileReader(wfile)
stream = New NAudio.Wave.WaveChannel32(mp3Reader)
ElseIf (wfile.EndsWith(".wav")) Then
wavReader = New NAudio.Wave.WaveFileReader(wfile)
stream = New NAudio.Wave.WaveChannel32(wavReader)
Else
stream = Nothing
End If
If Not _Player Is Nothing Then
If Not stream Is Nothing Then
SendStatus(_ClassName & "." & methodName & ": stream.CanRead = " & stream.CanRead.ToString)
SendStatus(_ClassName & "." & methodName & ": stream.WaveFormat = " & stream.WaveFormat.ToString)
SendStatus(_ClassName & "." & methodName & ": stream.TotalTime = " & stream.TotalTime.ToString)
SendStatus(_ClassName & "." & methodName & ": stream.Length = " & stream.Length)
SendStatus(_ClassName & "." & methodName & ": player.PlaybackState = " & _Player.PlaybackState.ToString)
' NOTE: Might want to make sure player has stopped before re-initing it?
_Player.Init(stream)
Thread.Sleep(100)
_Player.Play()
SendStatus(_ClassName & "." & methodName & ": Play Started")
Thread.Sleep(100)
logTimer = logTimerReload - 1
While _Player.PlaybackState = NAudio.Wave.PlaybackState.Playing
'SendStatus(_ClassName & "." & methodName & ": PlaybackState = " & player.PlaybackState.ToString)
'SendStatus(_ClassName & "." & methodName & ": Position = " & stream.Position)
'SendStatus(_ClassName & "." & methodName & ": CurrentTime = " & stream.CurrentTime.ToString)
If stream.Position > stream.Length Then
Exit While
End If
If stream.CurrentTime > stream.TotalTime Then
Exit While
End If
If _IsCancelled = True Then
Exit While
End If
Thread.Sleep(100)
If logTimer > 1 Then
logTimer -= 1
Else
logTimer = logTimerReload
If stream.Position = 0 Then
SendStatus(_ClassName & "." & methodName & ": WARNING - Not playing. Still at position 0. Aborting..")
Log(LogFile.WarningLog, _ClassName & "." & methodName & ": WARNING - Not playing. Still at position 0. Aborting..")
Exit While
Else
SendStatus(_ClassName & "." & methodName & ": Playing - " & stream.Position & "/" & stream.Length & ", " & stream.CurrentTime.ToString & "/" & stream.TotalTime.ToString)
End If
End If
End While
' Make sure player stops correctly
Thread.Sleep(100)
SendStatus(_ClassName & "." & methodName & ": player.PlaybackState = " & _Player.PlaybackState.ToString)
If _Player.PlaybackState <> NAudio.Wave.PlaybackState.Stopped Then
_Player.Stop()
SendStatus(_ClassName & "." & methodName & ": Stop issued")
logTimer = logTimerReload - 1
While _Player.PlaybackState <> NAudio.Wave.PlaybackState.Stopped
Thread.Sleep(100)
If _IsCancelled = True Then
Exit While
End If
If logTimer > 1 Then
logTimer -= 1
Else
logTimer = logTimerReload
SendStatus(_ClassName & "." & methodName & ": Waiting for stop (" & _Player.PlaybackState.ToString & ")")
End If
End While
SendStatus(_ClassName & "." & methodName & ": Stopped or Cancelled")
Thread.Sleep(100)
End If
' Clean-up
stream.Close()
stream.Dispose()
stream = Nothing
If Not mp3Reader Is Nothing Then
mp3Reader.Close()
mp3Reader.Dispose()
mp3Reader = Nothing
End If
If Not wavReader Is Nothing Then
wavReader.Close()
wavReader.Dispose()
wavReader = Nothing
End If
Else
Log(LogFile.WarningLog, _ClassName & "." & methodName & ": Unable to create stream. Most likely unsupported file type (" & System.IO.Path.GetExtension(wfile) & ")")
SendStatus(_ClassName & "." & methodName & ": Unable to create stream. Most likely unsupported file type (" & System.IO.Path.GetExtension(wfile) & ")")
End If
Else
Log(LogFile.WarningLog, _ClassName & "." & methodName & ": Player is Nothing")
SendStatus(_ClassName & "." & methodName & ": Player is Nothing")
End If
Catch ex As Exception
LogError(ex.message)
End Try
End Sub
The problem I am having is it will work for a while then either get in a state where it says it is playing but stays at position 0. Or alternatively it will crash my entire service. I'm using 1.5.4. Obviously it is a Windows Service so lacks in the user interface department which might be causing its own issues. Any help you can provide would be greatly appreciated. As a side note, I have starting using NAudio instead of the standard My.Computer.Audio.Play() because Windows 7 has somehow prevented Windows Services from playing audio (worked fine on XP), but the NAudio library seems to get me around that restriction.
Here is the relevant parts of the class:
Private WithEvents _Player As NAudio.Wave.IWavePlayer
Public Sub New()
_Player = New NAudio.Wave.DirectSoundOut(100)
End Sub
Private Sub PlayWAV(byval wavFile as String)
Try
Dim stream As NAudio.Wave.WaveChannel32
Dim mp3Reader As NAudio.Wave.WaveStream = Nothing
Dim wavReader As NAudio.Wave.WaveStream = Nothing
If (wfile.EndsWith(".mp3")) Then
mp3Reader = New NAudio.Wave.Mp3FileReader(wfile)
stream = New NAudio.Wave.WaveChannel32(mp3Reader)
ElseIf (wfile.EndsWith(".wav")) Then
wavReader = New NAudio.Wave.WaveFileReader(wfile)
stream = New NAudio.Wave.WaveChannel32(wavReader)
Else
stream = Nothing
End If
If Not _Player Is Nothing Then
If Not stream Is Nothing Then
SendStatus(_ClassName & "." & methodName & ": stream.CanRead = " & stream.CanRead.ToString)
SendStatus(_ClassName & "." & methodName & ": stream.WaveFormat = " & stream.WaveFormat.ToString)
SendStatus(_ClassName & "." & methodName & ": stream.TotalTime = " & stream.TotalTime.ToString)
SendStatus(_ClassName & "." & methodName & ": stream.Length = " & stream.Length)
SendStatus(_ClassName & "." & methodName & ": player.PlaybackState = " & _Player.PlaybackState.ToString)
' NOTE: Might want to make sure player has stopped before re-initing it?
_Player.Init(stream)
Thread.Sleep(100)
_Player.Play()
SendStatus(_ClassName & "." & methodName & ": Play Started")
Thread.Sleep(100)
logTimer = logTimerReload - 1
While _Player.PlaybackState = NAudio.Wave.PlaybackState.Playing
'SendStatus(_ClassName & "." & methodName & ": PlaybackState = " & player.PlaybackState.ToString)
'SendStatus(_ClassName & "." & methodName & ": Position = " & stream.Position)
'SendStatus(_ClassName & "." & methodName & ": CurrentTime = " & stream.CurrentTime.ToString)
If stream.Position > stream.Length Then
Exit While
End If
If stream.CurrentTime > stream.TotalTime Then
Exit While
End If
If _IsCancelled = True Then
Exit While
End If
Thread.Sleep(100)
If logTimer > 1 Then
logTimer -= 1
Else
logTimer = logTimerReload
If stream.Position = 0 Then
SendStatus(_ClassName & "." & methodName & ": WARNING - Not playing. Still at position 0. Aborting..")
Log(LogFile.WarningLog, _ClassName & "." & methodName & ": WARNING - Not playing. Still at position 0. Aborting..")
Exit While
Else
SendStatus(_ClassName & "." & methodName & ": Playing - " & stream.Position & "/" & stream.Length & ", " & stream.CurrentTime.ToString & "/" & stream.TotalTime.ToString)
End If
End If
End While
' Make sure player stops correctly
Thread.Sleep(100)
SendStatus(_ClassName & "." & methodName & ": player.PlaybackState = " & _Player.PlaybackState.ToString)
If _Player.PlaybackState <> NAudio.Wave.PlaybackState.Stopped Then
_Player.Stop()
SendStatus(_ClassName & "." & methodName & ": Stop issued")
logTimer = logTimerReload - 1
While _Player.PlaybackState <> NAudio.Wave.PlaybackState.Stopped
Thread.Sleep(100)
If _IsCancelled = True Then
Exit While
End If
If logTimer > 1 Then
logTimer -= 1
Else
logTimer = logTimerReload
SendStatus(_ClassName & "." & methodName & ": Waiting for stop (" & _Player.PlaybackState.ToString & ")")
End If
End While
SendStatus(_ClassName & "." & methodName & ": Stopped or Cancelled")
Thread.Sleep(100)
End If
' Clean-up
stream.Close()
stream.Dispose()
stream = Nothing
If Not mp3Reader Is Nothing Then
mp3Reader.Close()
mp3Reader.Dispose()
mp3Reader = Nothing
End If
If Not wavReader Is Nothing Then
wavReader.Close()
wavReader.Dispose()
wavReader = Nothing
End If
Else
Log(LogFile.WarningLog, _ClassName & "." & methodName & ": Unable to create stream. Most likely unsupported file type (" & System.IO.Path.GetExtension(wfile) & ")")
SendStatus(_ClassName & "." & methodName & ": Unable to create stream. Most likely unsupported file type (" & System.IO.Path.GetExtension(wfile) & ")")
End If
Else
Log(LogFile.WarningLog, _ClassName & "." & methodName & ": Player is Nothing")
SendStatus(_ClassName & "." & methodName & ": Player is Nothing")
End If
Catch ex As Exception
LogError(ex.message)
End Try
End Sub