diff --git a/cura/CameraImageProvider.py b/cura/CameraImageProvider.py deleted file mode 100644 index edb0f205c7..0000000000 --- a/cura/CameraImageProvider.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from PyQt5.QtGui import QImage -from PyQt5.QtQuick import QQuickImageProvider -from PyQt5.QtCore import QSize - -from UM.Application import Application - -## Creates screenshots of the current scene. -class CameraImageProvider(QQuickImageProvider): - def __init__(self): - super().__init__(QQuickImageProvider.Image) - - ## Request a new image. - # - # The image will be taken using the current camera position. - # Only the actual objects in the scene will get rendered. Not the build - # plate and such! - # \param id The ID for the image to create. This is the requested image - # source, with the "image:" scheme and provider identifier removed. It's - # a Qt thing, they'll provide this parameter. - # \param size The dimensions of the image to scale to. - def requestImage(self, id, size): - for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices(): - try: - image = output_device.activePrinter.camera.getImage() - if image.isNull(): - image = QImage() - - return image, QSize(15, 15) - except AttributeError: - try: - image = output_device.activeCamera.getImage() - - return image, QSize(15, 15) - except AttributeError: - pass - - return QImage(), QSize(15, 15) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 2b3677bcb1..ba49f2b824 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -96,7 +96,6 @@ from . import PrintInformation from . import CuraActions from cura.Scene import ZOffsetDecorator from . import CuraSplashScreen -from . import CameraImageProvider from . import PrintJobPreviewImageProvider from . import MachineActionManager @@ -525,7 +524,6 @@ class CuraApplication(QtApplication): CuraApplication.Created = True def _onEngineCreated(self): - self._qml_engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) self._qml_engine.addImageProvider("print_job_preview", PrintJobPreviewImageProvider.PrintJobPreviewImageProvider()) @pyqtProperty(bool) diff --git a/cura/PrinterOutput/NetworkCamera.py b/cura/PrinterOutput/NetworkCamera.py deleted file mode 100644 index 1fff9945c8..0000000000 --- a/cura/PrinterOutput/NetworkCamera.py +++ /dev/null @@ -1,112 +0,0 @@ -from UM.Logger import Logger - -from PyQt5.QtCore import QUrl, pyqtProperty, pyqtSignal, QObject, pyqtSlot -from PyQt5.QtGui import QImage -from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager - - -class NetworkCamera(QObject): - newImage = pyqtSignal() - - def __init__(self, target = None, parent = None): - super().__init__(parent) - self._stream_buffer = b"" - self._stream_buffer_start_index = -1 - self._manager = None - self._image_request = None - self._image_reply = None - self._image = QImage() - - self._target = target - self._started = False - - @pyqtSlot(str) - def setTarget(self, target): - restart_required = False - if self._started: - self.stop() - restart_required = True - - self._target = target - - if restart_required: - self.start() - - @pyqtProperty(QImage, notify=newImage) - def latestImage(self): - return self._image - - @pyqtSlot() - def start(self): - # Ensure that previous requests (if any) are stopped. - self.stop() - if self._target is None: - Logger.log("w", "Unable to start camera stream without target!") - return - self._started = True - url = QUrl(self._target) - self._image_request = QNetworkRequest(url) - if self._manager is None: - self._manager = QNetworkAccessManager() - - self._image_reply = self._manager.get(self._image_request) - self._image_reply.downloadProgress.connect(self._onStreamDownloadProgress) - - @pyqtSlot() - def stop(self): - self._stream_buffer = b"" - self._stream_buffer_start_index = -1 - - if self._image_reply: - try: - # disconnect the signal - try: - self._image_reply.downloadProgress.disconnect(self._onStreamDownloadProgress) - except Exception: - pass - # abort the request if it's not finished - if not self._image_reply.isFinished(): - self._image_reply.close() - except Exception as e: # RuntimeError - pass # It can happen that the wrapped c++ object is already deleted. - - self._image_reply = None - self._image_request = None - - self._manager = None - - self._started = False - - def getImage(self): - return self._image - - ## Ensure that close gets called when object is destroyed - def __del__(self): - self.stop() - - def _onStreamDownloadProgress(self, bytes_received, bytes_total): - # An MJPG stream is (for our purpose) a stream of concatenated JPG images. - # JPG images start with the marker 0xFFD8, and end with 0xFFD9 - if self._image_reply is None: - return - self._stream_buffer += self._image_reply.readAll() - - if len(self._stream_buffer) > 2000000: # No single camera frame should be 2 Mb or larger - Logger.log("w", "MJPEG buffer exceeds reasonable size. Restarting stream...") - self.stop() # resets stream buffer and start index - self.start() - return - - if self._stream_buffer_start_index == -1: - self._stream_buffer_start_index = self._stream_buffer.indexOf(b'\xff\xd8') - stream_buffer_end_index = self._stream_buffer.lastIndexOf(b'\xff\xd9') - # If this happens to be more than a single frame, then so be it; the JPG decoder will - # ignore the extra data. We do it like this in order not to get a buildup of frames - - if self._stream_buffer_start_index != -1 and stream_buffer_end_index != -1: - jpg_data = self._stream_buffer[self._stream_buffer_start_index:stream_buffer_end_index + 2] - self._stream_buffer = self._stream_buffer[stream_buffer_end_index + 2:] - self._stream_buffer_start_index = -1 - self._image.loadFromData(jpg_data) - - self.newImage.emit()