From f624e2807b4b9d052d6182d6e0135145cc7ffd41 Mon Sep 17 00:00:00 2001 From: Christoph Schmidt <christoph.,schmidt@tugraz.at> Date: Fri, 1 Dec 2023 20:06:18 +0100 Subject: [PATCH] Removed unused files. Process exits now with window close --- examples/main.py | 2 +- .../controller/BaseAD2CaptDevice.py | 55 +-- .../mp_AD2Capture/AD2StateMPSetter.py | 297 ---------------- .../mp_AD2Capture/MPCaptDeviceControl.py | 4 +- .../mp_AD2Capture/MPDeviceControl.py | 336 ------------------ .../view/AD2CaptDeviceView.py | 6 + 6 files changed, 14 insertions(+), 686 deletions(-) delete mode 100644 src/CaptDeviceControl/controller/mp_AD2Capture/AD2StateMPSetter.py delete mode 100644 src/CaptDeviceControl/controller/mp_AD2Capture/MPDeviceControl.py diff --git a/examples/main.py b/examples/main.py index 963bcc6..f065632 100644 --- a/examples/main.py +++ b/examples/main.py @@ -2,7 +2,7 @@ import logging import sys import os -sys.path.append('../src') +sys.path.append('./src') from PySide6.QtWidgets import QApplication from rich.logging import RichHandler diff --git a/src/CaptDeviceControl/controller/BaseAD2CaptDevice.py b/src/CaptDeviceControl/controller/BaseAD2CaptDevice.py index dfad80f..4b7c50a 100644 --- a/src/CaptDeviceControl/controller/BaseAD2CaptDevice.py +++ b/src/CaptDeviceControl/controller/BaseAD2CaptDevice.py @@ -1,5 +1,6 @@ import logging import os +import sys import time from abc import abstractmethod from collections import deque @@ -8,8 +9,7 @@ from PySide6.QtCore import QObject, QThreadPool from numpy import ndarray from rich.logging import RichHandler -from CaptDeviceControl.controller.mp_AD2Capture.AD2StateMPSetter import AD2State -from CaptDeviceControl.controller.mp_AD2Capture.MPDeviceControl import mp_capture + from CaptDeviceControl.model.AD2CaptDeviceModel import AD2CaptDeviceModel, AD2CaptDeviceSignals from CaptDeviceControl.model.AD2Constants import AD2Constants from multiprocessing import Process, Queue, Value, Lock @@ -224,56 +224,11 @@ class BaseAD2CaptDevice(QObject): #time.sleep(0.1) self.logger.info("Status data consume thread ended") - def _set_ad2state_from_process(self, ad2state: AD2State): - # print(ad2state.__dict__) - self.model.pid = ad2state.pid - - self.model.dwf_version = ad2state.dwf_version - - self.model.connected = ad2state.connected - self.model.device_name = ad2state.device_name - self.model.device_serial_number = ad2state.device_serial_number - self.model.device_index = ad2state.device_index - - if ad2state.acquisition_state == AD2Constants.CapturingState.RUNNING(): - self.logger.info("[START ACQ] Started acquisition") - self.model.capturing_finished = False - self.model.start_recording = True - self.model.stop_recording = False - elif ad2state.acquisition_state == AD2Constants.CapturingState.STOPPED(): - if self.model.start_recording: - self.model.capturing_finished = True - self.logger.info(f"[STOP ACQ] Finished acquisition {self.model.capturing_finished}.") - # Emit a signal, that the Capturing has finished - self.model.start_recording = False - self.model.stop_recording = True - self.model.device_capturing_state = ad2state.acquisition_state - - self.model.sample_rate = ad2state.sample_rate - self.model.selected_ain_channel = ad2state.selected_ain_channel - - self.model.ain_channels = ad2state.ain_channels - self.model.ain_buffer_size = ad2state.ain_buffer_size - self.model.ain_bits = ad2state.ain_bits - self.model.ain_device_state = ad2state.ain_device_state - - self.model.recording_time = ad2state.recording_time - # ================================================================================================================== # Destructor # ================================================================================================================== - def stop_process(self): - #self.end_process_flag.value = True - - time_start = time.time() - #while self.proc.is_alive(): - # time.sleep(0.1) - self.logger.warning(f"AD2 process exited after {time.time()-time_start}s") - self.kill_thread = True - - def __del__(self): - self.logger.info("Exiting AD2 controller") - self.stop_process() - self.logger.warning("AD2 controller exited") + def exit(self): + self.mpcaptdevicecontrol.safe_exit() + \ No newline at end of file diff --git a/src/CaptDeviceControl/controller/mp_AD2Capture/AD2StateMPSetter.py b/src/CaptDeviceControl/controller/mp_AD2Capture/AD2StateMPSetter.py deleted file mode 100644 index f1f0827..0000000 --- a/src/CaptDeviceControl/controller/mp_AD2Capture/AD2StateMPSetter.py +++ /dev/null @@ -1,297 +0,0 @@ -from ctypes import c_int, c_byte - -from CaptDeviceControl.model.AD2Constants import AD2Constants - -class AD2State: - def __init__(self): - # Multiprocessing Information - self._pid = None - self._ppid = None - - # WaveForms Runtime (DWF) Information - self._dwf_version: str = "Unknown" - - # Device information - self._connected: bool = False - self._device_name: str = "Unknown" - self._serial_number: str = "Unknown" - self._device_index: int = -1 - - # Acquisition Settings - self._sample_rate: int = -1 - self._selected_ain_channel: int = -1 - - # Analog In Information - self._ain_channels: list = [] - self._ain_buffer_size: int = -1 - self._ain_bits: int = -1 - self._ain_device_state: c_byte = c_byte() - - # Analog Out Information - self._aout_channels: list = [] - - # Acquired Signal Information - self._acquisition_state: int = AD2Constants.CapturingState.STOPPED() - - self._time_capture_started: float = -1 # The time the capturing has started - self._time_capture_ended: float = -1 # The time the capturing has ended - self._recording_time: float = -1 - - self._samples_captured: int = 0 - self._samples_lost: int = -1 - self._samples_corrupted: int = -1 - - # Device Status - self._device_ready: bool = False - self._device_capturing = False - - - def reinit(self, fields: dict): - for k, v in fields.items(): - setattr(self, k, v) - - # =========== Multiprocessing Information - @property - def pid(self): - return self._pid - - @property - def ppid(self): - return self._ppid - - # =========== WaveForms Runtime (DWF) Information - @property - def dwf_version(self): - return self._dwf_version - - # =========== Device Information - @property - def connected(self): - return self._connected - - @property - def device_name(self): - return self._device_name - - @property - def device_serial_number(self): - return self._serial_number - - @property - def device_index(self): - return self._device_index - - # ========== Acquisition Settings - @property - def sample_rate(self): - return self._sample_rate - - @property - def selected_ain_channel(self): - return self._selected_ain_channel - - # =========== Analog In Information - @property - def ain_channels(self): - return self._ain_channels - - @property - def ain_buffer_size(self): - return self._ain_buffer_size - - @property - def ain_bits(self): - return self._ain_bits - - @property - def ain_device_state(self): - return self._ain_device_state - - # =========== Analog Out Information - @property - def aout_channels(self): - return self._aout_channels - - # =========== Acquired Signal Information - @property - def acquisition_state(self): - return self._acquisition_state - - @property - def time_capture_started(self) -> float: - """The time the capturing has started""" - return self._time_capture_started - - @property - def time_capture_ended(self) -> float: - """The time the capturing has ended""" - return self._time_capture_ended - - @property - def recording_time(self): - return self._recording_time - - @property - def samples_captured(self): - return self._samples_captured - - @property - def samples_lost(self): - return self._samples_lost - - @property - def samples_corrupted(self): - return self._samples_corrupted - - # =========== Device Status - @property - def device_ready(self): - return self._device_ready - - @property - def device_capturing(self): - return self._device_capturing - - -class AD2StateMPSetter(AD2State): - - def __init__(self, state_queue): - super().__init__() - self._state_queue = state_queue - - # =========== Multiprocessing Information - @AD2State.pid.setter - def pid(self, value): - self._pid = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.ppid.setter - def ppid(self, value): - self._ppid = value - self._state_queue.put(self.to_simple_class()) - - # =========== WaveForms Runtime (DWF) Information - @AD2State.dwf_version.setter - def dwf_version(self, value): - - self._dwf_version = value - self._state_queue.put(self.to_simple_class()) - - # =========== Device Information - @AD2State.connected.setter - def connected(self, value): - self._connected = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.device_name.setter - def device_name(self, value): - self._device_name = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.device_serial_number.setter - def device_serial_number(self, value): - self._serial_number = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.device_index.setter - def device_index(self, value): - self._device_index = value - self._state_queue.put(self.to_simple_class()) - - # ========== Acquisition Settings - @AD2State.sample_rate.setter - def sample_rate(self, value): - self._sample_rate = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.selected_ain_channel.setter - def selected_ain_channel(self, value): - self._selected_ain_channel = value - self._state_queue.put(self.to_simple_class()) - - # =========== Analog In Information - @AD2State.ain_channels.setter - def ain_channels(self, value): - self._ain_channels = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.ain_buffer_size.setter - def ain_buffer_size(self, value): - self._ain_buffer_size = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.ain_bits.setter - def ain_bits(self, value): - self._ain_bits = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.ain_device_state.setter - def ain_device_state(self, value): - self._ain_device_state = value - self._state_queue.put(self.to_simple_class()) - - # =========== Analog Out Information - @AD2State.aout_channels.setter - def aout_channels(self, value): - self._aout_channels = value - self._state_queue.put(self.to_simple_class()) - - # =========== Acquired Signal Information - @AD2State.acquisition_state.setter - def acquisition_state(self, value): - self._acquisition_state = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.time_capture_ended.setter - def time_capture_started(self, value: float): - """The time the capturing has started""" - self._time_capture_started = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.time_capture_ended.setter - def time_capture_ended(self, value: float): - self._time_capture_ended = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.recording_time.setter - def recording_time(self, value): - self._recording_time = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.samples_captured.setter - def samples_captured(self, value): - self._samples_captured = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.samples_lost.setter - def samples_lost(self, value): - self._samples_lost = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.samples_corrupted.setter - def samples_corrupted(self, value): - self._samples_corrupted = value - self._state_queue.put(self.to_simple_class()) - - # =========== Device Status - @AD2State.device_ready.setter - def device_ready(self, value): - self._device_ready = value - self._state_queue.put(self.to_simple_class()) - - @AD2State.device_capturing.setter - def device_capturing(self, value): - self._device_capturing = value - self._state_queue.put(self.to_simple_class()) - - def to_simple_class(self) -> AD2State: - exclude = ["_state_queue"] - ad2state = AD2State() - to_dict = {} - for item, value in self.__dict__.items(): - if item in exclude: - continue - else: - to_dict[item] = value - ad2state.reinit(to_dict) - return ad2state diff --git a/src/CaptDeviceControl/controller/mp_AD2Capture/MPCaptDeviceControl.py b/src/CaptDeviceControl/controller/mp_AD2Capture/MPCaptDeviceControl.py index 5b73a81..62ff7ea 100644 --- a/src/CaptDeviceControl/controller/mp_AD2Capture/MPCaptDeviceControl.py +++ b/src/CaptDeviceControl/controller/mp_AD2Capture/MPCaptDeviceControl.py @@ -4,8 +4,8 @@ import cmp from PySide6.QtCore import Signal from CaptDeviceControl.controller.mp_AD2Capture.MPCaptDevice import MPCaptDevice -from model.AD2CaptDeviceModel import AD2CaptDeviceSignals, AD2CaptDeviceModel -from model.AD2Constants import AD2Constants +from CaptDeviceControl.model.AD2CaptDeviceModel import AD2CaptDeviceSignals, AD2CaptDeviceModel +from CaptDeviceControl.model.AD2Constants import AD2Constants class MPCaptDeviceControl(cmp.CProcessControl): diff --git a/src/CaptDeviceControl/controller/mp_AD2Capture/MPDeviceControl.py b/src/CaptDeviceControl/controller/mp_AD2Capture/MPDeviceControl.py deleted file mode 100644 index e669235..0000000 --- a/src/CaptDeviceControl/controller/mp_AD2Capture/MPDeviceControl.py +++ /dev/null @@ -1,336 +0,0 @@ -""" -File for methods that run the multiporcessing capture. -Here we can init the device capturing and stream the data using ques. -(c) Christoph Schmidt, 2023 -christoph.schmidt@tugraz.at -""" - -import os -import random -import sys -import time -from ctypes import c_int, byref, c_double, cdll, create_string_buffer, c_int32, CDLL - -from CaptDeviceControl.controller.mp_AD2Capture.AD2StateMPSetter import AD2StateMPSetter -from CaptDeviceControl.model.AD2Constants import AD2Constants -from CaptDeviceControl.constants.dwfconstants import acqmodeRecord, DwfStateConfig, DwfStatePrefill, DwfStateArmed, enumfilterType, \ - enumfilterUSB, enumfilterDemo - - -# ====================================================================================================================== -# Process logging function -# ====================================================================================================================== -def _mp_log_debug(msg, prefix="AD2 Thread"): - print(f"DBG | [{prefix}/{os.getpid()}]: {msg}") - - -def _mp_log_error(msg, prefix="AD2 Thread"): - print(f"ERR | [{prefix}/{os.getpid()}]: {msg}") - - -def _mp_log_info(msg, prefix="AD2 Thread"): - print(f"INF | [{prefix}/{os.getpid()}]: {msg}") - - -def _mp_log_warning(msg, prefix="AD2 Thread"): - print(f"WARN | [{prefix}/{os.getpid()}]: {msg}") - - -# ====================================================================================================================== -# Process Main function, used for capturing and streaming data -# ====================================================================================================================== -def mp_capture(stream_data_queue, capture_data_queue, state_queue, - start_capture, end_process, - device_id, channel, sample_rate): - """ - Captures data from the device and puts it into a queue. - :param capture_data_queue: - :param state_queue: - :param start_capture: - :param end_process: - :param device_id: - :param sample_rate: - :param stream_data_queue: Queue to put the data into. - :param channel: Channel to capture data from. - :return: None - """ - - time_capture_started = 0 - capturing_notified = False - - ad2_state = AD2StateMPSetter(state_queue) - ad2_state.pid = os.getpid() - ad2_state.ppid = os.getppid() - # Print pid and ppid - _mp_log_info(f"Starting capture thread, pid={ad2_state.pid}, ppid={ad2_state.ppid}") - - ad2_state.selected_ain_channel = channel - ad2_state.sample_rate = sample_rate - ad2_state.device_index = device_id - _mp_log_debug(f"Setting up device {ad2_state.device_index} with " - f"channel {ad2_state.selected_ain_channel} and " - f"acquisition rate {ad2_state.sample_rate} Hz") - - dwf, hdwf = _mp_open_device(device_id, ad2_state) - - # acquisition_state = c_byte() - - cAvailable = c_int() - cLost = c_int() - cCorrupted = c_int() - - # FDwfAnalogInStatus(HDWF hdwf, BOOL fReadData, DwfState* psts) - _t_setup_aquisition(dwf, hdwf, ad2_state) - _t_setup_sine_wave(dwf, hdwf, ad2_state) - - _mp_log_info("Configuring acquisition. Starting oscilloscope.") - # FDwfAnalogInConfigure(HDWF hdwf, int fReconfigure, int fStart) - # Configures the instrument and start or stop the acquisition. To reset the Auto trigger timeout, set - # fReconfigure to TRUE. - # hdwf – Interface handle. - # fReconfigure – Configure the device. - # fStart – Start the acquisition. - dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1)) - - _mp_log_info("Device configured. Starting acquisition.") - - cSamples = 0 - ad2_state.device_ready = True - capture_samples = 0 - print(end_process.value) - while end_process.value == int(False): - # Checks the state of the acquisition. To read the data from the device, set fReadData to TRUE. For - # single acquisition mode, the data will be read only when the acquisition is finished - dwf.FDwfAnalogInStatus(hdwf, c_int(1), - byref(ad2_state.ain_device_state)) # Variable to receive the acquisition state - - if cSamples == 0 and ( - ad2_state.ain_device_state == DwfStateConfig or - ad2_state.ain_device_state == DwfStatePrefill or - ad2_state.ain_device_state == DwfStateArmed): - _mp_log_info("Device in idle state. Waiting for acquisition to start.") - continue # Acquisition not yet started. - - dwf.FDwfAnalogInStatusRecord(hdwf, - byref(cAvailable), - byref(cLost), - byref(cCorrupted)) - cSamples += cLost.value - - if cLost.value: - ad2_state.samples_lost += cLost.value - if cCorrupted.value: - ad2_state.samples_corrupted += cCorrupted.value - - # self.dwf.FDwfAnalogInStatusSamplesValid(self.hdwf, byref(self.cValid)) - if cAvailable.value == 0: - continue - else: - # print(f"Available: {cAvailable.value}") - # if cSamples + cAvailable.value > self.ad2capt_model.n_samples: - # cAvailable = c_int(self.ad2capt_model.n_samples - cSamples) - rgdSamples = (c_double * cAvailable.value)() - - dwf.FDwfAnalogInStatusData(hdwf, c_int(ad2_state.selected_ain_channel), byref(rgdSamples), - cAvailable) # get channel data - # Print how many samples are available - status = {"available": cAvailable.value, 'captured': 0, 'lost': cLost.value, - 'corrupted': cCorrupted.value, "time": time.time()} - #print(status) - time.sleep(random.random()) - #print(len(rgdSamples)) - stream_data_queue.put( - ([(float(s)) for s in rgdSamples], status) - ) - - if start_capture.value == 1: - if not capturing_notified: - time_capture_started = time.time() - capture_samples = 0 - _mp_log_info("Starting command recieved. Acquisition started.") - ad2_state.acquisition_state = AD2Constants.CapturingState.RUNNING() - capturing_notified = True - capture_samples = capture_samples + len(rgdSamples) - status = { - "available": cAvailable.value, - "captured": capture_samples, - "lost": cLost.value, - "corrupted": cCorrupted.value, - "recording_time": time.time() - time_capture_started} - capture_data_queue.put(([float(s) for s in rgdSamples], status)) - # capture_data_queue.put([float(s) for s in rgdSamples]) - elif start_capture.value == 0: - if capturing_notified: - ad2_state.acquisition_state = AD2Constants.CapturingState.STOPPED() - time_capture_stopped = time.time() - time_captured = time_capture_stopped - time_capture_started - ad2_state.recording_time = time_captured - _mp_log_info(f"Acquisition stopped after {time_captured} seconds. Captured {capture_samples} " - f"samples. Resulting in a time of {capture_samples / ad2_state.sample_rate} s.") - status = { - "available": cAvailable.value, - "captured": capture_samples, - "lost": cLost.value, - "corrupted": cCorrupted.value, - "recording_time": time.time() - time_capture_started} - capture_data_queue.put(([float(s) for s in rgdSamples], status)) - - capturing_notified = False - cSamples += cAvailable.value - - _mp_close_device(dwf, hdwf, channel, ad2_state) - - -def _mp_update_device_information(dwf, hdwf, ad2_state: AD2StateMPSetter): - in_channel = c_int() - out_channel = c_int() - buffer_size = c_int() - # Get the Analog In Channels and Buffer Size - dwf.FDwfAnalogInChannelCount(hdwf, byref(in_channel)) - ad2_state.ain_channels = list(range(0, int(in_channel.value))) - dwf.FDwfAnalogInBufferSizeInfo(hdwf, 0, byref(buffer_size)) - - # Get the Analog Out Channels and Buffer Size - ad2_state.analog_analog_in_buffer_size = int(buffer_size.value) - dwf.FDwfAnalogOutCount(hdwf, byref(out_channel)) - ad2_state.aout_channels = list(range(0, int(out_channel.value))) - - # # Select the first Analog In Channel - # ad2_state.selected_channel = ad2_state.list_of_analog_in_channels[0] - - -def _mp_get_dwf_information(dwf, ad2_state: AD2StateMPSetter): - _mp_log_debug(f"Getting DWF version information...") - version = create_string_buffer(16) - dwf.FDwfGetVersion(version) - ad2_state.dwf_version = version.value.decode("utf-8") - _mp_log_debug(f"DWF Version: {ad2_state.dwf_version}") - -# ====================================================================================================================== -# Setup the device -# ====================================================================================================================== -def _t_setup_sine_wave(dwf, hdwf, ad2_state: AD2StateMPSetter): - _mp_log_debug("Generating AM sine wave...") - dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1)) # carrier - dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_int(1)) # sine - dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(0.1)) - dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(1)) - # dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), c_int(0), c_double(0.5)) - # dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(2), c_int(1)) # AM - # dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(2), c_int(3)) # triangle - # dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(2), c_double(0.1)) - # dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(2), c_double(50)) - dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1)) - _mp_log_debug("Sine wave on output channel 0 configured.") - - -def _t_setup_aquisition(dwf, hdwf, ad2_state: AD2StateMPSetter): - dwf.FDwfAnalogInStatus(hdwf, c_int(1), - byref(ad2_state.ain_device_state)) # Variable to receive the acquisition state - _mp_log_info(f"[Task] Setup for acquisition on channel" - f" {ad2_state.selected_ain_channel} with rate {ad2_state.sample_rate} Hz.") - dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(ad2_state.selected_ain_channel), c_int(1)) - dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(ad2_state.selected_ain_channel), c_double(5)) - dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord) - dwf.FDwfAnalogInFrequencySet(hdwf, c_double(ad2_state.sample_rate)) - dwf.FDwfAnalogInRecordLengthSet(hdwf, 0) # -1 infinite record length - - # Variable to receive the acquisition state - dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(ad2_state.ain_device_state)) - _mp_log_info(f"[Task] Wait 2 seconds for the offset to stabilize.") - # wait at least 2 seconds for the offset to stabilize - time.sleep(2) - _mp_log_info(f"[Task] Setup for acquisition done.") - - -def _mp_discover_connected_devices(dwf): - _mp_log_info(f"Discovering connected devices...") - num_of_connected_devices = 0 - - devicename = create_string_buffer(64) - serialnum = create_string_buffer(16) - - for iDevice in enumerate_devices(dwf, show_demo_devices=True): - dwf.FDwfEnumDeviceName(c_int(iDevice), devicename) - dwf.FDwfEnumSN(c_int(iDevice), serialnum) - connected_devices.append({ - 'type': type, - 'device_id': int(iDevice), - 'device_name': str(devicename.value.decode('UTF-8')), - 'serial_number': str(serialnum.value.decode('UTF-8')) - }) - #_mp_log_debug(f"Found {type} device: {devicename.value.decode('UTF-8')} ({serialnum.value.decode('UTF-8')})") - # print(connected_devices) - # print(f"Discoverd {len(self.model.connected_devices)} devices.") - return connected_devices - -def enumerate_devices(dwf: CDLL, show_demo_devices=False) -> list: - """ - Enumerates all connected devices. Function is used to discover all connected, compatible devices. - Builds an internal list of detected devices filtered by the enumfilter parameter. It must be called - before using other FDwfEnum functions because they obtain information about enumerated devices - from this list identified by the device index. - :param show_demo_devices: Specify if demo devices should be shown. - :return: A list from 0 to n devices. - """ - if show_demo_devices: - enum_filter = c_int32(enumfilterType.value | enumfilterUSB.value | enumfilterDemo.value) - else: - enum_filter = c_int32(enumfilterType.value | enumfilterUSB.value) - - cDevice = c_int() - dwf.FDwfEnum(enum_filter, byref(cDevice)) - return list(range(0, cDevice.value)) - -def _mp_open_device(ad2_state: AD2StateMPSetter): - """ - Opens the device and returns the handle. - :return: Device handle. - """ - _mp_log_debug(f"Importing dwf library for {sys.platform}...") - if sys.platform.startswith("win"): - dwf = cdll.dwf - elif sys.platform.startswith("darwin"): - dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf") - else: - dwf = cdll.LoadLibrary("libdwf.so") - hdwf = c_int() - - _mp_get_dwf_information(dwf, ad2_state) - # This is needed, otherwise, the device is not found. - _mp_discover_connected_devices(dwf) - - # Opens the device specified by idxDevice. The device handle is returned in hdwf. If idxDevice is -1, the - # first available device is opened. - _mp_log_info(f"[Task] Opening device #{ad2_state.device_index}...") - dwf.FDwfDeviceOpen(c_int(ad2_state.device_index), byref(hdwf)) - - devicename = create_string_buffer(64) - serialnum = create_string_buffer(16) - - dwf.FDwfEnumDeviceName(c_int(ad2_state.device_index), devicename) - dwf.FDwfEnumSN(c_int(ad2_state.device_index), serialnum) - - ad2_state.device_name = str(devicename.value.decode("utf-8")) - ad2_state.device_serial_number = str(serialnum.value.decode("utf-8")).replace("SN:", "") - # open device - - if hdwf.value == 0: - szerr = create_string_buffer(512) - dwf.FDwfGetLastErrorMsg(szerr) - _mp_log_error(f"Failed to open device: {szerr.value}") - ad2_state.connected = False - raise Exception(f"Failed to open device: {szerr.value}") - else: - _mp_log_info(f"Device opened: {ad2_state.device_name} ({ad2_state.device_serial_number})") - ad2_state.connected = True - - return dwf, hdwf - - -def _mp_close_device(dwf, hdwf, channel, ad2_state: AD2StateMPSetter): - dwf.FDwfAnalogOutReset(hdwf, c_int(channel)) - _mp_log_info(f"[Task] Closing device...") - dwf.FDwfDeviceClose(hdwf) - ad2_state.connected = False - _mp_log_info(f"[Task] Device closed.") diff --git a/src/CaptDeviceControl/view/AD2CaptDeviceView.py b/src/CaptDeviceControl/view/AD2CaptDeviceView.py index 46dfb25..4246c8d 100644 --- a/src/CaptDeviceControl/view/AD2CaptDeviceView.py +++ b/src/CaptDeviceControl/view/AD2CaptDeviceView.py @@ -481,3 +481,9 @@ class ControlWindow(QMainWindow): else: item = QStandardItem(str(data)) parent.appendRow(item) + + def closeEvent(self, args): + print("Destroyed") + self.controller.exit() + self.destroyed.emit() + \ No newline at end of file -- GitLab