如何让程序在音频播放完毕后自动退出

我正在写一个小工具,它可以播放command/terminalsox之类的音频文件。我正在为 Windows 使用bass.dllGolang 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))


}


有一个大问题:


如果未添加time.Sleep代码(bass.go第 68 行),则不会播放任何声音并快速退出。

当我添加time.Sleep(time.Second * 10)代码时,音频持续时间可能超过 10 秒。

有没有可能让程序在播放完音频后自动退出?


慕容森
浏览 222回答 3
3回答

holdtom

我认为您可以defer在播放功能完成后使用 golang 的关键字来触发退出。你可以参考这里:围棋之旅 | 推迟 或在这里:Golang 博客 | 推迟package mainimport "fmt"func main() {    defer fmt.Println("world")    fmt.Println("hello")}==========$ go run main.gohelloworld

阿波罗的战车

我强烈建议您阅读 golang.org 网站上的Effective Go(阅读时间不长,我相信您可以在一天内完成所有想法),特别注意并发部分。Go 背后的整个想法是使并发和异步编程变得容易,它使用了多种语言结构(通道、goroutines),这些结构是专门为帮助您处理这些情况而设计的。例如,您可以使用通道发出信号:func main() {&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // end signal&nbsp; &nbsp; finished := make(chan bool)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // create and run a goroutine&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp;// do your bass stuff here&nbsp; &nbsp; &nbsp; &nbsp;...&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// send a signal&nbsp; &nbsp; &nbsp; &nbsp;finished <- true&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; }()&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // wait&nbsp; &nbsp; <-finished}一种常见的模式是将通道传递给执行该工作的函数:func main() {&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // end signal&nbsp; &nbsp; finished := make(chan bool)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // PlayFile is responsible for&nbsp; &nbsp; // signalling 'finished' when done&nbsp; &nbsp; go PlayFile(someFile, finished);&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // wait&nbsp; &nbsp; <-finished}或者,如果您有多个例程,您将使用WaitGroup:func main() {&nbsp; &nbsp; // create the waitgroup&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; // number of semaphores&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp;// notify WaitGroup when done&nbsp; &nbsp; &nbsp; &nbsp;// (the 'defer' keyword means&nbsp; &nbsp; &nbsp; &nbsp;// this call will be executed before&nbsp; &nbsp; &nbsp; &nbsp;// returning from the method)&nbsp; &nbsp; &nbsp; &nbsp;defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// do your bass stuff here&nbsp; &nbsp; &nbsp; &nbsp;...&nbsp; &nbsp; }()&nbsp; &nbsp; wg.Wait()}

当年话下

BASS_ChannelGetLength可以用和BASS_ChannelGetPosition功能解决问题。这是代码:// +build windowspackage mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "syscall"&nbsp; &nbsp; "time"&nbsp; &nbsp; "unsafe")/*基于 [bass.dll](http://us2.un4seen.com/files/bass24.zip)和 [Golang syscall](https://github.com/golang/go/wiki/WindowsDLLs)实现的命令行版播放器。*/type (&nbsp; &nbsp; BASSErrorGetCode int32)const (&nbsp; &nbsp; BassUnicode uint32 = 0x80000000 // BASS_UNICODE&nbsp; &nbsp; BassSampleFloat uint32 = 256 // BASS_SAMPLE_FLOAT&nbsp; &nbsp; BassPosByte uint64 = 0&nbsp; // BASS_POS_BYTE)type BassLib struct {&nbsp; &nbsp; libBass syscall.Handle&nbsp; &nbsp; init&nbsp; &nbsp;uintptr&nbsp; &nbsp; free&nbsp; &nbsp;uintptr&nbsp; &nbsp; streamCreateFile uintptr&nbsp; &nbsp; channelPlay uintptr&nbsp; &nbsp; channelPause uintptr&nbsp; &nbsp; channelStop uintptr&nbsp; &nbsp; channelGetLength uintptr&nbsp; &nbsp; channelGetPosition uintptr&nbsp; &nbsp; channelBytes2Seconds uintptr}func (bass *BassLib) LoadBass(bassDllPath string) bool {&nbsp; &nbsp; bass.libBass, _ = syscall.LoadLibrary(bassDllPath)&nbsp; &nbsp; if bass.libBass == 0 {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Load `bass.dll` library failed!")&nbsp; &nbsp; &nbsp; &nbsp; errCode := bass.GetBassErrorGetCode()&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Bass_Init failed!")&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(errCode)&nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }&nbsp; &nbsp; bass.init, _ = syscall.GetProcAddress(bass.libBass, "BASS_Init")&nbsp; &nbsp; // BASS_Init(device, freq, flags, win, clsid)&nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_Init.html&nbsp; &nbsp; device := 1&nbsp; &nbsp; r, _, _ := syscall.Syscall6(bass.init, 5, uintptr(device), uintptr(44100), uintptr(0), uintptr(0), uintptr(0), 0)&nbsp; &nbsp; // var ret = *(* int)(unsafe.Pointer(&r))&nbsp; &nbsp; if r == 0 {&nbsp; &nbsp; &nbsp; &nbsp; errCode := bass.GetBassErrorGetCode()&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Bass_Init failed!")&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(errCode)&nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }&nbsp; &nbsp; return true}func StrPtr(s string) uintptr {&nbsp; &nbsp; p, _ := syscall.UTF16PtrFromString(s)&nbsp; &nbsp; return uintptr(unsafe.Pointer(p))}func (bass *BassLib) PlayFile(filePath string) {&nbsp; &nbsp; bass.streamCreateFile, _ = syscall.GetProcAddress(bass.libBass, "BASS_StreamCreateFile")&nbsp; &nbsp; // hStream = BASS_StreamCreateFile(mem=0, &file, offset=0, length=0, flags=(A_IsUnicode ? 0x80000000 : 0x40000))&nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_StreamCreateFile.html&nbsp; &nbsp; hStream, _, _ := syscall.Syscall6(bass.streamCreateFile, 5,&nbsp; uintptr(0), StrPtr(filePath), uintptr(0), uintptr(0), uintptr(BassUnicode|BassSampleFloat), 0)&nbsp; &nbsp; bass.channelPlay, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPlay")&nbsp; &nbsp; // BASS_ChannelPlay(hStream)&nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_ChannelPlay.html&nbsp; &nbsp; r, _, _ := syscall.Syscall(bass.channelPlay, 2, hStream, uintptr(0), 0)&nbsp; &nbsp; if r == 1 {&nbsp; &nbsp; &nbsp; &nbsp; totalDuration := bass.GetAudioByteLength(hStream)&nbsp; &nbsp; &nbsp; &nbsp; // currentPos := bass.GetAudioCurrentBytePosition(hStream)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(totalDuration)&nbsp; &nbsp; &nbsp; &nbsp; // fmt.Println(currentPos)&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(time.Second*1)&nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; currentPos := bass.GetAudioCurrentBytePosition(hStream)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if currentPos >= totalDuration {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; errCode := bass.GetBassErrorGetCode()&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Bass_ChannelPlay failed!")&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(errCode)&nbsp; &nbsp; }}func (bass *BassLib) GetBassErrorGetCode() BASSErrorGetCode {&nbsp; &nbsp; bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")&nbsp; &nbsp; // BASS_ErrorGetCode()&nbsp; &nbsp; // BASS_OK&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BASSErrorGetCode = 0&nbsp; &nbsp; // all is OK&nbsp; &nbsp; // BASS_ERROR_MEM&nbsp; &nbsp; &nbsp; &nbsp;BASSErrorGetCode = 1&nbsp; &nbsp; // memory error&nbsp; &nbsp; // ...&nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_ErrorGetCode.html&nbsp; &nbsp; errCode, _, _ := syscall.Syscall(bassErrorGetCode, 0, 0, 0, 0)&nbsp; &nbsp; var iErrCode = *(*BASSErrorGetCode)(unsafe.Pointer(&errCode))&nbsp; &nbsp; return iErrCode}func (bass *BassLib) GetAudioByteLength(handle uintptr) uintptr {&nbsp; &nbsp; // (QWORD) BASS_ChannelGetLength(handle=hStream, mode)&nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_ChannelGetLength.html&nbsp; &nbsp; bass.channelGetLength, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetLength")&nbsp; &nbsp; len, _, _ := syscall.Syscall(bass.channelGetLength, 2, handle,&nbsp; uintptr(BassPosByte), 0)&nbsp; &nbsp; return len}func (bass *BassLib) GetAudioCurrentBytePosition(handle uintptr) uintptr {&nbsp; &nbsp; // BASS_ChannelGetPosition(handle=hStream, mode)&nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_ChannelGetPosition.html&nbsp; &nbsp; bass.channelGetPosition, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetPosition")&nbsp; &nbsp; pos, _, _ := syscall.Syscall(bass.channelGetPosition, 2, handle,&nbsp; uintptr(BassPosByte), 0)&nbsp; &nbsp; return pos}func (bass *BassLib) GetChannelBytes2Seconds(handle uintptr, pos uintptr) uintptr {&nbsp; &nbsp; // BASS_ChannelBytes2Seconds(handle=hStream, pos)&nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_ChannelBytes2Seconds.html&nbsp; &nbsp; // bass.channelBytes2Seconds, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelBytes2Seconds")&nbsp; &nbsp; len, _, _ := syscall.Syscall(bass.channelBytes2Seconds, 2, handle, pos, 0)&nbsp; &nbsp; return len}func (bass *BassLib) UnLoad() {&nbsp; &nbsp; if bass.libBass != 0 {&nbsp; &nbsp; &nbsp; &nbsp; bass.free, _ = syscall.GetProcAddress(bass.libBass, "BASS_Free")&nbsp; &nbsp; &nbsp; &nbsp; syscall.Syscall(bass.free, 0, 0, 0, 0)&nbsp; &nbsp; &nbsp; &nbsp; // BASS_Free()&nbsp; &nbsp; &nbsp; &nbsp; // see http://www.un4seen.com/doc/#bass/BASS_Free.html&nbsp; &nbsp; &nbsp; &nbsp; syscall.FreeLibrary(bass.libBass)&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; bass := &BassLib{}&nbsp; &nbsp; bass.LoadBass("C:\\workspace\\play\\bass.dll")&nbsp; &nbsp; bass.PlayFile("C:\\workspace\\play\\sample.mp3")&nbsp; &nbsp; bass.UnLoad()}您也可以访问https://gist.github.com/ycrao/e7d1df181f870091b4a6d298d6ea2770#file-bass_play-go-L81-L91。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go