updating org-mode, auctex, ...
This commit is contained in:
parent
2abd65c79f
commit
37fb8b74f2
31
tox/Makefile.am
Normal file
31
tox/Makefile.am
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
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
Normal file
98
tox/README
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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.
|
||||||
20
tox/configure.ac
Normal file
20
tox/configure.ac
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
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
|
||||||
497
tox/jabber-tox.el
Normal file
497
tox/jabber-tox.el
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
;; 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
Normal file
70
tox/main.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
3
tox/tox-marshal.list
Normal file
3
tox/tox-marshal.list
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
VOID:BOXED
|
||||||
|
VOID:UCHAR,UCHAR
|
||||||
|
VOID:STRING,STRING
|
||||||
20
tox/tox-object.xml
Normal file
20
tox/tox-object.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?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>
|
||||||
752
tox/tox-session.c
Normal file
752
tox/tox-session.c
Normal file
@ -0,0 +1,752 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
24
tox/tox-session.h
Normal file
24
tox/tox-session.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#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__ */
|
||||||
91
tox/tox-session.xml
Normal file
91
tox/tox-session.xml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?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
Normal file
110
tox/tox.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#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
Normal file
24
tox/tox.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#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__ */
|
||||||
3
tox/tox.service.in
Normal file
3
tox/tox.service.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[D-BUS Service]
|
||||||
|
Name=net.sourceforge.emacs-jabber.Tox
|
||||||
|
Exec=@libexecdir@/tox
|
||||||
305
www/index.html
Normal file
305
www/index.html
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
<!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
Normal file
149
www/index.org
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#+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:
|
||||||
200
www/list-of-releases.html
Normal file
200
www/list-of-releases.html
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<!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>
|
||||||
167
www/list-of-releases.org
Normal file
167
www/list-of-releases.org
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#+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:
|
||||||
217
www/oldindex.html
Normal file
217
www/oldindex.html
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
<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>
|
||||||
14
www/upload.sh
Normal file
14
www/upload.sh
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/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