35 lines
24 KiB
XML
35 lines
24 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<project version="4">
|
|
<component name="CopilotDiffPersistence">
|
|
<option name="pendingDiffs">
|
|
<map>
|
|
<entry key="$PROJECT_DIR$/app/src/main/java/com/example/camcontrol/CameraManager.kt">
|
|
<value>
|
|
<PendingDiffInfo>
|
|
<option name="filePath" value="$PROJECT_DIR$/app/src/main/java/com/example/camcontrol/CameraManager.kt" />
|
|
<option name="originalContent" value="package com.example.camcontrol import android.content.Context import android.util.Log import androidx.camera.core.CameraSelector import androidx.camera.core.ImageCapture import androidx.camera.core.ImageCaptureException import androidx.camera.core.Preview import androidx.camera.lifecycle.ProcessCameraProvider import androidx.core.content.ContextCompat import androidx.lifecycle.LifecycleOwner import com.google.common.util.concurrent.ListenableFuture import java.util.concurrent.Executors class CameraManager(private val context: Context) { private var cameraProvider: ProcessCameraProvider? = null private var imageCapture: ImageCapture? = null private val cameraExecutor = Executors.newSingleThreadExecutor() fun startCamera( lifecycleOwner: LifecycleOwner, previewSurfaceProvider: (Preview.SurfaceProvider) -> Unit, onError: (String) -> Unit ) { val cameraProviderFuture = ProcessCameraProvider.getInstance(context) cameraProviderFuture.addListener( { try { cameraProvider = cameraProviderFuture.get() // Create preview val preview = Preview.Builder() .build() .also { it.setSurfaceProvider { surfaceProvider -> previewSurfaceProvider(surfaceProvider) } } // Create image capture imageCapture = ImageCapture.Builder() .setTargetRotation(android.view.Surface.ROTATION_0) .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) .build() // Select back camera val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA // Unbind all use cases cameraProvider?.unbindAll() // Bind use cases to camera cameraProvider?.bindToLifecycle( lifecycleOwner, cameraSelector, preview, imageCapture ) Log.d("CameraManager", "Camera started successfully") } catch (exc: Exception) { Log.e("CameraManager", "Use case binding failed", exc) onError("Failed to start camera: ${exc.message}") } }, ContextCompat.getMainExecutor(context) ) } fun captureFrame(onFrameCaptured: (ByteArray) -> Unit, onError: (String) -> Unit) { val imageCapture = imageCapture ?: return val outputOptions = ImageCapture.OutputFileOptions.Builder( context.contentResolver, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, android.content.ContentValues().apply { put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, System.currentTimeMillis()) put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") } ).build() imageCapture.takePicture( outputOptions, cameraExecutor, object : ImageCapture.OnImageSavedCallback { override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { Log.d("CameraManager", "Image captured successfully") } override fun onError(exception: ImageCaptureException) { Log.e("CameraManager", "Image capture failed: ${exception.message}") onError("Failed to capture image: ${exception.message}") } } ) } fun stopCamera() { try { cameraProvider?.unbindAll() cameraExecutor.shutdown() Log.d("CameraManager", "Camera stopped") } catch (exc: Exception) { Log.e("CameraManager", "Error stopping camera", exc) } } } " />
|
|
<option name="updatedContent" value="package com.example.camcontrol import android.content.Context import android.util.Log import androidx.camera.core.CameraSelector import androidx.camera.core.ImageCapture import androidx.camera.core.ImageCaptureException import androidx.camera.core.Preview import androidx.camera.lifecycle.ProcessCameraProvider import androidx.core.content.ContextCompat import androidx.lifecycle.LifecycleOwner import com.google.common.util.concurrent.ListenableFuture import java.util.concurrent.Executors class CameraManager(private val context: Context) { private var cameraProvider: ProcessCameraProvider? = null private var imageCapture: ImageCapture? = null private val cameraExecutor = Executors.newSingleThreadExecutor() fun startCamera( lifecycleOwner: LifecycleOwner, previewSurfaceProvider: (Preview.SurfaceProvider) -> Unit, onError: (String) -> Unit ) { val cameraProviderFuture = ProcessCameraProvider.getInstance(context) cameraProviderFuture.addListener( { try { cameraProvider = cameraProviderFuture.get() // Create preview val preview = Preview.Builder() .build() .apply { setSurfaceProvider { surfaceProvider -> previewSurfaceProvider(surfaceProvider) } } // Create image capture imageCapture = ImageCapture.Builder() .setTargetRotation(android.view.Surface.ROTATION_0) .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) .build() // Select back camera val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA // Unbind all use cases cameraProvider?.unbindAll() // Bind use cases to camera cameraProvider?.bindToLifecycle( lifecycleOwner, cameraSelector, preview, imageCapture ) Log.d("CameraManager", "Camera started successfully") } catch (exc: Exception) { Log.e("CameraManager", "Use case binding failed", exc) onError("Failed to start camera: ${exc.message}") } }, ContextCompat.getMainExecutor(context) ) } fun captureFrame(onFrameCaptured: (ByteArray) -> Unit, onError: (String) -> Unit) { val imageCapture = imageCapture ?: return val outputOptions = ImageCapture.OutputFileOptions.Builder( context.contentResolver, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, android.content.ContentValues().apply { put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, System.currentTimeMillis()) put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") } ).build() imageCapture.takePicture( outputOptions, cameraExecutor, object : ImageCapture.OnImageSavedCallback { override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { Log.d("CameraManager", "Image captured successfully") } override fun onError(exception: ImageCaptureException) { Log.e("CameraManager", "Image capture failed: ${exception.message}") onError("Failed to capture image: ${exception.message}") } } ) } fun stopCamera() { try { cameraProvider?.unbindAll() cameraExecutor.shutdown() Log.d("CameraManager", "Camera stopped") } catch (exc: Exception) { Log.e("CameraManager", "Error stopping camera", exc) } } } " />
|
|
</PendingDiffInfo>
|
|
</value>
|
|
</entry>
|
|
<entry key="$PROJECT_DIR$/app/src/main/java/com/example/camcontrol/StreamViewModel.kt">
|
|
<value>
|
|
<PendingDiffInfo>
|
|
<option name="filePath" value="$PROJECT_DIR$/app/src/main/java/com/example/camcontrol/StreamViewModel.kt" />
|
|
<option name="updatedContent" value="package com.example.camcontrol import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import android.util.Log class StreamViewModel : ViewModel() { private val _connectionState = MutableStateFlow<ConnectionState>(ConnectionState.Idle) val connectionState: StateFlow<ConnectionState> = _connectionState private val _statusMessage = MutableStateFlow("") val statusMessage: StateFlow<String> = _statusMessage private val _isStreaming = MutableStateFlow(false) val isStreaming: StateFlow<Boolean> = _isStreaming private val _isCameraRunning = MutableStateFlow(false) val isCameraRunning: StateFlow<Boolean> = _isCameraRunning private val _fps = MutableStateFlow(0) val fps: StateFlow<Int> = _fps private val _bytesTransferred = MutableStateFlow(0L) val bytesTransferred: StateFlow<Long> = _bytesTransferred private var wsManager: WebSocketManager? = null private var config: ServerConnectionConfig? = null private var frameCount = 0 private var lastFpsTime = System.currentTimeMillis() private var totalBytesTransferred = 0L fun initializeConnection( serverHost: String, serverPort: Int, roomId: String, password: String ) { config = ServerConnectionConfig(serverHost, serverPort, roomId, password) wsManager = WebSocketManager( onConnected = { onConnected() }, onDisconnected = { onDisconnected() }, onError = { error -> onError(error) }, onMessage = { message -> onMessage(message) } ) connect() } private fun connect() { viewModelScope.launch { try { _connectionState.value = ConnectionState.Connecting updateStatus("Подключение к серверу...") val config = config ?: return@launch wsManager?.connect(config.getWebSocketUrl()) } catch (e: Exception) { Log.e("StreamViewModel", "Connection error: ${e.message}") _connectionState.value = ConnectionState.Error(e.message ?: "Unknown error") updateStatus("Ошибка подключения: ${e.message}") } } } private fun onConnected() { viewModelScope.launch { _connectionState.value = ConnectionState.Connected _isStreaming.value = true _isCameraRunning.value = true updateStatus("Подключено к серверу ✓") Log.d("StreamViewModel", "Connected to server") } } private fun onDisconnected() { viewModelScope.launch { _connectionState.value = ConnectionState.Disconnected _isStreaming.value = false _isCameraRunning.value = false updateStatus("Отключено от сервера") Log.d("StreamViewModel", "Disconnected from server") } } private fun onError(error: String) { viewModelScope.launch { _connectionState.value = ConnectionState.Error(error) updateStatus("Ошибка: $error") Log.e("StreamViewModel", "Error: $error") } } private fun onMessage(message: String) { Log.d("StreamViewModel", "Message received: $message") viewModelScope.launch { if (!message.contains("ping")) { updateStatus("Получено: $message") } } } fun sendVideoFrame(frameData: ByteArray) { try { wsManager?.sendBinary(frameData) // Update statistics frameCount++ totalBytesTransferred += frameData.size _bytesTransferred.value = totalBytesTransferred // Update FPS every second val currentTime = System.currentTimeMillis() if (currentTime - lastFpsTime >= 1000) { _fps.value = frameCount frameCount = 0 lastFpsTime = currentTime } } catch (e: Exception) { Log.e("StreamViewModel", "Failed to send frame: ${e.message}") } } fun sendCommand(command: VideoCommand) { try { wsManager?.sendMessage(command.toJson()) updateStatus("Команда отправлена: ${command.type}") Log.d("StreamViewModel", "Command sent: ${command.type}") } catch (e: Exception) { Log.e("StreamViewModel", "Failed to send command: ${e.message}") updateStatus("Ошибка отправки команды: ${e.message}") } } fun disconnect() { viewModelScope.launch { _isStreaming.value = false _isCameraRunning.value = false wsManager?.disconnect() _connectionState.value = ConnectionState.Idle updateStatus("Отключение...") resetStatistics() } } private fun resetStatistics() { frameCount = 0 totalBytesTransferred = 0L _fps.value = 0 _bytesTransferred.value = 0L lastFpsTime = System.currentTimeMillis() } private fun updateStatus(message: String) { _statusMessage.value = message Log.d("StreamViewModel", "Status: $message") } override fun onCleared() { super.onCleared() wsManager?.disconnect() } } sealed class ConnectionState { object Idle : ConnectionState() object Connecting : ConnectionState() object Connected : ConnectionState() object Disconnected : ConnectionState() data class Error(val message: String) : ConnectionState() } " />
|
|
</PendingDiffInfo>
|
|
</value>
|
|
</entry>
|
|
<entry key="$PROJECT_DIR$/app/src/main/java/com/example/camcontrol/WebSocketManager.kt">
|
|
<value>
|
|
<PendingDiffInfo>
|
|
<option name="filePath" value="$PROJECT_DIR$/app/src/main/java/com/example/camcontrol/WebSocketManager.kt" />
|
|
<option name="originalContent" value="package com.example.camcontrol import android.util.Log import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.WebSocket import okhttp3.WebSocketListener import okhttp3.Response import java.util.concurrent.TimeUnit class WebSocketManager( private val onConnected: () -> Unit = {}, private val onDisconnected: () -> Unit = {}, private val onError: (String) -> Unit = {}, private val onMessage: (String) -> Unit = {} ) : WebSocketListener() { private var webSocket: WebSocket? = null private val client = OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build() fun connect(url: String) { try { val request = Request.Builder() .url(url) .build() webSocket = client.newWebSocket(request, this) Log.d("WebSocket", "Connecting to: $url") } catch (e: Exception) { Log.e("WebSocket", "Connection error: ${e.message}") onError(e.message ?: "Unknown error") } } fun sendMessage(message: String) { try { webSocket?.send(message) Log.d("WebSocket", "Message sent: $message") } catch (e: Exception) { Log.e("WebSocket", "Send error: ${e.message}") onError(e.message ?: "Failed to send message") } } fun sendBinary(data: ByteArray) { try { webSocket?.send(okhttp3.ByteString.of(*data)) Log.d("WebSocket", "Binary data sent: ${data.size} bytes") } catch (e: Exception) { Log.e("WebSocket", "Binary send error: ${e.message}") } } fun disconnect() { try { webSocket?.close(1000, "Client disconnecting") webSocket = null Log.d("WebSocket", "Disconnected") } catch (e: Exception) { Log.e("WebSocket", "Disconnect error: ${e.message}") } } override fun onOpen(webSocket: WebSocket, response: Response) { Log.d("WebSocket", "Connected!") onConnected() } override fun onMessage(webSocket: WebSocket, text: String) { Log.d("WebSocket", "Message received: $text") onMessage(text) } override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { webSocket.close(1000, null) Log.d("WebSocket", "Closing: $code $reason") } override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { Log.d("WebSocket", "Closed: $code $reason") onDisconnected() } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { Log.e("WebSocket", "Failure: ${t.message}") onError(t.message ?: "Connection failed") onDisconnected() } } " />
|
|
<option name="updatedContent" value="package com.example.camcontrol import android.util.Log import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.WebSocket import okhttp3.WebSocketListener import okhttp3.Response import java.util.concurrent.TimeUnit class WebSocketManager( private val onConnected: () -> Unit = {}, private val onDisconnected: () -> Unit = {}, private val onError: (String) -> Unit = {}, private val onMessage: (String) -> Unit = {} ) : WebSocketListener() { private var webSocket: WebSocket? = null private val client = OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build() fun connect(url: String) { try { val request = Request.Builder() .url(url) .build() webSocket = client.newWebSocket(request, this) Log.d("WebSocket", "Connecting to: $url") } catch (e: Exception) { Log.e("WebSocket", "Connection error: ${e.message}") onError(e.message ?: "Unknown error") } } fun sendMessage(message: String) { try { webSocket?.send(message) Log.d("WebSocket", "Message sent: $message") } catch (e: Exception) { Log.e("WebSocket", "Send error: ${e.message}") onError(e.message ?: "Failed to send message") } } fun sendBinary(data: ByteArray) { try { val byteString = okhttp3.ByteString.of(*data) webSocket?.send(byteString) Log.d("WebSocket", "Binary data sent: ${data.size} bytes") } catch (e: Exception) { Log.e("WebSocket", "Binary send error: ${e.message}") } } fun disconnect() { try { webSocket?.close(1000, "Client disconnecting") webSocket = null Log.d("WebSocket", "Disconnected") } catch (e: Exception) { Log.e("WebSocket", "Disconnect error: ${e.message}") } } override fun onOpen(webSocket: WebSocket, response: Response) { Log.d("WebSocket", "Connected!") onConnected() } override fun onMessage(webSocket: WebSocket, text: String) { Log.d("WebSocket", "Message received: $text") onMessage(text) } override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { webSocket.close(1000, null) Log.d("WebSocket", "Closing: $code $reason") } override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { Log.d("WebSocket", "Closed: $code $reason") onDisconnected() } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { Log.e("WebSocket", "Failure: ${t.message}") onError(t.message ?: "Connection failed") onDisconnected() } } " />
|
|
</PendingDiffInfo>
|
|
</value>
|
|
</entry>
|
|
</map>
|
|
</option>
|
|
</component>
|
|
</project> |