(For an English version, see below)

Deutsch

Einstieg

Der einfachste Weg GreenJ zu testen, besteht darin, unter Windows die Binaries herunterzuladen. Im Programmordner befindet sich das Verzeichnis “phone”. Dort liefern wir mit index.html ein Beispieltelefon, welches als Einführung dienen soll. Der kommentierte HTML und Javascript Code kann als Basis für das eigene VoIP Telefon verwendet werden.

Um den Einstieg noch etwas zu erleichtern, haben wir hier noch eine kurze Beschreibung der Javascript Library anhand eines einfachen Beispiels zusammengeschrieben.

Hello World Phone

Um eine Benutzeroberfläche für GreenJ zu erstellen, müssen wir zunächst eine HTML Datei anlegen:

[cc lang="html" escaped="true"]
<!DOCTYPE html>
<html>
<head>
<title>Hello World Phone</title>
</head>
<body>
<h1>Hello World Phone</h1>
<input type=”text” id=”number”/>
<button id=”makeCall”>Call</button>
<button id=”hangUp”>HangUp</button>
<div id=”calls”>Waiting for calls…<br/></div>
<div id=”log” style=”position:absolute;left:33%;top:100px;”>Log:<br/></div>
</body>
</html>
[/cc]

Die HTML5 Datei enthält einige Basiselemente:

  • Eingabefeld für die Telefonnummer
  • Anruf- und Auflegen-Button
  • Ausgabefelder für Telefonstatus und Log

Um die GreenJ Javascript Schnittstelle zu verwenden, stellen wir eine Library zur Verfügung. Obwohl es nicht zwingend notwendig ist, unsere Bibliothek zu verwenden, vereinfacht es den Umgang mit den Telefonfunktionen. Folgende Javascript Dateien müssen geladen werden:
jQuery (z.B. von https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js)
lilib.js
Enthält den li Namespace und einige Basisobjekte und Hilfsfunktionen für die Phone Library. Das Objekt li.errorHandler kann für die Fehlerbehandlung verwendet werden.
phone-lib.js
Die Phone Library mit den Objekten li.Phone, li.Phone.Call und li.Phone.Handler
qt-dummy.js
Die Verwendung dieser Datei ist optional. Falls die HTML Datei nicht in GreenJ geöffnet wird, sondern in einem normalen Browser (Firefox, etc.), wird ein Objekt erzeugt, welches die Javascript Schnittstelle von GreenJ simuliert. Zusätzlich wird ein kleines Fenster angezeigt, mit dem ein Gesprächsteilnehmer gesteuert werden kann. Dies kann während der Entwicklung der Oberfläche nützlich sein.

[cc lang="html" escaped="true"]
<script type=”text/javascript” src=”https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js”></script>
<script type=”text/javascript” src=”lilib.js”></script>
<script type=”text/javascript” src=”phone-lib.js”></script>
<script type=”text/javascript” src=”qt-dummy.js”></script>
[/cc]

Werfen wir nun einen Blick auf den Javascript Code.
Wir schreiben unseren Code in die Callback-Funktion der jQuery(document).ready() Methode:
[cc lang="html" escaped="true"]
<script type=”text/javascript”>
jQuery(document).ready(function() {
// code
});
</script>
[/cc]

Um Fehler abzufangen, kann zu li.errorHandler ein Listener hinzugefügt werden. Dieser wird aufgerufen, sobald ein Fehler aufgetreten ist.
[cc lang="js" escaped="true"]
li.errorHandler.addListener(‘onError’, function(data) {
jQuery(‘#log’).append(‘<div>’+data.errorMessage+’: ‘+data.errorData+’</div>’);
});
[/cc]

Im nächsten Schritt erstellen wir das Phone Objekt und registrieren es bei der GreenJ Javascript Schnittstelle.
[cc lang="js" escaped="true"]
window.phone = new li.Phone({
qthandler: window.qt_handler
});
window.qt_handler.registerJsCallbackHandler(“window.phone”+window.phone.getHandlerName());
[/cc]

GreenJ erstellt ein Objekt namens qt_handler im window Scope als Schnittstelle. Da die Kommunikation in beide Richtungen läuft, teilen wir zunächst li.Phone mit, dass window.qt_handler unsere Javascript Schnittstelle ist (z.B. für li.Phone.makeCall() ). Dann rufen wir window.qt_handler.registerJsCallbackHandler auf und übergeben “window.phone”+window.phone.getHandlerName(), damit GreenJ unser Javascript Library Objekt kennt (u.a. um Ereignisse wie einen eingehenden Anruf weiter zu geben).

Als nächstes fügen wir zwei Listener zum Phone Objekt hinzu (siehe Code-Dokumentation von li.Phone für eine vollständige Liste der Ereignisse):
[cc lang="js" escaped="true"]
window.phone.addListener(‘onIncomingCall’, function(data) {
var c = data.incomingCall;
jQuery(‘#calls’).append(‘['+c.id+'] incoming call from ‘+c.getFullNumber()+’ | ‘+c.getNumber()+’<br/>’);
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
c.accept();
});
window.phone.addListener(‘onLogMessage’, function(obj) {
jQuery(‘#log’).append(‘<div>’+obj.time+’: (‘+obj.status+’) <’+obj.domain+’> ['+obj.code+'] ‘+obj.message+’</div>’);
});
[/cc]
Der erste Listener (‘onIncomingCall’) wird aufgerufen, wenn ein eingehender Anruf erkannt wurde. In der Callback-Funktion hat man Zugriff auf das Gespräch (data.incomingCall). Diesem können wiederum Listener hinzugefügt werden: (1) ‘onAccept’ wird ausgelöst, sobald der Anruf angenommen wird (bei eingehenden Anrufen ist dies der Fall, sobald die Methode accept() aufgerufen wird). (2) ‘onClose’ wird ausgelöst, wenn ein Gesprächsteilnehmer den Anruf beendet.
Nachdem wir die Anruf-Listeners hinzugefügt haben, rufen wir sofort die accept() Methode auf. In einer echten Applikation würde dies normalerweise erst durch einen “Abheben” Button vom Benutzer ausgelöst.
Der zweite Listener (‘onLogMessage’) wird aufgerufen, sobald Log-Nachrichten eintreffen. Diese werden in unser Log-Ausgabefeld geschrieben.

Um das Telefon zu aktivieren, rufen wir die Methode register() auf:
[cc lang="js" escaped="true"]
window.phone.register({
host: ’127.0.0.1′,
name: ‘account’,
secret: ‘password’
});
[/cc]

Wir können hier die Host-Adresse und einen SIP-Account (Name und Secret/Passwort) angeben. Um die Antwort des Hosts abzufangen, kann das ‘onAccountState’ Ereignis abgefangen werden.

Schließlich implementieren wir ausgehende Anrufe und das Beenden bzw. Auflegen von Gesprächen.
[cc lang="js" escaped="true"]
jQuery(‘#makeCall’).click(function() {
var c = window.phone.makeCall({
number: jQuery(‘#number’).val()
});
if (c) {
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
}
});
[/cc]

Sobald der makeCall Button gedrückt wird, rufen wir die Methode window.phone.makeCall() auf. Diese versucht ein ausgehendes Gespräch mit der übergebenen Nummer herzustellen. Bei Erfolg fügen wir dem Call Objekt zwei Listener hinzu: ‘onAccept’ (ausgelöst, sobald das Gespräch angenommen wurde) und ‘onClose’, siehe oben.
[cc lang="js" escaped="true]
jQuery(‘#hangUp’).click(function() {
window.phone.hangUpAll();
});
[/cc]

Der hangUp Button beendet alle laufenden Gespräche mittels window.phone.hangUpAll(). Einzelne Gespräche können durch die hangUp() Methode der Call Objekte beendet werden.

Gesamter Beispielcode

[cc lang="html" escaped="true"]
<!DOCTYPE html>
<html>
<head>
<title>Hello World Phone</title>
<script type=”text/javascript” src=”https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js”></script>
<script type=”text/javascript” src=”lilib.js”></script>
<script type=”text/javascript” src=”phone-lib.js”></script>
<script type=”text/javascript” src=”qt-dummy.js”></script>
<script type=”text/javascript”>
jQuery(document).ready(function() {
li.errorHandler.addListener(‘onError’, function(data) {
jQuery(‘#log’).append(‘<div>’+data.errorMessage+’: ‘+data.errorData+’</div>’);
});
window.phone = new li.Phone({
qthandler: window.qt_handler
});
window.qt_handler.registerJsCallbackHandler(“window.phone”+window.phone.getHandlerName());

window.phone.addListener(‘onIncomingCall’, function(data) {
var c = data.incomingCall;
jQuery(‘#calls’).append(‘['+c.id+'] incoming call from ‘+c.getFullNumber()+’ | ‘+c.getNumber()+’<br/>’);
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
c.accept();
});

window.phone.addListener(‘onLogMessage’, function(obj) {
jQuery(‘#log’).append(‘<div>’+obj.time+’: (‘+obj.status+’) <’+obj.domain+’> ['+obj.code+'] ‘+obj.message+’</div>’);
});

window.phone.register({
host: ’127.0.0.1′,
name: ‘account’,
secret: ‘password’
});

jQuery(‘#makeCall’).click(function() {
var c = window.phone.makeCall({
number: jQuery(‘#number’).val()
});
if (c) {
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
}
});

jQuery(‘#hangUp’).click(function() {
window.phone.hangUpAll();
});
});
</script>
</head>
<body>
<h1>Hello World Phone</h1>
<input type=”text” id=”number”/>
<button id=”makeCall”>Call</button>
<button id=”hangUp”>HangUp</button>
<div id=”calls”>Waiting for calls…<br/></div>
<div id=”log” style=”position:absolute;left:33%;top:100px;”>Log:<br/></div>
</body>
</html>
[/cc]

Hinweis:
Um ein eigenes Javascript Objekt als Event-Listener agieren zu lassen, muss dieses um li.BaseObject erweitert werden. Siehe dazu die Javascript-Code-Dokumentation (li.BaseObject, insbesondere die Methoden addListener() und trigger(), in lilib.js).
Eine Instanz kann mittels jQuery.extend(myObject, li.BaseObject.prototype); erweitert werden.
Um ein Objekt und dessen Prototype zu erweitern, stattdessen li.inherit(myPrototypeObject, li.BaseObject); verwenden.

Wie man in diesem sehr kurzen, gerade einmal etwa 70 Zeilen umfassenden, Beispiel sehen kann, lässt sich mittels GreenJ sehr einfach und schnell ein eigenes VoIP Telefon erstellen.

Nächste Schritte:

  • Für ein umfangreicheres Beispiel bitte einen Blick in phone/index.html werfen.
  • GreenJ Dokumentation (doxygen)
  • Javascript Phone Library Dokumentation (jsdoc)

 


English

Get Started

The easiest way to test GreenJ is by downloading the binaries (Windows). In the program folder you will find a subfolder called “phone”. We have prepared a user interface in phone/index.html to show you a simple example of what can be done. Feel free to browser through the commented HTML and Javascript code and make your own phone based on it.

The following is a brief description of our Javascript phone library to control GreenJ and the underlying PJSIP library.

Hello World Phone

To create an user interface for GreenJ you need to start with an HTML file:

[cc lang="html" escaped="true"]
<!DOCTYPE html>
<html>
<head>
<title>Hello World Phone</title>
</head>
<body>
<h1>Hello World Phone</h1>
<input type=”text” id=”number”/>
<button id=”makeCall”>Call</button>
<button id=”hangUp”>HangUp</button>
<div id=”calls”>Waiting for calls…<br/></div>
<div id=”log” style=”position:absolute;left:33%;top:100px;”>Log:<br/></div>
</body>
</html>
[/cc]

Now you have a HTML5 file with some basic elements:

  • Input field for the phone number
  • Call and hang up buttons
  • Call status and log output fields

To use the GreenJ Javascript interface, we provide a library with li.Phone as the main object. Although it’s not necessary to use our library, it makes the communication with GreenJ easier. You have to load the following Javascript files, if you want to use our phone library:
jQuery (e.g. from https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js)
lilib.js
Provides the li namespace and some basic functionality used by phone library objects. li.errorHandler can be used for error handling.
phone-lib.js
The phone library with objects li.Phone, li.Phone.Call and li.Phone.Handler
qt-dummy.js
This file is optional. If the phone HTML file is not opened from within GreenJ, it provides an object that simulates the Javascript interface and a small control window. This can be useful during development, when using a regular browser instead of GreenJ.
[cc lang="html" escaped="true"]
<script type=”text/javascript” src=”https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js”></script>
<script type=”text/javascript” src=”lilib.js”></script>
<script type=”text/javascript” src=”phone-lib.js”></script>
<script type=”text/javascript” src=”qt-dummy.js”></script>
[/cc]

Now let’s take a look at the Javascript code to handle GreenJ.
We put our code into the jQuery(document).ready() method:
[cc lang="html" escaped="true"]
<script type=”text/javascript”>
jQuery(document).ready(function() {
// code
});
</script>
[/cc]

If you want to catch errors, you can add a listener to li.errorHandler, which is used by li.Phone.
[cc lang="js" escaped="true"]
li.errorHandler.addListener(‘onError’, function(data) {
jQuery(‘#log’).append(‘<div>’+data.errorMessage+’: ‘+data.errorData+’</div>’);
});
[/cc]

The next step is to create your phone object and register it with GreenJ Javascript interface.
[cc lang="js" escaped="true"]
window.phone = new li.Phone({
qthandler: window.qt_handler
});
window.qt_handler.registerJsCallbackHandler(“window.phone”+window.phone.getHandlerName());
[/cc]

GreenJ creates an object called qt_handler in the window scope to communicate with our library. The communication has to work in both ways, so we first tell li.Phone that window.qt_handler is GreenJ’s Javascript interface (e.g. used by li.Phone.makeCall() ). Then we call window.qt_handler.registerJsCallbackHandler with “window.phone”+window.phone.getHandlerName() to tell GreenJ the location of the handler/listener of our phone library (e.g. used when an incoming call has been detected).

Now we can add listeners to our phone object (for a complete list of events, see code documentation of li.Phone):
[cc lang="js" escaped="true"]
window.phone.addListener(‘onIncomingCall’, function(data) {
var c = data.incomingCall;
jQuery(‘#calls’).append(‘['+c.id+'] incoming call from ‘+c.getFullNumber()+’ | ‘+c.getNumber()+’<br/>’);
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
c.accept();
});
window.phone.addListener(‘onLogMessage’, function(obj) {
jQuery(‘#log’).append(‘<div>’+obj.time+’: (‘+obj.status+’) <’+obj.domain+’> ['+obj.code+'] ‘+obj.message+’</div>’);
});
[/cc]

The first listener (‘onIncomingCall’) is triggered when an incoming call has been detected. Inside the callback function you can access the call (data.incomingCall) and add listeners to it (see li.Phone.Call for call events). We added two listeners:
(1) When the call has been accepted (for incoming calls, that will be triggered, once you call the accept() method)
(2) When the call has been closed: Either the user or the caller has hung up.
After we added the call listeners we immediately call accept(). In a real application, we would wait until the user clicks an accept button.
The second phone listener (‘onLogMessage’) catches all log messages and adds them to our log output field.

It’s time to actually activate the phone by calling register()
[cc lang="js" escaped="true"]
window.phone.register({
host: ’127.0.0.1′,
name: ‘account’,
secret: ‘password’
});
[/cc]

Here you can set the host address and a SIP account (name and secret/password). You can add an ‘onAccountState’ listener to the phone, if you want to catch the host’s response (e.g. li.Phone.SIP_SC_OK).

Finally, we implement making an outgoing call and hanging up calls.
[cc lang="js" escaped="true"]
jQuery(‘#makeCall’).click(function() {
var c = window.phone.makeCall({
number: jQuery(‘#number’).val()
});
if (c) {
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
}
});
[/cc]

We use the ‘click’ event on our makeCall button: By calling window.phone.makeCall() with a settings object, we initiate a call to the given number (from our number input field). If the call object could be created successfully, two listeners are created: ‘onAccept’ and ‘onClose’, described above (onAccept is triggered, when the outgoing call has been accepted).
[cc lang="js" escaped="true]
jQuery(‘#hangUp’).click(function() {
window.phone.hangUpAll();
});
[/cc]
With the hangUp button, all calls are closed and removed by calling window.phone.hangUpAll(). You could also hang up a certain call by calling hangUp() on the call object.

Entire example code

[cc lang="html" escaped="true"]
<!DOCTYPE html>
<html>
<head>
<title>Hello World Phone</title>
<script type=”text/javascript” src=”https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js”></script>
<script type=”text/javascript” src=”lilib.js”></script>
<script type=”text/javascript” src=”phone-lib.js”></script>
<script type=”text/javascript” src=”qt-dummy.js”></script>
<script type=”text/javascript”>
jQuery(document).ready(function() {
li.errorHandler.addListener(‘onError’, function(data) {
jQuery(‘#log’).append(‘<div>’+data.errorMessage+’: ‘+data.errorData+’</div>’);
});
window.phone = new li.Phone({
qthandler: window.qt_handler
});
window.qt_handler.registerJsCallbackHandler(“window.phone”+window.phone.getHandlerName());

window.phone.addListener(‘onIncomingCall’, function(data) {
var c = data.incomingCall;
jQuery(‘#calls’).append(‘['+c.id+'] incoming call from ‘+c.getFullNumber()+’ | ‘+c.getNumber()+’<br/>’);
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
c.accept();
});

window.phone.addListener(‘onLogMessage’, function(obj) {
jQuery(‘#log’).append(‘<div>’+obj.time+’: (‘+obj.status+’) <’+obj.domain+’> ['+obj.code+'] ‘+obj.message+’</div>’);
});

window.phone.register({
host: ’127.0.0.1′,
name: ‘account’,
secret: ‘password’
});

jQuery(‘#makeCall’).click(function() {
var c = window.phone.makeCall({
number: jQuery(‘#number’).val()
});
if (c) {
c.addListener(‘onAccept’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] accepted<br />’);
});
c.addListener(‘onClose’, function() {
jQuery(‘#calls’).append(‘['+c.id+'] closed<br />’);
});
}
});

jQuery(‘#hangUp’).click(function() {
window.phone.hangUpAll();
});
});
</script>

</head>
<body>
<h1>Hello World Phone</h1>
<input type=”text” id=”number”/>
<button id=”makeCall”>Call</button>
<button id=”hangUp”>HangUp</button>
<div id=”calls”>Waiting for calls…<br/></div>
<div id=”log” style=”position:absolute;left:33%;top:100px;”>Log:<br/></div>
</body>
</html>
[/cc]

Note:
If you want to extend your Javascript objects with the event listener functionality we use in the phone library, take a look at li.BaseObject (in particular the methods addListener() and trigger() ) in lilib.js.
An instance of an object can be extend by jQuery.extend(myObject, li.BaseObject.prototype);
If you want to extend your prototype object use li.inherit(myPrototypeObject, li.BaseObject); instead.

As you can see in this very short example of about 70 lines, it’s pretty easy to create your own VoIP phone with GreenJ.

Next steps:

  • Take a look at phone/index.html for a more complex example.
  • GreenJ code documentation (doxygen)
  • Browse through the phone library documentation (jsdoc)