summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2010-10-04 06:04:19 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2010-10-04 06:04:19 +0200
commitcabc0995c0e0964ecbef18470c6a483022879071 (patch)
treeea78fc03c11302f847b429fe417cdde412923613
parent2b99ed6fd9cf84c405f426ea0914b233b1f40ef1 (diff)
downloadephraim-cabc0995c0e0964ecbef18470c6a483022879071.tar
ephraim-cabc0995c0e0964ecbef18470c6a483022879071.zip
Major reorganisation of the core, still unfinished...
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/ephraim.app6
-rw-r--r--src/core/ephraim.erl167
-rw-r--r--src/core/ephraim_account.erl17
-rw-r--r--src/core/ephraim_account_event_proxy.erl27
-rw-r--r--src/core/ephraim_accounts.erl11
-rw-r--r--src/core/ephraim_config.erl3
-rw-r--r--src/core/ephraim_conn.erl96
-rw-r--r--src/core/ephraim_event.erl46
-rw-r--r--src/core/ephraim_gui.erl62
-rw-r--r--src/core/ephraim_roster.erl148
-rw-r--r--src/core/ephraim_roster_handler.erl45
-rw-r--r--src/core/ephraim_util.erl10
-rwxr-xr-xsrc/ephraim2
-rw-r--r--src/gui/CoreConnector.vala4
15 files changed, 301 insertions, 349 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9c536aa..9baaeee 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,12 +1,14 @@
erl_target(ephraim-core
ephraim.erl
+ ephraim_account.erl
+ ephraim_account_event_proxy.erl
+ ephraim_accounts.erl
ephraim_config.erl
ephraim_conn.erl
ephraim_conv.erl
- ephraim_event.erl
ephraim_gui.erl
ephraim_roster.erl
- ephraim_util.erl
+ ephraim_roster_handler.erl
OPTIONS
+debug_info
)
diff --git a/src/core/ephraim.app b/src/core/ephraim.app
new file mode 100644
index 0000000..c3a5a9f
--- /dev/null
+++ b/src/core/ephraim.app
@@ -0,0 +1,6 @@
+{application, ephraim,
+ [{vsn, "1"},
+ {modules, [ephraim, ephraim_config]},
+ {applications, [kernel, stdlib, exmpp]},
+ {mod, {ephraim,[]}}
+ ]}.
diff --git a/src/core/ephraim.erl b/src/core/ephraim.erl
index 61387a5..c0736c6 100644
--- a/src/core/ephraim.erl
+++ b/src/core/ephraim.erl
@@ -1,152 +1,27 @@
-module(ephraim).
--compile([debug_info, export_all]).
+-behaviour(application).
+-behaviour(supervisor).
+-export([start/2, stop/1]).
+-export([init/1]).
+-export([notify/1]).
--record(state, {
- conn :: pid(),
- roster :: pid(),
- event :: pid(),
- gui :: pid(),
- convs :: dict(),
- uis :: set()
- }).
+%-spec start() -> ok.
+start(_Type, _Args) ->
+ Result = supervisor:start_link(?MODULE, []),
+ ephraim_gui:start(),
+ Result.
--spec start() -> ok.
-start() ->
- spawn(?MODULE, init, []),
+%-spec stop() -> ok.
+stop(_State) ->
ok.
--spec stop() -> ok.
-stop() ->
- ephraim ! stop,
- ok.
-
--spec init() -> ok.
-init() ->
- register(ephraim, self()),
-
- ephraim_config:start_link(),
-
- GUI = spawn(ephraim_gui, init, []),
- Conn = spawn(ephraim_conn, init, []),
- Roster = spawn(ephraim_roster, init, []),
- Event = spawn(ephraim_event, init, []),
- loop(#state{conn=Conn,roster=Roster,event=Event,gui=GUI,convs=dict:new(),uis=sets:new()}),
- init:stop().
-
--spec get_conv(#state{},exmpp_jid:jid()) -> {#state{},pid()|undefined}.
-get_conv(State, JID) ->
- {Node, Domain, Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)),
-
- case Resource of
- undefined ->
- {State, undefined};
- _ ->
- Key = list_to_binary([Node, <<"@">>, Domain, <<"/">>, Resource]),
-
- case dict:find(Key, State#state.convs) of
- {ok, Conv} ->
- {State, Conv};
- error ->
- Conv = spawn(ephraim_conv, init, [Key]),
- Dict = dict:store(Key, Conv, State#state.convs),
- self() ! {ui_update, {new_conversation, Key}},
- {State#state{convs=Dict}, Conv}
- end
- end.
-
--spec get_alias(binary()) -> binary().
-get_alias(JID) ->
- ephraim ! {self(),get_alias,JID},
- receive
- {alias,JID,Alias} ->
- Alias
- end.
+-spec init(term()) -> ok.
+init(_Args) ->
+ {ok, {{rest_for_one, 1, 60},
+ [{event_man, {gen_event, start_link, [{local, ephraim_event_man}]}, permanent, 1000, worker, [gen_event]},
+ {config, {ephraim_config, start_link, []}, permanent, 1000, worker, [ephraim_config]},
+ {accounts, {ephraim_accounts, start_link, []}, permanent, infinity, supervisor, [ephraim_accounts]}]}}.
--spec loop(#state{}) -> ok.
-loop(State) ->
- receive
- stop ->
- ephraim_util:send_all_values(State#state.convs, stop),
- State#state.conn ! stop,
- State#state.roster ! stop,
- State#state.event ! stop,
- State#state.gui ! stop,
- ok;
-
- {register_ui, Pid} ->
- io:format("Registered UI ~p~n", [Pid]),
- UIs = State#state.uis,
- State2 = State#state{uis=sets:add_element(Pid,UIs)},
- loop(State2);
-
- {unregister_ui, Pid} ->
- io:format("Unregistered UI ~p~n", [Pid]),
- UIs = State#state.uis,
- State2 = State#state{uis=sets:del_element(Pid,UIs)},
- Size = sets:size(State2#state.uis),
- if Size =:= 0 ->
- self() ! stop;
- true ->
- ok
- end,
- loop(State2);
-
- {ui_update, Msg} ->
- ephraim_util:send_all(sets:to_list(State#state.uis), Msg),
- loop(State);
-
- {roster, Packet} ->
- State#state.roster ! Packet,
- loop(State);
-
- {receive_message, From, Packet} ->
- {State2, Conv} = get_conv(State, From),
- case Conv of
- undefined ->
- io:format("~p~n", [Packet]);
- _ ->
- Conv ! {receive_message, Packet}
- end,
- loop(State2);
-
- {send_message, To, Type, Message} ->
- {State2, Conv} = get_conv(State, To),
- case Conv of
- undefined ->
- io:format("ephraim: send_message: ~p~n", [Message]);
- _ ->
- Conv ! {send_message, Type, Message}
- end,
- loop(State2);
-
- {start_conversation, To} ->
- {State2, _Conv} = get_conv(State, To),
- loop(State2);
-
- {send_packet, Packet} ->
- State#state.conn ! {send_packet, Packet},
- loop(State);
-
- {receive_event, From, Packet} ->
- State#state.event ! {receive_event, From, Packet},
- loop(State);
-
- {receive_iq, From, IQ} ->
- case IQ of
- {iq, response, result, _, 'jabber:iq:roster', Payload, _, _, 'jabber:client'} ->
- State#state.roster ! {roster_iq, Payload};
- {iq, response, result, _, 'vcard-temp', Payload, _, _, 'jabber:client'} ->
- State#state.roster ! {vcard_iq, From, Payload};
- _ ->
- ok %io:format("ephraim: IQ from ~p: ~p~n", [From, IQ])
- end,
- loop(State);
-
- {Pid, get_alias, JID} ->
- State#state.roster ! {Pid,get_alias,JID},
- loop(State);
-
- Msg ->
- io:format("ephraim: ~p~n", [Msg]),
- loop(State)
- end.
+-spec notify(term()) -> ok.
+notify(Event) ->
+ gen_event:notify(ephraim_event_man, Event).
diff --git a/src/core/ephraim_account.erl b/src/core/ephraim_account.erl
new file mode 100644
index 0000000..d79e118
--- /dev/null
+++ b/src/core/ephraim_account.erl
@@ -0,0 +1,17 @@
+-module(ephraim_account).
+-behaviour(supervisor).
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ {ok, Pid} = supervisor:start_link(?MODULE, []),
+
+ {ok, EventManager} = supervisor:start_child(Pid, {event_man, {gen_event, start_link, []}, permanent, 1000, worker, [gen_event]}),
+ ephraim_account_event_proxy:start(EventManager),
+
+ {ok, Connection} = supervisor:start_child(Pid, {connection, {ephraim_conn, start_link, [EventManager]}, permanent, 10000, worker, [ephraim_conn]}),
+ {ok, _} = supervisor:start_child(Pid, {roster, {ephraim_roster, start_link, [EventManager, Connection]}, permanent, 1000, worker, [ephraim_roster]}),
+ {ok, Pid}.
+
+init(_Args) ->
+ {ok, {{one_for_all, 0, 1}, []}}.
diff --git a/src/core/ephraim_account_event_proxy.erl b/src/core/ephraim_account_event_proxy.erl
new file mode 100644
index 0000000..d9cf94e
--- /dev/null
+++ b/src/core/ephraim_account_event_proxy.erl
@@ -0,0 +1,27 @@
+-module(ephraim_account_event_proxy).
+-behaviour(gen_event).
+
+-export([start/1]).
+-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).
+
+start(EventManager) ->
+ gen_event:add_handler(EventManager, ?MODULE, foo_account).
+
+init(Account) ->
+ {ok, Account}.
+
+handle_event({view_update, Event}, Account) ->
+ ephraim:notify({view_update, {account, Account, Event}}),
+ {ok, Account};
+
+handle_event(_Event, Account) ->
+ {ok, Account}.
+
+handle_call(_Msg, Account) ->
+ {noreply, Account}.
+handle_info(_Msg, Account) ->
+ {ok, Account}.
+terminate(_Reason, _Account) ->
+ ok.
+code_change(_OldVersion, Account, _Extra) ->
+ {ok, Account}.
diff --git a/src/core/ephraim_accounts.erl b/src/core/ephraim_accounts.erl
new file mode 100644
index 0000000..a35c486
--- /dev/null
+++ b/src/core/ephraim_accounts.erl
@@ -0,0 +1,11 @@
+-module(ephraim_accounts).
+-behaviour(supervisor).
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+init(_Args) ->
+ {ok, {{one_for_one, 1, 60},
+ [{account, {ephraim_account, start_link, []}, permanent, infinity, supervisor, [ephraim_account]}]}}.
diff --git a/src/core/ephraim_config.erl b/src/core/ephraim_config.erl
index 6c556c2..dd9e64d 100644
--- a/src/core/ephraim_config.erl
+++ b/src/core/ephraim_config.erl
@@ -11,6 +11,8 @@ start_link() ->
-spec init(term()) -> {ok, dict()}.
init(_Args) ->
+ process_flag(trap_exit, true),
+
{ok, Terms} = file:consult(config_path() ++ "/ephraim.cfg"),
Config = dict:from_list(lists:map(fun(Term) -> {element(1, Term), Term} end, Terms)),
@@ -40,7 +42,6 @@ get(Key) ->
-spec handle_call(term(), {pid(), term()}, dict()) -> {reply, tuple() | error, dict()}.
handle_call({get, Key}, _From, Config) ->
- ephraim_config ! {self(), get, Key},
case dict:find(Key, Config) of
{ok, Value} ->
{reply, Value, Config};
diff --git a/src/core/ephraim_conn.erl b/src/core/ephraim_conn.erl
index 1ac5236..f4e14e0 100644
--- a/src/core/ephraim_conn.erl
+++ b/src/core/ephraim_conn.erl
@@ -1,15 +1,23 @@
-module(ephraim_conn).
--compile([debug_info, export_all]).
-include_lib("exmpp/include/exmpp_client.hrl").
-include_lib("exmpp/include/exmpp_xml.hrl").
+-behaviour(gen_server).
+-export([start_link/1]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+-export([send_packet/2]).
-record(conn_state, {
- session :: any()
+ event_manager :: pid(),
+ session :: any()
}).
--spec init() -> ok.
-init() ->
- application:start(exmpp),
+start_link(EventManager) ->
+ gen_server:start_link(?MODULE, EventManager, []).
+
+%-spec init() -> ok.
+init(EventManager) ->
+ process_flag(trap_exit, true),
+
Session = exmpp_session:start(),
{jid, JID} = ephraim_config:get(jid),
@@ -20,55 +28,41 @@ init() ->
io:format("Connecting...~n"),
exmpp_session:connect_TCP(Session, Server, Port),
io:format("Connected.~n"),
- session(#conn_state{session=Session}).
+ session(Session),
+ {ok, #conn_state{event_manager=EventManager,session=Session}}.
--spec session(#conn_state{}) -> ok.
-session(State) ->
+-spec session(any()) -> ok.
+session(Session) ->
io:format("Logging in...~n"),
- exmpp_session:login(State#conn_state.session),
+ exmpp_session:login(Session),
io:format("Getting profile...~n"),
- exmpp_session:send_packet(State#conn_state.session, exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'})),
+ exmpp_session:send_packet(Session, exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'})),
io:format("Getting roster...~n"),
- exmpp_session:send_packet(State#conn_state.session, exmpp_client_roster:get_roster("foo")),
+ exmpp_session:send_packet(Session, exmpp_client_roster:get_roster("foo")),
io:format("Setting presence...~n"),
- exmpp_session:send_packet(State#conn_state.session, exmpp_presence:set_status(exmpp_presence:available(), "Foo/Test\\Bar")),
- io:format("Ok.~n"),
- loop(State).
+ exmpp_session:send_packet(Session, exmpp_presence:set_status(exmpp_presence:available(), "Foo/Test\\Bar")),
+ io:format("Ok.~n").
+
+send_packet(Connection, Packet) ->
+ gen_server:cast(Connection, {send_packet, Packet}).
+
+handle_call(_Msg, _From, State) ->
+ {noreply, State}.
+
+handle_cast({send_packet, Packet}, State) ->
+ exmpp_session:send_packet(State#conn_state.session, Packet),
+ {noreply, State}.
+
+handle_info(Msg = #received_packet{}, State) ->
+ gen_event:notify(State#conn_state.event_manager, {received_packet,Msg}),
+ {noreply, State};
+handle_info(Msg, State) ->
+ io:format("ephraim_conn: ~p~n", [Msg]),
+ {noreply, State}.
+
+terminate(_Reason, State) ->
+ io:format("Disconnecting...~n"),
+ exmpp_session:stop(State#conn_state.session).
--spec loop(#conn_state{}) -> ok.
-loop(State) ->
- receive
- stop ->
- exmpp_session:stop(State#conn_state.session);
-
- #received_packet{packet_type=presence, raw_packet=Packet} ->
- %io:format("Received packet ~p~n", [Packet]),
- ephraim ! {roster, {presence, Packet}},
- loop(State);
-
- #received_packet{packet_type=message, raw_packet=Packet} ->
- %io:format("Received packet ~p~n", [Packet]),
- From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
- HasElement = exmpp_xml:has_element(Packet,'http://jabber.org/protocol/pubsub#event',event),
- if HasElement ->
- ephraim ! {receive_event, From, Packet};
- true ->
- ephraim ! {receive_message, From, Packet}
- end,
- loop(State);
-
- #received_packet{packet_type=iq, raw_packet=Packet} ->
- %io:format("Received packet ~p~n", [Packet]),
- From = exmpp_stanza:get_sender(Packet),
- IQ = exmpp_iq:xmlel_to_iq(Packet),
- ephraim ! {receive_iq, From, IQ},
- loop(State);
-
- {send_packet, Packet} ->
- exmpp_session:send_packet(State#conn_state.session, Packet),
- loop(State);
-
- Msg ->
- io:format("ephraim_conn: ~p~n", [Msg]),
- loop(State)
- end.
+code_change(_OldVersion, State, _Extra) ->
+ {ok, State}.
diff --git a/src/core/ephraim_event.erl b/src/core/ephraim_event.erl
deleted file mode 100644
index d8778e4..0000000
--- a/src/core/ephraim_event.erl
+++ /dev/null
@@ -1,46 +0,0 @@
--module(ephraim_event).
--compile([debug_info, export_all]).
--include_lib("exmpp/include/exmpp.hrl").
-
--spec init() -> ok.
-init() ->
- loop().
-
--spec handleEvent(binary(), #xmlel{}) -> ok.
-handleEvent(From, Item) ->
- % HasAvatarData = exmpp_xml:has_element(Item, 'urn:xmpp:avatar:data', data),
- % HasAvatarMetaData = exmpp_xml:has_element(Item, 'urn:xmpp:avatar:metadata', metadata),
- if %HasAvatarData ->
- % Element = exmpp_xml:get_element(Item, 'urn:xmpp:avatar:data', data),
- % Data = base64:decode(exmpp_xml:get_cdata_from_list(Element#xmlel.children)),
- % ephraim ! {roster, {avatar, From, Data}},
- % ok;
- %HasAvatarMetaData ->
- % ok;
- true ->
- io:format("Received unhandled event from ~p:~n~p~n", [From, Item])
- end.
-
--spec handleEvents(binary(), [#xmlel{}]) -> ok.
-handleEvents(_, []) ->
- ok;
-handleEvents(From, [Item|Rest]) ->
- handleEvent(From, Item),
- handleEvents(From, Rest).
-
--spec loop() -> ok.
-loop() ->
- receive
- stop ->
- ok;
-
- {receive_event, From, Packet} ->
- Event = exmpp_xml:get_element(Packet, 'http://jabber.org/protocol/pubsub#event', event),
- Items = exmpp_xml:get_element(Event, 'http://jabber.org/protocol/pubsub#event', items),
- handleEvents(From, Items#xmlel.children),
- loop();
-
- Msg ->
- io:format("ephraim_event: ~p~n", [Msg]),
- loop()
- end.
diff --git a/src/core/ephraim_gui.erl b/src/core/ephraim_gui.erl
index b049da3..92ab521 100644
--- a/src/core/ephraim_gui.erl
+++ b/src/core/ephraim_gui.erl
@@ -1,29 +1,43 @@
-module(ephraim_gui).
--compile([debug_info, export_all]).
+-behaviour(gen_event).
+-export([start/0, stop/0]).
+-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).
--spec init() -> ok.
-init() ->
- %{jid,JID} = ephraim_config:get(jid),
+start() ->
+ gen_event:add_handler(ephraim_event_man, ?MODULE, []).
+stop() ->
+ gen_event:delete_handler(ephraim_event_man, ?MODULE, []).
+
+-spec init(term()) -> ok.
+init(_Args) ->
Port = open_port({spawn_executable, "ephraim-gtk"}, [binary, nouse_stdio, {packet, 4}]),
- ephraim ! {register_ui, self()},
- loop(Port),
- ephraim ! {unregister_ui, self()}.
+ {ok, Port}.
+
+handle_event({view_update, Msg}, Port) ->
+ Port ! {self(), {command, term_to_binary(Msg)}},
+ {ok, Port};
+
+handle_event(_Event, Port) ->
+ {ok, Port}.
--spec loop(port()) -> ok.
-loop(Port) ->
- receive
+handle_call(_Msg, Port) ->
+ {noreply, Port}.
+
+handle_info({Port, {data, Data}}, Port) ->
+ Msg = binary_to_term(Data),
+ case Msg of
stop ->
- ok;
- {Port, {data, Data}} ->
- Msg = binary_to_term(Data),
- case Msg of
- stop ->
- ok;
- _ ->
- ephraim ! Msg,
- loop(Port)
- end;
- Msg ->
- Port ! {self(), {command, term_to_binary(Msg)}},
- loop(Port)
- end.
+ init:stop(),
+ remove_handler;
+ _ ->
+ ephraim:notify({view_event, Msg}),
+ {ok, Port}
+ end;
+
+handle_info(_Msg, Port) ->
+ {ok, Port}.
+
+terminate(_Reason, _Port) ->
+ ok.
+code_change(_OldVersion, Port, _Extra) ->
+ {ok, Port}.
diff --git a/src/core/ephraim_roster.erl b/src/core/ephraim_roster.erl
index 502497f..f111f38 100644
--- a/src/core/ephraim_roster.erl
+++ b/src/core/ephraim_roster.erl
@@ -1,9 +1,15 @@
-module(ephraim_roster).
--compile([debug_info, export_all]).
-include_lib("exmpp/include/exmpp.hrl").
+-behaviour(gen_server).
--record(roster, {
- entries :: dict()
+-export([start_link/2]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+-export([presence/2, roster_iq/2, vcard_iq/3]).
+
+-record(roster_state, {
+ event_manager :: pid(),
+ connection :: pid(),
+ entries :: dict()
}).
-record(avatar, {
@@ -25,16 +31,23 @@
status :: binary()
}).
--spec init() -> ok.
-init() ->
- loop(#roster{entries=dict:new()}).
--spec updateResource(#roster{}, binary(), integer(), atom(), atom(), binary()) -> #roster{}.
+start_link(EventManager, Connection) ->
+ gen_server:start_link(?MODULE, {EventManager, Connection}, []).
+
+%-spec init() -> ok.
+init({EventManager, Connection}) ->
+ process_flag(trap_exit, true),
+
+ ephraim_roster_handler:start(EventManager, self()),
+ {ok, #roster_state{event_manager=EventManager,connection=Connection,entries=dict:new()}}.
+
+-spec updateResource(#roster_state{}, binary(), integer(), atom(), atom(), binary()) -> #roster_state{}.
updateResource(Roster, JID, Priority, Type, Show, Status) ->
{Node, Domain, Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)),
BareJID = list_to_binary([Node, <<"@">>, Domain]),
- RosterEntry = case dict:find(BareJID, Roster#roster.entries) of
+ RosterEntry = case dict:find(BareJID, Roster#roster_state.entries) of
{ok, Entry} ->
Entry;
error ->
@@ -52,28 +65,28 @@ updateResource(Roster, JID, Priority, Type, Show, Status) ->
end,
NewEntry = RosterEntry#roster_entry{resources=Resources},
- Entries = dict:store(BareJID, NewEntry, Roster#roster.entries),
- uiUpdate(BareJID, NewEntry),
+ Entries = dict:store(BareJID, NewEntry, Roster#roster_state.entries),
+ viewUpdate(Roster, BareJID, NewEntry),
- Roster#roster{entries=Entries}.
+ Roster#roster_state{entries=Entries}.
--spec updateRosterEntry(#roster{}, binary(), binary(), atom(), set()) -> #roster{}.
+-spec updateRosterEntry(#roster_state{}, binary(), binary(), atom(), set()) -> #roster_state{}.
updateRosterEntry(Roster, JID, Name, Subscription, Groups) ->
- OldEntry = case dict:find(JID, Roster#roster.entries) of
+ OldEntry = case dict:find(JID, Roster#roster_state.entries) of
{ok, Entry} ->
Entry;
error ->
#roster_entry{}
end,
NewEntry = OldEntry#roster_entry{subscription=Subscription,name=Name,groups=Groups},
- Entries = dict:store(JID, NewEntry, Roster#roster.entries),
- uiUpdate(JID, NewEntry),
+ Entries = dict:store(JID, NewEntry, Roster#roster_state.entries),
+ viewUpdate(Roster, JID, NewEntry),
- Roster#roster{entries=Entries}.
+ Roster#roster_state{entries=Entries}.
--spec updateVCard(#roster{}, binary(), dict()) -> #roster{}.
+-spec updateVCard(#roster_state{}, binary(), dict()) -> #roster_state{}.
updateVCard(Roster, JID, VCard) ->
- OldEntry = case dict:find(JID, Roster#roster.entries) of
+ OldEntry = case dict:find(JID, Roster#roster_state.entries) of
{ok, Entry} ->
Entry;
error ->
@@ -89,19 +102,19 @@ updateVCard(Roster, JID, VCard) ->
NewEntry = OldEntry#roster_entry{vcard=VCard,avatar=Avatar},
- Entries = dict:store(JID, NewEntry, Roster#roster.entries),
- uiUpdate(JID, NewEntry),
+ Entries = dict:store(JID, NewEntry, Roster#roster_state.entries),
+ viewUpdate(Roster, JID, NewEntry),
- Roster#roster{entries=Entries}.
+ Roster#roster_state{entries=Entries}.
--spec uiUpdate(binary(), #roster_entry{}) -> ok.
-uiUpdate(JID, RosterEntry) ->
+-spec viewUpdate(#roster_state{}, binary(), #roster_entry{}) -> ok.
+viewUpdate(State, JID, RosterEntry) ->
if RosterEntry#roster_entry.subscription =:= undefined ->
ok;
true ->
- ephraim ! {ui_update, {roster_update, JID, RosterEntry#roster_entry.name, RosterEntry#roster_entry.subscription,
- sets:to_list(RosterEntry#roster_entry.groups), dict:to_list(RosterEntry#roster_entry.resources),
- RosterEntry#roster_entry.avatar}},
+ gen_event:notify(State#roster_state.event_manager, {view_update, {roster_update, JID, RosterEntry#roster_entry.name, RosterEntry#roster_entry.subscription,
+ sets:to_list(RosterEntry#roster_entry.groups), dict:to_list(RosterEntry#roster_entry.resources),
+ RosterEntry#roster_entry.avatar}}),
ok
end.
@@ -117,18 +130,18 @@ getGroups(Groups, [#xmlel{ns='jabber:iq:roster',name=group,children=[#xmlcdata{c
getGroups(Groups, [_|Rest]) ->
getGroups(Groups, Rest).
--spec handleRosterIQ(#roster{}, #xmlel{}) -> #roster{}.
+-spec handleRosterIQ(#roster_state{}, #xmlel{}) -> #roster_state{}.
handleRosterIQ(Roster, Item) ->
JID = exmpp_xml:get_attribute(Item, jid, undefined),
Name = exmpp_xml:get_attribute(Item, name, undefined),
Groups = getGroups(Item#xmlel.children),
Subscription = binary_to_atom(exmpp_xml:get_attribute(Item, subscription, undefined), utf8),
- ephraim ! {send_packet, exmpp_stanza:set_recipient(exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'}), JID)},
+ ephraim_conn:send_packet(Roster#roster_state.connection, exmpp_stanza:set_recipient(exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'}), JID)),
updateRosterEntry(Roster, JID, Name, Subscription, Groups).
--spec handleRosterIQs(#roster{}, [#xmlel{}]) -> #roster{}.
+-spec handleRosterIQs(#roster_state{}, [#xmlel{}]) -> #roster_state{}.
handleRosterIQs(Roster, []) ->
Roster;
@@ -161,12 +174,12 @@ handleVCardIQs(VCard, [Item|Rest]) ->
VCard2 = handleVCardIQ(VCard, Item),
handleVCardIQs(VCard2, Rest).
--spec get_alias(#roster{}, binary()) -> binary().
+-spec get_alias(#roster_state{}, binary()) -> binary().
get_alias(Roster, JID) ->
{Node, Domain, _Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)),
BareJID = list_to_binary([Node, <<"@">>, Domain]),
- case dict:find(BareJID, Roster#roster.entries) of
+ case dict:find(BareJID, Roster#roster_state.entries) of
{ok, Entry} ->
case Entry#roster_entry.name of
undefined ->
@@ -183,38 +196,41 @@ get_alias(Roster, JID) ->
Node
end.
--spec loop(#roster{}) -> ok.
-loop(Roster) ->
- receive
- stop ->
- ok;
-
- {presence, Packet} ->
- %io:format("ephraim_roster: Presence: ~p~n", [Packet]),
- From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
-
- Priority = exmpp_presence:get_priority(Packet),
- Type = exmpp_presence:get_type(Packet),
- Show = exmpp_presence:get_show(Packet),
- Status = exmpp_presence:get_status(Packet),
-
- Roster2 = updateResource(Roster, From, Priority, Type, Show, Status),
- loop(Roster2);
-
- {roster_iq, Payload} ->
- Roster2 = handleRosterIQs(Roster, Payload#xmlel.children),
- loop(Roster2);
-
- {vcard_iq, From, Payload} ->
- Dict = handleVCardIQs(dict:new(), Payload#xmlel.children),
- Roster2 = updateVCard(Roster, From, Dict),
- loop(Roster2);
-
- {Pid, get_alias, JID} ->
- Pid ! {alias,JID,get_alias(Roster, JID)},
- loop(Roster);
-
- Msg ->
- io:format("ephraim_roster: ~p~n", [Msg]),
- loop(Roster)
- end.
+presence(Roster, Packet) ->
+ gen_server:cast(Roster, {presence, Packet}).
+roster_iq(Roster, Payload) ->
+ gen_server:cast(Roster, {roster_iq, Payload}).
+vcard_iq(Roster, From, Payload) ->
+ gen_server:cast(Roster, {vcard_iq, From, Payload}).
+
+handle_call(_Msg, _From, State) ->
+ {noreply, State}.
+
+handle_cast({presence, Packet}, State) ->
+ %io:format("ephraim_roster: Presence: ~p~n", [Packet]),
+ From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
+
+ Priority = exmpp_presence:get_priority(Packet),
+ Type = exmpp_presence:get_type(Packet),
+ Show = exmpp_presence:get_show(Packet),
+ Status = exmpp_presence:get_status(Packet),
+
+ State2 = updateResource(State, From, Priority, Type, Show, Status),
+ {noreply, State2};
+
+handle_cast({roster_iq, Payload}, State) ->
+ State2 = handleRosterIQs(State, Payload#xmlel.children),
+ {noreply, State2};
+
+handle_cast({vcard_iq, From, Payload}, State) ->
+ Dict = handleVCardIQs(dict:new(), Payload#xmlel.children),
+ State2 = updateVCard(State, From, Dict),
+ {noreply, State2}.
+
+handle_info(_Msg, State) ->
+ {noreply, State}.
+terminate(_Reason, State) ->
+ ephraim_roster_handler:stop(State#roster_state.event_manager),
+ ok.
+code_change(_OldVersion, State, _Extra) ->
+ {ok, State}.
diff --git a/src/core/ephraim_roster_handler.erl b/src/core/ephraim_roster_handler.erl
new file mode 100644
index 0000000..fa7c1c7
--- /dev/null
+++ b/src/core/ephraim_roster_handler.erl
@@ -0,0 +1,45 @@
+-module(ephraim_roster_handler).
+-include_lib("exmpp/include/exmpp_client.hrl").
+-behaviour(gen_event).
+
+-export([start/2, stop/1]).
+-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).
+
+start(EventManager, Roster) ->
+ gen_event:add_handler(EventManager, ?MODULE, Roster).
+stop(EventManager) ->
+ gen_event:delete_handler(EventManager, ?MODULE, []).
+
+init(Roster) ->
+ {ok, Roster}.
+
+handle_event({received_packet, #received_packet{packet_type=presence, raw_packet=Packet}}, Roster) ->
+ %io:format("Received packet ~p~n", [Packet]),
+ ephraim_roster:presence(Roster, Packet),
+ {ok, Roster};
+
+handle_event({received_packet, #received_packet{packet_type=iq, raw_packet=Packet}}, Roster) ->
+ %io:format("Received packet ~p~n", [Packet]),
+ From = exmpp_stanza:get_sender(Packet),
+ IQ = exmpp_iq:xmlel_to_iq(Packet),
+ case IQ of
+ {iq, response, result, _, 'jabber:iq:roster', Payload, _, _, 'jabber:client'} ->
+ ephraim_roster:roster_iq(Roster, Payload);
+ {iq, response, result, _, 'vcard-temp', Payload, _, _, 'jabber:client'} ->
+ ephraim_roster:vcard_iq(Roster, From, Payload);
+ _ ->
+ ok %io:format("ephraim: IQ from ~p: ~p~n", [From, IQ])
+ end,
+ {ok, Roster};
+
+handle_event(_Event, Roster) ->
+ {ok, Roster}.
+
+handle_call(_Msg, Roster) ->
+ {noreply, Roster}.
+handle_info(_Msg, Roster) ->
+ {ok, Roster}.
+terminate(_Reason, _Roster) ->
+ ok.
+code_change(_OldVersion, Roster, _Extra) ->
+ {ok, Roster}.
diff --git a/src/core/ephraim_util.erl b/src/core/ephraim_util.erl
deleted file mode 100644
index 73cb7fc..0000000
--- a/src/core/ephraim_util.erl
+++ /dev/null
@@ -1,10 +0,0 @@
--module(ephraim_util).
--compile([debug_info, export_all]).
-
--spec send_all([term()], term()) -> term().
-send_all(Dest, Message) ->
- lists:foldr(fun erlang:send/2, Message, Dest).
-
--spec send_all_values(dict(), term()) -> term().
-send_all_values(Dest, Message) ->
- dict:fold(fun(_,Value,Msg) -> Value ! Msg end, Message, Dest).
diff --git a/src/ephraim b/src/ephraim
index ce30386..472ffce 100755
--- a/src/ephraim
+++ b/src/ephraim
@@ -1,3 +1,3 @@
#!/bin/sh
-erl -pa core -run ephraim
+erl -pa core -eval 'application:start(exmpp).' -eval 'application:start(ephraim).'
diff --git a/src/gui/CoreConnector.vala b/src/gui/CoreConnector.vala
index d5f0ecc..4c853ff 100644
--- a/src/gui/CoreConnector.vala
+++ b/src/gui/CoreConnector.vala
@@ -7,8 +7,8 @@ public class CoreConnector {
static Eva.Term match_chat_message;
static construct {
- match_gui_init = Eva.parse("{gui_init,Terms}");
- match_roster_update = Eva.parse("{roster_update,JID,Name,Subscription,Groups,Resources,Avatar}");
+ match_gui_init = Eva.parse("{global,{gui_init,Terms}}");
+ match_roster_update = Eva.parse("{account,Account,{roster_update,JID,Name,Subscription,Groups,Resources,Avatar}}");
match_resource_entry = Eva.parse("{Name,{resource_entry,Priority,Show,Status}}");
match_avatar = Eva.parse("{avatar,Data}");
match_new_conversation = Eva.parse("{new_conversation,JID}");