summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
m---------cmake/erlang0
-rw-r--r--cmake/erlang/ErlangTarget.cmake35
-rw-r--r--cmake/erlang/FindErlang.cmake6
-rw-r--r--src/core/CMakeLists.txt7
-rw-r--r--src/core/advanced_event.erl154
-rw-r--r--src/core/ephraim_account.erl2
-rw-r--r--src/core/ephraim_account_event_proxy.erl4
-rw-r--r--src/core/ephraim_conn.erl2
-rw-r--r--src/core/ephraim_conv.erl4
-rw-r--r--src/core/ephraim_conv_handler.erl10
-rw-r--r--src/core/ephraim_event_proxy.erl2
-rw-r--r--src/core/ephraim_roster.erl2
-rw-r--r--src/core/ephraim_roster_handler.erl6
14 files changed, 177 insertions, 60 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..565d4bc
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "cmake/erlang"]
+ path = cmake/erlang
+ url = git://git.universe-factory.net/cmake-erlang
diff --git a/cmake/erlang b/cmake/erlang
new file mode 160000
+Subproject 60f4725115653919e9179ad5f01359568e14504
diff --git a/cmake/erlang/ErlangTarget.cmake b/cmake/erlang/ErlangTarget.cmake
deleted file mode 100644
index 2afbc7a..0000000
--- a/cmake/erlang/ErlangTarget.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-macro(erl_target name)
- parse_arguments(ARGS "HEADERS;OPTIONS" "" ${ARGN})
-
- set(headers "")
- set(out_files "")
-
- foreach(header ${ARGS_HEADERS})
- list(APPEND headers "${CMAKE_CURRENT_SOURCE_DIR}/${header}")
- endforeach(header ${ARGS_HEADERS})
-
- foreach(src ${ARGS_DEFAULT_ARGS})
- set(in_file "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
- string(REPLACE ".erl" ".beam" src ${src})
- set(out_file "${CMAKE_CURRENT_BINARY_DIR}/${src}")
-
- add_custom_command(
- OUTPUT
- ${out_file}
- COMMAND
- ${ERLC_EXECUTABLE}
- "-o" ${CMAKE_CURRENT_BINARY_DIR}
- ${ARGS_OPTIONS}
- ${in_file}
- DEPENDS
- ${in_file}
- ${headers}
- )
-
- list(APPEND out_files "${CMAKE_CURRENT_BINARY_DIR}/${src}")
- endforeach(src ${ARGS_DEFAULT_ARGS})
-
- add_custom_target(
- ${name} ALL DEPENDS ${out_files}
- )
-endmacro(erl_target)
diff --git a/cmake/erlang/FindErlang.cmake b/cmake/erlang/FindErlang.cmake
deleted file mode 100644
index e7cb60f..0000000
--- a/cmake/erlang/FindErlang.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-find_program(ERLC_EXECUTABLE NAMES erlc)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Erlang DEFAULT_MSG ERLC_EXECUTABLE)
-mark_as_advanced(ERLC_EXECUTABLE)
-
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 75055bb..96f760b 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,17 +1,18 @@
erl_target(ephraim-core
+ advanced_event.erl
ephraim.erl
ephraim_account.erl
- ephraim_account_event_proxy.erl
+ ephraim_account_event_proxy.erl USING advanced_event
ephraim_accounts.erl
ephraim_config.erl
ephraim_conn.erl
ephraim_conv.erl
- ephraim_conv_handler.erl
+ ephraim_conv_handler.erl USING advanced_event
ephraim_conv_man.erl
ephraim_event_proxy.erl
ephraim_gui.erl
ephraim_roster.erl
- ephraim_roster_handler.erl
+ ephraim_roster_handler.erl USING advanced_event
OPTIONS
+debug_info
)
diff --git a/src/core/advanced_event.erl b/src/core/advanced_event.erl
new file mode 100644
index 0000000..d4a5b7e
--- /dev/null
+++ b/src/core/advanced_event.erl
@@ -0,0 +1,154 @@
+-module(advanced_event).
+-behaviour(gen_server).
+-export([start_link/0, start_link/1, notify/2, sync_notify/2,
+ add_handler/3, delete_handler/3
+ %, call/3, call/4
+ ]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+-record(handler, {module :: atom(),
+ id,
+ state}).
+
+-callback init(InitArgs :: term()) ->
+ {ok, State :: term()}.
+-callback handle_event(Event :: term(), State :: term()) ->
+ {ok, NewState :: term()} |
+ {handled, NewState :: term()} |
+ handled_and_remove |
+ remove_handler.
+-callback handle_call(Request :: term(), State :: term()) ->
+ {ok, Reply :: term(), NewState :: term()} |
+ {remove_handler, Reply :: term()}.
+-callback handle_info(Info :: term(), State :: term()) ->
+ {ok, NewState :: term()} |
+ remove_handler.
+-callback terminate(Args :: (term() | {stop, Reason :: term()} |
+ stop | remove_handler |
+ {error, {'EXIT', Reason :: term()}} |
+ {error, term()}),
+ State :: term()) ->
+ term().
+-callback code_change(OldVsn :: (term() | {down, term()}),
+ State :: term(), Extra :: term()) ->
+ {ok, NewState :: term()}.
+
+-type handler() :: atom() | {atom(), term()}.
+-type emgr_name() :: {'local', atom()} | {'global', atom()}.
+-type emgr_ref() :: atom() | {atom(), atom()} | {'global', atom()} | pid().
+-type start_ret() :: {'ok', pid()} | {'error', term()}.
+
+-define(NO_CALLBACK, 'no callback module').
+
+%-spec start_link() -> start_ret().
+start_link() ->
+ gen_server:start_link(?MODULE, [], []).
+
+%-spec start_link(emgr_name()) -> start_ret().
+start_link(Name) ->
+ gen_server:start_link(Name, ?MODULE, [], []).
+
+init(_Args) ->
+ process_flag(trap_exit, true),
+ {ok, []}.
+
+-spec add_handler(emgr_ref(), handler(), term()) -> term().
+add_handler(Manager, Handler, Args) -> gen_server:call(Manager, {add_handler, Handler, Args}).
+
+-spec delete_handler(emgr_ref(), handler(), term()) -> term().
+delete_handler(Manager, Handler, Args) -> gen_server:call(Manager, {delete_handler, Handler, Args}).
+
+-spec notify(emgr_ref(), term()) -> 'ok'.
+notify(Manager, Event) -> gen_server:cast(Manager, {notify, Event}).
+
+-spec sync_notify(emgr_ref(), term()) -> 'ok'.
+sync_notify(Manager, Event) -> gen_server:call(Manager, {sync_notify, Event}).
+
+%-spec call(emgr_ref(), handler(), term()) -> term().
+%call(M, Handler, Query) -> call1(M, Handler, Query).
+
+%-spec call(emgr_ref(), handler(), term(), timeout()) -> term().
+%call(M, Handler, Query, Timeout) -> call1(M, Handler, Query, Timeout).
+
+
+-spec handle_call(term(), {pid(), term()}, list()) -> {reply, term(), list()}.
+handle_call({add_handler, Handler, Args}, _From, Handlers) ->
+ {Module, Id} = case Handler of
+ {_Mod, _Id} ->
+ Handler;
+ Mod ->
+ {Mod, undefined}
+ end,
+ case catch Module:init(Args) of
+ {ok, State} ->
+ {reply,ok,[#handler{module=Module,id=Id,state=State}|Handlers]};
+ Other ->
+ {reply,Other,Handlers}
+ end;
+handle_call({delete_handler, Handler, Args}, _From, Handlers) ->
+ {Module, Id} = case Handler of
+ {_Mod, _Id} ->
+ Handler;
+ Mod ->
+ {Mod, undefined}
+ end,
+ case remove_from_list(Module, Id, Handlers) of
+ error ->
+ {reply,{error,module_not_found},Handlers};
+ {H,Hs} ->
+ case catch (H#handler.module):terminate(Args, (H#handler.state)) of
+ Result ->
+ {reply,Result,Hs}
+ end
+ end;
+handle_call({sync_notify,Event}, _From, Handlers) ->
+ Handlers1 = call_handlers(Event, Handlers),
+ {reply,ok,Handlers1}.
+
+handle_cast({notify,Event}, Handlers) ->
+ Handlers1 = call_handlers(Event, Handlers),
+ {noreply,Handlers1}.
+
+handle_info(_Msg, Handlers) ->
+ {noreply,Handlers}.
+
+remove_from_list(Module, Id, [Handler|Handlers]) ->
+ case Handler of
+ #handler{module=Module,id=Id} ->
+ {Handler,Handlers};
+ _ ->
+ case remove_from_list(Module, id, Handlers) of
+ {H,Hs} ->
+ {H,[Handler|Hs]};
+ error ->
+ error
+ end
+ end;
+remove_from_list(_, _, []) ->
+ error.
+
+call_handlers(Event, [Handler|Handlers]) ->
+ case catch (Handler#handler.module):handle_event(Event, Handler#handler.state) of
+ {ok, State} ->
+ Rest = call_handlers(Event, Handlers),
+ [Handler#handler{state=State}|Rest];
+ {handled, State} ->
+ [Handler#handler{state=State}|Handlers];
+ remove_handler ->
+ (Handler#handler.module):terminate(remove_handler, Handler#handler.state),
+ call_handlers(Event, Handlers);
+ handled_and_remove ->
+ (Handler#handler.module):terminate(remove_handler, Handler#handler.state),
+ []
+ end;
+call_handlers(_, []) ->
+ [].
+
+terminate(Reason, [Handler|Handlers]) ->
+ (Handler#handler.module):terminate({stop, Reason}, (Handler#handler.state)),
+ terminate(Reason, Handlers);
+terminate(_Reason, []) ->
+ ok.
+
+code_change(_OldVersion, Config, _Extra) ->
+ {ok, Config}.
diff --git a/src/core/ephraim_account.erl b/src/core/ephraim_account.erl
index b71cb08..ad25483 100644
--- a/src/core/ephraim_account.erl
+++ b/src/core/ephraim_account.erl
@@ -6,7 +6,7 @@
start_link(Account) ->
{ok, Pid} = supervisor:start_link(?MODULE, []),
- {ok, EventManager} = supervisor:start_child(Pid, {event_man, {gen_event, start_link, []}, permanent, 1000, worker, [gen_event]}),
+ {ok, EventManager} = supervisor:start_child(Pid, {event_man, {advanced_event, start_link, []}, permanent, 1000, worker, [advanced_event]}),
ephraim_event_proxy:start(Account, EventManager),
ephraim_account_event_proxy:start(Account, EventManager),
diff --git a/src/core/ephraim_account_event_proxy.erl b/src/core/ephraim_account_event_proxy.erl
index 726b0e0..9f52d10 100644
--- a/src/core/ephraim_account_event_proxy.erl
+++ b/src/core/ephraim_account_event_proxy.erl
@@ -1,11 +1,11 @@
-module(ephraim_account_event_proxy).
--behaviour(gen_event).
+-behaviour(advanced_event).
-export([start/2]).
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).
start(Account, EventManager) ->
- gen_event:add_handler(EventManager, ?MODULE, Account).
+ advanced_event:add_handler(EventManager, ?MODULE, Account).
init(Account) ->
{ok, Account}.
diff --git a/src/core/ephraim_conn.erl b/src/core/ephraim_conn.erl
index 308f385..9bc6d2f 100644
--- a/src/core/ephraim_conn.erl
+++ b/src/core/ephraim_conn.erl
@@ -57,7 +57,7 @@ connected({send_packet, Packet}, Data) ->
{next_state,connected,Data}.
handle_info(Msg = #received_packet{}, State, Data) ->
- gen_event:notify(Data#conn_state.event_manager, {received_packet,Msg}),
+ advanced_event:notify(Data#conn_state.event_manager, {received_packet,Msg}),
{next_state, State, Data};
handle_info(Msg, State, Data) ->
io:format("ephraim_conn: ~p~n", [Msg]),
diff --git a/src/core/ephraim_conv.erl b/src/core/ephraim_conv.erl
index d6ab742..1c51067 100644
--- a/src/core/ephraim_conv.erl
+++ b/src/core/ephraim_conv.erl
@@ -15,7 +15,7 @@
-spec start_link(pid(), pid(), pid(), binary()) -> ok.
start_link(EventManager, Conn, Roster, JID) ->
- gen_event:notify(EventManager, {view_update, {conversation, JID, new}}),
+ advanced_event:notify(EventManager, {view_update, {conversation, JID, new}}),
{jid,MyJID} = ephraim_config:get(jid),
gen_server:start_link(?MODULE, #conv_state{event_manager=EventManager,connection=Conn,roster=Roster,my_jid=list_to_binary(MyJID),jid=JID}, []).
@@ -36,7 +36,7 @@ handle_call(_Msg, _From, State) ->
update_view(State, From, Type, Body) ->
Alias = ephraim_roster:get_alias(State#conv_state.roster, From),
- gen_event:notify(State#conv_state.event_manager, {view_update, {conversation, State#conv_state.jid, {message, Alias, Type, Body}}}).
+ advanced_event:notify(State#conv_state.event_manager, {view_update, {conversation, State#conv_state.jid, {message, Alias, Type, Body}}}).
handle_cast({received_message, From, Type, Body}, State) ->
update_view(State, From, Type, Body),
diff --git a/src/core/ephraim_conv_handler.erl b/src/core/ephraim_conv_handler.erl
index 681e53a..6949661 100644
--- a/src/core/ephraim_conv_handler.erl
+++ b/src/core/ephraim_conv_handler.erl
@@ -1,6 +1,6 @@
-module(ephraim_conv_handler).
-include_lib("exmpp/include/exmpp_client.hrl").
--behaviour(gen_event).
+-behaviour(advanced_event).
-export([start/4]).
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).
@@ -13,7 +13,7 @@
}).
start(Supervisor, EventManager, Conn, Roster) ->
- gen_event:add_handler(EventManager, ?MODULE, #conv_handler_state{supervisor=Supervisor,event_manager=EventManager,connection=Conn,roster=Roster}).
+ advanced_event:add_handler(EventManager, ?MODULE, #conv_handler_state{supervisor=Supervisor,event_manager=EventManager,connection=Conn,roster=Roster}).
init(State) ->
{ok, State}.
@@ -44,12 +44,12 @@ get_conv(State, JID) ->
handle_event({view_request, {conversation,JID,new}}, State) ->
{NewState, _} = get_conv(State, JID),
- {ok, NewState};
+ {handled, NewState};
handle_event({view_request, {conversation,JID,{send_message,Type,Body}}}, State) ->
{NewState, Conv} = get_conv(State, JID),
ephraim_conv:send_message(Conv, Type, Body),
- {ok, NewState};
+ {handled, NewState};
handle_event({received_packet, #received_packet{packet_type=message, raw_packet=Packet}}, State) ->
From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
@@ -69,7 +69,7 @@ handle_event({received_packet, #received_packet{packet_type=message, raw_packet=
io:format("Received strange message from ~p:~n~p~n", [From, Packet]),
State
end,
- {ok, NewState};
+ {handled, NewState};
handle_event(_Event, State) ->
{ok, State}.
diff --git a/src/core/ephraim_event_proxy.erl b/src/core/ephraim_event_proxy.erl
index 4b0e35b..dacc34c 100644
--- a/src/core/ephraim_event_proxy.erl
+++ b/src/core/ephraim_event_proxy.erl
@@ -11,7 +11,7 @@ init(State) ->
{ok, State}.
handle_event({view_request, {account, Account, Event}}, {Account, EventManager}) ->
- gen_event:notify(EventManager, {view_request, Event}),
+ advanced_event:notify(EventManager, {view_request, Event}),
{ok, {Account, EventManager}};
handle_event(_Event, State) ->
diff --git a/src/core/ephraim_roster.erl b/src/core/ephraim_roster.erl
index 955b108..3538533 100644
--- a/src/core/ephraim_roster.erl
+++ b/src/core/ephraim_roster.erl
@@ -112,7 +112,7 @@ viewUpdate(State, JID, RosterEntry) ->
if RosterEntry#roster_entry.subscription =:= undefined ->
ok;
true ->
- gen_event:notify(State#roster_state.event_manager, {view_update, {roster_update, JID, RosterEntry#roster_entry.name, RosterEntry#roster_entry.subscription,
+ advanced_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
diff --git a/src/core/ephraim_roster_handler.erl b/src/core/ephraim_roster_handler.erl
index fa7c1c7..8056797 100644
--- a/src/core/ephraim_roster_handler.erl
+++ b/src/core/ephraim_roster_handler.erl
@@ -1,14 +1,14 @@
-module(ephraim_roster_handler).
-include_lib("exmpp/include/exmpp_client.hrl").
--behaviour(gen_event).
+-behaviour(advanced_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).
+ advanced_event:add_handler(EventManager, ?MODULE, Roster).
stop(EventManager) ->
- gen_event:delete_handler(EventManager, ?MODULE, []).
+ advanced_event:delete_handler(EventManager, ?MODULE, []).
init(Roster) ->
{ok, Roster}.