我正在写一个小工具,它可以播放command/terminal
sox之类的音频文件。我正在为 Windows 使用bass.dll
Golang syscall
。
这是我的代码,文件可以从评论中下载,只能在 Windows X64 上运行。
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 BassLib struct {
libBass syscall.Handle
init uintptr
free uintptr
streamCreateFile uintptr
channelPlay uintptr
channelPause uintptr
channelStop uintptr
}
func (bass *BassLib) LoadBass(bassDllPath string) bool {
bass.libBass, _ = syscall.LoadLibrary(bassDllPath)
if bass.libBass == 0 {
fmt.Println("load library result")
fmt.Println(bass.libBass)
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
syscall.Syscall6(bass.init, 5, uintptr(device), uintptr(44100), uintptr(0), uintptr(0), uintptr(0), 0)
return true
}
func StrPtr(s string) uintptr {
// return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
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
var bassUnicode uint32 = 0x80000000
hstream, _, _ := syscall.Syscall6(bass.streamCreateFile, 5, uintptr(0), StrPtr(filePath), uintptr(0), uintptr(0), uintptr(bassUnicode), 0)
// bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")
// errCode, _, _ := syscall.Syscall(uintptr(bassErrorGetCode), 0, 0, 0, 0)
// fmt.Println(errCode)
fmt.Println("hstream")
fmt.Println(hstream)
bass.channelPlay, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPlay")
// BASS_ChannelPlay(hstream)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelPlay.html
ret, _, _ := syscall.Syscall(bass.channelPlay, 2, hstream, uintptr(0), 0)
bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")
errCode, _, _ := syscall.Syscall(bassErrorGetCode, 0, 0, 0, 0)
fmt.Println(errCode)
fmt.Println(ret)
// sleep to wait playing mp3 file
time.Sleep(time.Second * 10)
// bass.channelPause, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPause")
// bass.channelStop, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelStop")
// return true
}
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()
}
有一个大问题:
- 如果未添加
time.Sleep
代码(bass.go
第 68 行),则不会播放任何声音并快速退出。 - 当我添加
time.Sleep(time.Second * 10)
代码时,音频持续时间可能超过 10 秒。
有没有可能让程序在播放完音频后自动退出?