3 回答
TA贡献1805条经验 获得超10个赞
我认为您可以defer在播放功能完成后使用 golang 的关键字来触发退出。
你可以参考这里:围棋之旅 | 推迟 或在这里:Golang 博客 | 推迟
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
==========
$ go run main.go
hello
world
TA贡献1862条经验 获得超6个赞
我强烈建议您阅读 golang.org 网站上的Effective Go(阅读时间不长,我相信您可以在一天内完成所有想法),特别注意并发部分。
Go 背后的整个想法是使并发和异步编程变得容易,它使用了多种语言结构(通道、goroutines),这些结构是专门为帮助您处理这些情况而设计的。
例如,您可以使用通道发出信号:
func main() {
// end signal
finished := make(chan bool)
// create and run a goroutine
go func() {
// do your bass stuff here
...
// send a signal
finished <- true
}()
// wait
<-finished
}
一种常见的模式是将通道传递给执行该工作的函数:
func main() {
// end signal
finished := make(chan bool)
// PlayFile is responsible for
// signalling 'finished' when done
go PlayFile(someFile, finished);
// wait
<-finished
}
或者,如果您有多个例程,您将使用WaitGroup:
func main() {
// create the waitgroup
var wg sync.WaitGroup
// number of semaphores
wg.Add(1)
go func() {
// notify WaitGroup when done
// (the 'defer' keyword means
// this call will be executed before
// returning from the method)
defer wg.Done()
// do your bass stuff here
...
}()
wg.Wait()
}
TA贡献1890条经验 获得超9个赞
BASS_ChannelGetLength可以用和BASS_ChannelGetPosition功能解决问题。
这是代码:
// +build windows
package main
import (
"fmt"
"syscall"
"time"
"unsafe"
)
/*
基于 [bass.dll](http://us2.un4seen.com/files/bass24.zip)
和 [Golang syscall](https://github.com/golang/go/wiki/WindowsDLLs)
实现的命令行版播放器。
*/
type (
BASSErrorGetCode int32
)
const (
BassUnicode uint32 = 0x80000000 // BASS_UNICODE
BassSampleFloat uint32 = 256 // BASS_SAMPLE_FLOAT
BassPosByte uint64 = 0 // BASS_POS_BYTE
)
type BassLib struct {
libBass syscall.Handle
init uintptr
free uintptr
streamCreateFile uintptr
channelPlay uintptr
channelPause uintptr
channelStop uintptr
channelGetLength uintptr
channelGetPosition uintptr
channelBytes2Seconds uintptr
}
func (bass *BassLib) LoadBass(bassDllPath string) bool {
bass.libBass, _ = syscall.LoadLibrary(bassDllPath)
if bass.libBass == 0 {
fmt.Println("Load `bass.dll` library failed!")
errCode := bass.GetBassErrorGetCode()
fmt.Println("Bass_Init failed!")
fmt.Println(errCode)
return false
}
bass.init, _ = syscall.GetProcAddress(bass.libBass, "BASS_Init")
// BASS_Init(device, freq, flags, win, clsid)
// see http://www.un4seen.com/doc/#bass/BASS_Init.html
device := 1
r, _, _ := syscall.Syscall6(bass.init, 5, uintptr(device), uintptr(44100), uintptr(0), uintptr(0), uintptr(0), 0)
// var ret = *(* int)(unsafe.Pointer(&r))
if r == 0 {
errCode := bass.GetBassErrorGetCode()
fmt.Println("Bass_Init failed!")
fmt.Println(errCode)
return false
}
return true
}
func StrPtr(s string) uintptr {
p, _ := syscall.UTF16PtrFromString(s)
return uintptr(unsafe.Pointer(p))
}
func (bass *BassLib) PlayFile(filePath string) {
bass.streamCreateFile, _ = syscall.GetProcAddress(bass.libBass, "BASS_StreamCreateFile")
// hStream = BASS_StreamCreateFile(mem=0, &file, offset=0, length=0, flags=(A_IsUnicode ? 0x80000000 : 0x40000))
// see http://www.un4seen.com/doc/#bass/BASS_StreamCreateFile.html
hStream, _, _ := syscall.Syscall6(bass.streamCreateFile, 5, uintptr(0), StrPtr(filePath), uintptr(0), uintptr(0), uintptr(BassUnicode|BassSampleFloat), 0)
bass.channelPlay, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPlay")
// BASS_ChannelPlay(hStream)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelPlay.html
r, _, _ := syscall.Syscall(bass.channelPlay, 2, hStream, uintptr(0), 0)
if r == 1 {
totalDuration := bass.GetAudioByteLength(hStream)
// currentPos := bass.GetAudioCurrentBytePosition(hStream)
fmt.Println(totalDuration)
// fmt.Println(currentPos)
time.Sleep(time.Second*1)
for {
currentPos := bass.GetAudioCurrentBytePosition(hStream)
if currentPos >= totalDuration {
break
}
}
} else {
errCode := bass.GetBassErrorGetCode()
fmt.Println("Bass_ChannelPlay failed!")
fmt.Println(errCode)
}
}
func (bass *BassLib) GetBassErrorGetCode() BASSErrorGetCode {
bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")
// BASS_ErrorGetCode()
// BASS_OK BASSErrorGetCode = 0 // all is OK
// BASS_ERROR_MEM BASSErrorGetCode = 1 // memory error
// ...
// see http://www.un4seen.com/doc/#bass/BASS_ErrorGetCode.html
errCode, _, _ := syscall.Syscall(bassErrorGetCode, 0, 0, 0, 0)
var iErrCode = *(*BASSErrorGetCode)(unsafe.Pointer(&errCode))
return iErrCode
}
func (bass *BassLib) GetAudioByteLength(handle uintptr) uintptr {
// (QWORD) BASS_ChannelGetLength(handle=hStream, mode)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelGetLength.html
bass.channelGetLength, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetLength")
len, _, _ := syscall.Syscall(bass.channelGetLength, 2, handle, uintptr(BassPosByte), 0)
return len
}
func (bass *BassLib) GetAudioCurrentBytePosition(handle uintptr) uintptr {
// BASS_ChannelGetPosition(handle=hStream, mode)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelGetPosition.html
bass.channelGetPosition, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetPosition")
pos, _, _ := syscall.Syscall(bass.channelGetPosition, 2, handle, uintptr(BassPosByte), 0)
return pos
}
func (bass *BassLib) GetChannelBytes2Seconds(handle uintptr, pos uintptr) uintptr {
// BASS_ChannelBytes2Seconds(handle=hStream, pos)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelBytes2Seconds.html
// bass.channelBytes2Seconds, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelBytes2Seconds")
len, _, _ := syscall.Syscall(bass.channelBytes2Seconds, 2, handle, pos, 0)
return len
}
func (bass *BassLib) UnLoad() {
if bass.libBass != 0 {
bass.free, _ = syscall.GetProcAddress(bass.libBass, "BASS_Free")
syscall.Syscall(bass.free, 0, 0, 0, 0)
// BASS_Free()
// see http://www.un4seen.com/doc/#bass/BASS_Free.html
syscall.FreeLibrary(bass.libBass)
}
}
func main() {
bass := &BassLib{}
bass.LoadBass("C:\\workspace\\play\\bass.dll")
bass.PlayFile("C:\\workspace\\play\\sample.mp3")
bass.UnLoad()
}
您也可以访问https://gist.github.com/ycrao/e7d1df181f870091b4a6d298d6ea2770#file-bass_play-go-L81-L91。
- 3 回答
- 0 关注
- 181 浏览
添加回答
举报