001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.networktables;
006
007import java.util.EnumSet;
008
009/**
010 * Event listener poller. This queues events matching the specified mask. Code using the listener
011 * must periodically call readQueue() to read the events.
012 */
013public final class NetworkTableListenerPoller implements AutoCloseable {
014  /**
015   * Construct a topic listener poller.
016   *
017   * @param inst Instance
018   */
019  public NetworkTableListenerPoller(NetworkTableInstance inst) {
020    m_inst = inst;
021    m_handle = NetworkTablesJNI.createListenerPoller(inst.getHandle());
022  }
023
024  /**
025   * Start listening to topic changes for topics with names that start with any of the given
026   * prefixes. This creates a corresponding internal subscriber with the lifetime of the listener.
027   *
028   * @param prefixes Topic name string prefixes
029   * @param eventKinds set of event kinds to listen to
030   * @return Listener handle
031   */
032  public int addListener(String[] prefixes, EnumSet<NetworkTableEvent.Kind> eventKinds) {
033    return NetworkTablesJNI.addListener(m_handle, prefixes, eventKinds);
034  }
035
036  /**
037   * Start listening to changes to a particular topic. This creates a corresponding internal
038   * subscriber with the lifetime of the listener.
039   *
040   * @param topic Topic
041   * @param eventKinds set of event kinds to listen to
042   * @return Listener handle
043   */
044  public int addListener(Topic topic, EnumSet<NetworkTableEvent.Kind> eventKinds) {
045    return NetworkTablesJNI.addListener(m_handle, topic.getHandle(), eventKinds);
046  }
047
048  /**
049   * Start listening to topic changes on a subscriber. This does NOT keep the subscriber active.
050   *
051   * @param subscriber Subscriber
052   * @param eventKinds set of event kinds to listen to
053   * @return Listener handle
054   */
055  public int addListener(Subscriber subscriber, EnumSet<NetworkTableEvent.Kind> eventKinds) {
056    return NetworkTablesJNI.addListener(m_handle, subscriber.getHandle(), eventKinds);
057  }
058
059  /**
060   * Start listening to topic changes on a subscriber. This does NOT keep the subscriber active.
061   *
062   * @param subscriber Subscriber
063   * @param eventKinds set of event kinds to listen to
064   * @return Listener handle
065   */
066  public int addListener(MultiSubscriber subscriber, EnumSet<NetworkTableEvent.Kind> eventKinds) {
067    return NetworkTablesJNI.addListener(m_handle, subscriber.getHandle(), eventKinds);
068  }
069
070  /**
071   * Start listening to topic changes on an entry.
072   *
073   * @param entry Entry
074   * @param eventKinds set of event kinds to listen to
075   * @return Listener handle
076   */
077  public int addListener(NetworkTableEntry entry, EnumSet<NetworkTableEvent.Kind> eventKinds) {
078    return NetworkTablesJNI.addListener(m_handle, entry.getHandle(), eventKinds);
079  }
080
081  /**
082   * Add a connection listener. The callback function is called asynchronously on a separate thread,
083   * so it's important to use synchronization or atomics when accessing any shared state from the
084   * callback function.
085   *
086   * @param immediateNotify notify listener of all existing connections
087   * @return Listener handle
088   */
089  public int addConnectionListener(boolean immediateNotify) {
090    EnumSet<NetworkTableEvent.Kind> eventKinds = EnumSet.of(NetworkTableEvent.Kind.kConnection);
091    if (immediateNotify) {
092      eventKinds.add(NetworkTableEvent.Kind.kImmediate);
093    }
094    return NetworkTablesJNI.addListener(m_handle, m_inst.getHandle(), eventKinds);
095  }
096
097  /**
098   * Add a time synchronization listener. The callback function is called asynchronously on a
099   * separate thread, so it's important to use synchronization or atomics when accessing any shared
100   * state from the callback function.
101   *
102   * @param immediateNotify notify listener of current time synchronization value
103   * @return Listener handle
104   */
105  public int addTimeSyncListener(boolean immediateNotify) {
106    EnumSet<NetworkTableEvent.Kind> eventKinds = EnumSet.of(NetworkTableEvent.Kind.kTimeSync);
107    if (immediateNotify) {
108      eventKinds.add(NetworkTableEvent.Kind.kImmediate);
109    }
110    return NetworkTablesJNI.addListener(m_handle, m_inst.getHandle(), eventKinds);
111  }
112
113  /**
114   * Add logger callback function. By default, log messages are sent to stderr; this function sends
115   * log messages with the specified levels to the provided callback function instead. The callback
116   * function will only be called for log messages with level greater than or equal to minLevel and
117   * less than or equal to maxLevel; messages outside this range will be silently ignored.
118   *
119   * @param minLevel minimum log level
120   * @param maxLevel maximum log level
121   * @return Listener handle
122   */
123  public int addLogger(int minLevel, int maxLevel) {
124    return NetworkTablesJNI.addLogger(m_handle, minLevel, maxLevel);
125  }
126
127  /**
128   * Remove a listener.
129   *
130   * @param listener Listener handle
131   */
132  public void removeListener(int listener) {
133    NetworkTablesJNI.removeListener(listener);
134  }
135
136  /**
137   * Read topic notifications.
138   *
139   * @return Topic notifications since the previous call to readQueue()
140   */
141  public NetworkTableEvent[] readQueue() {
142    return NetworkTablesJNI.readListenerQueue(m_inst, m_handle);
143  }
144
145  @Override
146  public synchronized void close() {
147    if (m_handle != 0) {
148      NetworkTablesJNI.destroyListenerPoller(m_handle);
149    }
150    m_handle = 0;
151  }
152
153  /**
154   * Determines if the native handle is valid.
155   *
156   * @return True if the native handle is valid, false otherwise.
157   */
158  public boolean isValid() {
159    return m_handle != 0;
160  }
161
162  /**
163   * Gets the native handle.
164   *
165   * @return Handle
166   */
167  public int getHandle() {
168    return m_handle;
169  }
170
171  private final NetworkTableInstance m_inst;
172  private int m_handle;
173}