140 lines
4.7 KiB
Plaintext
140 lines
4.7 KiB
Plaintext
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: Play.sg
|
||
|
//
|
||
|
// Note: Simple audio test program.
|
||
|
//
|
||
|
using System;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using System.Threading;
|
||
|
using Microsoft.Contracts;
|
||
|
|
||
|
using Microsoft.SingSharp;
|
||
|
using Microsoft.Singularity;
|
||
|
using Microsoft.Singularity.Channels;
|
||
|
using Microsoft.Singularity.Directory;
|
||
|
using Microsoft.Singularity.Io;
|
||
|
using Microsoft.Singularity.Configuration;
|
||
|
using Microsoft.SingSharp.Reflection;
|
||
|
using Microsoft.Singularity.Applications;
|
||
|
|
||
|
[assembly: Transform(typeof(ApplicationResourceTransform))]
|
||
|
|
||
|
namespace Microsoft.Singularity.Applications
|
||
|
{
|
||
|
// use driver category for now.
|
||
|
// Once the appropriate categories have been defined this will need to change
|
||
|
// Also waiting for Compile Time reflection to eliminate static constructor etc.
|
||
|
|
||
|
[ConsoleCategory(DefaultAction=true)]
|
||
|
internal sealed class PlayConfiguration
|
||
|
{
|
||
|
[InputEndpoint("data")]
|
||
|
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
|
||
|
|
||
|
[OutputEndpoint("data")]
|
||
|
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
|
||
|
|
||
|
[Endpoint]
|
||
|
public readonly TRef<SoundDeviceContract.Imp:Start> ImpRef;
|
||
|
|
||
|
reflective internal PlayConfiguration();
|
||
|
|
||
|
internal int AppMain() {
|
||
|
return Play.AppMain(this);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
public class Play
|
||
|
{
|
||
|
private static SoundDeviceContract.Imp:Ready OpenSoundDevice(PlayConfiguration! config)
|
||
|
{
|
||
|
// extract imp handed in as part of process creation
|
||
|
SoundDeviceContract.Imp! imp = (config.ImpRef).Acquire();
|
||
|
|
||
|
// get it into the ready state
|
||
|
Console.WriteLine("[{0}] Waiting for SB channel.", Thread.CurrentThread.GetThreadId());
|
||
|
switch receive
|
||
|
{
|
||
|
case imp.Success():
|
||
|
Console.WriteLine("[{0}] Got SB channel.", Thread.CurrentThread.GetThreadId());
|
||
|
break;
|
||
|
case imp.ContractNotSupported():
|
||
|
delete imp;
|
||
|
throw new Exception("Didn't Get SB channel. (ContractNotSupported)");
|
||
|
case imp.ChannelClosed():
|
||
|
delete imp;
|
||
|
throw new Exception("Didn't Get SB channel. (Channel closed)");
|
||
|
}
|
||
|
return imp;
|
||
|
}
|
||
|
|
||
|
internal static int AppMain(PlayConfiguration! config)
|
||
|
{
|
||
|
if (WavAudio.Content == null || WavAudio.Content.Length == 0) {
|
||
|
Console.WriteLine("No WAV audio to play.");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return DoPlay(config);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
private static int DoPlay(PlayConfiguration! config) {
|
||
|
SoundDeviceContract.Imp audio = OpenSoundDevice(config);
|
||
|
if (audio == null) {
|
||
|
Console.WriteLine("Couldn't open audio device.");
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
int threadId = Thread.CurrentThread.GetThreadId();
|
||
|
|
||
|
assume WavAudio.Content != null;
|
||
|
|
||
|
try {
|
||
|
for (int i = 0; i < WavAudio.Content.Length; i++) {
|
||
|
Console.WriteLine("[{1}] Playing WAV audio {0}.", i, threadId);
|
||
|
|
||
|
byte[] wav = (!)WavAudio.Content[i];
|
||
|
|
||
|
byte[] in ExHeap buffer = Bitter.FromByteArray(wav);
|
||
|
|
||
|
// Copy contents into buffer WavAudio.Content[i]
|
||
|
|
||
|
audio.SendPlayWav(buffer);
|
||
|
switch receive
|
||
|
{
|
||
|
case audio.RecvAckPlayWav(oldbuffer):
|
||
|
Console.WriteLine("[{1}] Done playing WAV audio {0}.", i,
|
||
|
threadId);
|
||
|
delete oldbuffer;
|
||
|
break;
|
||
|
|
||
|
case audio.RecvNakPlayWav(oldbuffer):
|
||
|
Console.WriteLine("[{1}] Failed to play WAV audio {0}.",
|
||
|
i, threadId);
|
||
|
delete oldbuffer;
|
||
|
break;
|
||
|
|
||
|
case audio.ChannelClosed():
|
||
|
Console.WriteLine("[{1}] SoundDevice channel closed unexpectedly {0}.",
|
||
|
i, threadId);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
finally {
|
||
|
delete audio;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|