import 'dart:async'; import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../cekirdek/log.dart'; enum AceStepMod { gradio, api, ikisiDe } class AceStepDurum { final bool gradioCalisiyor; // 7860 final bool apiCalisiyor; // 8001 final String gradioUrl; final String apiUrl; final String? hata; const AceStepDurum({ required this.gradioCalisiyor, required this.apiCalisiyor, required this.gradioUrl, required this.apiUrl, this.hata, }); bool get calisiyor => gradioCalisiyor || apiCalisiyor; // Geriye dönük uyumluluk String get url => apiCalisiyor ? apiUrl : gradioUrl; int get port => apiCalisiyor ? 8001 : 7860; static const yok = AceStepDurum( gradioCalisiyor: false, apiCalisiyor: false, gradioUrl: 'http://127.0.0.1:7860', apiUrl: 'http://127.0.0.1:8001', ); AceStepDurum kopyala({ bool? gradio, bool? api, String? gradioUrl, String? apiUrl, String? hata, }) => AceStepDurum( gradioCalisiyor: gradio ?? gradioCalisiyor, apiCalisiyor: api ?? apiCalisiyor, gradioUrl: gradioUrl ?? this.gradioUrl, apiUrl: apiUrl ?? this.apiUrl, hata: hata, ); } /// Mevcut ACE-Step bat dosyalarını çağırır (dokunmadan). class AceStepBaslatici { static const _gradioBat = r'D:\__sistem__\Masaustu\FikoYT.Yeni.Cag\video-uretim\ACE-Step-Baslat.bat'; static const _apiBat = r'D:\__sistem__\Masaustu\FikoYT.Yeni.Cag\video-uretim\ace-step\ACE-Step-1.5\start_api_server.bat'; static Future calisiyorMu({int port = 8001}) async { try { final s = await Socket.connect( '127.0.0.1', port, timeout: const Duration(milliseconds: 500), ); s.destroy(); return true; } catch (_) { return false; } } static Future gradioBaslat() async { if (await calisiyorMu(port: 7860)) { Log.bilgi('AceStep', 'Gradio zaten çalışıyor (7860)'); return; } if (!await File(_gradioBat).exists()) { throw Exception('Gradio bat bulunamadı: $_gradioBat'); } Log.bilgi('AceStep', 'Gradio başlatılıyor'); await Process.start('cmd', ['/c', 'start', '""', _gradioBat], mode: ProcessStartMode.detached, runInShell: true); } static Future apiBaslat() async { if (await calisiyorMu(port: 8001)) { Log.bilgi('AceStep', 'API server zaten çalışıyor (8001)'); return; } if (!await File(_apiBat).exists()) { throw Exception('API server bat bulunamadı: $_apiBat'); } Log.bilgi('AceStep', 'API server başlatılıyor'); await Process.start('cmd', ['/c', 'start', '""', _apiBat], mode: ProcessStartMode.detached, runInShell: true); } static Future portaErisilebilirOlanaKadarBekle({ int port = 8001, Duration zaman = const Duration(minutes: 10), }) async { final son = DateTime.now().add(zaman); while (DateTime.now().isBefore(son)) { if (await calisiyorMu(port: port)) return true; await Future.delayed(const Duration(seconds: 2)); } return false; } } class AceStepNotifier extends StateNotifier { AceStepNotifier() : super(AceStepDurum.yok) { _periyodikKontrol(); } Timer? _timer; void _periyodikKontrol() { _timer = Timer.periodic(const Duration(seconds: 3), (_) async { final gradio = await AceStepBaslatici.calisiyorMu(port: 7860); final api = await AceStepBaslatici.calisiyorMu(port: 8001); if (gradio != state.gradioCalisiyor || api != state.apiCalisiyor) { state = state.kopyala(gradio: gradio, api: api); } }); } Future apiBaslat() async { try { await AceStepBaslatici.apiBaslat(); final ok = await AceStepBaslatici.portaErisilebilirOlanaKadarBekle( port: 8001, ); state = state.kopyala(api: ok, hata: ok ? null : 'API açılmadı (timeout)'); } catch (e) { state = state.kopyala(hata: e.toString()); } } Future gradioBaslat() async { try { await AceStepBaslatici.gradioBaslat(); final ok = await AceStepBaslatici.portaErisilebilirOlanaKadarBekle( port: 7860, ); state = state.kopyala(gradio: ok, hata: ok ? null : 'Gradio açılmadı (timeout)'); } catch (e) { state = state.kopyala(hata: e.toString()); } } @override void dispose() { _timer?.cancel(); super.dispose(); } } final aceStepProvider = StateNotifierProvider((ref) => AceStepNotifier());