//////////////////////////////////////////////////////////////////////////////// // // 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 Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; [Endpoint] public readonly TRef 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; } } }