// Play starts playing the source. func (s *Source) Play() bool { if s.IsPlaying() { return true } if s.IsPaused() { s.Resume() return true } //claim a source for ourselves and make sure it worked if !pool.claim(s) || !s.isValid() { return false } pool.mutex.Lock() defer pool.mutex.Unlock() if s.isStatic { s.source.SetBuffer(s.staticBuffer) } else { buffers := []al.Buffer{} for i := 0; i < MAX_BUFFERS; i++ { buffer := al.GenBuffers(1)[0] if s.stream(buffer) > 0 { buffers = append(buffers, buffer) } if s.decoder.IsFinished() { break } } if len(buffers) > 0 { s.source.QueueBuffers(buffers...) } } // This Source may now be associated with an OpenAL source that still has // the properties of another Source. Let's reset it to the settings // of the new one. s.reset() // Clear errors. al.Error() al.PlaySources(s.source) // alSourcePlay may fail if the system has reached its limit of simultaneous // playing sources. return al.Error() == al.NoError }
// createPool generates a new pool and gets the max sources. func createPool() { pool = &audioPool{ sources: [MAX_SOURCES]al.Source{}, available: []al.Source{}, playing: make(map[al.Source]*Source), } // Generate sources. for i := 0; i < MAX_SOURCES; i++ { pool.sources[i] = al.GenSources(1)[0] // We might hit an implementation-dependent limit on the total number // of sources before reaching MAX_SOURCES. if al.Error() != 0 { break } pool.totalSources++ } if pool.totalSources < 4 { panic("Could not generate audio sources.") } // Make all sources available initially. for i := 0; i < pool.totalSources; i++ { pool.available = append(pool.available, pool.sources[i]) } go func() { ticker := time.NewTicker(1 * time.Second) go func() { for { select { case <-ticker.C: pool.update() } } }() }() }