| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 // directly. This way we don't have to link to libpulse, which means our binary | 23 // directly. This way we don't have to link to libpulse, which means our binary |
| 24 // will work on systems that don't have it. | 24 // will work on systems that don't have it. |
| 25 #define LATE(sym) \ | 25 #define LATE(sym) \ |
| 26 LATESYM_GET(webrtc_adm_linux_pulse::PulseAudioSymbolTable, &PaSymbolTable, sym
) | 26 LATESYM_GET(webrtc_adm_linux_pulse::PulseAudioSymbolTable, &PaSymbolTable, sym
) |
| 27 | 27 |
| 28 namespace webrtc | 28 namespace webrtc |
| 29 { | 29 { |
| 30 | 30 |
| 31 AudioDeviceLinuxPulse::AudioDeviceLinuxPulse(const int32_t id) : | 31 AudioDeviceLinuxPulse::AudioDeviceLinuxPulse(const int32_t id) : |
| 32 _ptrAudioBuffer(NULL), | 32 _ptrAudioBuffer(NULL), |
| 33 _critSect(*CriticalSectionWrapper::CreateCriticalSection()), | |
| 34 _timeEventRec(*EventWrapper::Create()), | 33 _timeEventRec(*EventWrapper::Create()), |
| 35 _timeEventPlay(*EventWrapper::Create()), | 34 _timeEventPlay(*EventWrapper::Create()), |
| 36 _recStartEvent(*EventWrapper::Create()), | 35 _recStartEvent(*EventWrapper::Create()), |
| 37 _playStartEvent(*EventWrapper::Create()), | 36 _playStartEvent(*EventWrapper::Create()), |
| 38 _id(id), | 37 _id(id), |
| 39 _mixerManager(id), | 38 _mixerManager(id), |
| 40 _inputDeviceIndex(0), | 39 _inputDeviceIndex(0), |
| 41 _outputDeviceIndex(0), | 40 _outputDeviceIndex(0), |
| 42 _inputDeviceIsSpecified(false), | 41 _inputDeviceIsSpecified(false), |
| 43 _outputDeviceIsSpecified(false), | 42 _outputDeviceIsSpecified(false), |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 if (_recDeviceName) | 125 if (_recDeviceName) |
| 127 { | 126 { |
| 128 delete [] _recDeviceName; | 127 delete [] _recDeviceName; |
| 129 _recDeviceName = NULL; | 128 _recDeviceName = NULL; |
| 130 } | 129 } |
| 131 | 130 |
| 132 delete &_recStartEvent; | 131 delete &_recStartEvent; |
| 133 delete &_playStartEvent; | 132 delete &_playStartEvent; |
| 134 delete &_timeEventRec; | 133 delete &_timeEventRec; |
| 135 delete &_timeEventPlay; | 134 delete &_timeEventPlay; |
| 136 delete &_critSect; | |
| 137 } | 135 } |
| 138 | 136 |
| 139 void AudioDeviceLinuxPulse::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) | 137 void AudioDeviceLinuxPulse::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) |
| 140 { | 138 { |
| 141 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 139 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 142 | 140 |
| 143 _ptrAudioBuffer = audioBuffer; | 141 _ptrAudioBuffer = audioBuffer; |
| 144 | 142 |
| 145 // Inform the AudioBuffer about default settings for this implementation. | 143 // Inform the AudioBuffer about default settings for this implementation. |
| 146 // Set all values to zero here since the actual settings will be done by | 144 // Set all values to zero here since the actual settings will be done by |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 if (_playChannels == 2) | 742 if (_playChannels == 2) |
| 745 enabled = true; | 743 enabled = true; |
| 746 else | 744 else |
| 747 enabled = false; | 745 enabled = false; |
| 748 | 746 |
| 749 return 0; | 747 return 0; |
| 750 } | 748 } |
| 751 | 749 |
| 752 int32_t AudioDeviceLinuxPulse::SetAGC(bool enable) | 750 int32_t AudioDeviceLinuxPulse::SetAGC(bool enable) |
| 753 { | 751 { |
| 754 CriticalSectionScoped lock(&_critSect); | 752 rtc::CritScope lock(&_critSect); |
| 755 _AGC = enable; | 753 _AGC = enable; |
| 756 | 754 |
| 757 return 0; | 755 return 0; |
| 758 } | 756 } |
| 759 | 757 |
| 760 bool AudioDeviceLinuxPulse::AGC() const | 758 bool AudioDeviceLinuxPulse::AGC() const |
| 761 { | 759 { |
| 762 CriticalSectionScoped lock(&_critSect); | 760 rtc::CritScope lock(&_critSect); |
| 763 return _AGC; | 761 return _AGC; |
| 764 } | 762 } |
| 765 | 763 |
| 766 int32_t AudioDeviceLinuxPulse::MicrophoneVolumeIsAvailable( | 764 int32_t AudioDeviceLinuxPulse::MicrophoneVolumeIsAvailable( |
| 767 bool& available) | 765 bool& available) |
| 768 { | 766 { |
| 769 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 767 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 770 bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); | 768 bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); |
| 771 | 769 |
| 772 // Make an attempt to open up the | 770 // Make an attempt to open up the |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 } | 1337 } |
| 1340 | 1338 |
| 1341 // Set state to ensure that the recording starts from the audio thread. | 1339 // Set state to ensure that the recording starts from the audio thread. |
| 1342 _startRec = true; | 1340 _startRec = true; |
| 1343 | 1341 |
| 1344 // The audio thread will signal when recording has started. | 1342 // The audio thread will signal when recording has started. |
| 1345 _timeEventRec.Set(); | 1343 _timeEventRec.Set(); |
| 1346 if (kEventTimeout == _recStartEvent.Wait(10000)) | 1344 if (kEventTimeout == _recStartEvent.Wait(10000)) |
| 1347 { | 1345 { |
| 1348 { | 1346 { |
| 1349 CriticalSectionScoped lock(&_critSect); | 1347 rtc::CritScope lock(&_critSect); |
| 1350 _startRec = false; | 1348 _startRec = false; |
| 1351 } | 1349 } |
| 1352 StopRecording(); | 1350 StopRecording(); |
| 1353 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1351 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, |
| 1354 " failed to activate recording"); | 1352 " failed to activate recording"); |
| 1355 return -1; | 1353 return -1; |
| 1356 } | 1354 } |
| 1357 | 1355 |
| 1358 { | 1356 { |
| 1359 CriticalSectionScoped lock(&_critSect); | 1357 rtc::CritScope lock(&_critSect); |
| 1360 if (_recording) | 1358 if (_recording) |
| 1361 { | 1359 { |
| 1362 // The recording state is set by the audio thread after recording | 1360 // The recording state is set by the audio thread after recording |
| 1363 // has started. | 1361 // has started. |
| 1364 } else | 1362 } else |
| 1365 { | 1363 { |
| 1366 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1364 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, |
| 1367 " failed to activate recording"); | 1365 " failed to activate recording"); |
| 1368 return -1; | 1366 return -1; |
| 1369 } | 1367 } |
| 1370 } | 1368 } |
| 1371 | 1369 |
| 1372 return 0; | 1370 return 0; |
| 1373 } | 1371 } |
| 1374 | 1372 |
| 1375 int32_t AudioDeviceLinuxPulse::StopRecording() | 1373 int32_t AudioDeviceLinuxPulse::StopRecording() |
| 1376 { | 1374 { |
| 1377 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1375 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 1378 CriticalSectionScoped lock(&_critSect); | 1376 rtc::CritScope lock(&_critSect); |
| 1379 | 1377 |
| 1380 if (!_recIsInitialized) | 1378 if (!_recIsInitialized) |
| 1381 { | 1379 { |
| 1382 return 0; | 1380 return 0; |
| 1383 } | 1381 } |
| 1384 | 1382 |
| 1385 if (_recStream == NULL) | 1383 if (_recStream == NULL) |
| 1386 { | 1384 { |
| 1387 return -1; | 1385 return -1; |
| 1388 } | 1386 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 return -1; | 1460 return -1; |
| 1463 } | 1461 } |
| 1464 | 1462 |
| 1465 if (_playing) | 1463 if (_playing) |
| 1466 { | 1464 { |
| 1467 return 0; | 1465 return 0; |
| 1468 } | 1466 } |
| 1469 | 1467 |
| 1470 // Set state to ensure that playout starts from the audio thread. | 1468 // Set state to ensure that playout starts from the audio thread. |
| 1471 { | 1469 { |
| 1472 CriticalSectionScoped lock(&_critSect); | 1470 rtc::CritScope lock(&_critSect); |
| 1473 _startPlay = true; | 1471 _startPlay = true; |
| 1474 } | 1472 } |
| 1475 | 1473 |
| 1476 // Both |_startPlay| and |_playing| needs protction since they are also | 1474 // Both |_startPlay| and |_playing| needs protction since they are also |
| 1477 // accessed on the playout thread. | 1475 // accessed on the playout thread. |
| 1478 | 1476 |
| 1479 // The audio thread will signal when playout has started. | 1477 // The audio thread will signal when playout has started. |
| 1480 _timeEventPlay.Set(); | 1478 _timeEventPlay.Set(); |
| 1481 if (kEventTimeout == _playStartEvent.Wait(10000)) | 1479 if (kEventTimeout == _playStartEvent.Wait(10000)) |
| 1482 { | 1480 { |
| 1483 { | 1481 { |
| 1484 CriticalSectionScoped lock(&_critSect); | 1482 rtc::CritScope lock(&_critSect); |
| 1485 _startPlay = false; | 1483 _startPlay = false; |
| 1486 } | 1484 } |
| 1487 StopPlayout(); | 1485 StopPlayout(); |
| 1488 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1486 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, |
| 1489 " failed to activate playout"); | 1487 " failed to activate playout"); |
| 1490 return -1; | 1488 return -1; |
| 1491 } | 1489 } |
| 1492 | 1490 |
| 1493 { | 1491 { |
| 1494 CriticalSectionScoped lock(&_critSect); | 1492 rtc::CritScope lock(&_critSect); |
| 1495 if (_playing) | 1493 if (_playing) |
| 1496 { | 1494 { |
| 1497 // The playing state is set by the audio thread after playout | 1495 // The playing state is set by the audio thread after playout |
| 1498 // has started. | 1496 // has started. |
| 1499 } else | 1497 } else |
| 1500 { | 1498 { |
| 1501 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 1499 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, |
| 1502 " failed to activate playing"); | 1500 " failed to activate playing"); |
| 1503 return -1; | 1501 return -1; |
| 1504 } | 1502 } |
| 1505 } | 1503 } |
| 1506 | 1504 |
| 1507 return 0; | 1505 return 0; |
| 1508 } | 1506 } |
| 1509 | 1507 |
| 1510 int32_t AudioDeviceLinuxPulse::StopPlayout() | 1508 int32_t AudioDeviceLinuxPulse::StopPlayout() |
| 1511 { | 1509 { |
| 1512 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1510 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 1513 CriticalSectionScoped lock(&_critSect); | 1511 rtc::CritScope lock(&_critSect); |
| 1514 | 1512 |
| 1515 if (!_playIsInitialized) | 1513 if (!_playIsInitialized) |
| 1516 { | 1514 { |
| 1517 return 0; | 1515 return 0; |
| 1518 } | 1516 } |
| 1519 | 1517 |
| 1520 if (_playStream == NULL) | 1518 if (_playStream == NULL) |
| 1521 { | 1519 { |
| 1522 return -1; | 1520 return -1; |
| 1523 } | 1521 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1567 { | 1565 { |
| 1568 delete [] _playBuffer; | 1566 delete [] _playBuffer; |
| 1569 _playBuffer = NULL; | 1567 _playBuffer = NULL; |
| 1570 } | 1568 } |
| 1571 | 1569 |
| 1572 return 0; | 1570 return 0; |
| 1573 } | 1571 } |
| 1574 | 1572 |
| 1575 int32_t AudioDeviceLinuxPulse::PlayoutDelay(uint16_t& delayMS) const | 1573 int32_t AudioDeviceLinuxPulse::PlayoutDelay(uint16_t& delayMS) const |
| 1576 { | 1574 { |
| 1577 CriticalSectionScoped lock(&_critSect); | 1575 rtc::CritScope lock(&_critSect); |
| 1578 delayMS = (uint16_t) _sndCardPlayDelay; | 1576 delayMS = (uint16_t) _sndCardPlayDelay; |
| 1579 return 0; | 1577 return 0; |
| 1580 } | 1578 } |
| 1581 | 1579 |
| 1582 int32_t AudioDeviceLinuxPulse::RecordingDelay(uint16_t& delayMS) const | 1580 int32_t AudioDeviceLinuxPulse::RecordingDelay(uint16_t& delayMS) const |
| 1583 { | 1581 { |
| 1584 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1582 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 1585 delayMS = (uint16_t) _sndCardRecDelay; | 1583 delayMS = (uint16_t) _sndCardRecDelay; |
| 1586 return 0; | 1584 return 0; |
| 1587 } | 1585 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1624 int32_t AudioDeviceLinuxPulse::CPULoad(uint16_t& /*load*/) const | 1622 int32_t AudioDeviceLinuxPulse::CPULoad(uint16_t& /*load*/) const |
| 1625 { | 1623 { |
| 1626 | 1624 |
| 1627 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 1625 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 1628 " API call not supported on this platform"); | 1626 " API call not supported on this platform"); |
| 1629 return -1; | 1627 return -1; |
| 1630 } | 1628 } |
| 1631 | 1629 |
| 1632 bool AudioDeviceLinuxPulse::PlayoutWarning() const | 1630 bool AudioDeviceLinuxPulse::PlayoutWarning() const |
| 1633 { | 1631 { |
| 1634 CriticalSectionScoped lock(&_critSect); | 1632 rtc::CritScope lock(&_critSect); |
| 1635 return (_playWarning > 0); | 1633 return (_playWarning > 0); |
| 1636 } | 1634 } |
| 1637 | 1635 |
| 1638 bool AudioDeviceLinuxPulse::PlayoutError() const | 1636 bool AudioDeviceLinuxPulse::PlayoutError() const |
| 1639 { | 1637 { |
| 1640 CriticalSectionScoped lock(&_critSect); | 1638 rtc::CritScope lock(&_critSect); |
| 1641 return (_playError > 0); | 1639 return (_playError > 0); |
| 1642 } | 1640 } |
| 1643 | 1641 |
| 1644 bool AudioDeviceLinuxPulse::RecordingWarning() const | 1642 bool AudioDeviceLinuxPulse::RecordingWarning() const |
| 1645 { | 1643 { |
| 1646 CriticalSectionScoped lock(&_critSect); | 1644 rtc::CritScope lock(&_critSect); |
| 1647 return (_recWarning > 0); | 1645 return (_recWarning > 0); |
| 1648 } | 1646 } |
| 1649 | 1647 |
| 1650 bool AudioDeviceLinuxPulse::RecordingError() const | 1648 bool AudioDeviceLinuxPulse::RecordingError() const |
| 1651 { | 1649 { |
| 1652 CriticalSectionScoped lock(&_critSect); | 1650 rtc::CritScope lock(&_critSect); |
| 1653 return (_recError > 0); | 1651 return (_recError > 0); |
| 1654 } | 1652 } |
| 1655 | 1653 |
| 1656 void AudioDeviceLinuxPulse::ClearPlayoutWarning() | 1654 void AudioDeviceLinuxPulse::ClearPlayoutWarning() |
| 1657 { | 1655 { |
| 1658 CriticalSectionScoped lock(&_critSect); | 1656 rtc::CritScope lock(&_critSect); |
| 1659 _playWarning = 0; | 1657 _playWarning = 0; |
| 1660 } | 1658 } |
| 1661 | 1659 |
| 1662 void AudioDeviceLinuxPulse::ClearPlayoutError() | 1660 void AudioDeviceLinuxPulse::ClearPlayoutError() |
| 1663 { | 1661 { |
| 1664 CriticalSectionScoped lock(&_critSect); | 1662 rtc::CritScope lock(&_critSect); |
| 1665 _playError = 0; | 1663 _playError = 0; |
| 1666 } | 1664 } |
| 1667 | 1665 |
| 1668 void AudioDeviceLinuxPulse::ClearRecordingWarning() | 1666 void AudioDeviceLinuxPulse::ClearRecordingWarning() |
| 1669 { | 1667 { |
| 1670 CriticalSectionScoped lock(&_critSect); | 1668 rtc::CritScope lock(&_critSect); |
| 1671 _recWarning = 0; | 1669 _recWarning = 0; |
| 1672 } | 1670 } |
| 1673 | 1671 |
| 1674 void AudioDeviceLinuxPulse::ClearRecordingError() | 1672 void AudioDeviceLinuxPulse::ClearRecordingError() |
| 1675 { | 1673 { |
| 1676 CriticalSectionScoped lock(&_critSect); | 1674 rtc::CritScope lock(&_critSect); |
| 1677 _recError = 0; | 1675 _recError = 0; |
| 1678 } | 1676 } |
| 1679 | 1677 |
| 1680 // ============================================================================ | 1678 // ============================================================================ |
| 1681 // Private Methods | 1679 // Private Methods |
| 1682 // ============================================================================ | 1680 // ============================================================================ |
| 1683 | 1681 |
| 1684 void AudioDeviceLinuxPulse::PaContextStateCallback(pa_context *c, void *pThis) | 1682 void AudioDeviceLinuxPulse::PaContextStateCallback(pa_context *c, void *pThis) |
| 1685 { | 1683 { |
| 1686 static_cast<AudioDeviceLinuxPulse*> (pThis)-> | 1684 static_cast<AudioDeviceLinuxPulse*> (pThis)-> |
| (...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2595 case kEventSignaled: | 2593 case kEventSignaled: |
| 2596 break; | 2594 break; |
| 2597 case kEventError: | 2595 case kEventError: |
| 2598 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 2596 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 2599 "EventWrapper::Wait() failed"); | 2597 "EventWrapper::Wait() failed"); |
| 2600 return true; | 2598 return true; |
| 2601 case kEventTimeout: | 2599 case kEventTimeout: |
| 2602 return true; | 2600 return true; |
| 2603 } | 2601 } |
| 2604 | 2602 |
| 2605 CriticalSectionScoped lock(&_critSect); | 2603 rtc::CritScope lock(&_critSect); |
| 2606 | 2604 |
| 2607 if (_startPlay) | 2605 if (_startPlay) |
| 2608 { | 2606 { |
| 2609 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 2607 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 2610 "_startPlay true, performing initial actions"); | 2608 "_startPlay true, performing initial actions"); |
| 2611 | 2609 |
| 2612 _startPlay = false; | 2610 _startPlay = false; |
| 2613 _playDeviceName = NULL; | 2611 _playDeviceName = NULL; |
| 2614 | 2612 |
| 2615 // Set if not default device | 2613 // Set if not default device |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2836 case kEventSignaled: | 2834 case kEventSignaled: |
| 2837 break; | 2835 break; |
| 2838 case kEventError: | 2836 case kEventError: |
| 2839 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 2837 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 2840 "EventWrapper::Wait() failed"); | 2838 "EventWrapper::Wait() failed"); |
| 2841 return true; | 2839 return true; |
| 2842 case kEventTimeout: | 2840 case kEventTimeout: |
| 2843 return true; | 2841 return true; |
| 2844 } | 2842 } |
| 2845 | 2843 |
| 2846 CriticalSectionScoped lock(&_critSect); | 2844 rtc::CritScope lock(&_critSect); |
| 2847 | 2845 |
| 2848 if (_startRec) | 2846 if (_startRec) |
| 2849 { | 2847 { |
| 2850 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 2848 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 2851 "_startRec true, performing initial actions"); | 2849 "_startRec true, performing initial actions"); |
| 2852 | 2850 |
| 2853 _recDeviceName = NULL; | 2851 _recDeviceName = NULL; |
| 2854 | 2852 |
| 2855 // Set if not default device | 2853 // Set if not default device |
| 2856 if (_inputDeviceIndex > 0) | 2854 if (_inputDeviceIndex > 0) |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2987 | 2985 |
| 2988 // A bit change in keymap means a key is pressed | 2986 // A bit change in keymap means a key is pressed |
| 2989 for (i = 0; i < sizeof(szKey); i++) | 2987 for (i = 0; i < sizeof(szKey); i++) |
| 2990 state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; | 2988 state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; |
| 2991 | 2989 |
| 2992 // Save old state | 2990 // Save old state |
| 2993 memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); | 2991 memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); |
| 2994 return (state != 0); | 2992 return (state != 0); |
| 2995 } | 2993 } |
| 2996 } | 2994 } |
| OLD | NEW |