声音部分的代码仍需调试,现在panic

This commit is contained in:
TonyChyi
2022-09-27 14:36:25 +08:00
parent 7ef721afb7
commit edbe406f5b
6 changed files with 104 additions and 116 deletions

View File

@@ -15,12 +15,19 @@ import (
"github.com/sirupsen/logrus"
)
const waveHeaderSize = 16
var waveHeader = &audiodriver.WavHeader{
Size: waveHeaderSize,
AudioFormat: 1,
NumChannels: 2,
SampleRate: 44100,
BlockAlign: 4,
BitsPerSample: 16,
}
type Server struct {
options *Options
QmpConnector struct {
RX chan *qemuconnection.Event
TX chan qemu.Status
}
options *Options
qemu *qemu.Domain
audioHeader chan *audiodriver.WavHeader
pcm chan [audiodriver.BufferSize]byte
@@ -38,8 +45,6 @@ func NewServer(o *Options) (*Server, error) {
audioHeader: make(chan *audiodriver.WavHeader, 1),
pcm: make(chan [audiodriver.BufferSize]byte),
}
server.QmpConnector.RX = make(chan *qemuconnection.Event)
server.QmpConnector.TX = make(chan qemu.Status)
u, err := url.Parse(o.QmpAddress)
if err != nil {
@@ -80,7 +85,7 @@ func NewServer(o *Options) (*Server, error) {
return nil, err
}
audio.PCM = server.pcm
audio.WaveHeader = server.audioHeader
audio.WaveHeader = waveHeader
if err := driver.GetManager().Register(
vncdriver.NewVnc(o.VNCAddress),
@@ -98,84 +103,26 @@ func NewServer(o *Options) (*Server, error) {
func (s *Server) Run() error {
logrus.Debug("qemu server running")
defer logrus.Debug("qemu server exit")
defer s.qemu.Close()
s.startCapture()
logrus.Debug("qemu capture start")
for ev := range s.QmpConnector.RX {
if ev.Type == qemuconnection.QueryStatusEvent {
status, err := s.qemu.Status()
if err != nil {
logrus.Error("get qemu status error: ", err)
continue
}
s.QmpConnector.TX <- status
continue
}
for _, cmd := range ev.ToQemuCommand() {
_, err := s.qemu.Run(cmd)
if err != nil {
logrus.Error("run command error: ", err)
}
}
}
return nil
}
func (s *Server) startCapture() {
const waveHeaderSize = 16
waveHeader := &audiodriver.WavHeader{
Size: waveHeaderSize,
AudioFormat: 1,
NumChannels: 2,
SampleRate: 44100,
BlockAlign: 4,
BitsPerSample: 16,
f, err := os.Open(s.options.AudioPipe)
if err != nil {
logrus.Fatal(err)
}
defer f.Close()
logrus.Debug("start reading fifo")
go func() {
f, err := os.Open(s.options.AudioPipe)
if err != nil {
logrus.Fatal(err)
}
defer f.Close()
logrus.Debug("start reading from fifo")
s.audioHeader <- waveHeader
close(s.audioHeader) // only once
// skip to pcm data, for 44 bytes.
var _dataChunkHeader [audiodriver.FmtHeaderOffset +
audiodriver.FmtHeaderIDSize + audiodriver.FmtHeaderChunkSizeSize + waveHeaderSize +
audiodriver.DataChunkIDSize + audiodriver.DataChunkSizeSize]byte
if _, err := f.Read(_dataChunkHeader[:]); err != nil {
logrus.Fatal(err)
}
defer close(s.pcm)
for {
var b [audiodriver.BufferSize]byte
if _, err := f.Read(b[:]); err != nil {
logrus.Error(err)
}
select {
case s.pcm <- b:
case <-time.After(waveHeader.GetLatnecy()):
}
}
}()
go func() {
logrus.Debug("setting audio capture")
if _, err := s.qemu.Run(qmp.Command{
Execute: "human-monitor-command",
Args: map[string]string{
"command-line": fmt.Sprintf(
"wavcapture %s %s",
"wavcapture %s %s %d %d %d",
s.options.AudioPipe,
s.options.AudioDevice,
waveHeader.SampleRate,
waveHeader.BitsPerSample,
waveHeader.NumChannels,
),
},
}); err != nil {
@@ -183,6 +130,27 @@ func (s *Server) startCapture() {
}
logrus.Debug("audio capture set")
}()
logrus.Debug("skip wave headers, to the PCM!")
// skip to pcm data, for 44 bytes.
var _dataChunkHeader [audiodriver.FmtHeaderOffset +
audiodriver.FmtHeaderIDSize + audiodriver.FmtHeaderChunkSizeSize + waveHeaderSize +
audiodriver.DataChunkIDSize + audiodriver.DataChunkSizeSize]byte
if _, err := f.Read(_dataChunkHeader[:]); err != nil {
logrus.Fatal(err)
}
defer close(s.pcm)
for {
var b [audiodriver.BufferSize]byte
if _, err := f.Read(b[:]); err != nil {
logrus.Error(err)
}
select {
case s.pcm <- b:
case <-time.After(waveHeader.GetLatnecy()):
}
}
}
func (s *Server) SendEvent(b []byte) error {
@@ -190,13 +158,19 @@ func (s *Server) SendEvent(b []byte) error {
if err != nil {
return err
}
s.QmpConnector.RX <- ev
for _, cmd := range ev.ToQemuCommand() {
_, err := s.qemu.Run(cmd)
if err != nil {
return err
}
}
return nil
}
func (s *Server) GetStatus() qemu.Status {
s.QmpConnector.RX <- &qemuconnection.Event{
Type: qemuconnection.QueryStatusEvent,
status, err := s.qemu.Status()
if err != nil {
return qemu.StatusIOError
}
return <-s.QmpConnector.TX
return status
}