声音部分的代码仍需调试,现在panic
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user