remove tox, www
This commit is contained in:
parent
37fb8b74f2
commit
80459bbecd
@ -1,31 +0,0 @@
|
||||
libexec_PROGRAMS=tox
|
||||
tox_SOURCES=main.c tox.c tox-session.c tox.h tox-session.h \
|
||||
$(BUILT_SOURCES)
|
||||
|
||||
EXTRA_DIST=tox-object.xml tox-session.xml tox-marshal.list
|
||||
|
||||
BUILT_SOURCES=tox-object-glue.h tox-session-glue.h tox-marshal.c tox-marshal.h
|
||||
|
||||
tox-object-glue.h : tox-object.xml
|
||||
$(DBUS_BINDING_TOOL) --mode=glib-server --output=$@ --prefix=tox $(srcdir)/tox-object.xml
|
||||
|
||||
tox-session-glue.h : tox-session.xml
|
||||
$(DBUS_BINDING_TOOL) --mode=glib-server --output=$@ --prefix=tox_session $(srcdir)/tox-session.xml
|
||||
|
||||
tox-marshal.c : tox-marshal.list
|
||||
$(GLIB_GENMARSHAL) --prefix=tox_marshal $(srcdir)/tox-marshal.list --header --body > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
tox-marshal.h : tox-marshal.list
|
||||
$(GLIB_GENMARSHAL) --prefix=tox_marshal $(srcdir)/tox-marshal.list --header > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
|
||||
dbusservicedir=$(datadir)/dbus-1/services
|
||||
dbusservice_DATA=tox.service
|
||||
EXTRA_DIST+=tox.service.in
|
||||
CLEANFILES=tox.service
|
||||
tox.service: tox.service.in config.status
|
||||
sed -e "s,@""libexecdir@,$(libexecdir)," $(srcdir)/tox.service.in > $@
|
||||
|
||||
dist_lisp_LISP=jabber-tox.el
|
||||
98
tox/README
98
tox/README
@ -1,98 +0,0 @@
|
||||
Tox (Talk Over XMPP, or something) is a utility for adding Jingle
|
||||
functionality to a Jabber client, primarily voice communication. It
|
||||
interfaces to the Jabber client using DBus.
|
||||
|
||||
To actually get it to compile, you need the Farsight library. If you
|
||||
use Debian, the packages "libfarsight0.1-dev" and
|
||||
"gstreamer0.10-plugins-farsight" and their dependencies should be
|
||||
enough. If you need to compile them yourself, look for Farsight at
|
||||
http://farsight.freedesktop.org/ and Libjingle at
|
||||
http://tapioca-voip.sourceforge.net/. Do _not_ use Google's
|
||||
libjingle.
|
||||
|
||||
The DBus interface is described below. From this you should be able
|
||||
to piece together a Jingle client. Good luck!
|
||||
|
||||
Tox registers the well-known name net.sourceforge.emacs-jabber.Tox
|
||||
(NB: hyphen, not underscore) on the session bus.
|
||||
/net/sourceforge/emacs_jabber/Tox (NB: underscore, not hyphen) is the
|
||||
path to the main object.
|
||||
|
||||
This object has one method in the interface
|
||||
net.sourceforge.emacs_jabber.Tox (NB: underscore, not hyphen):
|
||||
|
||||
object_path CreateSession(byte direction)
|
||||
|
||||
Creates an audio session. direction is 1 for "send only", 2 for
|
||||
"receive only", and 3 for "send and receive". The path to the new
|
||||
session is returned.
|
||||
|
||||
The session object in turn has methods in the interface
|
||||
net.sourceforge.emacs_jabber.ToxSession (NB: underscore, not hyphen):
|
||||
|
||||
void Destroy()
|
||||
|
||||
Destroys the session.
|
||||
|
||||
void SetDefaultAudioSink()
|
||||
|
||||
Create an "autoaudiosink" GStreamer element and connect it to the
|
||||
session. This usually means that you will hear things in your
|
||||
speakers.
|
||||
|
||||
void SetOggVorbisAudioSource(string filename)
|
||||
|
||||
Set the named Ogg Vorbis file as audio source, i.e. what to send
|
||||
over the session.
|
||||
|
||||
void AddRemoteCandidate(array components)
|
||||
|
||||
Add a transport candidate of the remote party, consisting of the
|
||||
given components. "components" is an array of structs with
|
||||
signature "(susqsssyyss)" and meaning:
|
||||
|
||||
- Candidate ID
|
||||
- Component (starting from 1)
|
||||
- IP number (as a string)
|
||||
- Port number
|
||||
- Protocol ("tcp" or "udp")
|
||||
- Protocol subtype (only "RTP" supported)
|
||||
- Protocol profile (only "AVP" supported)
|
||||
- Preference, between 0 and 100
|
||||
- Type. 0 means local, 1 means derived (e.g. through
|
||||
STUN), 2 means relay
|
||||
- Username (may be empty)
|
||||
- Password (may be empty)
|
||||
|
||||
signal NewNativeCandidate(array components)
|
||||
|
||||
Signalled when a new local candidate has been determined. The
|
||||
argument is the same as to AddRemoteCandidate.
|
||||
|
||||
signal NativeCandidatesPrepared(array components)
|
||||
|
||||
Signalled when the local candidates have been determined, and are
|
||||
ready to send to the other party. The argument is the same as to
|
||||
AddRemoteCandidate.
|
||||
|
||||
void SetRemoteCodecs(array codecs)
|
||||
|
||||
Set the codecs that the remote party claims to support. codecs is
|
||||
an array of structs with signature "(isyuua{ss})" and meaning:
|
||||
|
||||
- numeric identifier
|
||||
- codec name
|
||||
- media type: 0 is audio, 1 is video
|
||||
- clock rate
|
||||
- number of channels
|
||||
- optional parameters
|
||||
|
||||
array GetLocalCodecs()
|
||||
|
||||
Get the codecs supported by this implementation. The return value
|
||||
is of the same type as the argument to SetRemoteCodecs.
|
||||
|
||||
array GetCodecIntersection()
|
||||
|
||||
Get the intersection of supported codecs of remote and local
|
||||
parties. The return value is like the argument to SetRemoteCodecs.
|
||||
@ -1,20 +0,0 @@
|
||||
AC_INIT([Talk over XMPP], [0.0.0], [emacs-jabber-general@lists.sourceforge.net], [tox])
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2 -Wall -Werror])
|
||||
|
||||
AC_PROG_CC
|
||||
|
||||
AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool,
|
||||
[$am_missing_run dbus-binding-tool])
|
||||
AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal,
|
||||
[$am_missing_run glib-genmarshal])
|
||||
|
||||
PKG_CHECK_MODULES(FARSIGHT, [farsight-0.1], [], AC_MSG_ERROR([farsight not found; see README]))
|
||||
PKG_CHECK_MODULES(DBUS, [dbus-glib-1], [], AC_MSG_ERROR([dbus-glib not found; see README]))
|
||||
|
||||
AC_SUBST(AM_CFLAGS, "$FARSIGHT_CFLAGS $DBUS_CFLAGS")
|
||||
AC_SUBST(LDADD, "$FARSIGHT_LIBS $DBUS_LIBS")
|
||||
|
||||
AM_PATH_LISPDIR
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
@ -1,497 +0,0 @@
|
||||
;; jabber-tox.el - Jingle support using TOX
|
||||
|
||||
;; Copyright (C) 2008 - Magnus Henoch - mange@freemail.hu
|
||||
|
||||
;; This file is (soon) a part of jabber.el.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program; if not, write to the Free Software
|
||||
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
(require 'dbus)
|
||||
(require 'fsm)
|
||||
(require 'cl)
|
||||
|
||||
(require 'jabber-xml)
|
||||
|
||||
(defconst jingle-ns "urn:xmpp:jingle:0"
|
||||
"Jingle namespace (XEP-0166)")
|
||||
|
||||
(defconst jingle-error-ns "urn:xmpp:jingle:errors:0"
|
||||
"Jingle error namespace (XEP-0166)")
|
||||
|
||||
(defconst jingle-rtp-ns "urn:xmpp:jingle:apps:rtp:0"
|
||||
"Jingle RTP Sessions namespace (XEP-0167)")
|
||||
|
||||
(defconst jingle-ice-udp-ns "urn:xmpp:jingle:transports:ice-udp:0"
|
||||
"Jingle ICE namespace (XEP-0176)")
|
||||
|
||||
(defvar jingle-acct-sid-map (make-hash-table :test 'equal)
|
||||
"Mapping from pairs of JIDs and Jingle SIDs to FSMs.
|
||||
The JID is the full JID of the account using the session.")
|
||||
|
||||
(defconst tox-name "net.sourceforge.emacs-jabber.Tox"
|
||||
"Well-known D-BUS name of the tox service.")
|
||||
|
||||
(defconst tox-path "/net/sourceforge/emacs_jabber/Tox"
|
||||
"Well-known path of the main Tox object.")
|
||||
|
||||
(defconst tox-interface "net.sourceforge.emacs_jabber.Tox"
|
||||
"Interface of main Tox object.")
|
||||
|
||||
(defconst tox-session-interface "net.sourceforge.emacs_jabber.ToxSession"
|
||||
"Interface of ToxSession object.")
|
||||
|
||||
(defvar tox-my-ogg-answering-machine
|
||||
(replace-regexp-in-string
|
||||
"\n" ""
|
||||
(shell-command-to-string "locate '*.ogg' | head -1"))
|
||||
"The Ogg file to play to anyone who calls to us.
|
||||
This should go away once we have hooked up everything properly,
|
||||
with microphone and so on. (Or maybe not...)")
|
||||
|
||||
(define-fsm jingle
|
||||
:start ((jc sid role jid) "Start a Jingle FSM.
|
||||
\(Specifically, for Jingle Audio, as that's all we support for now.)
|
||||
JC is the account we're using.
|
||||
SID is a string, the session ID.
|
||||
ROLE is either :initiator or :target.
|
||||
JID is the full JID of the partner."
|
||||
(let ((state-data (list :jc jc :jid jid :sid sid :role role)))
|
||||
(setq state-data (jingle-create-tox-session fsm state-data))
|
||||
(list
|
||||
(ecase (plist-get state-data :role)
|
||||
(:initiator
|
||||
:initiate)
|
||||
(:target
|
||||
:wait-for-initiate))
|
||||
state-data))))
|
||||
|
||||
(defun jingle-create-tox-session (fsm state-data)
|
||||
"Helper function to create a Tox session.
|
||||
Accepts, modifies, and returns STATE-DATA."
|
||||
;; XXX: should this always be bidirectional?
|
||||
(let* ((tox-session
|
||||
(dbus-call-method :session tox-name tox-path tox-interface
|
||||
"CreateSession"
|
||||
:byte 3)) ;3=bidirectional stream
|
||||
;; Find the codecs that we support
|
||||
(our-codecs
|
||||
(dbus-call-method :session tox-name tox-session tox-session-interface
|
||||
"GetLocalCodecs")))
|
||||
(setq state-data (plist-put state-data :tox-session tox-session))
|
||||
(setq state-data (plist-put state-data :our-codecs our-codecs))
|
||||
|
||||
(fsm-debug-output "tox-session: %S, our-codecs: %S" tox-session our-codecs)
|
||||
;; Set up the pipeline, so we can search for transport candidates.
|
||||
(fsm-debug-output "About to call SetDefaultAudioSink")
|
||||
(dbus-call-method :session tox-name tox-session tox-session-interface
|
||||
"SetDefaultAudioSink")
|
||||
(fsm-debug-output "About to call SetOggVorbisAudioSource")
|
||||
(dbus-call-method :session tox-name tox-session tox-session-interface
|
||||
"SetOggVorbisAudioSource"
|
||||
tox-my-ogg-answering-machine)
|
||||
;; There, now we just wait for the NativeCandidatesPrepared signal...
|
||||
;; NO! Don't do like those dead people do! That signal will never
|
||||
;; come. I don't know why, though...
|
||||
(fsm-debug-output "About to register signal")
|
||||
(dbus-register-signal :session tox-name tox-session tox-session-interface
|
||||
"NativeCandidatesPrepared"
|
||||
(lexical-let ((fsm fsm))
|
||||
(lambda (components)
|
||||
(fsm-send-sync
|
||||
fsm
|
||||
(cons :native-candidates-prepared components)))))
|
||||
;; This is more like it. At least it will provide us with some
|
||||
;; debugging information.
|
||||
(dbus-register-signal :session tox-name tox-session tox-session-interface
|
||||
"NewNativeCandidate"
|
||||
(lexical-let ((fsm fsm))
|
||||
(lambda (components)
|
||||
(fsm-send-sync
|
||||
fsm
|
||||
(cons :new-native-candidate components)))))
|
||||
;; And we also want to know about state changes.
|
||||
(dbus-register-signal :session tox-name tox-session tox-session-interface
|
||||
"StateChanged"
|
||||
(lexical-let ((fsm fsm))
|
||||
(lambda (state direction)
|
||||
(fsm-send-sync
|
||||
fsm
|
||||
(list :state-changed state direction)))))
|
||||
;; And about active candidate pairs.
|
||||
(dbus-register-signal :session tox-name tox-session tox-session-interface
|
||||
"NewActiveCandidatePair"
|
||||
(lexical-let ((fsm fsm))
|
||||
(lambda (native-candidate remote-candidate)
|
||||
(fsm-send-sync
|
||||
fsm
|
||||
(list :new-active-candidate-pair
|
||||
native-candidate remote-candidate)))))
|
||||
(fsm-debug-output "Waiting")
|
||||
state-data))
|
||||
|
||||
(define-enter-state jingle nil
|
||||
(fsm state-data)
|
||||
;; XXX: send termination stanza, if appropriate
|
||||
;; clean up
|
||||
(let ((tox-session (plist-get state-data :tox-session)))
|
||||
(when tox-session
|
||||
(ignore-errors
|
||||
(dbus-call-method :session tox-name tox-session tox-session-interface
|
||||
"Destroy"))))
|
||||
(remhash (cons (jabber-connection-jid (plist-get state-data :jc))
|
||||
(plist-get state-data :sid))
|
||||
jingle-acct-sid-map)
|
||||
(list nil nil))
|
||||
|
||||
(define-enter-state jingle :initiate
|
||||
(fsm state-data)
|
||||
(let ((jc (plist-get state-data :jc))
|
||||
(jid (plist-get state-data :jid))
|
||||
(sid (plist-get state-data :sid))
|
||||
(payload-types (mapcar
|
||||
(lambda (codec)
|
||||
`(payload-type
|
||||
((id . ,(number-to-string (nth 0 codec)))
|
||||
(name . ,(nth 1 codec))
|
||||
;; (nth 2 codec) is media type;
|
||||
;; should we filter out
|
||||
;; non-audio codecs? then
|
||||
;; again, the value seems to be
|
||||
;; bogus...
|
||||
(clockrate . ,(number-to-string (nth 3 codec)))
|
||||
,@(let ((channels (nth 4 codec)))
|
||||
(unless (= channels 0)
|
||||
`((channels . ,(number-to-string channels))))))
|
||||
,@(mapcar
|
||||
(lambda (param)
|
||||
`(parameter
|
||||
((name . ,(nth 0 param))
|
||||
(value . ,(nth 1 param)))))
|
||||
(nth 5 codec))))
|
||||
(plist-get state-data :our-codecs))))
|
||||
(jabber-send-iq jc jid "set"
|
||||
`(jingle ((xmlns . ,jingle-ns)
|
||||
(action . "session-initiate")
|
||||
(initiator . ,(jabber-connection-jid jc))
|
||||
(sid . ,sid))
|
||||
(content
|
||||
((creator . "initiator")
|
||||
(name . "foo")
|
||||
(senders . "initiator"))
|
||||
(description
|
||||
((xmlns . ,jingle-rtp-ns)
|
||||
(media . "audio"))
|
||||
,@payload-types)
|
||||
(transport ((xmlns . ,jingle-ice-udp-ns)))))
|
||||
(lambda (jc iq fsm)
|
||||
(fsm-send-sync fsm (cons :iq-result iq)))
|
||||
fsm
|
||||
(lambda (jc iq fsm)
|
||||
(fsm-send-sync fsm (cons :iq-error iq)))
|
||||
fsm)
|
||||
(list state-data nil)))
|
||||
|
||||
(define-state jingle :initiate
|
||||
(fsm state-data event callback)
|
||||
(case (car-safe event)
|
||||
(:iq-result
|
||||
;; Receiver provisionally accepted the session request. Move on
|
||||
;; to PENDING.
|
||||
(list :pending state-data))
|
||||
(:iq-error
|
||||
(message "Couldn't initiate Jingle audio session: %s"
|
||||
(jabber-parse-error (jabber-iq-error (cdr event))))
|
||||
(list nil state-data))
|
||||
(:new-native-candidate
|
||||
(let ((components (cdr event)))
|
||||
(jingle-send-native-candidate state-data components)
|
||||
(list :initiate state-data)))))
|
||||
|
||||
(define-state jingle :wait-for-initiate
|
||||
(fsm state-data event callback)
|
||||
(case (car-safe event)
|
||||
(:iq-set
|
||||
(let* ((jc (plist-get state-data :jc))
|
||||
(iq (cdr event))
|
||||
(from (jabber-xml-get-attribute iq 'from))
|
||||
(id (jabber-xml-get-attribute iq 'id))
|
||||
(jingle (jabber-iq-query iq))
|
||||
(action (jabber-xml-get-attribute jingle 'action))
|
||||
;; XXX: could be more than one...
|
||||
(content (car (jabber-xml-get-children jingle 'content)))
|
||||
;; XXX: is it really audio?
|
||||
(audio-content (find jingle-rtp-ns (jabber-xml-node-children content)
|
||||
:test 'string=
|
||||
:key 'jabber-xml-get-xmlns))
|
||||
(payload-types (jabber-xml-get-children audio-content 'payload-type)))
|
||||
;; There are very few reasons for which we should not send an
|
||||
;; acknowledgement here; see section 6.3.2 of XEP-0166.
|
||||
;; Notably, we might want to check that there is a presence
|
||||
;; subscription.
|
||||
(jabber-send-iq jc from "result" ()
|
||||
nil nil nil nil id)
|
||||
|
||||
(unless (string= action "session-initiate")
|
||||
(fsm-debug-output "Action is %S. Why is it not \"session-initiate\"?" action))
|
||||
|
||||
(cond
|
||||
;; Make sure audio is in the list of contents. We can
|
||||
;; negotiate away other content types later.
|
||||
((null audio-content)
|
||||
(jingle-send-iq state-data "session-terminate"
|
||||
'((reason () (unsupported-applications))))
|
||||
(list nil state-data))
|
||||
|
||||
;; Make sure ICE is in the list of transports.
|
||||
((not (member* jingle-ice-udp-ns
|
||||
(jabber-xml-get-children content 'transport)
|
||||
:test 'string=
|
||||
:key 'jabber-xml-get-xmlns))
|
||||
(jingle-send-iq state-data "session-terminate"
|
||||
'((reason () (unsupported-transports))))
|
||||
(list nil state-data))
|
||||
|
||||
(t
|
||||
(let ((tox-session (plist-get state-data :tox-session))
|
||||
(their-codecs (mapcar
|
||||
(lambda (pt)
|
||||
(jabber-xml-let-attributes
|
||||
(id name clockrate channels) pt
|
||||
(list :struct
|
||||
:int32 (string-to-number id)
|
||||
:string name
|
||||
:byte 0
|
||||
:uint32 (string-to-number clockrate)
|
||||
:uint32 (if channels
|
||||
(string-to-number channels)
|
||||
1)
|
||||
(cons
|
||||
:array
|
||||
(or
|
||||
(mapcar
|
||||
(lambda (param)
|
||||
(jabber-xml-let-attributes
|
||||
(name value) param
|
||||
(list :dict-entry :string name :string value)))
|
||||
(jabber-xml-get-children pt 'parameter))
|
||||
(list :signature "{ss}"))))))
|
||||
payload-types)))
|
||||
(fsm-debug-output "Their codecs are %S" their-codecs)
|
||||
;; Tell tox what codecs the remote side supports
|
||||
(dbus-call-method
|
||||
:session tox-name tox-session tox-session-interface
|
||||
"SetRemoteCodecs"
|
||||
;;'((array (struct int32 string byte uint32 uint32 (array (dict-entry string string)))))
|
||||
their-codecs)
|
||||
|
||||
;; Check if we have any codecs in common
|
||||
(let ((codec-intersection
|
||||
(dbus-call-method
|
||||
:session tox-name tox-session tox-session-interface
|
||||
"GetCodecIntersection")))
|
||||
(fsm-debug-output "The codec intersection is %S" codec-intersection)
|
||||
(setq state-data
|
||||
(plist-put
|
||||
state-data
|
||||
:codec-intersection codec-intersection))
|
||||
|
||||
(if codec-intersection
|
||||
;; So, now we know that we stand a basic chance of fulfilling
|
||||
;; the request. Let's move on to PENDING.
|
||||
(list :pending state-data)
|
||||
|
||||
;; Or, it might turn out that we don't have any codecs
|
||||
;; in common with our partner.
|
||||
(jingle-send-iq state-data "session-terminate"
|
||||
'((reason () (media-error))))
|
||||
(list nil state-data))))))))))
|
||||
|
||||
;; Thu Jan 1 16:49:23 2009: Warning: event (:new-native-candidate ("L1" 1 "127.0.0.1" 33582 "udp" "RTP" "AVP" 100 0 "Pmc4YPYhJyGPWKIv" "GKQ5/XFIE0pp8+6y")) ignored in state jingle/:pending
|
||||
;; Thu Jan 1 16:49:23 2009: Warning: event (:iq-set iq ((from . "legoscia@jabber.cd.chalmers.se/2868723341230824321901526") (to . "magnus.henoch@jabber.se/2635526438123082419775630") (type . "set") (id . "emacs-iq-18780.58883.21969")) (jingle ((xmlns . "urn:xmpp:jingle:0") (action . "transport-info") (initiator . "legoscia@jabber.cd.chalmers.se/2868723341230824321901526") (sid . "emacs-sid-18780.58881.712027")) (content ((creator . "initiator") (name . "foo")) (transport ((xmlns . "urn:xmpp:jingle:transports:ice-udp:0")) (candidate ((component . "1") (ip . "127.0.0.1") (port . "44319") (protocol . "udp") (priority . "100"))))))) ignored in state jingle/:pending
|
||||
;; Thu Jan 1 16:50:07 2009: Warning: event (:state-changed 0 0) ignored in state jingle/:pending
|
||||
|
||||
(define-state jingle :pending
|
||||
(fsm state-data event callback)
|
||||
|
||||
(case (car-safe event)
|
||||
(:state-changed
|
||||
(let ((state (car (assq (second event)
|
||||
'((0 . :disconnected)
|
||||
(1 . :connecting)
|
||||
(2 . :connected)))))
|
||||
(direction (car (assq (third event)
|
||||
'((0 . nil)
|
||||
(1 . :send-only)
|
||||
(2 . :receive-only)
|
||||
(3 . :send-and-receive))))))
|
||||
(fsm-debug-output "Got :state-changed; new state %s, new direction %s"
|
||||
state direction)
|
||||
|
||||
(case state
|
||||
(0
|
||||
;; Do we have enough information to send the termination stanza?
|
||||
(list nil state-data)))
|
||||
;; Still, not sure what we should do here...
|
||||
))
|
||||
|
||||
(:new-native-candidate
|
||||
(let ((components (cdr event)))
|
||||
(jingle-send-native-candidate state-data components)
|
||||
(list :pending state-data)))
|
||||
|
||||
(:iq-set
|
||||
(fsm-debug-output "iq-set event is %S" event)
|
||||
(let* ((jc (plist-get state-data :jc))
|
||||
(iq (cdr event)))
|
||||
(jabber-xml-let-attributes (action) (jabber-iq-query iq)
|
||||
(fsm-debug-output "action is %S" action)
|
||||
(cond
|
||||
((string= action "transport-info")
|
||||
(fsm-debug-output "transport-info is %S" iq)
|
||||
(let ((tox-session (plist-get state-data :tox-session))
|
||||
(candidates
|
||||
(jabber-xml-get-children
|
||||
(jabber-xml-path
|
||||
iq
|
||||
`(jingle content (,jingle-ice-udp-ns . "transport")))
|
||||
'candidate)))
|
||||
;; XXX: send iq error for no candidates
|
||||
(when candidates
|
||||
(fsm-debug-output "Adding remote candidate...")
|
||||
(dbus-call-method :session tox-name tox-session tox-session-interface
|
||||
"AddRemoteCandidate"
|
||||
(mapcar
|
||||
'jingle-parse-candidate
|
||||
candidates))
|
||||
;; XXX: iq result
|
||||
(list :pending state-data)
|
||||
)))
|
||||
(t
|
||||
;; XXX: send "bad-request" or something
|
||||
)))))))
|
||||
|
||||
(defun jingle-send-iq (state-data action payload)
|
||||
"Send a Jingle IQ stanza from within a Jingle FSM.
|
||||
STATE-DATA is the state data plist of the FSM.
|
||||
ACTION is the value of the action attribute of the <jingle/>
|
||||
element.
|
||||
PAYLOAD is a list of XML elements to include as children
|
||||
of the <jingle/> element.
|
||||
The recipient and the SID are determined from STATE-DATA."
|
||||
(let ((jc (plist-get state-data :jc))
|
||||
(jid (plist-get state-data :jid))
|
||||
(role (plist-get state-data :role))
|
||||
(sid (plist-get state-data :sid)))
|
||||
(jabber-send-iq
|
||||
jc jid "set"
|
||||
`(jingle ((xmlns . ,jingle-ns)
|
||||
(action . ,action)
|
||||
(initiator
|
||||
. ,(ecase role
|
||||
(:initiator
|
||||
(jabber-connection-jid jc))
|
||||
(:target
|
||||
jid)))
|
||||
(sid . ,sid))
|
||||
,@payload)
|
||||
;; XXX: we probably want error checking, to see if our partner
|
||||
;; went offline.
|
||||
nil nil nil nil)))
|
||||
|
||||
(defun jingle-send-native-candidate (state-data candidate)
|
||||
"Send a native candidate for ICE-UDP.
|
||||
The CANDIDATE is a list of components, as provided by the
|
||||
NewNativeCandidate signal of Tox."
|
||||
;; XXX: check against XEP-0176
|
||||
(jingle-send-iq state-data "transport-info"
|
||||
`((content
|
||||
((creator . "initiator")
|
||||
(name . "foo"))
|
||||
(transport
|
||||
((xmlns . ,jingle-ice-udp-ns))
|
||||
,@(mapcar
|
||||
(lambda (c)
|
||||
`(candidate
|
||||
((id . ,(nth 0 c))
|
||||
(component . ,(number-to-string (nth 1 c)))
|
||||
;; foundation?
|
||||
;; generation?
|
||||
(ip . ,(nth 2 c))
|
||||
;; network?
|
||||
(port . ,(number-to-string (nth 3 c)))
|
||||
(protocol . ,(nth 4 c))
|
||||
;; (nth 5 c) is always "RTP"
|
||||
;; (nth 6 c) is always "AVP"
|
||||
(priority . ,(nth 7 c))
|
||||
;; (nth 8 c) is type. how to translate it?
|
||||
(username . ,(nth 9 c))
|
||||
(password . ,(nth 10 c))
|
||||
)))
|
||||
candidate))))))
|
||||
|
||||
(defun jingle-parse-candidate (candidate)
|
||||
"Parse an XEP-0176 <candidate/> element into DBus format.
|
||||
Specifically, the signature is \"(susqsssyyss)\"."
|
||||
;; XXX: check against XEP-0176 again
|
||||
(jabber-xml-let-attributes
|
||||
(id component foundation generation
|
||||
ip port protocol priority type
|
||||
username password)
|
||||
candidate
|
||||
(list :string id
|
||||
:uint32 (string-to-number component)
|
||||
:string ip
|
||||
:uint16 (string-to-number port)
|
||||
"udp" "RTP" "AVP"
|
||||
:byte (string-to-number priority) ;XXX: priority is preference?
|
||||
:byte 0 ;XXX: fix type
|
||||
:string (or username "")
|
||||
:string (or password ""))))
|
||||
|
||||
(add-to-list 'jabber-iq-set-xmlns-alist
|
||||
(cons jingle-ns 'jabber-jingle-incoming-iq))
|
||||
(defun jabber-jingle-incoming-iq (jc iq)
|
||||
(jabber-xml-let-attributes
|
||||
(sid action) (jabber-iq-query iq)
|
||||
(unless (and sid action)
|
||||
(jabber-signal-error "modify" 'bad-request))
|
||||
(let ((fsm (gethash (cons (jabber-connection-jid jc) sid) jingle-acct-sid-map)))
|
||||
(cond
|
||||
(fsm
|
||||
(fsm-send-sync fsm (cons :iq-set iq)))
|
||||
((string= action "session-initiate")
|
||||
(condition-case e
|
||||
(setq fsm (start-jingle jc sid :target (jabber-xml-get-attribute iq 'from)))
|
||||
(error
|
||||
(jabber-signal-error "wait" 'internal-server-error
|
||||
(concat "Couldn't accept Jingle session: "
|
||||
(error-message-string e)))))
|
||||
(puthash (cons (jabber-connection-jid jc) sid) fsm jingle-acct-sid-map)
|
||||
(fsm-send-sync fsm (cons :iq-set iq)))
|
||||
(t
|
||||
(jabber-signal-error "modify" 'bad-request
|
||||
(format "Session \"%s\" unknown" sid)
|
||||
`((unknown-session ((xmlns . ,jingle-error-ns))))))))))
|
||||
|
||||
(defun jabber-jingle-start-audio-session (jc jid)
|
||||
(interactive
|
||||
(list (jabber-read-account)
|
||||
(jabber-read-jid-completing "Voice call to: " nil nil nil 'full)))
|
||||
(let* ((sid (apply 'format "emacs-sid-%d.%d.%d" (current-time)))
|
||||
(fsm (start-jingle jc sid :initiator jid)))
|
||||
(puthash (cons (jabber-connection-jid jc) sid) fsm jingle-acct-sid-map)))
|
||||
|
||||
|
||||
(provide 'jabber-tox)
|
||||
70
tox/main.c
70
tox/main.c
@ -1,70 +0,0 @@
|
||||
#include <farsight/farsight.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <string.h>
|
||||
#include "tox.h"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
GMainLoop *loop;
|
||||
DBusGConnection *connection;
|
||||
DBusGProxy *bus_proxy;
|
||||
GError *error = NULL;
|
||||
ToxObject *obj;
|
||||
guint32 x;
|
||||
|
||||
g_type_init();
|
||||
gst_init(&argc, &argv);
|
||||
|
||||
{
|
||||
GLogLevelFlags fatal_mask;
|
||||
|
||||
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||
/* not aborting on warnings because of:
|
||||
farsight-rtp-WARNING **: Not enough information in rtp caps
|
||||
*/
|
||||
fatal_mask |= /*G_LOG_LEVEL_WARNING | */ G_LOG_LEVEL_CRITICAL;
|
||||
g_log_set_always_fatal (fatal_mask);
|
||||
}
|
||||
|
||||
connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
|
||||
if (connection == NULL) {
|
||||
g_printerr("Failed to open connection to bus: %s\n",
|
||||
error->message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bus_proxy = dbus_g_proxy_new_for_name(connection, "org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus");
|
||||
|
||||
g_debug("About to request D-Bus name...\n");
|
||||
if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error,
|
||||
G_TYPE_STRING, "net.sourceforge.emacs-jabber.Tox",
|
||||
G_TYPE_UINT,
|
||||
/* these settings are good for debugging. we
|
||||
should listen for the NameLost signal, though. */
|
||||
DBUS_NAME_FLAG_ALLOW_REPLACEMENT
|
||||
| DBUS_NAME_FLAG_REPLACE_EXISTING
|
||||
| DBUS_NAME_FLAG_DO_NOT_QUEUE,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_UINT, &x,
|
||||
G_TYPE_INVALID)) {
|
||||
g_printerr("Couldn't acquire name: %s\n", error->message);
|
||||
exit(1);
|
||||
}
|
||||
else if (x != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
||||
g_printerr("Couldn't acquire name: RequestName returned %u\n", x);
|
||||
exit(1);
|
||||
}
|
||||
g_debug("D-Bus name acquired\n");
|
||||
|
||||
obj = g_object_new(TOX_TYPE_OBJECT, "dbus-connection", connection, NULL);
|
||||
dbus_g_connection_register_g_object(connection, "/net/sourceforge/emacs_jabber/Tox", G_OBJECT(obj));
|
||||
|
||||
loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
g_main_loop_run(loop);
|
||||
return 0;
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
VOID:BOXED
|
||||
VOID:UCHAR,UCHAR
|
||||
VOID:STRING,STRING
|
||||
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node name='/net/sourceforce/emacs_jabber/Tox'>
|
||||
|
||||
<!-- Note the underscore in the interface name!
|
||||
Bus names can have hyphens, but interface names can't.
|
||||
I guess that's a good way to distinguish them. -->
|
||||
|
||||
<interface name='net.sourceforge.emacs_jabber.Tox'>
|
||||
<method name='CreateSession'>
|
||||
<!-- 1: send only.
|
||||
2: receive only.
|
||||
3: send and receive.
|
||||
-->
|
||||
<arg name='direction' direction='in' type='y'/>
|
||||
<arg name='session' type='o' direction='out'/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
@ -1,752 +0,0 @@
|
||||
#include <glib.h>
|
||||
#include <farsight/farsight.h>
|
||||
#include <farsight/farsight-transport.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <string.h>
|
||||
#include "tox-session.h"
|
||||
#include "tox-marshal.h"
|
||||
|
||||
G_DEFINE_TYPE(ToxSession, tox_session, G_TYPE_OBJECT)
|
||||
|
||||
typedef struct _ToxSessionPrivate {
|
||||
FarsightSession *session;
|
||||
/* for now, one stream is enough */
|
||||
FarsightStream *stream;
|
||||
|
||||
int have_source, have_sink;
|
||||
|
||||
gboolean dispose_has_run;
|
||||
} ToxSessionPrivate;
|
||||
|
||||
gboolean tox_session_destroy(ToxSession *obj, GError **error);
|
||||
gboolean tox_session_set_default_audio_sink(ToxSession *obj, GError **error);
|
||||
gboolean tox_session_set_ogg_vorbis_audio_source(ToxSession *obj, char *filename, GError **error);
|
||||
gboolean tox_session_add_remote_candidate(ToxSession *obj, GPtrArray *candidate, GError **error);
|
||||
gboolean tox_session_set_remote_codecs(ToxSession *obj, GPtrArray *codecs, GError **error);
|
||||
gboolean tox_session_get_local_codecs(ToxSession *obj, GPtrArray **codecs, GError **error);
|
||||
gboolean tox_session_get_codec_intersection(ToxSession *obj, GPtrArray **codecs, GError **error);
|
||||
|
||||
/* properties */
|
||||
enum {
|
||||
DIRECTION = 1
|
||||
};
|
||||
static void tox_session_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec);
|
||||
|
||||
/* signals */
|
||||
enum {
|
||||
NEW_NATIVE_CANDIDATE,
|
||||
NATIVE_CANDIDATES_PREPARED,
|
||||
STATE_CHANGED,
|
||||
NEW_ACTIVE_CANDIDATE_PAIR,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
#include "tox-session-glue.h"
|
||||
|
||||
static GstElement *prepare_source(const char *filename);
|
||||
static void new_pad(GstElement *, GstPad *, gpointer);
|
||||
static GstElement *prepare_sink(void);
|
||||
static void stream_done(ToxSession *);
|
||||
|
||||
static GValueArray * candidate_list_to_dbus_array(const GList *candidates);
|
||||
|
||||
static void tox_session_native_candidates_prepared(FarsightStream *stream, gpointer user_data);
|
||||
static void tox_session_new_native_candidate(FarsightStream *stream, gchar *candidate_id, ToxSession *self);
|
||||
static void tox_session_state_changed(FarsightStream *stream, gint state, gint direction, ToxSession *self);
|
||||
static void tox_session_new_active_candidate_pair(FarsightStream *stream, gchar *native_candidate_id, gchar *remote_candidate_id, ToxSession *self);
|
||||
|
||||
void
|
||||
tox_session_init(ToxSession *obj)
|
||||
{
|
||||
ToxSessionPrivate *priv;
|
||||
priv = g_new0(ToxSessionPrivate, 1);
|
||||
obj->priv = priv;
|
||||
|
||||
priv->session = farsight_session_factory_make("rtp");
|
||||
g_assert(priv->session);
|
||||
|
||||
/* we need to know the direction to create a stream,
|
||||
so we do that when that property is set.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
|
||||
static void
|
||||
tox_session_dispose(GObject *obj)
|
||||
{
|
||||
ToxSession *self = (ToxSession *)obj;
|
||||
|
||||
if (self->priv->dispose_has_run) {
|
||||
return;
|
||||
}
|
||||
g_debug("in tox_session_dispose\n");
|
||||
self->priv->dispose_has_run = TRUE;
|
||||
|
||||
if (self->priv->stream)
|
||||
g_object_unref(self->priv->stream);
|
||||
if (self->priv->session)
|
||||
g_object_unref(self->priv->session);
|
||||
|
||||
self->priv->stream = NULL;
|
||||
self->priv->session = NULL;
|
||||
|
||||
G_OBJECT_CLASS(parent_class)->dispose(obj);
|
||||
}
|
||||
|
||||
static void
|
||||
tox_session_finalize(GObject *obj)
|
||||
{
|
||||
ToxSession *self = (ToxSession *)obj;
|
||||
|
||||
g_debug("in tox_session_finalize\n");
|
||||
g_free(self->priv);
|
||||
|
||||
G_OBJECT_CLASS(parent_class)->finalize(obj);
|
||||
}
|
||||
|
||||
void
|
||||
tox_session_class_init(ToxSessionClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
|
||||
GParamSpec *direction_param_spec;
|
||||
|
||||
gobject_class->dispose = tox_session_dispose;
|
||||
gobject_class->finalize = tox_session_finalize;
|
||||
|
||||
gobject_class->set_property = tox_session_set_property;
|
||||
|
||||
direction_param_spec = g_param_spec_uint("direction",
|
||||
"stream direction",
|
||||
"1 means send-only, 2 means receive-only, 3 means both",
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
|
||||
g_object_class_install_property(gobject_class,
|
||||
DIRECTION,
|
||||
direction_param_spec);
|
||||
|
||||
signals[NEW_NATIVE_CANDIDATE] =
|
||||
g_signal_new("new-native-candidate",
|
||||
G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
|
||||
0,
|
||||
NULL, NULL,
|
||||
tox_marshal_VOID__BOXED,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_VALUE_ARRAY);
|
||||
|
||||
signals[NATIVE_CANDIDATES_PREPARED] =
|
||||
g_signal_new("native-candidates-prepared",
|
||||
G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
|
||||
0,
|
||||
NULL, NULL,
|
||||
tox_marshal_VOID__BOXED,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_VALUE_ARRAY);
|
||||
|
||||
signals[STATE_CHANGED] =
|
||||
g_signal_new("state-changed",
|
||||
G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
|
||||
0,
|
||||
NULL, NULL,
|
||||
tox_marshal_VOID__UCHAR_UCHAR,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_UCHAR,
|
||||
G_TYPE_UCHAR);
|
||||
|
||||
signals[NEW_ACTIVE_CANDIDATE_PAIR] =
|
||||
g_signal_new("new-active-candidate-pair",
|
||||
G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
|
||||
0,
|
||||
NULL, NULL,
|
||||
tox_marshal_VOID__STRING_STRING,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
|
||||
dbus_g_object_type_install_info(TOX_TYPE_SESSION, &dbus_glib_tox_session_object_info);
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
}
|
||||
|
||||
static void
|
||||
tox_session_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ToxSession *self = (ToxSession *)obj;
|
||||
guint dir;
|
||||
|
||||
switch(property_id) {
|
||||
case DIRECTION:
|
||||
if (self->priv->stream)
|
||||
g_object_unref(self->priv->stream);
|
||||
/* Now we know the direction, so we create a stream. */
|
||||
dir = g_value_get_uint(value);
|
||||
self->priv->stream = farsight_session_create_stream(self->priv->session,
|
||||
FARSIGHT_MEDIA_TYPE_AUDIO,
|
||||
dir);
|
||||
g_assert(self->priv->stream);
|
||||
|
||||
g_object_set(G_OBJECT(self->priv->stream), "transmitter", "libjingle", NULL);
|
||||
|
||||
/* XXX: should we set null source/sink here? */
|
||||
switch (dir) {
|
||||
case 1:
|
||||
/* send-only, we need no sink */
|
||||
self->priv->have_sink = 1;
|
||||
break;
|
||||
case 2:
|
||||
/* receive-only, we need no source */
|
||||
self->priv->have_source = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* start preparing native candidates */
|
||||
g_debug("About to prepare native candidates...\n");
|
||||
g_signal_connect(self->priv->stream, "new-native-candidate",
|
||||
(GCallback)tox_session_new_native_candidate, (gpointer)self);
|
||||
g_signal_connect(self->priv->stream, "native-candidates-prepared",
|
||||
(GCallback)tox_session_native_candidates_prepared, (gpointer)self);
|
||||
/* but we can't actually do it until we have a pipeline.
|
||||
so, we'll call stream_done when we do. */
|
||||
|
||||
/* Other signals we want to forward */
|
||||
g_signal_connect(self->priv->stream, "state-changed",
|
||||
(GCallback)tox_session_state_changed, (gpointer)self);
|
||||
g_signal_connect(self->priv->stream, "new-active-candidate-pair",
|
||||
(GCallback)tox_session_new_active_candidate_pair, (gpointer)self);
|
||||
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_session_destroy(ToxSession *obj, GError **error)
|
||||
{
|
||||
g_object_unref(obj);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_session_set_default_audio_sink(ToxSession *obj, GError **error)
|
||||
{
|
||||
GstElement *sink = prepare_sink();
|
||||
farsight_stream_set_sink(obj->priv->stream, sink);
|
||||
obj->priv->have_sink = 1;
|
||||
|
||||
if (obj->priv->have_sink && obj->priv->have_source)
|
||||
stream_done(obj);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_session_set_ogg_vorbis_audio_source(ToxSession *obj, char *filename, GError **error)
|
||||
{
|
||||
GstElement *source = prepare_source(filename);
|
||||
farsight_stream_set_source(obj->priv->stream, source);
|
||||
obj->priv->have_source = 1;
|
||||
|
||||
if (obj->priv->have_sink && obj->priv->have_source)
|
||||
stream_done(obj);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
prepare_source(const char *filename)
|
||||
{
|
||||
GstElement *bin, *filesrc, *demux, *decode;
|
||||
|
||||
bin = gst_bin_new("mysource");
|
||||
filesrc = gst_element_factory_make("filesrc", "file-source");
|
||||
g_object_set(G_OBJECT(filesrc), "location", filename, NULL);
|
||||
|
||||
demux = gst_element_factory_make("oggdemux", "ogg-parser");
|
||||
decode = gst_element_factory_make("vorbisdec", "vorbis-decoder");
|
||||
|
||||
gst_element_link(filesrc, demux);
|
||||
g_signal_connect(demux, "pad-added", G_CALLBACK(new_pad), decode);
|
||||
|
||||
gst_bin_add_many(GST_BIN(bin), filesrc, demux, decode, NULL);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
static void
|
||||
new_pad(GstElement *demux, GstPad *pad, gpointer data)
|
||||
{
|
||||
GstElement *decode = (GstElement*)data;
|
||||
GstPad *decoder_pad;
|
||||
|
||||
decoder_pad = gst_element_get_pad(decode, "sink");
|
||||
gst_pad_link(pad, decoder_pad);
|
||||
|
||||
gst_object_unref(decoder_pad);
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
prepare_sink(void)
|
||||
{
|
||||
GstElement *bin, *converter, *audiosink;
|
||||
|
||||
bin = gst_bin_new("mysink");
|
||||
converter = gst_element_factory_make("audioconvert", "converter");
|
||||
audiosink = gst_element_factory_make("autoaudiosink", "audiosink");
|
||||
gst_element_link(converter, audiosink);
|
||||
|
||||
gst_bin_add_many(GST_BIN(bin), converter, audiosink, NULL);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
static void
|
||||
stream_done(ToxSession *self)
|
||||
{
|
||||
farsight_stream_prepare_transports(self->priv->stream);
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_session_add_remote_candidate(ToxSession *self, GPtrArray *candidate, GError **error)
|
||||
{
|
||||
int i;
|
||||
guint n;
|
||||
GList *candidate_list;
|
||||
|
||||
candidate_list = NULL;
|
||||
|
||||
/* Here we convert the array of structs into a GList of
|
||||
FarsightTransportInfo. The argument list is described in
|
||||
tox-session.xml. */
|
||||
for (i = 0; i < candidate->len; i++) {
|
||||
GValueArray *component;
|
||||
FarsightTransportInfo *info;
|
||||
gchar *s;
|
||||
|
||||
component = g_ptr_array_index(candidate, i);
|
||||
info = g_new0(FarsightTransportInfo, 1);
|
||||
|
||||
info->candidate_id =
|
||||
g_value_dup_string(
|
||||
g_value_array_get_nth(component, 0));
|
||||
info->component =
|
||||
g_value_get_uint(
|
||||
g_value_array_get_nth(component, 1));
|
||||
info->ip =
|
||||
g_value_dup_string(
|
||||
g_value_array_get_nth(component, 2));
|
||||
info->port =
|
||||
g_value_get_uint(
|
||||
g_value_array_get_nth(component, 3));
|
||||
|
||||
s = g_value_dup_string(g_value_array_get_nth(component, 4));
|
||||
if (strcmp(s, "tcp") == 0)
|
||||
info->proto = FARSIGHT_NETWORK_PROTOCOL_TCP;
|
||||
else if (strcmp(s, "udp") == 0)
|
||||
info->proto = FARSIGHT_NETWORK_PROTOCOL_UDP;
|
||||
else {
|
||||
g_set_error(error, DBUS_GERROR,
|
||||
DBUS_GERROR_REMOTE_EXCEPTION,
|
||||
"Unexpected protocol '%s'",
|
||||
s);
|
||||
g_free(s);
|
||||
g_free(info);
|
||||
goto fail;
|
||||
}
|
||||
g_free(s);
|
||||
|
||||
/* this should be "RTP" */
|
||||
info->proto_subtype =
|
||||
g_value_dup_string(
|
||||
g_value_array_get_nth(component, 5));
|
||||
/* this should be "AVP" */
|
||||
info->proto_profile =
|
||||
g_value_dup_string(
|
||||
g_value_array_get_nth(component, 6));
|
||||
|
||||
info->preference =
|
||||
g_value_get_uint(
|
||||
g_value_array_get_nth(component, 7))
|
||||
* 0.01;
|
||||
|
||||
n = g_value_get_uint(g_value_array_get_nth(component, 8));
|
||||
switch (n) {
|
||||
case 0:
|
||||
info->type = FARSIGHT_CANDIDATE_TYPE_LOCAL;
|
||||
break;
|
||||
case 1:
|
||||
info->type = FARSIGHT_CANDIDATE_TYPE_DERIVED;
|
||||
break;
|
||||
case 2:
|
||||
info->type = FARSIGHT_CANDIDATE_TYPE_RELAY;
|
||||
break;
|
||||
default:
|
||||
g_set_error(error, DBUS_GERROR,
|
||||
DBUS_GERROR_REMOTE_EXCEPTION,
|
||||
"Unexpected type %u",
|
||||
n);
|
||||
g_free(info);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
info->username = g_value_dup_string(
|
||||
g_value_array_get_nth(component, 9));
|
||||
info->password = g_value_dup_string(
|
||||
g_value_array_get_nth(component, 10));
|
||||
|
||||
candidate_list = g_list_append(candidate_list, info);
|
||||
}
|
||||
|
||||
farsight_stream_add_remote_candidate(self->priv->stream, candidate_list);
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
farsight_transport_list_destroy(candidate_list);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_session_set_remote_codecs(ToxSession *obj, GPtrArray *codecs, GError **error)
|
||||
{
|
||||
GList *codec_list;
|
||||
int i;
|
||||
/* GList *j; */
|
||||
|
||||
codec_list = NULL;
|
||||
|
||||
for (i = 0; i < codecs->len; i++) {
|
||||
GValueArray *codec_in;
|
||||
FarsightCodec *codec_out;
|
||||
|
||||
codec_in = g_ptr_array_index(codecs, i);
|
||||
codec_out = g_new0(FarsightCodec, 1);
|
||||
|
||||
codec_out->id = g_value_get_int(g_value_array_get_nth(codec_in, 0));
|
||||
codec_out->encoding_name = g_value_dup_string(g_value_array_get_nth(codec_in, 1));
|
||||
/* maybe check range of media_type... */
|
||||
codec_out->media_type = g_value_get_uchar(g_value_array_get_nth(codec_in, 2));
|
||||
codec_out->clock_rate = g_value_get_uint(g_value_array_get_nth(codec_in, 3));
|
||||
codec_out->channels = g_value_get_uint(g_value_array_get_nth(codec_in, 4));
|
||||
|
||||
codec_list = g_list_append(codec_list, codec_out);
|
||||
}
|
||||
|
||||
farsight_stream_set_remote_codecs(obj->priv->stream, codec_list);
|
||||
|
||||
/* should the elements be freed, or just the list itself? */
|
||||
/*for (j = codec_list; j; j = g_list_next(j)) {
|
||||
g_free(j->data);
|
||||
}*/
|
||||
g_list_free(codec_list);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_session_get_local_codecs(ToxSession *obj, GPtrArray **codecs, GError **error)
|
||||
{
|
||||
FarsightStream *stream;
|
||||
const GList *codec_list;
|
||||
|
||||
GType hash_string_string;
|
||||
|
||||
stream = obj->priv->stream;
|
||||
codec_list = farsight_stream_get_local_codecs(stream);
|
||||
|
||||
hash_string_string = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
*codecs = g_ptr_array_sized_new(g_list_length(codec_list));
|
||||
for (; codec_list; codec_list = g_list_next(codec_list)) {
|
||||
GValueArray *codec_struct;
|
||||
const FarsightCodec *codec;
|
||||
GValue value;
|
||||
GHashTable *parameters;
|
||||
GList *p;
|
||||
|
||||
memset(&value, 0, sizeof value);
|
||||
|
||||
codec = (const FarsightCodec*)codec_list->data;
|
||||
codec_struct = g_value_array_new(2);
|
||||
|
||||
g_value_init(&value, G_TYPE_INT);
|
||||
g_value_set_int(&value, codec->id);
|
||||
g_value_array_append(codec_struct, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
g_value_set_string(&value, codec->encoding_name);
|
||||
g_value_array_append(codec_struct, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
/* XXX: why is this the same as id? */
|
||||
g_value_init(&value, G_TYPE_UCHAR);
|
||||
g_value_set_uchar(&value, codec->media_type);
|
||||
g_value_array_append(codec_struct, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_UINT);
|
||||
g_value_set_uint(&value, codec->clock_rate);
|
||||
g_value_array_append(codec_struct, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_UINT);
|
||||
g_value_set_uint(&value, codec->channels);
|
||||
g_value_array_append(codec_struct, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
/* optional parameters - this should be a hash table, I think */
|
||||
/* parameters = g_hash_table_new(g_str_hash, g_str_equal); */
|
||||
parameters = dbus_g_type_specialized_construct(hash_string_string);
|
||||
for (p = codec->optional_params; p; p = g_list_next(p)) {
|
||||
FarsightCodecParameter *param = p->data;
|
||||
|
||||
g_hash_table_insert(parameters, param->name, param->value);
|
||||
}
|
||||
g_value_init(&value, hash_string_string);
|
||||
g_value_set_boxed(&value, parameters);
|
||||
g_value_array_append(codec_struct, &value);
|
||||
g_value_unset(&value);
|
||||
g_hash_table_unref(parameters);
|
||||
|
||||
g_assert(codec_struct->n_values == 6);
|
||||
|
||||
g_ptr_array_add(*codecs, codec_struct);
|
||||
|
||||
g_debug("Local codec: %s\n", codec->encoding_name);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_session_get_codec_intersection(ToxSession *obj, GPtrArray **codecs, GError **error)
|
||||
{
|
||||
FarsightStream *stream;
|
||||
GList *codec_list;
|
||||
|
||||
stream = obj->priv->stream;
|
||||
codec_list = farsight_stream_get_codec_intersection(stream);
|
||||
|
||||
*codecs = g_ptr_array_sized_new(g_list_length(codec_list));
|
||||
for (; codec_list; codec_list = g_list_next(codec_list)) {
|
||||
GValueArray *codec_struct;
|
||||
FarsightCodec *codec;
|
||||
GValue *value;
|
||||
|
||||
codec = (FarsightCodec*)codec_list->data;
|
||||
codec_struct = g_value_array_new(6);
|
||||
|
||||
value = g_new0(GValue, 1);
|
||||
g_value_init(value, G_TYPE_INT);
|
||||
g_value_set_int(value, codec->id);
|
||||
g_value_array_append(codec_struct, value);
|
||||
|
||||
value = g_new0(GValue, 1);
|
||||
g_value_init(value, G_TYPE_STRING);
|
||||
g_value_set_string(value, codec->encoding_name);
|
||||
g_value_array_append(codec_struct, value);
|
||||
|
||||
value = g_new0(GValue, 1);
|
||||
g_value_init(value, G_TYPE_UCHAR);
|
||||
g_value_set_uchar(value, codec->media_type);
|
||||
g_value_array_append(codec_struct, value);
|
||||
|
||||
value = g_new0(GValue, 1);
|
||||
g_value_init(value, G_TYPE_UINT);
|
||||
g_value_set_uint(value, codec->clock_rate);
|
||||
g_value_array_append(codec_struct, value);
|
||||
|
||||
value = g_new0(GValue, 1);
|
||||
g_value_init(value, G_TYPE_UINT);
|
||||
g_value_set_uint(value, codec->channels);
|
||||
g_value_array_append(codec_struct, value);
|
||||
|
||||
/* XXX: do something about optional parameters */
|
||||
value = g_new0(GValue, 1);
|
||||
g_value_init(value, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
|
||||
g_value_set_boxed(value, g_hash_table_new(g_str_hash, g_str_equal));
|
||||
g_value_array_append(codec_struct, value);
|
||||
|
||||
g_assert(codec_struct->n_values == 6);
|
||||
|
||||
g_ptr_array_add(*codecs, codec_struct);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
tox_session_native_candidates_prepared(FarsightStream *stream, gpointer user_data)
|
||||
{
|
||||
ToxSession *self = (ToxSession *)user_data;
|
||||
const GList *candidates;
|
||||
GValueArray *array;
|
||||
|
||||
candidates = farsight_stream_get_native_candidate_list(stream);
|
||||
|
||||
array = candidate_list_to_dbus_array(candidates);
|
||||
|
||||
g_debug("Sending signal NativeCandidatesPrepared!\n");
|
||||
g_signal_emit(self, signals[NATIVE_CANDIDATES_PREPARED], 0, array);
|
||||
}
|
||||
|
||||
static void
|
||||
tox_session_new_native_candidate(FarsightStream *stream, gchar *candidate_id, ToxSession *self)
|
||||
{
|
||||
GList *candidate =
|
||||
farsight_stream_get_native_candidate (stream, candidate_id);
|
||||
FarsightTransportInfo *trans = candidate->data;
|
||||
GValueArray *array;
|
||||
|
||||
g_debug ("tox_session_new_native_candidate: New native candidate"
|
||||
" with %d components, the first being: "
|
||||
"<id: %s, "
|
||||
"component: %d, "
|
||||
"ip: %s port: %d "
|
||||
"proto: %d, "
|
||||
"proto_subtype: %s, "
|
||||
"proto_profile: %s, "
|
||||
"preference: %f, "
|
||||
"type: %d "
|
||||
"username: %s password: %s>",
|
||||
g_list_length(candidate),
|
||||
trans->candidate_id, trans->component,
|
||||
trans->ip, trans->port, trans->proto, trans->proto_subtype,
|
||||
trans->proto_profile, trans->preference,
|
||||
trans->type, trans->username, trans->password);
|
||||
|
||||
array = candidate_list_to_dbus_array(candidate);
|
||||
g_debug("Sending signal NewNativeCandidate!\n");
|
||||
g_signal_emit(self, signals[NEW_NATIVE_CANDIDATE], 0, array);
|
||||
}
|
||||
|
||||
static GValueArray *
|
||||
candidate_list_to_dbus_array(const GList *candidates)
|
||||
{
|
||||
GValueArray *array;
|
||||
|
||||
array = g_value_array_new(1);
|
||||
|
||||
for (; candidates; candidates = g_list_next(candidates)) {
|
||||
GValueArray *candidate;
|
||||
FarsightTransportInfo *info;
|
||||
GValue value;
|
||||
|
||||
info = (FarsightTransportInfo*)candidates->data;
|
||||
candidate = g_value_array_new(11);
|
||||
|
||||
memset(&value, 0, sizeof value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
g_value_set_string(&value, info->candidate_id);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_UINT);
|
||||
g_value_set_uint(&value, info->component);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
g_value_set_string(&value, info->ip);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_UINT);
|
||||
g_value_set_uint(&value, info->port);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
switch(info->proto) {
|
||||
case FARSIGHT_NETWORK_PROTOCOL_UDP:
|
||||
g_value_set_static_string(&value, "udp");
|
||||
break;
|
||||
case FARSIGHT_NETWORK_PROTOCOL_TCP:
|
||||
g_value_set_static_string(&value, "tcp");
|
||||
break;
|
||||
default:
|
||||
g_error("Unknown protocol value %u\n", info->proto);
|
||||
}
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
g_value_set_string(&value, info->proto_subtype);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
g_value_set_string(&value, info->proto_profile);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_UINT);
|
||||
g_value_set_uint(&value, (guint)(info->preference * 100));
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_UINT);
|
||||
switch(info->type) {
|
||||
case FARSIGHT_CANDIDATE_TYPE_LOCAL:
|
||||
g_value_set_uint(&value, 0);
|
||||
break;
|
||||
case FARSIGHT_CANDIDATE_TYPE_DERIVED:
|
||||
g_value_set_uint(&value, 1);
|
||||
break;
|
||||
case FARSIGHT_CANDIDATE_TYPE_RELAY:
|
||||
g_value_set_uint(&value, 2);
|
||||
break;
|
||||
default:
|
||||
g_error("Unknown candidate type %u\n", info->proto);
|
||||
}
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
g_value_set_string(&value, info->username);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_value_init(&value, G_TYPE_STRING);
|
||||
g_value_set_string(&value, info->password);
|
||||
g_value_array_append(candidate, &value);
|
||||
g_value_unset(&value);
|
||||
|
||||
g_assert(candidate->n_values == 11);
|
||||
|
||||
g_value_init(&value, G_TYPE_VALUE_ARRAY);
|
||||
/* apparently GValueArray is a "boxed" type */
|
||||
g_value_set_boxed(&value, candidate);
|
||||
g_value_array_append(array, &value);
|
||||
g_value_unset(&value);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
static void
|
||||
tox_session_state_changed(FarsightStream *stream, gint state, gint direction, ToxSession *self)
|
||||
{
|
||||
g_signal_emit(self, signals[STATE_CHANGED], 0, state, direction);
|
||||
}
|
||||
|
||||
static void
|
||||
tox_session_new_active_candidate_pair(FarsightStream *stream, gchar *native_candidate_id, gchar *remote_candidate_id, ToxSession *self)
|
||||
{
|
||||
g_signal_emit(self, signals[NEW_ACTIVE_CANDIDATE_PAIR], 0, native_candidate_id, remote_candidate_id);
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
#ifndef __TOX_SESSION_H__
|
||||
#define __TOX_SESSION_H__
|
||||
|
||||
typedef struct ToxSession
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
struct _ToxSessionPrivate *priv;
|
||||
} ToxSession;
|
||||
|
||||
typedef struct ToxSessionClass
|
||||
{
|
||||
GObjectClass parent;
|
||||
} ToxSessionClass;
|
||||
|
||||
GType tox_session_get_type(void);
|
||||
#define TOX_TYPE_SESSION (tox_session_get_type())
|
||||
#define TOX_SESSION(object) (G_TYPE_CHECK_INSTANCE_CAST((object), TOX_TYPE_SESSION, ToxSession))
|
||||
#define TOX_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TOX_TYPE_SESSION, ToxSessionClass))
|
||||
#define TOX_IS_SESSION(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TOX_TYPE_SESSION))
|
||||
#define TOX_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TOX_TYPE_SESSION))
|
||||
#define TOX_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TOX_TYPE_SESSION, ToxSessionClass))
|
||||
|
||||
#endif /* __TOX_SESSION_H__ */
|
||||
@ -1,91 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
|
||||
<interface name='net.sourceforge.emacs_jabber.ToxSession'>
|
||||
<method name='Destroy'/>
|
||||
|
||||
<method name='SetDefaultAudioSink'/>
|
||||
|
||||
<method name='SetOggVorbisAudioSource'>
|
||||
<arg name='filename' direction='in' type='s'/>
|
||||
</method>
|
||||
|
||||
<method name='AddRemoteCandidate'>
|
||||
<arg name='transport' direction='in' type='a(susqsssyyss)'/>
|
||||
<!-- Each element is a candidate component. (Usually each
|
||||
candidate has only one component)
|
||||
|
||||
Struct members are:
|
||||
- Candidate ID
|
||||
- Component (starting from 1)
|
||||
- IP number (as a string)
|
||||
- Port number
|
||||
- Protocol ("tcp" or "udp")
|
||||
- Protocol subtype (only "RTP" supported)
|
||||
- Protocol profile (only "AVP" supported)
|
||||
- Preference, between 0 and 100
|
||||
- Type. 0 means local, 1 means derived (e.g. through
|
||||
STUN), 2 means relay
|
||||
- Username (may be empty)
|
||||
- Password (may be empty)
|
||||
-->
|
||||
</method>
|
||||
|
||||
<signal name="NewNativeCandidate">
|
||||
<arg name="candidates" type="a(susqsssyyss)"/>
|
||||
<!-- Argument as to AddRemoteCandidate -->
|
||||
</signal>
|
||||
|
||||
<signal name="NativeCandidatesPrepared">
|
||||
<arg name="candidates" type="a(susqsssyyss)"/>
|
||||
<!-- Argument as to AddRemoteCandidate -->
|
||||
</signal>
|
||||
|
||||
<method name='SetRemoteCodecs'>
|
||||
<arg name='codec-list' direction='in' type='a(isyuua{ss})'/>
|
||||
<!-- Each element is a codec. Struct members are:
|
||||
|
||||
- numeric identifier
|
||||
- codec name
|
||||
- media type: 0 is audio, 1 is video
|
||||
- clock rate
|
||||
- number of channels
|
||||
- optional parameters
|
||||
-->
|
||||
</method>
|
||||
|
||||
<method name='GetLocalCodecs'>
|
||||
<arg name='codec-list' direction='out' type='a(isyuua{ss})'/>
|
||||
<!-- Argument as to SetRemoteCodecs -->
|
||||
</method>
|
||||
|
||||
<method name='GetCodecIntersection'>
|
||||
<arg name='codec-list' direction='out' type='a(isyuua{ss})'/>
|
||||
<!-- Argument layout: see SetRemoteCodecs -->
|
||||
</method>
|
||||
|
||||
<signal name="StateChanged">
|
||||
<!-- state is one of:
|
||||
0: disconnected
|
||||
1: connecting
|
||||
2: connected
|
||||
-->
|
||||
<arg name='newstate' type='y'/>
|
||||
<!-- direction is one of:
|
||||
0: nothing
|
||||
1: send only.
|
||||
2: receive only.
|
||||
3: send and receive.
|
||||
-->
|
||||
<arg name='direction' type='y'/>
|
||||
</signal>
|
||||
|
||||
<signal name="NewActiveCandidatePair">
|
||||
<arg name="nativeCandidateId" type="s"/>
|
||||
<arg name="removeCandidateId" type="s"/>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
110
tox/tox.c
110
tox/tox.c
@ -1,110 +0,0 @@
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include "tox.h"
|
||||
#include "tox-session.h"
|
||||
|
||||
typedef struct _ToxObjectPrivate {
|
||||
guint session_counter;
|
||||
DBusGConnection *connection;
|
||||
} ToxObjectPrivate;
|
||||
|
||||
G_DEFINE_TYPE(ToxObject, tox_object, G_TYPE_OBJECT)
|
||||
|
||||
gboolean tox_create_session(ToxObject *obj, guint8 dir, char **ret, GError **error);
|
||||
|
||||
/* properties */
|
||||
enum {
|
||||
TOX_DBUS_CONNECTION = 1,
|
||||
};
|
||||
|
||||
static void tox_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec);
|
||||
static void tox_get_property(GObject *obj, guint property_id, GValue *value, GParamSpec *pspec);
|
||||
|
||||
#include "tox-object-glue.h"
|
||||
|
||||
void
|
||||
tox_object_init(ToxObject *obj)
|
||||
{
|
||||
obj->priv = g_new0(ToxObjectPrivate, 1);
|
||||
}
|
||||
|
||||
void
|
||||
tox_object_class_init(ToxObjectClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
|
||||
GParamSpec *connection_param_spec;
|
||||
|
||||
gobject_class->set_property = tox_set_property;
|
||||
gobject_class->get_property = tox_get_property;
|
||||
|
||||
connection_param_spec = g_param_spec_boxed("dbus-connection",
|
||||
"D-Bus connection",
|
||||
"Connection where new sessions are registered",
|
||||
DBUS_TYPE_G_CONNECTION,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
g_object_class_install_property(gobject_class,
|
||||
TOX_DBUS_CONNECTION,
|
||||
connection_param_spec);
|
||||
|
||||
dbus_g_object_type_install_info(TOX_TYPE_OBJECT, &dbus_glib_tox_object_info);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
tox_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ToxObject *self = (ToxObject *)obj;
|
||||
|
||||
switch(property_id) {
|
||||
case TOX_DBUS_CONNECTION:
|
||||
/* XXX: this should be a weak ref */
|
||||
/* hm? */
|
||||
/* if (self->priv->connection) */
|
||||
/* dbus_g_connection_unref(self->priv->connection); */
|
||||
self->priv->connection = (DBusGConnection *)g_value_get_boxed(value);
|
||||
/* dbus_g_connection_ref(self->priv->connection); */
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tox_get_property(GObject *obj, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ToxObject *self = (ToxObject *)obj;
|
||||
|
||||
switch(property_id) {
|
||||
case TOX_DBUS_CONNECTION:
|
||||
g_value_set_boxed(value, self->priv->connection);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
tox_create_session(ToxObject *obj, guint8 dir, char **ret, GError **error)
|
||||
{
|
||||
guint session_number = ++obj->priv->session_counter;
|
||||
DBusGConnection *connection = obj->priv->connection;
|
||||
ToxSession *session;
|
||||
|
||||
if (dir < 1 || dir > 3) {
|
||||
/* XXX: how to set the D-Bus error name? */
|
||||
g_set_error(error, DBUS_GERROR,
|
||||
DBUS_GERROR_REMOTE_EXCEPTION,
|
||||
"Direction out of range (was %u, should be 1 <= dir <= 3)",
|
||||
dir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
session = g_object_new(TOX_TYPE_SESSION, "direction", dir, NULL);
|
||||
|
||||
*ret = g_strdup_printf("/net/sourceforge/emacs_jabber/Tox/%u", session_number);
|
||||
dbus_g_connection_register_g_object(connection, *ret, G_OBJECT(session));
|
||||
|
||||
g_debug("CreateSession called, returning %s\n", *ret);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
24
tox/tox.h
24
tox/tox.h
@ -1,24 +0,0 @@
|
||||
#ifndef __TOX_H__
|
||||
#define __TOX_H__
|
||||
|
||||
typedef struct ToxObject
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
struct _ToxObjectPrivate *priv;
|
||||
} ToxObject;
|
||||
|
||||
typedef struct ToxObjectClass
|
||||
{
|
||||
GObjectClass parent;
|
||||
} ToxObjectClass;
|
||||
|
||||
GType tox_object_get_type(void);
|
||||
#define TOX_TYPE_OBJECT (tox_object_get_type())
|
||||
#define TOX_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST((object), TOX_TYPE_OBJECT, ToxObject))
|
||||
#define TOX_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TOX_TYPE_OBJECT, ToxObjectClass))
|
||||
#define TOX_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TOX_TYPE_OBJECT))
|
||||
#define TOX_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TOX_TYPE_OBJECT))
|
||||
#define TOX_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TOX_TYPE_OBJECT, ToxObjectClass))
|
||||
|
||||
#endif /* __TOX_H__ */
|
||||
@ -1,3 +0,0 @@
|
||||
[D-BUS Service]
|
||||
Name=net.sourceforge.emacs-jabber.Tox
|
||||
Exec=@libexecdir@/tox
|
||||
305
www/index.html
305
www/index.html
@ -1,305 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>jabber.el</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
|
||||
<meta name="generator" content="Org-mode"/>
|
||||
<meta name="generated" content="2009/02/19 1:31:21 AM"/>
|
||||
<meta name="author" content=""/>
|
||||
<style type="text/css">
|
||||
html {
|
||||
font-family: Times, serif;
|
||||
font-size: 12pt;
|
||||
}
|
||||
.title { text-align: center; }
|
||||
.todo { color: red; }
|
||||
.done { color: green; }
|
||||
.timestamp { color: grey }
|
||||
.timestamp-kwd { color: CadetBlue }
|
||||
.tag { background-color:lightblue; font-weight:normal }
|
||||
.target { background-color: lavender; }
|
||||
pre {
|
||||
border: 1pt solid #AEBDCC;
|
||||
background-color: #F3F5F7;
|
||||
padding: 5pt;
|
||||
font-family: courier, monospace;
|
||||
}
|
||||
table { border-collapse: collapse; }
|
||||
td, th {
|
||||
vertical-align: top;
|
||||
<!--border: 1pt solid #ADB9CC;-->
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
<h1 class="title">jabber.el</h1>
|
||||
<a href="http://sourceforge.net">
|
||||
<img border="0" src="http://sourceforge.net/sflogo.php?group_id=88346&type=2" width="125" height="37" alt="SourceForge.net Logo" style="position: absolute; top: 0em; right: 0em;"></a>
|
||||
|
||||
jabber.el is a Jabber client for Emacs.
|
||||
|
||||
<div id="table-of-contents">
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#sec-1">What is Jabber?</a></li>
|
||||
<li><a href="#sec-2">What is jabber.el?</a></li>
|
||||
<li><a href="#sec-3">Downloading and installing</a>
|
||||
<ul>
|
||||
<li><a href="#sec-4">Prepackaged</a></li>
|
||||
<li><a href="#sec-5">Dependencies</a></li>
|
||||
<li><a href="#sec-6">Downloading</a></li>
|
||||
<li><a href="#sec-7">Using</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#sec-8">Reporting bugs</a></li>
|
||||
<li><a href="#sec-9">Latest source</a>
|
||||
<ul>
|
||||
<li><a href="#sec-10">CVS</a></li>
|
||||
<li><a href="#sec-11">GNU Arch</a></li>
|
||||
<li><a href="#sec-12">git</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#sec-13">List of releases</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<a name="impatient"> </a>
|
||||
For the impatient:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Latest release: <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=482983">0.7.1</a> (31-Jan-2007)
|
||||
</li>
|
||||
<li>
|
||||
Latest pretest release: <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=278300&release_id=662240">0.7.93</a> (19-Feb-2009)
|
||||
</li>
|
||||
<li>
|
||||
Full <a href="#list-of-releases">list of releases</a>, including lists of features and changes
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<p>External resources:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://sourceforge.net/projects/emacs-jabber/">Sourceforge project page</a>, containing:
|
||||
<ul>
|
||||
<li>
|
||||
trackers for
|
||||
<a href="http://sourceforge.net/tracker/?atid=586350&group_id=88346&func=browse">bugs</a>,
|
||||
<a href="http://sourceforge.net/tracker/?atid=586353&group_id=88346&func=browse">feature requests</a>,
|
||||
<a href="http://sourceforge.net/tracker/?atid=586352&group_id=88346&func=browse">patches</a> and
|
||||
<a href="http://sourceforge.net/tracker/?atid=586351&group_id=88346&func=browse">support requests</a>, open for anonymous posters
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://sourceforge.net/forum/?group_id=88346">forums</a>, open for anonymous posters
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
<a href="http://www.emacswiki.org/cgi-bin/wiki/JabberEl">the JabberEl page of EmacsWiki</a>
|
||||
</li>
|
||||
<li>
|
||||
Mailing lists (also available at <a href="http://gmane.net">Gmane</a>):
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://lists.sourceforge.net/lists/listinfo/emacs-jabber-general">emacs-jabber-general</a>, for posts by humans (also <a href="http://dir.gmane.org/gmane.emacs.jabber.general">gmane.emacs.jabber.general</a>)
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://lists.sourceforge.net/lists/listinfo/emacs-jabber-commit">emacs-jabber-commit</a>, read-only mailing list of CVS commits (also <a href="http://dir.gmane.org/gmane.emacs.jabber.scm">gmane.emacs.jabber.scm</a>)
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://lists.sourceforge.net/lists/listinfo/emacs-jabber-bugs">emacs-jabber-bugs</a>, read-only mailing list of bug tracker activity (also <a href="http://dir.gmane.org/gmane.emacs.jabber.bugs">gmane.emacs.jabber.bugs</a>)
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
the Jabber chat room
|
||||
<a href="xmpp:jabber.el@conference.jabber.se?join">jabber.el@conference.jabber.se</a>
|
||||
</li>
|
||||
<li>
|
||||
the <a href="manual-0.7.1/">manual for jabber.el 0.7.1</a> (also included in the release files)
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<div class="outline-2">
|
||||
<h2 id="sec-1">What is Jabber?</h2>
|
||||
|
||||
|
||||
<p>
|
||||
Jabber is an open instant messaging (IM) system, also known as XMPP.
|
||||
It is described in <a href="http://www.xmpp.org/rfcs/">RFCs 3920-3923</a> and a series of <a href="http://www.xmpp.org/extensions/">XEPs</a> (XMPP Extension
|
||||
Proposals). That is, unlike legacy IM systems (such as ICQ or MSN
|
||||
Messenger), the protocol is published in the open, free for anyone to
|
||||
implement. Therefore you shouldn't be surprised that there is a
|
||||
Jabber client for Emacs, too. (If you are not of the Emacs
|
||||
persuasion, see this <a href="http://www.jabber.org/software/clients.shtml">list of Jabber clients</a>.)
|
||||
</p>
|
||||
<p>
|
||||
Jabber is, like e-mail, a decentralised system. A Jabber identifier
|
||||
(JID) is of the form <code>username@server</code>, just like an e-mail address, and
|
||||
every Jabber user whose server is open to Internet connections can
|
||||
communicate with any other user. This is in stark contrast to the
|
||||
legacy "walled-garden" IM systems, where you need a separate account
|
||||
for each system to be able to communicate with its users. Note that
|
||||
the <a href="http://talk.google.com">Google Talk</a> service is an XMPP service, so if you have a GMail
|
||||
account, you already have a JID ending with <code>@gmail.com</code>.
|
||||
</p>
|
||||
<p>
|
||||
In Jabber, you have a "roster", a list of contacts. You can see
|
||||
which of them are online at the moment, and chat with them. (You can
|
||||
also send messages to an offline contact, and the message will be
|
||||
stored on the server for later delivery.) Jabber also supports
|
||||
IRC-style chat rooms.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="outline-2">
|
||||
<h2 id="sec-2">What is jabber.el?</h2>
|
||||
|
||||
|
||||
<p>
|
||||
jabber.el is a Jabber client for Emacs. It may seem strange to have a
|
||||
chat client in an editor, but consider that chatting is, after all,
|
||||
just a special case of text editing.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="outline-2">
|
||||
<h2 id="sec-3">Downloading and installing</h2>
|
||||
|
||||
|
||||
|
||||
<div class="outline-3">
|
||||
<h3 id="sec-4">Prepackaged</h3>
|
||||
|
||||
|
||||
<p>
|
||||
Note that jabber.el is available as <a href="http://packages.debian.org/emacs-jabber">emacs-jabber in Debian</a>, and in
|
||||
<a href="http://packages.ubuntu.com/emacs-jabber">Ubuntu's "universe" section</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="outline-3">
|
||||
<h3 id="sec-5">Dependencies</h3>
|
||||
|
||||
|
||||
<p>
|
||||
jabber.el requires either GNU Emacs 22, or GNU Emacs 21 combined with
|
||||
Gnus 5.10. You should get these from your distribution, or from the
|
||||
<a href="http://www.gnu.org/software/emacs/">Emacs</a> and <a href="http://gnus.org">Gnus</a> web sites.
|
||||
</p>
|
||||
<p>
|
||||
However, if you want to connect to servers that use SRV records
|
||||
(e.g. Google Talk), it is recommended to use either No Gnus or Gnus
|
||||
5.13.
|
||||
</p>
|
||||
<p>
|
||||
If you want encrypted connections (some servers, e.g. Google Talk,
|
||||
require it), you need <a href="http://www.gnu.org/software/gnutls/">GnuTLS</a> installed.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="outline-3">
|
||||
<h3 id="sec-6">Downloading</h3>
|
||||
|
||||
|
||||
<p>
|
||||
Download the <a href="#impatient">latest release</a> and unpack it in a suitable location. Add
|
||||
something like the following to your <code>.emacs</code> file:
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
;; adjust this path:
|
||||
(add-to-list 'load-path "/path/to/emacs-jabber")
|
||||
;; For 0.7.1 and below:
|
||||
(require 'jabber)
|
||||
;; For 0.7.90 and above:
|
||||
(require 'jabber-autoloads)
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
Either evaluate those lines, or restart Emacs.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="outline-3">
|
||||
<h3 id="sec-7">Using</h3>
|
||||
|
||||
|
||||
<p>
|
||||
See the <a href="manual-0.7.1/Basic-operation.html">Basic Operation</a> in the manual.
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="outline-2">
|
||||
<h2 id="sec-8">Reporting bugs</h2>
|
||||
|
||||
|
||||
<p>
|
||||
Bug reports can be sent either to the mailing list
|
||||
<a href="http://lists.sourceforge.net/lists/listinfo/emacs-jabber-general">emacs-jabber-general</a> or to the <a href="http://sourceforge.net/tracker/?group_id=88346&atid=586350">bug tracker</a>.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="outline-2">
|
||||
<h2 id="sec-9">Latest source</h2>
|
||||
|
||||
|
||||
<p>
|
||||
jabber.el releases are, unfortunately, less frequent than they would
|
||||
be in an ideal world. You can get the latest development version
|
||||
using various version control systems.
|
||||
</p>
|
||||
|
||||
<div class="outline-3">
|
||||
<h3 id="sec-10">CVS</h3>
|
||||
|
||||
|
||||
<p>
|
||||
See <a href="http://sourceforge.net/cvs/?group_id=88346">the Sourceforge CVS page</a>. In short, run the following command:
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
cvs -z3 -d:pserver:anonymous@emacs-jabber.cvs.sourceforge.net:/cvsroot/emacs-jabber co -P emacs-jabber
|
||||
</pre>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="outline-3">
|
||||
<h3 id="sec-11">GNU Arch</h3>
|
||||
|
||||
|
||||
<p>
|
||||
The GNU Arch mirror is no longer being updated.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="outline-3">
|
||||
<h3 id="sec-12">git</h3>
|
||||
|
||||
|
||||
<p>
|
||||
<pre>
|
||||
git-clone git://git.catap.ru/emacs-jabber.git
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="outline-2">
|
||||
<h2 id="sec-13">List of releases</h2>
|
||||
|
||||
|
||||
<p>
|
||||
The list of releases has been moved to a <a href="list-of-releases.html">separate page</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div id="postamble"><p class="date"> Date: 2009/02/19 1:31:21 AM</p>
|
||||
</div></body>
|
||||
</html>
|
||||
149
www/index.org
149
www/index.org
@ -1,149 +0,0 @@
|
||||
#+TITLE: jabber.el
|
||||
#+OPTIONS: num:nil author:nil skip:nil
|
||||
|
||||
#+BEGIN_HTML
|
||||
<a href="http://sourceforge.net">
|
||||
<img border="0" src="http://sourceforge.net/sflogo.php?group_id=88346&type=2" width="125" height="37" alt="SourceForge.net Logo" style="position: absolute; top: 0em; right: 0em;"></a>
|
||||
#+END_HTML
|
||||
|
||||
jabber.el is a Jabber client for Emacs.
|
||||
|
||||
[TABLE-OF-CONTENTS]
|
||||
|
||||
# <<impatient>>
|
||||
For the impatient:
|
||||
|
||||
- Latest release: [[http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=482983][0.7.1]] (31-Jan-2007)
|
||||
- Latest pretest release: [[http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=278300&release_id=662240][0.7.93]] (19-Feb-2009)
|
||||
- Full [[list-of-releases][list of releases]], including lists of features and changes
|
||||
|
||||
External resources:
|
||||
|
||||
- [[http://sourceforge.net/projects/emacs-jabber/][Sourceforge project page]], containing:
|
||||
- trackers for
|
||||
[[http://sourceforge.net/tracker/?atid=586350&group_id=88346&func=browse][bugs]],
|
||||
[[http://sourceforge.net/tracker/?atid=586353&group_id=88346&func=browse][feature requests]],
|
||||
[[http://sourceforge.net/tracker/?atid=586352&group_id=88346&func=browse][patches]] and
|
||||
[[http://sourceforge.net/tracker/?atid=586351&group_id=88346&func=browse][support requests]], open for anonymous posters
|
||||
- [[http://sourceforge.net/forum/?group_id=88346][forums]], open for anonymous posters
|
||||
- [[http://www.emacswiki.org/cgi-bin/wiki/JabberEl][the JabberEl page of EmacsWiki]]
|
||||
- Mailing lists (also available at [[http://gmane.net][Gmane]]):
|
||||
- [[http://lists.sourceforge.net/lists/listinfo/emacs-jabber-general][emacs-jabber-general]], for posts by humans (also [[http://dir.gmane.org/gmane.emacs.jabber.general][gmane.emacs.jabber.general]])
|
||||
- [[http://lists.sourceforge.net/lists/listinfo/emacs-jabber-commit][emacs-jabber-commit]], read-only mailing list of CVS commits (also [[http://dir.gmane.org/gmane.emacs.jabber.scm][gmane.emacs.jabber.scm]])
|
||||
- [[http://lists.sourceforge.net/lists/listinfo/emacs-jabber-bugs][emacs-jabber-bugs]], read-only mailing list of bug tracker activity (also [[http://dir.gmane.org/gmane.emacs.jabber.bugs][gmane.emacs.jabber.bugs]])
|
||||
- the Jabber chat room
|
||||
#+HTML: <a href="xmpp:jabber.el@conference.jabber.se?join">jabber.el@conference.jabber.se</a>
|
||||
- the [[file:manual-0.7.1/][manual for jabber.el 0.7.1]] (also included in the release files)
|
||||
|
||||
* What is Jabber?
|
||||
|
||||
Jabber is an open instant messaging (IM) system, also known as XMPP.
|
||||
It is described in [[http://www.xmpp.org/rfcs/][RFCs 3920-3923]] and a series of [[http://www.xmpp.org/extensions/][XEPs]] (XMPP Extension
|
||||
Proposals). That is, unlike legacy IM systems (such as ICQ or MSN
|
||||
Messenger), the protocol is published in the open, free for anyone to
|
||||
implement. Therefore you shouldn't be surprised that there is a
|
||||
Jabber client for Emacs, too. (If you are not of the Emacs
|
||||
persuasion, see this [[http://www.jabber.org/software/clients.shtml][list of Jabber clients]].)
|
||||
|
||||
Jabber is, like e-mail, a decentralised system. A Jabber identifier
|
||||
(JID) is of the form =username@server=, just like an e-mail address, and
|
||||
every Jabber user whose server is open to Internet connections can
|
||||
communicate with any other user. This is in stark contrast to the
|
||||
legacy "walled-garden" IM systems, where you need a separate account
|
||||
for each system to be able to communicate with its users. Note that
|
||||
the [[http://talk.google.com][Google Talk]] service is an XMPP service, so if you have a GMail
|
||||
account, you already have a JID ending with =@gmail.com=.
|
||||
|
||||
In Jabber, you have a "roster", a list of contacts. You can see
|
||||
which of them are online at the moment, and chat with them. (You can
|
||||
also send messages to an offline contact, and the message will be
|
||||
stored on the server for later delivery.) Jabber also supports
|
||||
IRC-style chat rooms.
|
||||
|
||||
* What is jabber.el?
|
||||
|
||||
jabber.el is a Jabber client for Emacs. It may seem strange to have a
|
||||
chat client in an editor, but consider that chatting is, after all,
|
||||
just a special case of text editing.
|
||||
|
||||
* Downloading and installing
|
||||
|
||||
** Prepackaged
|
||||
|
||||
Note that jabber.el is available as [[http://packages.debian.org/emacs-jabber][emacs-jabber in Debian]], and in
|
||||
[[http://packages.ubuntu.com/emacs-jabber][Ubuntu's "universe" section]].
|
||||
|
||||
** Dependencies
|
||||
|
||||
jabber.el requires either GNU Emacs 22, or GNU Emacs 21 combined with
|
||||
Gnus 5.10. You should get these from your distribution, or from the
|
||||
[[http://www.gnu.org/software/emacs/][Emacs]] and [[http://gnus.org][Gnus]] web sites.
|
||||
|
||||
However, if you want to connect to servers that use SRV records
|
||||
(e.g. Google Talk), it is recommended to use either No Gnus or Gnus
|
||||
5.13.
|
||||
|
||||
If you want encrypted connections (some servers, e.g. Google Talk,
|
||||
require it), you need [[http://www.gnu.org/software/gnutls/][GnuTLS]] installed.
|
||||
|
||||
** Downloading
|
||||
|
||||
Download the [[impatient][latest release]] and unpack it in a suitable location. Add
|
||||
something like the following to your =.emacs= file:
|
||||
|
||||
#+BEGIN_EXAMPLE
|
||||
;; adjust this path:
|
||||
(add-to-list 'load-path "/path/to/emacs-jabber")
|
||||
;; For 0.7.1 and below:
|
||||
(require 'jabber)
|
||||
;; For 0.7.90 and above:
|
||||
(require 'jabber-autoloads)
|
||||
#+END_EXAMPLE
|
||||
|
||||
Either evaluate those lines, or restart Emacs.
|
||||
|
||||
** Using
|
||||
|
||||
See the [[file:manual-0.7.1/Basic-operation.html][Basic Operation]] in the manual.
|
||||
|
||||
|
||||
|
||||
* Reporting bugs
|
||||
|
||||
Bug reports can be sent either to the mailing list
|
||||
[[http://lists.sourceforge.net/lists/listinfo/emacs-jabber-general][emacs-jabber-general]] or to the [[http://sourceforge.net/tracker/?group_id=88346&atid=586350][bug tracker]].
|
||||
|
||||
|
||||
* Latest source
|
||||
|
||||
jabber.el releases are, unfortunately, less frequent than they would
|
||||
be in an ideal world. You can get the latest development version
|
||||
using various version control systems.
|
||||
|
||||
** CVS
|
||||
|
||||
See [[http://sourceforge.net/cvs/?group_id=88346][the Sourceforge CVS page]]. In short, run the following command:
|
||||
|
||||
#+BEGIN_EXAMPLE
|
||||
cvs -z3 -d:pserver:anonymous@emacs-jabber.cvs.sourceforge.net:/cvsroot/emacs-jabber co -P emacs-jabber
|
||||
#+END_EXAMPLE
|
||||
|
||||
** GNU Arch
|
||||
|
||||
The GNU Arch mirror is no longer being updated.
|
||||
|
||||
** git
|
||||
|
||||
#+BEGIN_EXAMPLE
|
||||
git-clone git://git.catap.ru/emacs-jabber.git
|
||||
#+END_EXAMPLE
|
||||
|
||||
|
||||
* List of releases
|
||||
|
||||
The list of releases has been moved to a [[file:list-of-releases.org][separate page]].
|
||||
|
||||
# Local variables:
|
||||
# mode: org
|
||||
# eval: (progn (add-to-list 'org-link-types "xmpp") (org-make-link-regexps))
|
||||
# End:
|
||||
@ -1,200 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>List of releases - jabber.el</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
|
||||
<meta name="generator" content="Org-mode"/>
|
||||
<meta name="generated" content="2009/01/31 3:00:13 AM"/>
|
||||
<meta name="author" content=""/>
|
||||
<style type="text/css">
|
||||
html {
|
||||
font-family: Times, serif;
|
||||
font-size: 12pt;
|
||||
}
|
||||
.title { text-align: center; }
|
||||
.todo { color: red; }
|
||||
.done { color: green; }
|
||||
.timestamp { color: grey }
|
||||
.timestamp-kwd { color: CadetBlue }
|
||||
.tag { background-color:lightblue; font-weight:normal }
|
||||
.target { background-color: lavender; }
|
||||
pre {
|
||||
border: 1pt solid #AEBDCC;
|
||||
background-color: #F3F5F7;
|
||||
padding: 5pt;
|
||||
font-family: courier, monospace;
|
||||
}
|
||||
table { border-collapse: collapse; }
|
||||
td, th {
|
||||
vertical-align: top;
|
||||
<!--border: 1pt solid #ADB9CC;-->
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
<h1 class="title">List of releases - jabber.el</h1>
|
||||
<a href="index.html">Back to main page</a>
|
||||
|
||||
|
||||
|
||||
<h3>version 0.7.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=482983">31-Jan-2007</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>STARTTLS</li>
|
||||
<li>SRV records (requires No Gnus)</li>
|
||||
<li>Message composition buffer</li>
|
||||
<li>XMPP URIs are handled (see <a href="manual-0.7.1/XMPP-URIs.html">manual</a> for setup)</li>
|
||||
<li>Autoaway</li>
|
||||
<li>MUC improvements
|
||||
|
||||
<ul>
|
||||
<li>Don't display alerts for your own messages</li>
|
||||
<li>Presence changes are sent to MUC rooms too</li>
|
||||
<li>Check room features before joining</li>
|
||||
</ul>
|
||||
|
||||
<li>Avatars</li>
|
||||
|
||||
<li>File transfer</li>
|
||||
|
||||
<li>Sound files per contact for alerts</li>
|
||||
|
||||
<li>New function: jabber-send-directed-presence</li>
|
||||
|
||||
<li>Entity time supported (XEP-0090)</li>
|
||||
|
||||
<li>Last activity supported (XEP-0012)</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="manual-0.7.1/">manual</a>.</p>
|
||||
|
||||
|
||||
<h3>version 0.7 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=381160">27-Dec-2005</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>SSL connections possible</li>
|
||||
<li>Chat buffers rewritten</li>
|
||||
<li>MUC improved</li>
|
||||
<li>Global key bindings under C-x C-j</li>
|
||||
<li>Vcard viewer and editor</li>
|
||||
<li>Roster export</li>
|
||||
<li>Message events (JEP-0022)</li>
|
||||
<li>Easy way to define external notifiers</li>
|
||||
<li>Activity mode improved</li>
|
||||
<li>Roster display optimized</li>
|
||||
<li>Optionally use per-contact history files</li>
|
||||
<li>Jabber menu in menubar not enabled by default</li>
|
||||
<li>Flyspell in chat buffers</li>
|
||||
<li>Different time formats for instant and delayed messages</li>
|
||||
<li>Chat buffers in inactive windows are scrolled</li>
|
||||
<li>Roster is sorted by name also</li>
|
||||
<li>Countless bugfixes</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.7/">manual</a>.</p>
|
||||
|
||||
<h3>version 0.6.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=292750">27-Dec-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Now works with ejabberd</li>
|
||||
<li>Message history (Mathias Dahl)</li>
|
||||
<li>Backlogs</li>
|
||||
<li>Activity tracking on the mode line (Carl Henrik Lunde)</li>
|
||||
<li>Receive an alert when a specific person goes online (Mathias Dahl)</li>
|
||||
<li>Support for /me in chats (Nolan Eakins)</li>
|
||||
<li>Message alerts for current buffer can be disabled</li>
|
||||
<li>Basic moderation support in MUC</li>
|
||||
<li>MUC alerts are separated from ordinary message alerts</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the
|
||||
<a href="http://emacs-jabber.sourceforge.net/manual-0.6.1/">manual</a>,
|
||||
in which there is now a section on
|
||||
<a href="http://emacs-jabber.sourceforge.net/manual-0.6.1/Protocol-support.html">protocol support</a>.</p>
|
||||
|
||||
<h3>version 0.6 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=275815">17-Oct-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Chat buffers no longer use the minibuffer, making it easier to use
|
||||
ordinary editor commands and to pause writing halfway</li>
|
||||
<li>The roster display and the chat buffer prompts are now customizable</li>
|
||||
<li>The online status of the contact is displayed in the chat buffer
|
||||
(Emacs only)</li>
|
||||
<li>The connect function automatically sends presence after connecting</li>
|
||||
<li>The names of the roster buffer and chat buffers are customizable</li>
|
||||
<li>RET and C-k do what you would expect in the roster buffer</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.6/">manual</a>.</p>
|
||||
|
||||
<h3>version 0.5.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=236857">08-May-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Nicknames are accepted whenever a JID is asked for.</li>
|
||||
<li>Roster entry spacing is customizable (default is none)</li>
|
||||
<li>Bug fix regarding mixed-case JIDs</li>
|
||||
<li>Experimental code for receiving files - see the README</li>
|
||||
<li>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.5.1/">manual</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.5 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=228471">03-April-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Modular design; plugins easier to write</li>
|
||||
<li>Support for Ad-Hoc Commands and setting presence remotely</li>
|
||||
<li><a href="manual-0.5/">Browse documentation here</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.4.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=217577">16-February-2004</a></h3>
|
||||
<ul>
|
||||
<li> XEmacs support - basically works, needs testing and care.</li>
|
||||
<li> "Set status" menu fixed</li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.4 - 05-February-2004</h3>
|
||||
<ul>
|
||||
<li> SHA-1 password hashing</li>
|
||||
<li> customisation hooks</li>
|
||||
<li> browsing improved</li>
|
||||
<li> added service discovery</li>
|
||||
<li> added in-band registration</li>
|
||||
<li> added searching</li>
|
||||
<li> <a href="/emacs-jabber/jabber.html">new manual</a></li>
|
||||
</ul>
|
||||
<h3>version 0.3 - 21-April-2002</h3>
|
||||
<ul>
|
||||
<li> improved groupchat support (thanks to nimrod for tip)</li>
|
||||
<li> improved roster (buddy-list) display</li>
|
||||
<li> infoquery rewritten - great improvement</li>
|
||||
<li> improved minimal browsing support !</li>
|
||||
<li> added customizable faces</li>
|
||||
<li> added more customizable variables</li>
|
||||
<li> more (helpful) comments in code</li>
|
||||
<li> added explicit licensing (GPL, like emacs itself)</li>
|
||||
</ul><br>
|
||||
<h3>version 0.2 - 05-April-2002</h3>
|
||||
<ul>
|
||||
<li> added groupchat support !</li>
|
||||
<li> added minimal browsing support !</li>
|
||||
<li> fixed bug in chat mode</li>
|
||||
<li> abolished message mode (i only use chat mode anyway)</li>
|
||||
<li> fixed some problems with incoming xml</li>
|
||||
<li> added a pull-down menu</li>
|
||||
<li> added customizable variables</li>
|
||||
</ul><br>
|
||||
<br>
|
||||
<h3>features currently missing (TODO)</h3>
|
||||
<ul>
|
||||
<li> global keymaps</li>
|
||||
<li> logging (history)</li>
|
||||
<li> overall exception handling</li>
|
||||
<li> sanity checks (for incoming xml, and for myself :)</li>
|
||||
<li> clickable URLs in messages</li>
|
||||
<li> support for versions other than gnu-emacs-21 (older emacs, xemacs, jemacs)</li>
|
||||
<li> and more...</li>
|
||||
</ul><br>
|
||||
|
||||
<div id="postamble"><p class="date"> Date: 2009/01/31 3:00:13 AM</p>
|
||||
</div></body>
|
||||
</html>
|
||||
@ -1,167 +0,0 @@
|
||||
#+TITLE: List of releases - jabber.el
|
||||
#+OPTIONS: author:nil skip:nil
|
||||
|
||||
[[file:index.org][Back to main page]]
|
||||
|
||||
#+BEGIN_HTML
|
||||
<h3>version 0.7.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=482983">31-Jan-2007</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>STARTTLS</li>
|
||||
<li>SRV records (requires No Gnus)</li>
|
||||
<li>Message composition buffer</li>
|
||||
<li>XMPP URIs are handled (see <a href="manual-0.7.1/XMPP-URIs.html">manual</a> for setup)</li>
|
||||
<li>Autoaway</li>
|
||||
<li>MUC improvements
|
||||
|
||||
<ul>
|
||||
<li>Don't display alerts for your own messages</li>
|
||||
<li>Presence changes are sent to MUC rooms too</li>
|
||||
<li>Check room features before joining</li>
|
||||
</ul>
|
||||
|
||||
<li>Avatars</li>
|
||||
|
||||
<li>File transfer</li>
|
||||
|
||||
<li>Sound files per contact for alerts</li>
|
||||
|
||||
<li>New function: jabber-send-directed-presence</li>
|
||||
|
||||
<li>Entity time supported (XEP-0090)</li>
|
||||
|
||||
<li>Last activity supported (XEP-0012)</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="manual-0.7.1/">manual</a>.</p>
|
||||
|
||||
|
||||
<h3>version 0.7 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=381160">27-Dec-2005</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>SSL connections possible</li>
|
||||
<li>Chat buffers rewritten</li>
|
||||
<li>MUC improved</li>
|
||||
<li>Global key bindings under C-x C-j</li>
|
||||
<li>Vcard viewer and editor</li>
|
||||
<li>Roster export</li>
|
||||
<li>Message events (JEP-0022)</li>
|
||||
<li>Easy way to define external notifiers</li>
|
||||
<li>Activity mode improved</li>
|
||||
<li>Roster display optimized</li>
|
||||
<li>Optionally use per-contact history files</li>
|
||||
<li>Jabber menu in menubar not enabled by default</li>
|
||||
<li>Flyspell in chat buffers</li>
|
||||
<li>Different time formats for instant and delayed messages</li>
|
||||
<li>Chat buffers in inactive windows are scrolled</li>
|
||||
<li>Roster is sorted by name also</li>
|
||||
<li>Countless bugfixes</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.7/">manual</a>.</p>
|
||||
|
||||
<h3>version 0.6.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=292750">27-Dec-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Now works with ejabberd</li>
|
||||
<li>Message history (Mathias Dahl)</li>
|
||||
<li>Backlogs</li>
|
||||
<li>Activity tracking on the mode line (Carl Henrik Lunde)</li>
|
||||
<li>Receive an alert when a specific person goes online (Mathias Dahl)</li>
|
||||
<li>Support for /me in chats (Nolan Eakins)</li>
|
||||
<li>Message alerts for current buffer can be disabled</li>
|
||||
<li>Basic moderation support in MUC</li>
|
||||
<li>MUC alerts are separated from ordinary message alerts</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the
|
||||
<a href="http://emacs-jabber.sourceforge.net/manual-0.6.1/">manual</a>,
|
||||
in which there is now a section on
|
||||
<a href="http://emacs-jabber.sourceforge.net/manual-0.6.1/Protocol-support.html">protocol support</a>.</p>
|
||||
|
||||
<h3>version 0.6 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=275815">17-Oct-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Chat buffers no longer use the minibuffer, making it easier to use
|
||||
ordinary editor commands and to pause writing halfway</li>
|
||||
<li>The roster display and the chat buffer prompts are now customizable</li>
|
||||
<li>The online status of the contact is displayed in the chat buffer
|
||||
(Emacs only)</li>
|
||||
<li>The connect function automatically sends presence after connecting</li>
|
||||
<li>The names of the roster buffer and chat buffers are customizable</li>
|
||||
<li>RET and C-k do what you would expect in the roster buffer</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.6/">manual</a>.</p>
|
||||
|
||||
<h3>version 0.5.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=236857">08-May-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Nicknames are accepted whenever a JID is asked for.</li>
|
||||
<li>Roster entry spacing is customizable (default is none)</li>
|
||||
<li>Bug fix regarding mixed-case JIDs</li>
|
||||
<li>Experimental code for receiving files - see the README</li>
|
||||
<li>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.5.1/">manual</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.5 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=228471">03-April-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Modular design; plugins easier to write</li>
|
||||
<li>Support for Ad-Hoc Commands and setting presence remotely</li>
|
||||
<li><a href="manual-0.5/">Browse documentation here</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.4.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=217577">16-February-2004</a></h3>
|
||||
<ul>
|
||||
<li> XEmacs support - basically works, needs testing and care.</li>
|
||||
<li> "Set status" menu fixed</li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.4 - 05-February-2004</h3>
|
||||
<ul>
|
||||
<li> SHA-1 password hashing</li>
|
||||
<li> customisation hooks</li>
|
||||
<li> browsing improved</li>
|
||||
<li> added service discovery</li>
|
||||
<li> added in-band registration</li>
|
||||
<li> added searching</li>
|
||||
<li> <a href="/emacs-jabber/jabber.html">new manual</a></li>
|
||||
</ul>
|
||||
<h3>version 0.3 - 21-April-2002</h3>
|
||||
<ul>
|
||||
<li> improved groupchat support (thanks to nimrod for tip)</li>
|
||||
<li> improved roster (buddy-list) display</li>
|
||||
<li> infoquery rewritten - great improvement</li>
|
||||
<li> improved minimal browsing support !</li>
|
||||
<li> added customizable faces</li>
|
||||
<li> added more customizable variables</li>
|
||||
<li> more (helpful) comments in code</li>
|
||||
<li> added explicit licensing (GPL, like emacs itself)</li>
|
||||
</ul><br>
|
||||
<h3>version 0.2 - 05-April-2002</h3>
|
||||
<ul>
|
||||
<li> added groupchat support !</li>
|
||||
<li> added minimal browsing support !</li>
|
||||
<li> fixed bug in chat mode</li>
|
||||
<li> abolished message mode (i only use chat mode anyway)</li>
|
||||
<li> fixed some problems with incoming xml</li>
|
||||
<li> added a pull-down menu</li>
|
||||
<li> added customizable variables</li>
|
||||
</ul><br>
|
||||
<br>
|
||||
<h3>features currently missing (TODO)</h3>
|
||||
<ul>
|
||||
<li> global keymaps</li>
|
||||
<li> logging (history)</li>
|
||||
<li> overall exception handling</li>
|
||||
<li> sanity checks (for incoming xml, and for myself :)</li>
|
||||
<li> clickable URLs in messages</li>
|
||||
<li> support for versions other than gnu-emacs-21 (older emacs, xemacs, jemacs)</li>
|
||||
<li> and more...</li>
|
||||
</ul><br>
|
||||
#+END_HTML
|
||||
|
||||
# Local variables:
|
||||
# mode: org
|
||||
# End:
|
||||
@ -1,217 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<title>jabber.el</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>jabber.el</h1><br>
|
||||
<h2>a minimal jabber client for emacs</h2><br>
|
||||
<!-- here are some <a href="http://intellectronica.net/emacs-jabber/screenshots/">screenshots</a>.<br>
|
||||
<b>newsflash : jabber.el is no longer here. go to <a href="http://www.sf.net/projects/emacs-jabber">sourceforge</a> for the latest version</b>
|
||||
<br>-->
|
||||
<a href="http://sourceforge.net">
|
||||
<img border="0" src="http://sourceforge.net/sflogo.php?group_id=88346&type=2" width="125" height="37" alt="SourceForge.net Logo" style="position: absolute; top: 0em; right: 0em;"></a>
|
||||
|
||||
<p>see also <a href="http://www.emacswiki.org/cgi-bin/wiki/JabberEl">the
|
||||
JabberEl page of EmacsWiki</a>, <a href="http://lists.sourceforge.net/lists/listinfo/emacs-jabber-general">
|
||||
the mailing list</a> and <a href="xmpp:jabber.el@conference.jabber.se?join">the chat room</a> (it's <code>jabber.el@conference.jabber.se</code>, if your web browser is not configured for XMPP URIs).</p>
|
||||
|
||||
<p>if you use <a href="http://wiki.gnuarch.org">GNU Arch</a>, you can use the
|
||||
Arch mirror of the CVS repository. these commands get it for you:</p>
|
||||
|
||||
<pre>tla register-archive http://www.dtek.chalmers.se/~henoch/archive-2005
|
||||
tla get mange@freemail.hu--2005/emacs-jabber--cvs-head--0 emacs-jabber</pre>
|
||||
|
||||
<p>it's manually maintained, so bug Magnus (JID: <a href="xmpp:legoscia@jabber.cd.chalmers.se">legoscia@jabber.cd.chalmers.se</a>) if it
|
||||
doesn't seem up to date.</p>
|
||||
|
||||
<h3>version 0.7.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=482983">31-Jan-2007</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>STARTTLS</li>
|
||||
<li>SRV records (requires No Gnus)</li>
|
||||
<li>Message composition buffer</li>
|
||||
<li>XMPP URIs are handled (see <a href="manual-0.7.1/XMPP-URIs.html">manual</a> for setup)</li>
|
||||
<li>Autoaway</li>
|
||||
<li>MUC improvements
|
||||
|
||||
<ul>
|
||||
<li>Don't display alerts for your own messages</li>
|
||||
<li>Presence changes are sent to MUC rooms too</li>
|
||||
<li>Check room features before joining</li>
|
||||
</ul>
|
||||
|
||||
<li>Avatars</li>
|
||||
|
||||
<li>File transfer</li>
|
||||
|
||||
<li>Sound files per contact for alerts</li>
|
||||
|
||||
<li>New function: jabber-send-directed-presence</li>
|
||||
|
||||
<li>Entity time supported (XEP-0090)</li>
|
||||
|
||||
<li>Last activity supported (XEP-0012)</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="manual-0.7.1/">manual</a>.</p>
|
||||
|
||||
|
||||
<h3>version 0.7 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=381160">27-Dec-2005</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>SSL connections possible</li>
|
||||
<li>Chat buffers rewritten</li>
|
||||
<li>MUC improved</li>
|
||||
<li>Global key bindings under C-x C-j</li>
|
||||
<li>Vcard viewer and editor</li>
|
||||
<li>Roster export</li>
|
||||
<li>Message events (JEP-0022)</li>
|
||||
<li>Easy way to define external notifiers</li>
|
||||
<li>Activity mode improved</li>
|
||||
<li>Roster display optimized</li>
|
||||
<li>Optionally use per-contact history files</li>
|
||||
<li>Jabber menu in menubar not enabled by default</li>
|
||||
<li>Flyspell in chat buffers</li>
|
||||
<li>Different time formats for instant and delayed messages</li>
|
||||
<li>Chat buffers in inactive windows are scrolled</li>
|
||||
<li>Roster is sorted by name also</li>
|
||||
<li>Countless bugfixes</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.7/">manual</a>.</p>
|
||||
|
||||
<h3>version 0.6.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=292750">27-Dec-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Now works with ejabberd</li>
|
||||
<li>Message history (Mathias Dahl)</li>
|
||||
<li>Backlogs</li>
|
||||
<li>Activity tracking on the mode line (Carl Henrik Lunde)</li>
|
||||
<li>Receive an alert when a specific person goes online (Mathias Dahl)</li>
|
||||
<li>Support for /me in chats (Nolan Eakins)</li>
|
||||
<li>Message alerts for current buffer can be disabled</li>
|
||||
<li>Basic moderation support in MUC</li>
|
||||
<li>MUC alerts are separated from ordinary message alerts</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the
|
||||
<a href="http://emacs-jabber.sourceforge.net/manual-0.6.1/">manual</a>,
|
||||
in which there is now a section on
|
||||
<a href="http://emacs-jabber.sourceforge.net/manual-0.6.1/Protocol-support.html">protocol support</a>.</p>
|
||||
|
||||
<h3>version 0.6 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=275815">17-Oct-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Chat buffers no longer use the minibuffer, making it easier to use
|
||||
ordinary editor commands and to pause writing halfway</li>
|
||||
<li>The roster display and the chat buffer prompts are now customizable</li>
|
||||
<li>The online status of the contact is displayed in the chat buffer
|
||||
(Emacs only)</li>
|
||||
<li>The connect function automatically sends presence after connecting</li>
|
||||
<li>The names of the roster buffer and chat buffers are customizable</li>
|
||||
<li>RET and C-k do what you would expect in the roster buffer</li>
|
||||
</ul>
|
||||
|
||||
<p>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.6/">manual</a>.</p>
|
||||
|
||||
<h3>version 0.5.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=236857">08-May-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Nicknames are accepted whenever a JID is asked for.</li>
|
||||
<li>Roster entry spacing is customizable (default is none)</li>
|
||||
<li>Bug fix regarding mixed-case JIDs</li>
|
||||
<li>Experimental code for receiving files - see the README</li>
|
||||
<li>Read the <a href="http://emacs-jabber.sourceforge.net/manual-0.5.1/">manual</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.5 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=228471">03-April-2004</a></h3>
|
||||
|
||||
<ul>
|
||||
<li>Modular design; plugins easier to write</li>
|
||||
<li>Support for Ad-Hoc Commands and setting presence remotely</li>
|
||||
<li><a href="manual-0.5/">Browse documentation here</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.4.1 - <a href="http://sourceforge.net/project/showfiles.php?group_id=88346&package_id=92339&release_id=217577">16-February-2004</a></h3>
|
||||
<ul>
|
||||
<li> XEmacs support - basically works, needs testing and care.</li>
|
||||
<li> "Set status" menu fixed</li>
|
||||
</ul>
|
||||
|
||||
<h3>version 0.4 - 05-February-2004</h3>
|
||||
<ul>
|
||||
<li> SHA-1 password hashing</li>
|
||||
<li> customisation hooks</li>
|
||||
<li> browsing improved</li>
|
||||
<li> added service discovery</li>
|
||||
<li> added in-band registration</li>
|
||||
<li> added searching</li>
|
||||
<li> <a href="/emacs-jabber/jabber.html">new manual</a></li>
|
||||
</ul>
|
||||
<h3>version 0.3 - 21-April-2002</h3>
|
||||
<ul>
|
||||
<li> improved groupchat support (thanks to nimrod for tip)</li>
|
||||
<li> improved roster (buddy-list) display</li>
|
||||
<li> infoquery rewritten - great improvement</li>
|
||||
<li> improved minimal browsing support !</li>
|
||||
<li> added customizable faces</li>
|
||||
<li> added more customizable variables</li>
|
||||
<li> more (helpful) comments in code</li>
|
||||
<li> added explicit licensing (GPL, like emacs itself)</li>
|
||||
</ul><br>
|
||||
<h3>version 0.2 - 05-April-2002</h3>
|
||||
<ul>
|
||||
<li> added groupchat support !</li>
|
||||
<li> added minimal browsing support !</li>
|
||||
<li> fixed bug in chat mode</li>
|
||||
<li> abolished message mode (i only use chat mode anyway)</li>
|
||||
<li> fixed some problems with incoming xml</li>
|
||||
<li> added a pull-down menu</li>
|
||||
<li> added customizable variables</li>
|
||||
</ul><br>
|
||||
<br>
|
||||
<h3>features currently missing (TODO)</h3>
|
||||
<ul>
|
||||
<li> global keymaps</li>
|
||||
<li> logging (history)</li>
|
||||
<li> overall exception handling</li>
|
||||
<li> sanity checks (for incoming xml, and for myself :)</li>
|
||||
<li> clickable URLs in messages</li>
|
||||
<li> support for versions other than gnu-emacs-21 (older emacs, xemacs, jemacs)</li>
|
||||
<li> and more...</li>
|
||||
</ul><br>
|
||||
<br>
|
||||
<h3>installation</h3>
|
||||
<p>get the module <kbd>emacs-jabber</kbd> from <a href="http://sourceforge.net/cvs/?group_id=88346">Sourceforge CVS</a>.
|
||||
additionally, if you don't have Gnus 5.10 (<kbd>M-x gnus-version</kbd> will tell), you will need <kbd>hex-util.el</kbd>
|
||||
and <kbd>sha1-el.el</kbd> from <a href="http://quimby.gnus.org/cgi-bin/cvsweb.cgi/gnus/lisp/">Gnus CVS</a>.
|
||||
copy these to a directory in your emacs load path.</p>
|
||||
<p>in your .emacs file add the call <kbd>(require 'jabber)</kbd>. you can also use auto-load.</p>
|
||||
<p>set your account details with <kbd>M-x jabber-customize</kbd>. then, type <kbd>M-x jabber-connect</kbd> to connect,
|
||||
and <kbd>M-x jabber-send-presence</kbd> to send initial presence.</p>
|
||||
<p>please note that the current version is dependant on gnu-emacs-21 - it depends on xml.el (which you can download separately) and on some newer functions.</p>
|
||||
<h3>howto</h3>
|
||||
<p>as jabber.el is still very young, you'll have to be rather emacs-savvy to use it (or at least have the willingness to learn a little).<br></p>
|
||||
<p>to connect to the server, call <i>(<b>jabber-connect</b>)</i>.<br>
|
||||
call it from the pull-down menu or call interactively : [M-x jabber-connect RET] and enter the parameters from the minibuffer.</p>
|
||||
<p>after a successful connection, a new buffer should appear, named <b>*-jabber-*</b>. this buffer is your roster view. click any user with the mouse to start a 1-on-1 chat.</p>
|
||||
<p>alternatively, you can also call <i>(<b>jabber-chat-with</b> jid)</i>.<br>
|
||||
for example : (jabber-chat-with "object@magaf.org")<br>
|
||||
or [M-x jabber-chat-with RET]. in that case you will be asked for a jid. use the TAB key to complete a partial jid from the roster. (nice, eh?)</p>
|
||||
<p>to send a message, call <i>(<b>jabber-send-message</b> to body subject type)</i><br>
|
||||
for example : (jabber-send-message "object@magaf.org" "hi there" "" "") will appear as an instant message.<br>
|
||||
(jabber-send-message "object@magaf.org" "tom, you are the best" "the truth, nothing but the truth" "normal") too.<br>
|
||||
(jabber-send-message "object@magaf.org" "hya" "" "chat") will appear as a 1-on-1 chat<br>
|
||||
of course, this too can be called interactively : [M-x jabber-send-message RET] (with jid completion, like anywhere else).</p>
|
||||
<p>to change your status, call <i>(<b>jabber-send-presence</b> show status)</i>.<br>
|
||||
for example : (jabber-send-presence "" "Online") to appear online, or (jabber-send-presence "dnd" "copulating") to appear lucky.<br>
|
||||
needless to say, this can be called from the minibuffer too. do [M-x jabber-send-presence RET] and enjoy TAB completion from "", "away", "xa", "dnd" or "chat" for the first parameter (show).</p>
|
||||
<p>when a new chat message arrives, it is sent to the chat buffer ("*jabber-chat-:-user*"). if such a buffer does not exist it is created. in this buffer, all straight keystrokes are being captured for starting the reply command. to send a line, simply start typing...</p>
|
||||
<p>all messages are converted to 1-on-1 chats (simply because i find that more convinient).</p>
|
||||
<h3>contact</h3>
|
||||
<p>jabber.el is written by <a href="http://intellectronica.net/object/">Tom Berger</a> (Jabber: object@jabber.org.uk) and
|
||||
Magnus Henoch (Jabber: legoscia@jabber.cd.chalmers.se). feel free to contact us. you can also report bugs at the
|
||||
<a href="http://sourceforge.net/projects/emacs-jabber/">Sourceforge project page</a>.</p>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# In ~/.ssh/config, include the following
|
||||
#
|
||||
# Host emacs-jabber-www
|
||||
# HostName web.sourceforge.net
|
||||
# User SFUSERNAME,emacs-jabber
|
||||
|
||||
if [ ! -f index.org ]; then
|
||||
echo "Error: must be run in www checkout root" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rsync -v *.html emacs-jabber-www:htdocs/
|
||||
Loading…
x
Reference in New Issue
Block a user