Skip to content

Commit

Permalink
headless client library
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneP-Zello committed Jun 10, 2018
1 parent b1855df commit 72e3d89
Show file tree
Hide file tree
Showing 43 changed files with 4,497 additions and 3 deletions.
Binary file added Headless/ZelloPTT.chm
Binary file not shown.
Binary file added Headless/ZelloPTT.dll
Binary file not shown.
18 changes: 16 additions & 2 deletions README.md
@@ -1,8 +1,8 @@
# ZelloWork client SDK for Windows
*Push-to-talk SDK for your Windows or Windows Mobile application*

Version: 2.17<br>
Date: March 1, 2017
Version: 2.19<br>
Date: May 31, 2018

### Introduction
Thanks for downloading ZelloWork SDK. It’s designed to enable easy integration of push-to-talk function into any application. This document will guide you through the installation and use of the SDK.
Expand Down Expand Up @@ -68,6 +68,20 @@ If chorus mode is active, all incoming audio messages are activated concurrently

![alt text](Screenshots/SoundSample.png "SoundSample.exe main screen")

###Sample8.exe
Win32 C++ application for Windows based on headless SDK, implementing custom GUI

![alt text](Screenshots/Sample5-1.png "Sample8.exe sign in screen")
![alt text](Screenshots/Sample5-2.png "Sample8.exe contact list")

###MultiClientSample
.NET 2.0 C# application based on headless SDK, implementing audio integration interfaces.
Main window allows to create several in-proc zello clients, each one having functionality similar to SoundSample
If integration mode is active, Zello client doesn't use playback and rendering hardware audio devices.
Instead host app receives uncompressed PCM audio stream for each incoming message, and provides custom PCM audio stream for each outgoing message.

![alt text](Screenshots/MultiClientSample.png "MultiClientSample.exe main screen")

The samples are compiled for the use with ‘default.zellowork.com’ Zello for Work network. You can use any of the following login / password pairs to sign in:

```
Expand Down
86 changes: 86 additions & 0 deletions Samples/MultiClientSample/AudioMessagePlaybackImpl.cs
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace MultiClientSample
{
class AudioMessagePlaybackImpl : ZelloPTTLib.IAudioMessagePlayback
{
private int cntMessages = 1;
List<AudioStreamImpl> lstActiveStreams = new List<AudioStreamImpl>();
public AudioMessagePlaybackImpl(WavBuffer.dlgtAudioRcvStarted _dlgt)
{
savePath = string.Empty;
dlgt = _dlgt;
}

#region IAudioMessagePlayback Members

ZelloPTTLib.IAudioStream ZelloPTTLib.IAudioMessagePlayback.MessageInBegin(ZelloPTTLib.IMessage pMessage)
{
AudioStreamImpl rv = new AudioStreamImpl(cntMessages);
if(false==String.IsNullOrEmpty(savePath)) {
WriteWav ww = new WriteWav(GetSaveFileName(pMessage));
if (ww.Valid)
rv.AddSink(ww);
}
if (bForwardAudio)
{
WavBuffer wb = new WavBuffer();
wb.AudioRcvStarted += dlgt;
rv.AddSink(wb);
}
cntMessages++;
lstActiveStreams.Add(rv);
rv.OnEndOfStream +=new AudioStreamImpl.dlgtFinished(OnEndOfStream);
return rv as ZelloPTTLib.IAudioStream;
}

int ZelloPTTLib.IAudioMessagePlayback.NativeSampleRate
{
get { return 0; }
}

#endregion

public String savePath { get; set; }
public bool bForwardAudio = false;
WavBuffer.dlgtAudioRcvStarted dlgt;
///public List<ZelloPTTLib.IContact> lstForwardAudio = new List<ZelloPTTLib.IContact>();

String GetSaveFileName(ZelloPTTLib.IMessage pMessage)
{
StringBuilder sb = new StringBuilder(savePath);
sb.Append(@"\msg");
sb.Append((cntMessages).ToString("D4"));
ZelloPTTLib.IContact cnt = null;
if (pMessage.Incoming)
{
ZelloPTTLib.IAudioInMessage pAIM = pMessage as ZelloPTTLib.IAudioInMessage;
if (pAIM != null)
{
sb.Append("(");
cnt = pAIM.Sender;
if (cnt != null)
sb.Append(cnt.Name);
if (pAIM.Author != null)
{
sb.Append("__");
sb.Append(pAIM.Author.Name);
}
sb.Append(")");
}
}
sb.Append(".wav");
return sb.ToString();
}

void OnEndOfStream(AudioStreamImpl obj)
{
Program.inf.BeginInvoke((System.Windows.Forms.MethodInvoker)delegate
{
lstActiveStreams.Remove(obj);
});
}
}
}
92 changes: 92 additions & 0 deletions Samples/MultiClientSample/AudioMessageRecording.cs
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;

namespace MultiClientSample
{
class AudioMessageRecording : IDisposable
{
public event EventHandler AllDataWritten;
IReadWav wavDataProvider;
ZelloPTTLib.IAudioStream m_stream;
Thread trdFeed;
public AudioMessageRecording(IReadWav _wavDataProvider)
{
wavDataProvider = _wavDataProvider;
}
public void SetStream(ZelloPTTLib.IAudioStream _stream)
{
if (null != trdFeed)
return;
m_stream = _stream;
m_stream.Start(Convert.ToInt32(wavDataProvider.SampleRate));
trdFeed = new Thread(new ThreadStart(this.ThreadRun));
trdFeed.SetApartmentState(ApartmentState.MTA);
trdFeed.Start();
}
bool PushSamples(Object samples)
{
try
{
m_stream.WriteSamples(samples);
}
catch (OutOfMemoryException)//not enough memory to save samples
{
return false;
}
catch (ArgumentException)//data format unsupported
{
//System.Diagnostics.Debugger.Log(0,"","");
}
return true;
}

public void ThreadRun()
{
try
{
m_stream.Start(Convert.ToInt32(wavDataProvider.SampleRate));
int nSamples = Convert.ToInt32(wavDataProvider.SampleRate / 50);
do
{
while (wavDataProvider.WaitForData)
{
Thread.Sleep(20);
}
System.Runtime.InteropServices.ComTypes.IStream strm = wavDataProvider.GetNextAudioChunk(nSamples);
if (null == strm)
break;
while (false == PushSamples(strm))
Thread.Sleep(20);

System.Runtime.InteropServices.Marshal.FinalReleaseComObject(strm);
strm = null;

//if (m_Reader.HasMoreData)
//{
// Array arr = m_Reader.GetNextAudioChunkArray(nSamples);
// while (false == PushSamples(arr))
// Thread.Sleep(20);
//}
} while (wavDataProvider.HasMoreData);
}
catch (COMException)
{
}
m_stream.Stop();
AllDataWritten.Invoke(this, null);
}

#region IDisposable Members

void IDisposable.Dispose()
{
trdFeed.Join();
}

#endregion
}

}
84 changes: 84 additions & 0 deletions Samples/MultiClientSample/AudioStreamImpl.cs
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace MultiClientSample
{
interface IAudioStreamSink
{
void onAudioStart(int iSampleRate);
void onAudioStop();
void onAudioData(byte[] arr);
}
//Transform Audio stream callbacks to events, transform unmanaged audio data to byte array
class AudioStreamImpl : ZelloPTTLib.IAudioStream
{
List<IAudioStreamSink> lstSinks = new List<IAudioStreamSink>();
public delegate void dlgtFinished(AudioStreamImpl stream);
public event dlgtFinished OnEndOfStream;
int totalCount;
int sampleCount = 0;

[DllImport("ole32.dll")]
static extern int CreateStreamOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease, out System.Runtime.InteropServices.ComTypes.IStream ppstm);

public AudioStreamImpl(int nCounter)
{
totalCount = nCounter;
}
public void AddSink(IAudioStreamSink sink)
{
lstSinks.Add(sink);
}
#region IAudioStream Members

int ZelloPTTLib.IAudioStream.NativeSampleRate
{
get { return 44100; }
}

void ZelloPTTLib.IAudioStream.Start(int iSampleRate)
{
foreach(IAudioStreamSink sink in lstSinks)
sink.onAudioStart(iSampleRate);
}

void ZelloPTTLib.IAudioStream.Stop()
{
foreach (IAudioStreamSink sink in lstSinks)
sink.onAudioStop();
OnEndOfStream.Invoke(this);
}

void ZelloPTTLib.IAudioStream.WriteSamples(object vData)
{
byte[] arr;
try
{
System.Runtime.InteropServices.ComTypes.IStream comStream = vData as System.Runtime.InteropServices.ComTypes.IStream;
if (comStream != null)
{
System.Runtime.InteropServices.ComTypes.STATSTG stg;
comStream.Stat(out stg, 1/*STATFLAG_NONAME*/);
long lSize = stg.cbSize;
sampleCount += Convert.ToInt32(lSize / 2);
arr = new byte[lSize];
IntPtr pInt = (IntPtr)0;
comStream.Read(arr, Convert.ToInt32(lSize), pInt);
foreach (IAudioStreamSink sink in lstSinks)
sink.onAudioData(arr);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(comStream);
comStream = null;
}
}
catch (System.Exception _ex)
{
System.Diagnostics.Debug.WriteLine("Exception in AudioStreamImpl.WriteSamples : " + _ex.Message);
}

}

#endregion
}
}

0 comments on commit 72e3d89

Please sign in to comment.