/* Jappix - An open social platform These are the Muji helpers & launchers ------------------------------------------------- License: AGPL Author: Valérian Saliou */ // Bundle var Muji = (function() { /** * Alias of this * @private */ var self = {}; /* Constants */ self.INVITE_MAX_DELAY = 60; /* Variables */ self._session = null; self._caller_xid = null; /** * Opens the Muji interface (depending on the state) * @public * @return {boolean} */ self.open = function() { try { var call_tool_sel = $('#top-content .tools.call'); if(call_tool_sel.is('.active')) { Console.info('Opened call notification drawer'); } else if(call_tool_sel.is('.streaming')) { self._show_interface(); Console.info('Opened Muji box'); } else { Console.warn('Could not open any Muji tool (race condition on state)'); } } catch(e) { Console.error('Muji.open', e); } finally { return false; } }; /** * Returns the Muji session arguments (used to configure it) * @private * @param connection * @param xid * @param hash * @param local_view * @return {object} */ self._args = function(connection, xid, hash, media, local_view) { args = {}; try { // Network configuration var ice_servers = Call.generate_ice_servers(); // Muji arguments args = { // Configuration (required) connection: connection, to: xid, media: media, local_view: local_view, stun: ice_servers.stun, turn: ice_servers.turn, resolution: 'sd', debug: Call._consoleAdapter, // Safety options (optional) password_protect: true, // Custom handlers (optional) room_message_in: function(muji, stanza) { var from = muji.utils.stanza_from(stanza); var username = muji.utils.extract_username(from); var body = stanza.getBody(); var muji_sel = $('#muji'); var mode = (username === $('#muji').attr('data-username')) ? 'me' : 'him'; if(username && body && muji_sel.size()) { var avatar_html = ''; if(mode === 'him') { avatar_html = '
' + '' + '
'; } muji_sel.find('.chatroom .chatroom_view').append( '
' + avatar_html + '
' + '' + body.htmlEnc() + '' + '' + username.htmlEnc() + '' + '
' + '
' + '
' ); if($('#muji').is(':visible')) { self._message_scroll(); } else { self._message_notify(); } Console.log('Muji._args > room_message_in', 'Displayed Muji message from: ' + username); } Console.log('Muji._args', 'room_message_in'); }, room_message_out: function(muji, stanza) { Console.log('Muji._args', 'room_message_out'); }, room_presence_in: function(muji, stanza) { Console.log('Muji._args', 'room_presence_in'); }, room_presence_out: function(muji, stanza) { Console.log('Muji._args', 'room_presence_out'); }, session_prepare_pending: function(muji, stanza) { // Temporary username $('#muji').attr('data-username', muji.get_username()); // Notify user about preparing call Call.notify( JSJAC_JINGLE_SESSION_MUJI, muji.get_to(), 'preparing', muji.get_media(), self.get_caller_xid() ); Console.log('Muji._args', 'session_prepare_pending'); }, session_prepare_success: function(muji, stanza) { // Final username $('#muji').attr('data-username', muji.get_username()); Console.log('Muji._args', 'session_prepare_success'); }, session_prepare_error: function(muji, stanza) { self._reset(); Call.notify( JSJAC_JINGLE_SESSION_MUJI, muji.get_to(), 'error', muji.get_media(), self.get_caller_xid() ); Console.log('Muji._args', 'session_prepare_error'); }, session_initiate_pending: function(muji) { Call.notify( JSJAC_JINGLE_SESSION_MUJI, muji.get_to(), 'waiting', muji.get_media(), self.get_caller_xid() ); Console.log('Muji._args', 'session_initiate_pending'); }, session_initiate_success: function(muji, stanza) { Call._unnotify(); // Start call! Go Go Go! Call.start_session(muji.get_media()); self._show_interface(); Call.start_counter(); Console.log('Muji._args', 'session_initiate_success'); }, session_initiate_error: function(muji, stanza) { self._reset(); Call.notify( JSJAC_JINGLE_SESSION_MUJI, muji.get_to(), 'error', muji.get_media(), self.get_caller_xid() ); Console.log('Muji._args', 'session_initiate_error'); }, session_leave_pending: function(muji) { self._reset(); Call.notify( JSJAC_JINGLE_SESSION_MUJI, muji.get_to(), 'ending', muji.get_media(), self.get_caller_xid() ); Console.log('Muji._args', 'session_leave_pending'); }, session_leave_success: function(muji, stanza) { self._reset(); Call.notify( JSJAC_JINGLE_SESSION_MUJI, muji.get_to(), 'ended', muji.get_media(), self.get_caller_xid() ); Console.log('Muji._args', 'session_leave_success'); }, session_leave_error: function(muji, stanza) { self._reset(); if(typeof muji.parent != 'undefined') { muji = muji.parent; } Call.notify( JSJAC_JINGLE_SESSION_MUJI, muji.get_to(), 'ended', muji.get_media(), self.get_caller_xid() ); Console.log('Muji._args', 'session_leave_error'); }, participant_prepare: function(muji, stanza) { Console.log('Muji._args', 'participant_prepare'); }, participant_initiate: function(muji, stanza) { Console.log('Muji._args', 'participant_initiate'); }, participant_leave: function(muji, stanza) { Console.log('Muji._args', 'participant_leave'); }, participant_session_initiate_pending: function(muji, session) { Console.log('Muji._args', 'participant_session_initiate_pending'); }, participant_session_initiate_success: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_initiate_success'); }, participant_session_initiate_error: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_initiate_error'); }, participant_session_initiate_request: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_initiate_request'); }, participant_session_accept_pending: function(muji, session) { Console.log('Muji._args', 'participant_session_accept_pending'); }, participant_session_accept_success: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_accept_success'); }, participant_session_accept_error: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_accept_error'); }, participant_session_accept_request: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_accept_request'); }, participant_session_info_pending: function(muji, session) { Console.log('Muji._args', 'participant_session_info_pending'); }, participant_session_info_success: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_info_success'); }, participant_session_info_error: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_info_error'); }, participant_session_info_request: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_info_request'); }, participant_session_terminate_pending: function(muji, session) { Console.log('Muji._args', 'participant_session_terminate_pending'); }, participant_session_terminate_success: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_terminate_success'); }, participant_session_terminate_error: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_terminate_error'); }, participant_session_terminate_request: function(muji, session, stanza) { Console.log('Muji._args', 'participant_session_terminate_request'); }, add_remote_view: function(muji, username, media) { Console.log('Muji._args', 'add_remote_view'); var muji_sel = $('#muji'); var nobody_sel = muji_sel.find('.empty_message'); var remote_container_sel = $('#muji .remote_container'); var remote_video_shaper_sel = remote_container_sel.find('.remote_video_shaper'); var view_sel = null; var container_sel = remote_video_shaper_sel.filter(function() { return ($(this).attr('data-username') + '') === (username + ''); }); var count_participants = remote_video_shaper_sel.filter(':has(video)').size(); // Not already in view? if(!container_sel.size()) { // Select first empty view var first_empty_view_sel = remote_video_shaper_sel.filter(':not(:has(video)):first'); if(first_empty_view_sel.size()) { container_sel = first_empty_view_sel; // Remote poster var remote_poster = './images/placeholders/jingle_video_remote.png'; if(media === 'audio') { remote_poster = './images/placeholders/jingle_audio_remote.png'; } // Append view view_sel = $(''); container_sel.attr('data-username', username); view_sel.appendTo(container_sel); // Append username label container_sel.append( '' + username.htmlEnc() + '' ); // Update counter muji_sel.attr( 'data-count', ++count_participants ); } else { // Room is full... muji_sel.find('.chatroom_participants .participants_full:hidden').show(); } } nobody_sel.hide(); Muji._update_count_participants(count_participants); Muji._update_invite_participants(); // IMPORTANT: return view selector return (view_sel !== null) ? view_sel[0] : view_sel; }, remove_remote_view: function(muji, username) { Console.log('Muji._args', 'remove_remote_view'); var muji_sel = $('#muji'); var nobody_sel = muji_sel.find('.empty_message'); var remote_container_sel = $('#muji .remote_container'); var remote_video_shaper_sel = remote_container_sel.find('.remote_video_shaper'); var container_sel = remote_video_shaper_sel.filter(function() { return ($(this).attr('data-username') + '') === (username + ''); }); var count_participants = remote_video_shaper_sel.filter(':has(video)').size(); // Exists in view? if(container_sel.size()) { var view_sel = container_sel.find('video'); // Remove video view_sel.stop(true).fadeOut(250, function() { container_sel.empty(); // Update counter muji_sel.attr( 'data-count', --count_participants ); // Nobody left in the room? if(!remote_video_shaper_sel.find('video').size()) { nobody_sel.show(); muji_sel.removeAttr('data-count'); } // Update participants counter muji_sel.find('.chatroom_participants .participants_full:visible').hide(); Muji._update_count_participants(count_participants); Muji._update_invite_participants(); }); // IMPORTANT: return view selector if(view_sel.size()) { return view_sel[0]; } } return null; } }; } catch(e) { Console.error('Muji._args', e); } finally { return args; } }; /** * Launch a new Muji session with given buddy * @private * @param room * @param mode * @param args_invite * @return {boolean} */ self._new = function(room, mode, stanza, args_invite) { var status = false; try { if(!room) { throw 'No room to be joined given!'; } var hash = hex_md5(room); // Create interface for video containers $('body').addClass('in_muji_call'); var muji_sel = self._create_interface(room, mode); // Filter media var media = null; switch(mode) { case 'audio': media = JSJAC_JINGLE_MEDIA_AUDIO; break; case 'video': media = JSJAC_JINGLE_MEDIA_VIDEO; break; } // Start the Jingle negotiation var args = self._args( con, room, hash, media, muji_sel.find('.local_video video')[0] ); if(typeof args_invite == 'object') { if(args_invite.password) { args.password = args_invite.password; } args.media = (args_invite.media == JSJAC_JINGLE_MEDIA_VIDEO) ? JSJAC_JINGLE_MEDIA_VIDEO : JSJAC_JINGLE_MEDIA_AUDIO; self._session = new JSJaCJingle.session(JSJAC_JINGLE_SESSION_MUJI, args); self._caller_xid = Common.bareXID(args_invite.from); Console.debug('Receive Muji call: ' + room); } else { self._session = new JSJaCJingle.session(JSJAC_JINGLE_SESSION_MUJI, args); self._caller_xid = Common.getXID(); self._session.join(); Console.debug('Create Muji call: ' + room); } Console.debug('Join Muji conference: ' + room); status = true; } catch(e) { Console.error('Muji._new', e); } finally { return status; } }; /** * Updates the participants counter value * @private * @param {number} count_participants * @return {undefined} */ self._update_count_participants = function(count_participants) { try { count_participants = (count_participants || 0); var participants_counter_sel = $('#muji .chatroom_participants .participants_counter'); if(count_participants === 1) { participants_counter_sel.text( Common.printf(Common._e("%s participant"), count_participants) ); } else { participants_counter_sel.text( Common.printf(Common._e("%s participants"), count_participants) ); } } catch(e) { Console.error('Muji._update_count_participants', e); } }; /** * Updates the participants invite tool * @private * @return {undefined} */ self._update_invite_participants = function() { try { var chatroom_participants_sel = $('#muji .chatroom_participants'); var participants_invite_sel = chatroom_participants_sel.find('.participants_invite'); var participants_invite_box_sel = chatroom_participants_sel.find('.participants_invite_box'); if(self.is_full()) { if(participants_invite_box_sel.is(':visible')) { participants_invite_box_sel.stop(true); participants_invite_sel.click(); } participants_invite_sel.filter(':visible').hide(); } else { participants_invite_sel.filter(':hidden').show(); } } catch(e) { Console.error('Muji._update_invite_participants', e); } }; /** * Resets the participants invite filter * @private * @return {undefined} */ self._reset_participants_invite_filter = function() { try { // Selectors var chatroom_sel = $('#muji .chatroom'); var invite_form_sel = chatroom_sel.find('form.participants_invite_form'); var invite_search_sel = chatroom_sel.find('.participants_invite_search'); // Apply invite_form_sel.find('input.invite_xid').val(''); invite_search_sel.empty(); } catch(e) { Console.error('Muji._reset_participants_invite_filter', e); } }; /** * Engages the participants invite filter * @private * @param {string} value * @return {undefined} */ self._engage_participants_invite_filter = function(value) { try { // Selectors var chatroom_sel = $('#muji .chatroom'); var invite_input_sel = chatroom_sel.find('form.participants_invite_form input.invite_xid'); var invite_search_sel = chatroom_sel.find('.participants_invite_search'); // Reset UI invite_search_sel.empty(); // Proceed search var results_arr = Search.processBuddy(value); var results_html = ''; var bold_regex = new RegExp('((^)|( ))' + value, 'gi'); // Exclude already selected buddies var exclude_obj = self._list_participants_invite_list(); if(results_arr && results_arr.length) { var i, j, cur_xid, cur_full_xid, cur_hash, cur_support, cur_name, cur_title, cur_name_bolded, cur_support_class; for(i = 0; i < results_arr.length; i++) { // Generate result data cur_xid = results_arr[i]; if(exclude_obj[cur_xid] !== 1) { cur_hash = hex_md5(cur_xid); cur_name = Name.getBuddy(cur_xid); // Get target's full XID cur_full_xid = Caps.getFeatureResource(cur_xid, NS_MUJI); cur_support = null; if(cur_full_xid) { if(Caps.getFeatureResource(cur_xid, NS_JINGLE_APPS_RTP_VIDEO)) { cur_support = 'video'; } else { cur_support = 'audio'; } } // Generate a hint title & a class if(cur_support) { cur_title = Common.printf(Common._e("%s is able to receive group calls."), cur_name); cur_support_class = 'participant_search_has_' + cur_support; } else { cur_title = Common.printf(Common._e("%s may not support group calls."), cur_name); cur_support_class = 'participant_search_unsupported'; } // Bold matches in name cur_name_bolded = cur_name.htmlEnc().replace(bold_regex, '$&'); // Generate result HTML results_html += '' + '' + '' + '' + '' + '' + cur_name_bolded + '' + '' + '' + ''; } } // Add to DOM invite_search_sel.append(results_html); var search_one_sel = invite_search_sel.find('a.participant_search_one'); search_one_sel.filter(':first').addClass('hover'); // Apply avatars for(j = 0; j < results_arr.length; j++) { Avatar.get(results_arr[j], 'cache', 'true', 'forget'); } // Apply events search_one_sel.click(function() { var this_sel = $(this); self._add_participants_invite_list( this_sel.attr('data-xid'), this_sel.text(), this_sel.attr('data-support') ); self._reset_participants_invite_filter(); invite_input_sel.focus(); }); search_one_sel.hover(function() { search_one_sel.filter('.hover').removeClass('hover'); $(this).addClass('hover'); }, function() { $(this).removeClass('hover'); }); } } catch(e) { Console.error('Muji._engage_participants_invite_filter', e); } }; /** * Sends participant actual Muji invite * @private * @param {string|object} xid * @return {undefined} */ self._send_participants_invite_list = function(xid) { try { if(self.in_call()) { self._session.invite(xid); } } catch(e) { Console.error('Muji._send_participants_invite_list', e); } }; /** * Adds a participant to the invite list * @private * @param {string} xid * @param {string} name * @param {string} support * @return {undefined} */ self._add_participants_invite_list = function(xid, name, support) { try { // Selectors var chatroom_sel = $('#muji .chatroom'); var invite_form_sel = chatroom_sel.find('form.participants_invite_form'); var invite_list_sel = chatroom_sel.find('.participants_invite_list'); var pre_invite_one_sel = invite_list_sel.find('.invite_one').filter(function() { return (xid === $(this).attr('data-xid')) && true; }); if(pre_invite_one_sel.size()) { throw 'Already existing for: ' + xid; } var title; var _class = []; switch(support) { case 'audio': case 'video': title = Common.printf(Common._e("%s is able to receive group calls."), name); break; default: title = Common.printf(Common._e("%s may not support group calls."), name); _class.push('invite_unsupported'); } // Append element var invite_one_sel = $('' + name.htmlEnc() + ''); invite_one_sel.appendTo(invite_list_sel); // Events invite_one_sel.find('a.invite_one_remove').click(function() { self._remove_participants_invite_list(invite_one_sel); }); if(invite_list_sel.find('.invite_one').size() >= 1) { invite_form_sel.find('.invite_validate').show(); invite_list_sel.filter(':hidden').show(); } } catch(e) { Console.error('Muji._add_participants_invite_list', e); } }; /** * Removes a participant from the invite list * @private * @param {object} participant_sel * @return {undefined} */ self._remove_participants_invite_list = function(participant_sel) { try { // Selectors var chatroom_sel = $('#muji .chatroom'); var invite_form_sel = chatroom_sel.find('form.participants_invite_form'); var invite_list_sel = chatroom_sel.find('.participants_invite_list'); participant_sel.remove(); if(invite_list_sel.find('.invite_one').size() === 0) { invite_form_sel.find('.invite_validate').hide(); invite_list_sel.filter(':visible').hide(); } invite_form_sel.find('input.invite_xid').focus(); } catch(e) { Console.error('Muji._remove_participants_invite_list', e); } }; /** * Hovers either the next or previous participant * @private * @param {string} direction * @return {undefined} */ self._hover_participants_invite_list = function(direction) { try { // Up/down: navigate through results var chatroom_sel = $('#muji .chatroom'); var participants_invite_search_sel = chatroom_sel.find('.participants_invite_search'); var participant_search_one_sel = chatroom_sel.find('.participant_search_one'); if(participant_search_one_sel.size()) { var hover_index = participant_search_one_sel.index($('.hover')); // Up (decrement) or down (increment)? if(direction === 'up') { hover_index--; } else { hover_index++; } if(!hover_index) { hover_index = 0; } // Nobody before/after? if(participant_search_one_sel.eq(hover_index).size() === 0) { if(direction === 'up') { hover_index = participant_search_one_sel.filter(':last').index(); } else { hover_index = 0; } } // Hover the previous/next user participant_search_one_sel.removeClass('hover'); participant_search_one_sel.eq(hover_index).addClass('hover'); // Scroll to the hovered user (if out of limits) participants_invite_search_sel.scrollTo( participant_search_one_sel.filter('.hover:first'), 0, { margin: true } ); } } catch(e) { Console.error('Muji._hover_participants_invite_list', e); } }; /** * Lists the participants in the invite list * @private * @return {object} */ self._list_participants_invite_list = function() { var participants_obj = {}; try { $('#muji .chatroom .participants_invite_list .invite_one').each(function() { participants_obj[$(this).attr('data-xid')] = 1; }); } catch(e) { Console.error('Muji._list_participants_invite_list', e); } finally { return participants_obj; } }; /** * Adapts the Muji view to the window size * @private * @return {undefined} */ self._adapt = function() { try { if(self.in_call() && Common.exists('#muji')) { Call.adapt_local( $('#muji .local_video') ); Call.adapt_remote( $('#muji .videoroom') ); } } catch(e) { Console.error('Muji._adapt', e); } }; /** * Scrolls down to last received message * @private * @return {undefined} */ self._message_scroll = function() { try { var chatroom_view_sel = $('#muji .chatroom .chatroom_view'); // Scroll down to message if(chatroom_view_sel.size() && chatroom_view_sel.is(':visible')) { chatroom_view_sel[0].scrollTop = chatroom_view_sel[0].scrollHeight; } } catch(e) { Console.error('Muji._message_scroll', e); } }; /** * Notifies that a new message has been received * @private * @return {undefined} */ self._message_notify = function() { try { // Selectors var tools_call_sel = $('#top-content .tools.call'); var notify_sel = tools_call_sel.find('.notify'); if(!notify_sel.size()) { notify_sel = $( '
0
' ); notify_sel.appendTo(tools_call_sel); } // Count & update var count_notifications = parseInt((notify_sel.attr('data-counter') || 0), 10); count_notifications++; notify_sel.text(count_notifications); notify_sel.attr('data-counter', count_notifications); // Update general interface Interface.updateTitle(); } catch(e) { Console.error('Muji._message_notify', e); } }; /** * Removes displayed message notifications * @private * @return {undefined} */ self._message_unnotify = function() { try { $('#top-content .tools.call .notify').remove(); // Update general interface Interface.updateTitle(); } catch(e) { Console.error('Muji._message_unnotify', e); } }; /** * Receive a Muji call * @public * @param {object} args * @param {object} stanza * @return {boolean} */ self.receive = function(args, stanza) { try { if(!Call.is_ongoing()) { // Outdated invite? var invite_delay = DateUtils.readMessageDelay(stanza.getNode(), true); var date_now = DateUtils.getTimeStamp(); if(invite_delay && (date_now - DateUtils.extractStamp(invite_delay)) >= self.INVITE_MAX_DELAY) { Console.warn('Muji.receive', 'Discarded outdated invite from: ' + Common.getStanzaFrom(stanza)); return; } // Create call session self._new( args.jid, (args.media || JSJAC_JINGLE_MEDIA_VIDEO), stanza, args ); // Notify user Call.notify( JSJAC_JINGLE_SESSION_MUJI, args.jid, ('call_' + (args.media || 'video')), args.media, Common.bareXID(args.from) ); Audio.play('incoming-call', true); } } catch(e) { Console.error('Muji.receive', e); } finally { return false; } }; /** * Start a Muji call * @public * @param {string} room * @param {string} mode * @return {boolean} */ self.start = function(room, mode) { try { if(!Call.is_ongoing()) { self._new(room, mode); } } catch(e) { Console.error('Muji.start', e); } finally { return false; } }; /** * Reset current Muji call * @public * @return {boolean} */ self._reset = function() { try { // Trash interface Call.stop_counter(); Call.stop_session(); self._destroy_interface(); $('body').removeClass('in_muji_call'); // Clean notifications self._message_unnotify(); // Hack: stop audio in case it is still ringing Audio.stop('incoming-call'); Audio.stop('outgoing-call'); } catch(e) { Console.error('Muji._reset', e); } finally { return false; } }; /** * Stops current Muji call * @public * @param {boolean} abort * @return {boolean} */ self.stop = function(abort) { try { // Reset interface self._reset(); // Stop Muji session if(self._session !== null) { if(abort === true) { self._session.abort(); self._session.get_session_leave_error(self._session, null); } else { self._session.leave(); } Console.debug('Stopping current Muji call...'); } else { Console.warn('No Muji call to be terminated!'); } } catch(e) { Console.error('Muji.stop', e); } finally { return false; } }; /** * Mutes current Muji call * @public * @return {undefined} */ self.mute = function() { try { Call.mute( $('#muji .videoroom .topbar .controls a') ); } catch(e) { Console.error('Muji.mute', e); } }; /** * Unmutes current Muji call * @public * @return {undefined} */ self.unmute = function() { try { Call.unmute( $('#muji .videoroom .topbar .controls a') ); } catch(e) { Console.error('Muji.mute', e); } }; /** * Checks whether room given is Muji room or not * @public * @param {string} room * @return {boolean} */ self.is_room = function(room) { is_room = false; try { if(self.in_call() && self._session.get_to()) { is_room = (room === self._session.get_to()); } } catch(e) { Console.error('Muji.is_room', e); } finally { return is_room; } }; /** * Checks whether room is full or not (over-capacity) * @public * @return {boolean} */ self.is_full = function() { is_full = false; try { if($('#muji .chatroom_participants .participants_full').is(':visible')) { is_full = true; } } catch(e) { Console.error('Muji.is_full', e); } finally { return is_full; } }; /** * Checks whether user is in call or not * @public * @return {boolean} */ self.in_call = function() { in_call = false; try { if(self._session && (self._session.get_status() === JSJAC_JINGLE_MUJI_STATUS_PREPARING || self._session.get_status() === JSJAC_JINGLE_MUJI_STATUS_PREPARED || self._session.get_status() === JSJAC_JINGLE_MUJI_STATUS_INITIATING || self._session.get_status() === JSJAC_JINGLE_MUJI_STATUS_INITIATED || self._session.get_status() === JSJAC_JINGLE_MUJI_STATUS_LEAVING)) { in_call = true; } } catch(e) { Console.error('Muji.in_call', e); } finally { return in_call; } }; /** * Checks if the given call SID is the same as the current call's one * @public * @param {object} * @return {boolean} */ self.is_same_sid = function(muji) { try { return Call.is_same_sid(self._session, muji); } catch(e) { Console.error('Muji.is_same_sid', e); } }; /** * Returns if current Muji call is audio * @public * @return {boolean} */ self.is_audio = function() { try { return Call.is_audio(self._session); } catch(e) { Console.error('Muji.is_audio', e); } }; /** * Returns if current Muji call is video * @public * @return {boolean} */ self.is_video = function() { try { return Call.is_video(self._session); } catch(e) { Console.error('Muji.is_video', e); } }; /** * Returns the caller XID * @public * @return {string} */ self.get_caller_xid = function() { try { return self._caller_xid || Common.getXID(); } catch(e) { Console.error('Muji.get_caller_xid', e); } }; /** * Get the notification map * @private * @return {object} */ self._notify_map = function() { try { return { 'call_audio': { 'text': Common._e("Incoming group call"), 'buttons': { 'accept': { 'text': Common._e("Accept"), 'color': 'green', 'cb': function(xid, mode) { self._session.join(); Audio.stop('incoming-call'); } }, 'decline': { 'text': Common._e("Decline"), 'color': 'red', 'cb': function(xid, mode) { self.stop(true); Audio.stop('incoming-call'); } } } }, 'call_video': { 'text': Common._e("Incoming group call"), 'buttons': { 'accept': { 'text': Common._e("Accept"), 'color': 'green', 'cb': function(xid, mode) { self._session.join(); Audio.stop('incoming-call'); } }, 'decline': { 'text': Common._e("Decline"), 'color': 'red', 'cb': function(xid, mode) { self.stop(true); Audio.stop('incoming-call'); } } } }, 'preparing': { 'text': Common._e("Preparing group call..."), 'buttons': { 'cancel': { 'text': Common._e("Cancel"), 'color': 'red', 'cb': function(xid, mode) { self.stop(true); } } } }, 'waiting': { 'text': Common._e("Preparing group call..."), 'buttons': { 'cancel': { 'text': Common._e("Cancel"), 'color': 'red', 'cb': function(xid, mode) { self._session.leave(); } } } }, 'connecting': { 'text': Common._e("Connecting to group call..."), 'buttons': { 'cancel': { 'text': Common._e("Cancel"), 'color': 'red', 'cb': function(xid, mode) { self._session.leave(); } } } }, 'error': { 'text': Common._e("Group call error"), 'buttons': { 'retry': { 'text': Common._e("Retry"), 'color': 'blue', 'cb': function(xid, mode) { self.start(xid, mode); } }, 'cancel': { 'text': Common._e("Cancel"), 'color': 'red', 'cb': function(xid, mode) { self._reset(); } } } }, 'ending': { 'text': Common._e("Ending group call...") }, 'ended': { 'text': Common._e("Group call ended"), 'buttons': { 'okay': { 'text': Common._e("Okay"), 'color': 'blue', 'cb': function(xid, mode) { self._reset(); } } } } }; } catch(e) { Console.error('Muji._notify_map', e); return {}; } }; /** * Create the Muji interface * @public * @param {string} room * @param {string} mode * @return {object} */ self._create_interface = function(room, mode) { try { // Jingle interface already exists? if(Common.exists('#muji')) { throw 'Muji interface already exist!'; } // Local poster var local_poster = './images/placeholders/jingle_video_local.png'; if(mode === 'audio') { local_poster = './images/placeholders/jingle_audio_local.png'; } // Create DOM $('body').append( '
' + '
' + '
' + '
' + '' + '
00:00:00
' + '
' + '' + '
' + '
' + '
' + '' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '' + Common._e("Nobody there. Invite some people!") + '' + '
' + '
' + '
' + '
' + '
' + '
' + '' + Common.printf(Common._e("%s participants"), 0) + '' + '' + Common._e("(full)") + '' + '
' + '' + '
' + '
' + '
' + '
' + '
' + '' + '
' + '' + '' + '' + '
' + '' + '
' + '
' + '
' + '
' + '' + '' + '
' + '' + '
' + '
' + '
' + '
' + '
' ); // Apply events self._events_interface(); // Apply user avatar Avatar.get(xid, 'cache', 'true', 'forget'); } catch(e) { Console.error('Muji._create_interface', e); } finally { return $('#muji'); } }; /** * Destroy the Muji interface * @public * @return {undefined} */ self._destroy_interface = function() { try { Call.destroy_interface( $('#muji') ); } catch(e) { Console.error('Muji._destroy_interface', e); } }; /** * Show the Muji interface * @private * @return {boolean} */ self._show_interface = function() { try { Call.show_interface( self, $('#muji'), $('#muji .videoroom') ); self._message_scroll(); self._message_unnotify(); } catch(e) { Console.error('Muji._show_interface', e); } finally { return false; } }; /** * Hide the Muji interface * @private * @return {boolean} */ self._hide_interface = function() { try { Call.hide_interface( $('#muji'), $('#muji .videoroom') ); } catch(e) { Console.error('Muji._hide_interface', e); } finally { return false; } }; /** * Attaches interface events * @private * @return {boolean} */ self._events_interface = function() { try { // Common selectors var muji_chatroom = $('#muji .chatroom'); var chatroom_form = muji_chatroom.find('form.chatroom_form'); var chatroom_participants = muji_chatroom.find('.chatroom_participants'); var participants_invite = chatroom_participants.find('.participants_default_view .participants_invite'); var participants_invite_box = chatroom_participants.find('.participants_invite_box'); var participants_invite_list = participants_invite_box.find('.participants_invite_list'); var participants_invite_form = participants_invite_box.find('.participants_invite_form'); var participants_invite_input = participants_invite_form.find('input[name="xid"]'); var participants_invite_validate = participants_invite_form.find('.invite_validate'); var participants_invite_search = participants_invite_box.find('.participants_invite_search'); // Apply events Call.events_interface( self, $('#muji'), $('#muji .videoroom') ); // People invite event participants_invite.click(function() { try { if(!participants_invite_box.is(':animated')) { if(participants_invite_box.is(':hidden')) { participants_invite_box.stop(true).slideDown(250, function() { participants_invite_input.focus(); }); } else { participants_invite_input.blur(); participants_invite_box.stop(true).slideUp(250, function() { // Reset everything participants_invite_list.empty().hide(); participants_invite_validate.hide(); participants_invite_input.val(''); self._reset_participants_invite_filter(); }); } } } catch(_e) { Console.error('Muji._show_interface[event]', _e); } finally { return false; } }); // Invite input key events participants_invite_input.keydown(function(e) { try { if(e.keyCode == 9) { self._hover_participants_invite_list('down'); return false; } } catch(_e) { Console.error('Muji._show_interface[event]', _e); } }); participants_invite_input.keyup(function(e) { try { var this_sel = $(this); if(e.keyCode == 27) { // Escape: close interface if(!this_sel.val().trim()) { participants_invite.click(); } else { self._reset_participants_invite_filter(); } return false; } else if(e.keyCode == 9) { // Tabulate: skip there (see keydown above) return false; } else if(e.keyCode == 38 || e.keyCode == 40) { var direction = (e.keyCode == 38) ? 'up' : 'down'; self._hover_participants_invite_list(direction); return false; } else { // Other keys: assume something has been typed self._engage_participants_invite_filter( this_sel.val() ); } } catch(_e) { Console.error('Muji._show_interface[event]', _e); } }); // Input auto-focus chatroom_form.click(function() { chatroom_form.find('input[name="message"]').focus(); }); // Invite form send event participants_invite_form.submit(function() { try { if(participants_invite_search.find('.participant_search_one.hover').size()) { // Add the hovered user var participant_search_one_hover_sel = participants_invite_search.find('.participant_search_one.hover:first'); if(participant_search_one_hover_sel.size() >= 1) { participant_search_one_hover_sel.click(); return false; } } else { var invite_arr = Object.keys(self._list_participants_invite_list()); if(invite_arr && invite_arr.length) { self._send_participants_invite_list(invite_arr); } participants_invite.click(); } } catch(_e) { Console.error('Muji._show_interface[event]', _e); } finally { return false; } }); // Invite form validate event participants_invite_validate.click(function() { try { participants_invite_form.submit(); } catch(_e) { Console.error('Muji._show_interface[event]', _e); } finally { return false; } }); // Message send event chatroom_form.submit(function() { try { if(self._session === null) { throw 'Muji session unavailable'; } var input_sel = $(this).find('input[name="message"]'); var body = input_sel.val(); if(body) { self._session.send_message(body); input_sel.val(''); } } catch(_e) { Console.error('Muji._show_interface[event]', _e); } finally { return false; } }); } catch(e) { Console.error('Muji._events_interface', e); } finally { return false; } }; /** * Plugin launcher * @public * @return {undefined} */ self.launch = function() { try { $(window).resize(self._adapt()); } catch(e) { Console.error('Muji.launch', e); } }; /** * Return class scope */ return self; })(); Muji.launch();