import { assign, setup } from "xstate" import { MediaFile } from "@/features/media/types/media" export interface PlayerContextType { video: MediaFile | null currentTime: number duration: number volume: number isPlaying: boolean isSeeking: boolean isChangingCamera: boolean isRecording: boolean isVideoLoading: boolean isVideoReady: boolean isResizableMode: boolean // Флаг, указывающий, что шаблоны должны быть resizable // Speed Ramping speedRampingEnabled: boolean currentPlaybackRate: number basePlaybackRate: number // Настройки пререндера prerenderEnabled: boolean prerenderQuality: number prerenderSegmentDuration: number prerenderApplyEffects: boolean prerenderAutoPrerender: boolean // Новые поля для функции "Применить" previewMedia: MediaFile | null // Медиа для предпросмотра videoSource: "browser" | "timeline" // Источник видео // Примененные эффекты и фильтры appliedEffects: Array<{ id: string; name: string; params: any }> appliedFilters: Array<{ id: string; name: string; params: any }> appliedTemplate: { id: string name: string files: MediaFile[] } | null } // Начальный контекст для машины состояний плеера // Значение громкости будет заменено на значение из пользовательских настроек в провайдере const initialContext: PlayerContextType = { video: null, currentTime: 0, isPlaying: false, isSeeking: false, isChangingCamera: false, isRecording: false, isVideoLoading: false, isVideoReady: false, isResizableMode: false, duration: 0, volume: 100, // Значение по умолчанию, будет заменено из пользовательских настроек // Speed Ramping speedRampingEnabled: false, currentPlaybackRate: 1.0, basePlaybackRate: 1.0, // Настройки пререндера по умолчанию prerenderEnabled: false, prerenderQuality: 75, prerenderSegmentDuration: 5, prerenderApplyEffects: true, prerenderAutoPrerender: true, // Новые поля previewMedia: null, videoSource: "browser", // Примененные эффекты и фильтры appliedEffects: [], appliedFilters: [], appliedTemplate: null, } interface SetCurrentTimeEvent { type: "setCurrentTime" currentTime: number } interface SetIsPlayingEvent { type: "setIsPlaying" isPlaying: boolean } interface SetIsSeekingEvent { type: "setIsSeeking" isSeeking: boolean } interface SetIsChangingCameraEvent { type: "setIsChangingCamera" isChangingCamera: boolean } interface SetIsRecordingEvent { type: "setIsRecording" isRecording: boolean } interface SetDurationEvent { type: "setDuration" duration: number } interface SetVolumeEvent { type: "setVolume" volume: number } interface SetVideoEvent { type: "setVideo" video: MediaFile } interface SetVideoLoadingEvent { type: "setVideoLoading" isVideoLoading: boolean } interface SetVideoReadyEvent { type: "setVideoReady" isVideoReady: boolean } interface SetIsResizableModeEvent { type: "setIsResizableMode" isResizableMode: boolean } interface SetPrerenderSettingsEvent { type: "setPrerenderSettings" prerenderEnabled?: boolean prerenderQuality?: number prerenderSegmentDuration?: number prerenderApplyEffects?: boolean prerenderAutoPrerender?: boolean } interface SetPreviewMediaEvent { type: "setPreviewMedia" media: MediaFile | null } interface SetVideoSourceEvent { type: "setVideoSource" source: "browser" | "timeline" } interface ApplyEffectEvent { type: "applyEffect" effect: { id: string; name: string; params: any } } interface ApplyFilterEvent { type: "applyFilter" filter: { id: string; name: string; params: any } } interface ApplyTemplateEvent { type: "applyTemplate" template: { id: string; name: string } files: MediaFile[] } interface ClearEffectsEvent { type: "clearEffects" } interface ClearFiltersEvent { type: "clearFilters" } interface ClearTemplateEvent { type: "clearTemplate" } interface SetSpeedRampingEnabledEvent { type: "setSpeedRampingEnabled" enabled: boolean } interface UpdatePlaybackRateEvent { type: "updatePlaybackRate" rate: number } interface SetBasePlaybackRateEvent { type: "setBasePlaybackRate" rate: number } export type PlayerEvent = | SetCurrentTimeEvent | SetIsPlayingEvent | SetIsSeekingEvent | SetIsChangingCameraEvent | SetIsRecordingEvent | SetDurationEvent | SetVolumeEvent | SetVideoEvent | SetVideoLoadingEvent | SetVideoReadyEvent | SetIsResizableModeEvent | SetPrerenderSettingsEvent | SetPreviewMediaEvent | SetVideoSourceEvent | ApplyEffectEvent | ApplyFilterEvent | ApplyTemplateEvent | ClearEffectsEvent | ClearFiltersEvent | ClearTemplateEvent | SetSpeedRampingEnabledEvent | UpdatePlaybackRateEvent | SetBasePlaybackRateEvent export const playerMachine = setup({ types: { context: {} as PlayerContextType, events: {} as PlayerEvent, }, actions: { logVideoSet: ({ event }) => { if (event.type === "setVideo") { console.log(`[PlayerMachine] Установлено видео: ${event.video?.id}, path=${event.video?.path}`) } }, logPreviewMediaSet: ({ event }) => { if (event.type === "setPreviewMedia") { console.log(`[PlayerMachine] Установлено preview media: ${event.media?.id}`) } }, logVideoSourceSet: ({ event }) => { if (event.type === "setVideoSource") { console.log(`[PlayerMachine] Установлен источник видео: ${event.source}`) } }, logEffectApplied: ({ event }) => { if (event.type === "applyEffect") { console.log(`[PlayerMachine] Применен эффект: ${event.effect.name}`) } }, logFilterApplied: ({ event }) => { if (event.type === "applyFilter") { console.log(`[PlayerMachine] Применен фильтр: ${event.filter.name}`) } }, logTemplateApplied: ({ event }) => { if (event.type === "applyTemplate") { console.log(`[PlayerMachine] Применен шаблон: ${event.template.name} с ${event.files.length} файлами`) } }, logEffectsCleared: () => { console.log("[PlayerMachine] Очищены эффекты") }, logFiltersCleared: () => { console.log("[PlayerMachine] Очищены фильтры") }, logTemplateCleared: () => { console.log("[PlayerMachine] Очищен шаблон") }, logSpeedRampingToggled: ({ event }) => { if (event.type === "setSpeedRampingEnabled") { console.log(`[PlayerMachine] Speed ramping ${event.enabled ? "включен" : "выключен"}`) } }, logPlaybackRateUpdated: ({ event }) => { if (event.type === "updatePlaybackRate") { console.log(`[PlayerMachine] Playback rate обновлен: ${event.rate}`) } }, logBasePlaybackRateSet: ({ event }) => { if (event.type === "setBasePlaybackRate") { console.log(`[PlayerMachine] Base playback rate установлен: ${event.rate}`) } }, logVideoReady: ({ context }) => { console.log(`[PlayerMachine] Видео ${context.video?.id} готово к воспроизведению`) }, applyEffectAction: assign(({ context, event }) => { if (event.type === "applyEffect") { return { appliedEffects: [...context.appliedEffects, event.effect], } } return {} }), applyFilterAction: assign(({ context, event }) => { if (event.type === "applyFilter") { return { appliedFilters: [...context.appliedFilters, event.filter], } } return {} }), applyTemplateAction: assign(({ event }) => { if (event.type === "applyTemplate") { return { appliedTemplate: { id: event.template.id, name: event.template.name, files: event.files, }, } } return {} }), clearEffectsAction: assign({ appliedEffects: [] }), clearFiltersAction: assign({ appliedFilters: [] }), clearTemplateAction: assign({ appliedTemplate: null }), setSpeedRampingEnabledAction: assign(({ event }) => { if (event.type === "setSpeedRampingEnabled") { return { speedRampingEnabled: event.enabled } } return {} }), updatePlaybackRateAction: assign(({ event }) => { if (event.type === "updatePlaybackRate") { return { currentPlaybackRate: event.rate } } return {} }), setBasePlaybackRateAction: assign(({ event }) => { if (event.type === "setBasePlaybackRate") { return { basePlaybackRate: event.rate } } return {} }), }, }).createMachine({ id: "player", initial: "idle", context: initialContext, states: { idle: { on: { setVideo: { target: "loading", actions: [assign({ video: ({ event }) => event.video }), assign({ isVideoLoading: true }), "logVideoSet"], }, setCurrentTime: { actions: assign({ currentTime: ({ event }) => event.currentTime }), }, setIsPlaying: { actions: assign({ isPlaying: ({ event }) => event.isPlaying }), }, setIsSeeking: { actions: assign({ isSeeking: ({ event }) => event.isSeeking }), }, setIsChangingCamera: { actions: assign({ isChangingCamera: ({ event }) => event.isChangingCamera, }), }, setIsRecording: { actions: assign({ isRecording: ({ event }) => event.isRecording }), }, setDuration: { actions: assign({ duration: ({ event }) => event.duration }), }, setVolume: { actions: assign({ volume: ({ event }) => event.volume }), }, setIsResizableMode: { actions: assign({ isResizableMode: ({ event }) => event.isResizableMode, }), }, setPrerenderSettings: { actions: assign({ prerenderEnabled: ({ event, context }) => event.prerenderEnabled ?? context.prerenderEnabled, prerenderQuality: ({ event, context }) => event.prerenderQuality ?? context.prerenderQuality, prerenderSegmentDuration: ({ event, context }) => event.prerenderSegmentDuration ?? context.prerenderSegmentDuration, prerenderApplyEffects: ({ event, context }) => event.prerenderApplyEffects ?? context.prerenderApplyEffects, prerenderAutoPrerender: ({ event, context }) => event.prerenderAutoPrerender ?? context.prerenderAutoPrerender, }), }, setPreviewMedia: { actions: [assign({ previewMedia: ({ event }) => event.media }), "logPreviewMediaSet"], }, setVideoSource: { actions: [assign({ videoSource: ({ event }) => event.source }), "logVideoSourceSet"], }, applyEffect: { actions: ["applyEffectAction", "logEffectApplied"], }, applyFilter: { actions: ["applyFilterAction", "logFilterApplied"], }, applyTemplate: { actions: ["applyTemplateAction", "logTemplateApplied"], }, clearEffects: { actions: ["clearEffectsAction", "logEffectsCleared"], }, clearFilters: { actions: ["clearFiltersAction", "logFiltersCleared"], }, clearTemplate: { actions: ["clearTemplateAction", "logTemplateCleared"], }, setSpeedRampingEnabled: { actions: ["setSpeedRampingEnabledAction", "logSpeedRampingToggled"], }, updatePlaybackRate: { actions: ["updatePlaybackRateAction", "logPlaybackRateUpdated"], }, setBasePlaybackRate: { actions: ["setBasePlaybackRateAction", "logBasePlaybackRateSet"], }, }, }, loading: { on: { setVideoReady: { target: "ready", actions: [ assign({ isVideoReady: true, isVideoLoading: false }), // Добавляем логирование "logVideoReady", ], }, setVideoLoading: { actions: assign({ isVideoLoading: ({ event }) => event.isVideoLoading, }), }, setIsPlaying: { actions: assign({ isPlaying: ({ event }) => event.isPlaying }), }, setCurrentTime: { actions: assign({ currentTime: ({ event }) => event.currentTime }), }, setIsSeeking: { actions: assign({ isSeeking: ({ event }) => event.isSeeking }), }, setIsChangingCamera: { actions: assign({ isChangingCamera: ({ event }) => event.isChangingCamera, }), }, setIsRecording: { actions: assign({ isRecording: ({ event }) => event.isRecording }), }, setDuration: { actions: assign({ duration: ({ event }) => event.duration }), }, setVolume: { actions: assign({ volume: ({ event }) => event.volume }), }, setIsResizableMode: { actions: assign({ isResizableMode: ({ event }) => event.isResizableMode, }), }, setPrerenderSettings: { actions: assign({ prerenderEnabled: ({ event, context }) => event.prerenderEnabled ?? context.prerenderEnabled, prerenderQuality: ({ event, context }) => event.prerenderQuality ?? context.prerenderQuality, prerenderSegmentDuration: ({ event, context }) => event.prerenderSegmentDuration ?? context.prerenderSegmentDuration, prerenderApplyEffects: ({ event, context }) => event.prerenderApplyEffects ?? context.prerenderApplyEffects, prerenderAutoPrerender: ({ event, context }) => event.prerenderAutoPrerender ?? context.prerenderAutoPrerender, }), }, setPreviewMedia: { actions: [assign({ previewMedia: ({ event }) => event.media }), "logPreviewMediaSet"], }, setVideoSource: { actions: [assign({ videoSource: ({ event }) => event.source }), "logVideoSourceSet"], }, applyEffect: { actions: ["applyEffectAction"], }, applyFilter: { actions: ["applyFilterAction"], }, applyTemplate: { actions: ["applyTemplateAction"], }, clearEffects: { actions: ["clearEffectsAction"], }, clearFilters: { actions: ["clearFiltersAction"], }, clearTemplate: { actions: ["clearTemplateAction"], }, setSpeedRampingEnabled: { actions: ["setSpeedRampingEnabledAction"], }, updatePlaybackRate: { actions: ["updatePlaybackRateAction"], }, setBasePlaybackRate: { actions: ["setBasePlaybackRateAction"], }, }, }, ready: { on: { setVideo: { target: "loading", actions: [ assign({ video: ({ event }) => event.video }), assign({ isVideoLoading: true }), // Добавляем логирование "logVideoSet", ], }, setIsPlaying: { actions: assign({ isPlaying: ({ event }) => event.isPlaying }), }, setCurrentTime: { actions: assign({ currentTime: ({ event }) => event.currentTime }), }, setIsSeeking: { actions: assign({ isSeeking: ({ event }) => event.isSeeking }), }, setIsChangingCamera: { actions: assign({ isChangingCamera: ({ event }) => event.isChangingCamera, }), }, setIsRecording: { actions: assign({ isRecording: ({ event }) => event.isRecording }), }, setDuration: { actions: assign({ duration: ({ event }) => event.duration }), }, setVolume: { actions: assign({ volume: ({ event }) => event.volume }), }, setIsResizableMode: { actions: assign({ isResizableMode: ({ event }) => event.isResizableMode, }), }, setPrerenderSettings: { actions: assign({ prerenderEnabled: ({ event, context }) => event.prerenderEnabled ?? context.prerenderEnabled, prerenderQuality: ({ event, context }) => event.prerenderQuality ?? context.prerenderQuality, prerenderSegmentDuration: ({ event, context }) => event.prerenderSegmentDuration ?? context.prerenderSegmentDuration, prerenderApplyEffects: ({ event, context }) => event.prerenderApplyEffects ?? context.prerenderApplyEffects, prerenderAutoPrerender: ({ event, context }) => event.prerenderAutoPrerender ?? context.prerenderAutoPrerender, }), }, setPreviewMedia: { actions: [assign({ previewMedia: ({ event }) => event.media }), "logPreviewMediaSet"], }, setVideoSource: { actions: [assign({ videoSource: ({ event }) => event.source }), "logVideoSourceSet"], }, applyEffect: { actions: ["applyEffectAction"], }, applyFilter: { actions: ["applyFilterAction"], }, applyTemplate: { actions: ["applyTemplateAction"], }, clearEffects: { actions: ["clearEffectsAction"], }, clearFilters: { actions: ["clearFiltersAction"], }, clearTemplate: { actions: ["clearTemplateAction"], }, setSpeedRampingEnabled: { actions: ["setSpeedRampingEnabledAction"], }, updatePlaybackRate: { actions: ["updatePlaybackRateAction"], }, setBasePlaybackRate: { actions: ["setBasePlaybackRateAction"], }, }, }, }, })