diff options
author | Damian Minkov <damencho@jitsi.org> | 2015-04-01 14:19:30 +0300 |
---|---|---|
committer | Damian Minkov <damencho@jitsi.org> | 2015-04-01 14:28:24 +0300 |
commit | e812038241452ca0c169e918655e27cedfee6a56 (patch) | |
tree | 04a94c8f26b8f98fe41d90ceff467b290f6ba7e3 /src | |
parent | bdb5b62fb155f9b65a7dbaa9060c79c78e519479 (diff) | |
download | jitsi-e812038241452ca0c169e918655e27cedfee6a56.zip jitsi-e812038241452ca0c169e918655e27cedfee6a56.tar.gz jitsi-e812038241452ca0c169e918655e27cedfee6a56.tar.bz2 |
Adds plugin that adds contact source services (groups to the contact list) with the monitored lines of OperationSetTelephonyBLF. Adds custom action button to pickup calls is possible.
Diffstat (limited to 'src')
7 files changed, 885 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/plugin/busylampfield/BLFActivator.java b/src/net/java/sip/communicator/plugin/busylampfield/BLFActivator.java new file mode 100644 index 0000000..a8b7807 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/busylampfield/BLFActivator.java @@ -0,0 +1,249 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.busylampfield; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.customcontactactions.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.*; +import org.jitsi.service.configuration.*; +import org.osgi.framework.*; + +import java.util.*; + +/** + * OSGi Activator for the Busy Lamp Field Plugin. + * + * @author Damian Minkov + */ +public class BLFActivator + implements BundleActivator, + ServiceListener, + BLFStatusListener +{ + /** + * The bundle context. + */ + static BundleContext bundleContext; + + /** + * Property to enable/disable this plugin. + */ + private static final String BLF_PLUGIN_ENABLED = + "net.java.sip.communicator.plugin.busylampfield.ENABLED"; + + /** + * The name of default group name if none is present. + */ + private static final String BLF_DEFAULT_GROUP_NAME = "Monitored Lines"; + + /** + * List of currently registered contact source services for the + * corresponding group. + */ + private Map<String, ServiceRegistration<ContactSourceService>> + currentBLFGroups = new LinkedHashMap + <String, ServiceRegistration<ContactSourceService>>(); + + /** + * Starts implementation. + * + * @param bundleContext + * @throws Exception + */ + @Override + public void start(BundleContext bundleContext) + throws Exception + { + ConfigurationService config = ServiceUtils.getService( + bundleContext, ConfigurationService.class); + + if(!config.getBoolean(BLF_PLUGIN_ENABLED, false)) + return; + + BLFActivator.bundleContext = bundleContext; + + bundleContext.addServiceListener(this); + + initProviders(); + + bundleContext.registerService( + CustomContactActionsService.class.getName(), + new CustomActionsBLFSourceContact(), + null + ); + } + + /** + * Stops. + * @param bundleContext + * @throws Exception + */ + @Override + public void stop(BundleContext bundleContext) + throws Exception + {} + + /** + * Listens for registered providers. + * @param serviceEvent + */ + @Override + public void serviceChanged(ServiceEvent serviceEvent) + { + ServiceReference<?> serviceRef = serviceEvent.getServiceReference(); + + // if the event is caused by a bundle being stopped, we don't want to + // know + if(serviceRef.getBundle().getState() == Bundle.STOPPING) + return; + + Object service = bundleContext.getService(serviceRef); + + // we don't care if the source service is not a protocol provider + if(!(service instanceof ProtocolProviderService)) + return; + + switch(serviceEvent.getType()) + { + case ServiceEvent.REGISTERED: + handleProviderAdded((ProtocolProviderService) service); + break; + case ServiceEvent.UNREGISTERING: + handleProviderRemoved((ProtocolProviderService) service); + break; + } + } + + /** + * Initializes all currently registered protocol providers that contain + * the desired operation set. + */ + private void initProviders() + { + for(ServiceReference<ProtocolProviderService> serRef : + ServiceUtils.getServiceReferences( + bundleContext, ProtocolProviderService.class)) + { + handleProviderAdded(bundleContext.getService(serRef)); + } + } + + /** + * Adds a protocol provider, when such provider is registered. + * + * @param protocolProvider the <tt>ProtocolProviderService</tt> to add + */ + private void handleProviderAdded(ProtocolProviderService protocolProvider) + { + OperationSetTelephonyBLF opset = + protocolProvider.getOperationSet(OperationSetTelephonyBLF.class); + + if(opset == null) + return; + + opset.addStatusListener(this); + + for(OperationSetTelephonyBLF.Line line + : opset.getCurrentlyMonitoredLines()) + { + String groupName = line.getGroup(); + if(groupName == null) + groupName = BLF_DEFAULT_GROUP_NAME; + + ServiceRegistration<ContactSourceService> serviceReg + = currentBLFGroups.get(groupName); + + if(serviceReg != null) + { + BLFContactSourceService css + = (BLFContactSourceService)bundleContext.getService( + serviceReg.getReference()); + css.addLine(line); + + continue; + } + else + { + BLFContactSourceService css + = new BLFContactSourceService( + groupName, currentBLFGroups.size() + 1); + + serviceReg = (ServiceRegistration<ContactSourceService>) + bundleContext.registerService( + ContactSourceService.class.getName(), + css, + null); + currentBLFGroups.put(groupName, serviceReg); + + css.addLine(line); + } + } + } + + /** + * Removes a protocol provider from the list when unregistered. + * @param protocolProvider the <tt>ProtocolProviderService</tt> to remove + */ + private void handleProviderRemoved(ProtocolProviderService protocolProvider) + { + OperationSetTelephonyBLF opset = + protocolProvider.getOperationSet(OperationSetTelephonyBLF.class); + + if(opset == null) + return; + + opset.removeStatusListener(this); + + for(OperationSetTelephonyBLF.Line line + : opset.getCurrentlyMonitoredLines()) + { + String groupName = line.getGroup(); + if(groupName == null) + groupName = BLF_DEFAULT_GROUP_NAME; + + ServiceRegistration<ContactSourceService> serviceReg + = currentBLFGroups.remove(groupName); + + if(serviceReg == null) + continue; + + serviceReg.unregister(); + } + } + + /** + * Called whenever a change occurs in the BLFStatus of one of the + * monitored lines that we have subscribed for. + * @param event the BLFStatusEvent describing the status change. + */ + @Override + public void blfStatusChanged(BLFStatusEvent event) + { + if(!(event.getSource() instanceof OperationSetTelephonyBLF.Line)) + return; + + OperationSetTelephonyBLF.Line line + = (OperationSetTelephonyBLF.Line)event.getSource(); + + String gr = line.getGroup(); + if(gr == null) + gr = BLF_DEFAULT_GROUP_NAME; + + ServiceRegistration<ContactSourceService> serviceReg + = currentBLFGroups.get(gr); + + if(serviceReg == null) + return; + + BLFContactSourceService css + = (BLFContactSourceService)bundleContext.getService( + serviceReg.getReference()); + css.updateLineStatus(line, event.getType()); + } +}
\ No newline at end of file diff --git a/src/net/java/sip/communicator/plugin/busylampfield/BLFContactQuery.java b/src/net/java/sip/communicator/plugin/busylampfield/BLFContactQuery.java new file mode 100644 index 0000000..ef0150a --- /dev/null +++ b/src/net/java/sip/communicator/plugin/busylampfield/BLFContactQuery.java @@ -0,0 +1,152 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.busylampfield; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; + +import java.util.*; + +/** + * The query that will update lines. + * + * @author Damian Minkov + */ +public class BLFContactQuery + extends AbstractContactQuery<BLFContactSourceService> +{ + /** + * The query string. + */ + private String queryString; + + /** + * The query result list. + */ + private final List<SourceContact> results; + + /** + * Constructs new query. + * + * @param parentService the parent contact source service + * @param queryString the query string + * @param contactCount contacts to process, not used currently. + */ + public BLFContactQuery( + BLFContactSourceService parentService, + Collection<OperationSetTelephonyBLF.Line> monitoredLines, + String queryString, int contactCount) + { + super(parentService); + + this.queryString = queryString; + this.results = new ArrayList<SourceContact>(); + for(OperationSetTelephonyBLF.Line line : monitoredLines) + { + addLine(line, false); + } + } + + /** + * Returns the query string. + * + * @return the query string + */ + @Override + public String getQueryString() + { + return queryString; + } + + /** + * Returns the list of query results. + * + * @return the list of query results + */ + @Override + public List<SourceContact> getQueryResults() + { + return results; + } + + /** + * Starts this <tt>BLFContactQuery</tt>. + */ + @Override + public void start() + { + for(SourceContact sc : results) + { + fireContactReceived(sc, false); + } + } + + /** + * Adds new line to display. + * @param line to display status. + * @param fireEvent whether to fire events + */ + void addLine(OperationSetTelephonyBLF.Line line, boolean fireEvent) + { + for(SourceContact sc : results) + { + BLFSourceContact blfSC = (BLFSourceContact)sc; + + if(blfSC.getLine().equals(line)) + return; + } + + BLFSourceContact sc + = new BLFSourceContact(getContactSource(), line); + results.add(sc); + + if(fireEvent) + fireContactReceived(sc, false); + } + + /** + * Updates the source contact status. + * @param line + * @param status + */ + void updateLineStatus(OperationSetTelephonyBLF.Line line, int status) + { + for(SourceContact sc : results) + { + BLFSourceContact blfSC = (BLFSourceContact)sc; + if(blfSC.getLine().equals(line)) + { + blfSC.setPresenceStatus(getPresenceStatus(status)); + fireContactChanged(blfSC); + break; + } + } + } + + /** + * Maps BLFStatusEvent.type to BLFPresenceStatus. + * @param status the staus to map. + * @return the corresponding BLFPresenceStatus. + */ + private BLFPresenceStatus getPresenceStatus(int status) + { + switch(status) + { + case BLFStatusEvent.STATUS_BUSY: + return BLFPresenceStatus.BLF_BUSY; + case BLFStatusEvent.STATUS_OFFLINE: + return BLFPresenceStatus.BLF_OFFLINE; + case BLFStatusEvent.STATUS_RINGING: + return BLFPresenceStatus.BLF_RINGING; + case BLFStatusEvent.STATUS_FREE: + return BLFPresenceStatus.BLF_FREE; + default: + return null; + } + } +} diff --git a/src/net/java/sip/communicator/plugin/busylampfield/BLFContactSourceService.java b/src/net/java/sip/communicator/plugin/busylampfield/BLFContactSourceService.java new file mode 100644 index 0000000..264758c --- /dev/null +++ b/src/net/java/sip/communicator/plugin/busylampfield/BLFContactSourceService.java @@ -0,0 +1,158 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.busylampfield; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.Logger; +import org.jitsi.util.*; + +import java.util.*; + +/** + * The contact source service to manage query and lines. + * + * @author Damian Minkov + */ +public class BLFContactSourceService + implements ContactSourceService +{ + /** + * The <tt>Logger</tt> used by the + * <tt>ConfCallsContactSource</tt> class for logging output. + */ + private static final Logger logger + = Logger.getLogger(BLFContactSourceService.class); + + /** + * Type of a recent messages source. + */ + public static final int BLF_TYPE = CONTACT_LIST_TYPE; + + + /** + * Constants to display name <tt>ContactSource</tt>. + */ + private final String displayName; + + /** + * The latest query. + */ + private BLFContactQuery ourContactQuery = null; + + /** + * The list of lines this service will handle. + */ + private Set<OperationSetTelephonyBLF.Line> monitoredLines + = new HashSet<OperationSetTelephonyBLF.Line>(); + + /** + * The current group index. + */ + private final int index; + + /** + * Constructs. + * @param displayName + */ + public BLFContactSourceService(String displayName, int index) + { + this.displayName = displayName; + this.index = index; + } + + /** + * Returns the identifier of this contact source. Some of the common + * identifiers are defined here (For example the CALL_HISTORY identifier + * should be returned by all call history implementations of this interface) + * @return the identifier of this contact source + */ + @Override + public int getType() + { + return BLF_TYPE; + } + + /** + * Returns a user-friendly string that identifies this contact source. + * @return the display name of this contact source + */ + @Override + public String getDisplayName() + { + return displayName; + } + + /** + * Queries this search source for the given <tt>queryString</tt>. + * @param queryString the string to search for + * @return the created query + */ + @Override + public ContactQuery createContactQuery(String queryString) + { + return createContactQuery(queryString, 20); + } + + /** + * Queries this search source for the given <tt>queryString</tt>. + * + * @param queryString the string to search for + * @param contactCount the maximum count of result contacts + * @return the created query + */ + @Override + public ContactQuery createContactQuery(String queryString, int contactCount) + { + if(!StringUtils.isNullOrEmpty(queryString)) + return null; + + if(ourContactQuery == null) + ourContactQuery = new BLFContactQuery( + this, monitoredLines, queryString, contactCount); + + return ourContactQuery; + } + + /** + * Returns the index of the contact source in the result list. + * + * @return the index of the contact source in the result list + */ + @Override + public int getIndex() + { + // shift it with 2 position (recent messages-0 and chat rooms-1), + // counting from 0 + return 1 + index; + } + + /** + * Adds new line to display. + * @param line to display status. + */ + void addLine(OperationSetTelephonyBLF.Line line) + { + monitoredLines.add(line); + + if(ourContactQuery != null) + ourContactQuery.addLine(line, true); + } + + /** + * Updates the source contact status. + * @param line + * @param status + */ + void updateLineStatus(OperationSetTelephonyBLF.Line line, int status) + { + if(ourContactQuery == null) + return; + + ourContactQuery.updateLineStatus(line, status); + } +} diff --git a/src/net/java/sip/communicator/plugin/busylampfield/BLFPresenceStatus.java b/src/net/java/sip/communicator/plugin/busylampfield/BLFPresenceStatus.java new file mode 100644 index 0000000..d448be7 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/busylampfield/BLFPresenceStatus.java @@ -0,0 +1,77 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.busylampfield; + +import net.java.sip.communicator.service.protocol.*; + +/** + * The status to display for the contact srouces. + * @author Damian Minkov + */ +public class BLFPresenceStatus + extends PresenceStatus +{ + /** + * The Online status. Indicate that the line is available and free. + */ + public static final String AVAILABLE = "Available"; + + /** + * On The Phone Chat status. + * Indicates that the line is used. + */ + public static final String BUSY = "Busy"; + + /** + * Ringing status. + * Indicates that the line is currently ringing. + */ + public static final String RINGING = "On the phone"; + + /** + * Indicates an Offline status or status with 0 connectivity. + */ + public static final String OFFLINE = "Offline"; + + /** + * The Online status. Indicate that the line is free. + */ + public static final BLFPresenceStatus BLF_FREE = new BLFPresenceStatus( + 65, AVAILABLE); + + /** + * The Offline status. Indicates the line status retrieval + * is not available. + */ + public static final BLFPresenceStatus BLF_OFFLINE = new BLFPresenceStatus( + 0, OFFLINE); + + /** + * Indicates an On The Phone status. + */ + public static final BLFPresenceStatus BLF_BUSY = new BLFPresenceStatus( + 30, BUSY); + + /** + * Indicates Ringing status. + */ + public static final BLFPresenceStatus BLF_RINGING = new BLFPresenceStatus( + 31, RINGING); + + /** + * Creates an instance of <tt>BLFPresenceStatus</tt> with the + * specified parameters. + * + * @param status the connectivity level of the new presence status + * instance + * @param statusName the name of the presence status. + */ + private BLFPresenceStatus(int status, String statusName) + { + super(status, statusName); + } +} diff --git a/src/net/java/sip/communicator/plugin/busylampfield/BLFSourceContact.java b/src/net/java/sip/communicator/plugin/busylampfield/BLFSourceContact.java new file mode 100644 index 0000000..6ec3167 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/busylampfield/BLFSourceContact.java @@ -0,0 +1,47 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.busylampfield; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.protocol.*; + +import java.util.*; + +/** + * The BLF source contact. + * @author Damian Minkov + */ +public class BLFSourceContact + extends GenericSourceContact +{ + private final OperationSetTelephonyBLF.Line line; + + /** + * Initializes a new <tt>AddrBookSourceContact</tt> instance. + * + * @param contactSource the <tt>ContactSourceService</tt> which is creating + * the new instance + */ + public BLFSourceContact(ContactSourceService contactSource, + OperationSetTelephonyBLF.Line line) + { + super(contactSource, + line.getName() != null ? line.getName() : line.getAddress(), + new ArrayList<ContactDetail>()); + + this.line = line; + } + + /** + * Returns the line displayed. + * @return + */ + public OperationSetTelephonyBLF.Line getLine() + { + return line; + } +} diff --git a/src/net/java/sip/communicator/plugin/busylampfield/CustomActionsBLFSourceContact.java b/src/net/java/sip/communicator/plugin/busylampfield/CustomActionsBLFSourceContact.java new file mode 100644 index 0000000..23edae9 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/busylampfield/CustomActionsBLFSourceContact.java @@ -0,0 +1,188 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.busylampfield; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.customcontactactions.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.util.*; + +import java.util.*; + +/** + * Custom acction to show pickup call button. + * + * @author Damian Minkov + */ +public class CustomActionsBLFSourceContact + implements CustomContactActionsService<SourceContact> +{ + /** + * Our logger. + */ + private final Logger logger = Logger.getLogger( + CustomActionsBLFSourceContact.class); + + /** + * List of actions. + */ + private final List<ContactAction<SourceContact>> actionsList + = new LinkedList<ContactAction<SourceContact>>(); + + public CustomActionsBLFSourceContact() + { + actionsList.add(new PickupAction()); + } + + /** + * Returns the template class that this service has been initialized with + * + * @return the template class + */ + @Override + public Class<SourceContact> getContactSourceClass() + { + return SourceContact.class; + } + + /** + * Returns all custom actions defined by this service. + * + * @return an iterator over a list of <tt>ContactAction</tt>s + */ + @Override + public Iterator<ContactAction<SourceContact>> getCustomContactActions() + { + return actionsList.iterator(); + } + + /** + * Returns all custom actions menu items defined by this service. + * + * @return an iterator over a list of <tt>ContactActionMenuItem</tt>s + */ + @Override + public Iterator<ContactActionMenuItem<SourceContact>> + getCustomContactActionsMenuItems() + { + return null; + } + + /** + * Action that represents pickup button. + */ + private class PickupAction + implements ContactAction<SourceContact> + { + /** + * Invoked when an action occurs. + * + * @param actionSource the source of the action + * @param x the x coordinate of the action + * @param y the y coordinate of the action + */ + @Override + public void actionPerformed(final SourceContact actionSource, int x, int y) + throws + OperationFailedException + { + if(!(actionSource instanceof BLFSourceContact)) + return; + + new Thread(new Runnable() + { + public void run() + { + try + { + OperationSetTelephonyBLF.Line line + = ((BLFSourceContact)actionSource).getLine(); + OperationSetTelephonyBLF opset = + line.getProvider().getOperationSet( + OperationSetTelephonyBLF.class); + opset.pickup(line); + } + catch(Exception ex) + { + logger.error("Error picking up call", ex); + } + } + }).start(); + } + + /** + * The icon used by the UI to visualize this action. + * @return the button icon. + */ + @Override + public byte[] getIcon() + { + return ResourceManagementServiceUtils.getService( + BLFActivator.bundleContext).getImageInBytes( + "plugin.busylampfield.PICKUP_CALL"); + } + + /** + * The icon used by the UI to visualize this action. + * @return the button icon. + */ + @Override + public byte[] getRolloverIcon() + { + return ResourceManagementServiceUtils.getService( + BLFActivator.bundleContext).getImageInBytes( + "plugin.busylampfield.PICKUP_CALL_ROLLOVER"); + } + + /** + * The icon used by the UI to visualize this action. + * @return the button icon. + */ + @Override + public byte[] getPressedIcon() + { + return ResourceManagementServiceUtils.getService( + BLFActivator.bundleContext).getImageInBytes( + "plugin.busylampfield.PICKUP_CALL_PRESSED"); + } + + /** + * Returns the tool tip text of the component to create for this contact + * action. + * + * @return the tool tip text of the component to create for this contact + * action + */ + @Override + public String getToolTipText() + { + return ResourceManagementServiceUtils.getService( + BLFActivator.bundleContext).getI18NString( + "plugin.busylampfield.PICKUP"); + } + + /** + * Indicates if this action is visible for the + * given <tt>actionSource</tt>. + * + * @param actionSource the action source for which we're verifying the + * action. + * @return <tt>true</tt> if the action should be visible for the given + * <tt>actionSource</tt>, <tt>false</tt> - otherwise + */ + @Override + public boolean isVisible(SourceContact actionSource) + { + if(actionSource.getPresenceStatus() + .equals(BLFPresenceStatus.BLF_RINGING)) + return true; + else + return false; + } + } +}
\ No newline at end of file diff --git a/src/net/java/sip/communicator/plugin/busylampfield/busylampfield.manifest.mf b/src/net/java/sip/communicator/plugin/busylampfield/busylampfield.manifest.mf new file mode 100644 index 0000000..91f2de6 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/busylampfield/busylampfield.manifest.mf @@ -0,0 +1,14 @@ +Bundle-Activator: net.java.sip.communicator.plugin.busylampfield.BLFActivator +Bundle-Name: Busy Lamp Field Plugin +Bundle-Description: Contact Sources that show and control BLF operation sets +Bundle-Vendor: jitsi.org +Bundle-Version: 0.0.1 +Bundle-SymbolicName: net.java.sip.communicator.plugin.busylampfield +Import-Package: org.osgi.framework, + org.jitsi.service.configuration, + net.java.sip.communicator.service.contactsource, + net.java.sip.communicator.service.customcontactactions, + net.java.sip.communicator.service.protocol, + net.java.sip.communicator.service.protocol.event, + net.java.sip.communicator.service.resources, org.jitsi.service.resources, + net.java.sip.communicator.util, org.jitsi.util |