RtpCapability.java

  1package eu.siacs.conversations.xmpp.jingle;
  2
  3import com.google.common.base.Strings;
  4import com.google.common.collect.Collections2;
  5
  6import java.util.ArrayList;
  7import java.util.Arrays;
  8import java.util.Collection;
  9import java.util.Collections;
 10import java.util.List;
 11import java.util.Map;
 12
 13import eu.siacs.conversations.entities.Contact;
 14import eu.siacs.conversations.entities.Presence;
 15import eu.siacs.conversations.entities.Presences;
 16import eu.siacs.conversations.entities.ServiceDiscoveryResult;
 17import eu.siacs.conversations.xml.Namespace;
 18
 19public class RtpCapability {
 20
 21    private static final List<String> BASIC_RTP_REQUIREMENTS = Arrays.asList(
 22            Namespace.JINGLE,
 23            Namespace.JINGLE_TRANSPORT_ICE_UDP,
 24            Namespace.JINGLE_APPS_RTP,
 25            Namespace.JINGLE_APPS_DTLS
 26    );
 27    private static final List<String> VIDEO_REQUIREMENTS = Arrays.asList(
 28            Namespace.JINGLE_FEATURE_AUDIO,
 29            Namespace.JINGLE_FEATURE_VIDEO
 30    );
 31
 32    public static Capability check(final Presence presence) {
 33        final ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
 34        final List<String> features = disco == null ? Collections.emptyList() : disco.getFeatures();
 35        if (features.containsAll(BASIC_RTP_REQUIREMENTS)) {
 36            if (features.containsAll(VIDEO_REQUIREMENTS)) {
 37                return Capability.VIDEO;
 38            }
 39            if (features.contains(Namespace.JINGLE_FEATURE_AUDIO)) {
 40                return Capability.AUDIO;
 41            }
 42        }
 43        return Capability.NONE;
 44    }
 45
 46    public static String[] filterPresences(final Contact contact, Capability required) {
 47        final Presences presences = contact.getPresences();
 48        final ArrayList<String> resources = new ArrayList<>();
 49        for (final Map.Entry<String, Presence> presence : presences.getPresencesMap().entrySet()) {
 50            final Capability capability = check(presence.getValue());
 51            if (capability == Capability.NONE) {
 52                continue;
 53            }
 54            if (required == Capability.AUDIO || capability == required) {
 55                resources.add(presence.getKey());
 56            }
 57        }
 58        return resources.toArray(new String[0]);
 59    }
 60
 61    public static Capability check(final Contact contact) {
 62        return check(contact, true);
 63    }
 64
 65    public static Capability check(final Contact contact, final boolean allowFallback) {
 66        final Presences presences = contact.getPresences();
 67        if (presences.size() == 0 && allowFallback && contact.getAccount().isEnabled()) {
 68            return contact.getRtpCapability();
 69        }
 70        Capability result = Capability.NONE;
 71        for (final Presence presence : presences.getPresences()) {
 72            Capability capability = check(presence);
 73            if (capability == Capability.VIDEO) {
 74                result = capability;
 75            } else if (capability == Capability.AUDIO && result == Capability.NONE) {
 76                result = capability;
 77            }
 78        }
 79        return result;
 80    }
 81
 82    // do all devices that support Rtp Call also support JMI?
 83    public static boolean jmiSupport(final Contact contact) {
 84        return !Collections2.transform(
 85                Collections2.filter(
 86                        contact.getPresences().getPresences(),
 87                        p -> RtpCapability.check(p) != RtpCapability.Capability.NONE),
 88                p -> {
 89                    ServiceDiscoveryResult disco = p.getServiceDiscoveryResult();
 90                    return disco != null && disco.getFeatures().contains(Namespace.JINGLE_MESSAGE);
 91                }).contains(false);
 92    }
 93
 94    public enum Capability {
 95        NONE, AUDIO, VIDEO;
 96
 97        public static Capability of(String value) {
 98            if (Strings.isNullOrEmpty(value)) {
 99                return NONE;
100            }
101            try {
102                return valueOf(value);
103            } catch (IllegalArgumentException e) {
104                return NONE;
105            }
106        }
107    }
108
109}