For newer versions of CallManager, the JTAPI Device State Server was made available to do exactly that. A snippet from the Developer Guide:
Device State Server provides the cumulative state of all the addresses on a terminal. These events are delivered as TerminalEvent. Applications need to add TerminalObserver to get these events.
States are defined as follows
IDLEIf there are no calls on any of the addresses on the terminal, then the DeviceState is considered IDLE, and Cisco JTAPI sends CiscoTermDeviceStateIdleEv toapplications.
ACTIVEIf any of the addresses on the terminal have an outgoing call (in CTI State Dialtone, Dialing, Proceeding, Ringback, or Connected) or an incoming call (in CTI State Connected), then the DeviceState is ACTIVE and Cisco JTAPI sends CiscoTermDeviceStateActiveEv to the application.
ALERTINGIf none of the addresses on the terminal have an outgoing call (in CTI State Dialtone, Dialing, Proceeding, Ringback, or Connected) or an incoming call (in CTI State Connected) and at least one of the addresses on the terminal has an unanswered incoming call (in CTI State Offering, Accepted, or Tinging), then the DeviceState is ALERTING and Cisco JTAPI sends CiscoTermDeviceStateAlertingEv to the application.
HELDIf all the calls on any of the address on the terminal are held (in CTI State OnHold) the DeviceState is HELD and Cisco JTAPI sends CiscoTermDeviceStateHeldEv to the application.
Search cisco.com for "JTAPI developer guide" to find out more.