@kajidog/voicevox-client 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +14 -14
  2. package/dist/api.d.ts +36 -2
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +76 -0
  5. package/dist/api.js.map +1 -1
  6. package/dist/client.d.ts +1 -1
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +6 -0
  9. package/dist/client.js.map +1 -1
  10. package/dist/effect/config.d.ts +43 -0
  11. package/dist/effect/config.d.ts.map +1 -0
  12. package/dist/effect/config.js +45 -0
  13. package/dist/effect/config.js.map +1 -0
  14. package/dist/effect/context.d.ts +33 -0
  15. package/dist/effect/context.d.ts.map +1 -0
  16. package/dist/effect/context.js +10 -0
  17. package/dist/effect/context.js.map +1 -0
  18. package/dist/effect/errors.d.ts +130 -0
  19. package/dist/effect/errors.d.ts.map +1 -0
  20. package/dist/effect/errors.js +121 -0
  21. package/dist/effect/errors.js.map +1 -0
  22. package/dist/effect/index.d.ts +34 -0
  23. package/dist/effect/index.d.ts.map +1 -0
  24. package/dist/effect/index.js +67 -0
  25. package/dist/effect/index.js.map +1 -0
  26. package/dist/effect/queue-manager.d.ts +34 -0
  27. package/dist/effect/queue-manager.d.ts.map +1 -0
  28. package/dist/effect/queue-manager.js +59 -0
  29. package/dist/effect/queue-manager.js.map +1 -0
  30. package/dist/effect/services/api-service.d.ts +58 -0
  31. package/dist/effect/services/api-service.d.ts.map +1 -0
  32. package/dist/effect/services/api-service.js +90 -0
  33. package/dist/effect/services/api-service.js.map +1 -0
  34. package/dist/effect/services/audio-generator-service.d.ts +78 -0
  35. package/dist/effect/services/audio-generator-service.d.ts.map +1 -0
  36. package/dist/effect/services/audio-generator-service.js +187 -0
  37. package/dist/effect/services/audio-generator-service.js.map +1 -0
  38. package/dist/effect/services/audio-player-service.d.ts +101 -0
  39. package/dist/effect/services/audio-player-service.d.ts.map +1 -0
  40. package/dist/effect/services/audio-player-service.js +297 -0
  41. package/dist/effect/services/audio-player-service.js.map +1 -0
  42. package/dist/effect/services/event-manager-service.d.ts +96 -0
  43. package/dist/effect/services/event-manager-service.d.ts.map +1 -0
  44. package/dist/effect/services/event-manager-service.js +208 -0
  45. package/dist/effect/services/event-manager-service.js.map +1 -0
  46. package/dist/effect/services/file-manager-service.d.ts +91 -0
  47. package/dist/effect/services/file-manager-service.d.ts.map +1 -0
  48. package/dist/effect/services/file-manager-service.js +215 -0
  49. package/dist/effect/services/file-manager-service.js.map +1 -0
  50. package/dist/effect/utils.d.ts +118 -0
  51. package/dist/effect/utils.d.ts.map +1 -0
  52. package/dist/effect/utils.js +186 -0
  53. package/dist/effect/utils.js.map +1 -0
  54. package/dist/error.js.map +1 -1
  55. package/dist/player.d.ts +110 -0
  56. package/dist/player.d.ts.map +1 -0
  57. package/dist/player.js +183 -0
  58. package/dist/player.js.map +1 -0
  59. package/dist/queue/audio-player.d.ts +44 -0
  60. package/dist/queue/audio-player.d.ts.map +1 -0
  61. package/dist/queue/audio-player.js +344 -0
  62. package/dist/queue/audio-player.js.map +1 -0
  63. package/dist/queue/file-manager.js +9 -9
  64. package/dist/queue/manager.d.ts +134 -0
  65. package/dist/queue/manager.d.ts.map +1 -0
  66. package/dist/queue/manager.js +564 -0
  67. package/dist/queue/manager.js.map +1 -0
  68. package/dist/queue/queue-service.d.ts.map +1 -1
  69. package/dist/queue/queue-service.js +16 -4
  70. package/dist/queue/queue-service.js.map +1 -1
  71. package/dist/shared-queue-manager.d.ts +119 -0
  72. package/dist/shared-queue-manager.d.ts.map +1 -0
  73. package/dist/shared-queue-manager.js +487 -0
  74. package/dist/shared-queue-manager.js.map +1 -0
  75. package/dist/state/types.js.map +1 -1
  76. package/dist/types.d.ts +28 -0
  77. package/dist/types.d.ts.map +1 -1
  78. package/package.json +1 -1
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ /**
3
+ * Effect-based AudioGenerator service implementation
4
+ * Provides structured error handling and resource management for audio generation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.generateAudioWithPreprocessing = exports.batchGenerateAudio = exports.EffectAudioGeneratorServiceScoped = exports.EffectAudioGeneratorServiceLive = exports.makeEffectAudioGeneratorService = exports.EffectAudioGeneratorServiceImpl = exports.EffectAudioGeneratorContext = void 0;
8
+ const effect_1 = require("effect");
9
+ const audio_generator_1 = require("../../queue/audio-generator");
10
+ const context_1 = require("../context");
11
+ const errors_1 = require("../errors");
12
+ const utils_1 = require("../utils");
13
+ exports.EffectAudioGeneratorContext = effect_1.Context.GenericTag('@voicevox/EffectAudioGenerator');
14
+ /**
15
+ * Effect-based implementation of AudioGenerator service
16
+ */
17
+ class EffectAudioGeneratorServiceImpl {
18
+ constructor(audioGenerator) {
19
+ this.audioGenerator = audioGenerator;
20
+ /**
21
+ * Traditional generateQuery method (Promise-based)
22
+ */
23
+ this.generateQuery = (text, speaker) => this.audioGenerator.generateQuery(text, speaker);
24
+ /**
25
+ * Traditional generateAudioFromQuery method (Promise-based)
26
+ */
27
+ this.generateAudioFromQuery = (item, statusCallback) => this.audioGenerator.generateAudioFromQuery(item, statusCallback);
28
+ /**
29
+ * Traditional generateAudio method (Promise-based)
30
+ */
31
+ this.generateAudio = (item, statusCallback) => this.audioGenerator.generateAudio(item, statusCallback);
32
+ /**
33
+ * Generate audio query with Effect-based error handling
34
+ */
35
+ this.generateQueryEffect = (text, speaker) => (0, utils_1.logTimed)(`generateQueryEffect-speaker-${speaker}`, (0, errors_1.retryWithBackoff)((0, errors_1.safeAsync)(() => this.audioGenerator.generateQuery(text, speaker), (error) => (0, errors_1.makeQueryGenerationError)('Failed to generate audio query in audio generator', text, speaker, error)), 3, // max retries
36
+ 1000 // base delay 1s
37
+ ));
38
+ /**
39
+ * Generate audio from text with Effect-based workflow
40
+ */
41
+ this.generateAudioEffect = (item, updateStatus) => {
42
+ const self = this;
43
+ return (0, utils_1.logTimed)(`generateAudioEffect-${item.id}`, effect_1.Effect.gen(function* () {
44
+ // Check if item is in correct status
45
+ if (item.status !== 'pending') {
46
+ return item;
47
+ }
48
+ // Update status to generating
49
+ yield* updateStatus(item, 'generating');
50
+ // Generate query
51
+ const query = yield* self.generateQueryEffect(item.text, item.speaker);
52
+ // Get services from context
53
+ const apiService = yield* context_1.VoicevoxApiContext;
54
+ const fileService = yield* context_1.EffectFileManagerContext;
55
+ // Synthesize audio
56
+ const audioData = yield* (0, errors_1.safeAsync)(() => apiService.getApi().synthesize(query, item.speaker), (error) => (0, errors_1.makeSynthesisError)('Failed to synthesize audio in audio generator', item.speaker, error));
57
+ // Save to temporary file
58
+ const tempFile = yield* fileService.saveTempAudioFile(audioData);
59
+ // Update item with generated data
60
+ const updatedItem = {
61
+ ...item,
62
+ query,
63
+ tempFile,
64
+ status: 'ready',
65
+ };
66
+ // Update status to ready
67
+ yield* updateStatus(updatedItem, 'ready');
68
+ return updatedItem;
69
+ }));
70
+ };
71
+ /**
72
+ * Generate audio from existing query with Effect-based workflow
73
+ */
74
+ this.generateAudioFromQueryEffect = (item, updateStatus) => {
75
+ return (0, utils_1.logTimed)(`generateAudioFromQueryEffect-${item.id}`, effect_1.Effect.gen(function* () {
76
+ // Check if item is in correct status and has query
77
+ if (item.status !== 'pending' || !item.query) {
78
+ return item;
79
+ }
80
+ // Update status to generating
81
+ yield* updateStatus(item, 'generating');
82
+ // Get services from context
83
+ const apiService = yield* context_1.VoicevoxApiContext;
84
+ const fileService = yield* context_1.EffectFileManagerContext;
85
+ // Synthesize audio from existing query
86
+ const audioData = yield* (0, errors_1.safeAsync)(() => apiService.getApi().synthesize(item.query, item.speaker), (error) => (0, errors_1.makeSynthesisError)('Failed to synthesize audio from query in audio generator', item.speaker, error));
87
+ // Save to temporary file
88
+ const tempFile = yield* fileService.saveTempAudioFile(audioData);
89
+ // Update item with generated data
90
+ const updatedItem = {
91
+ ...item,
92
+ tempFile,
93
+ status: 'ready',
94
+ };
95
+ // Update status to ready
96
+ yield* updateStatus(updatedItem, 'ready');
97
+ return updatedItem;
98
+ }));
99
+ };
100
+ /**
101
+ * Health check to verify audio generation capabilities
102
+ */
103
+ this.healthCheck = () => {
104
+ const self = this;
105
+ return (0, utils_1.logTimed)('audioGeneratorHealthCheck', effect_1.Effect.gen(function* () {
106
+ // Try to generate a simple query as health check
107
+ const result = yield* self.generateQueryEffect('テスト', 1).pipe(effect_1.Effect.map(() => true), effect_1.Effect.catchAll(() => effect_1.Effect.succeed(false)));
108
+ return result;
109
+ }));
110
+ };
111
+ }
112
+ }
113
+ exports.EffectAudioGeneratorServiceImpl = EffectAudioGeneratorServiceImpl;
114
+ /**
115
+ * Create AudioGenerator service instance
116
+ */
117
+ const makeEffectAudioGeneratorService = () => effect_1.Effect.gen(function* () {
118
+ const apiService = yield* context_1.VoicevoxApiContext;
119
+ const fileManager = yield* context_1.EffectFileManagerContext;
120
+ // Get the underlying VoicevoxApi instance and create a dummy AudioFileManager for the AudioGenerator
121
+ const api = apiService.getApi();
122
+ // We need to create a bridge AudioFileManager that uses our Effect-based file service
123
+ const bridgeFileManager = {
124
+ saveTempAudioFile: (audioData) => effect_1.Effect.runPromise(fileManager.saveTempAudioFile(audioData)),
125
+ deleteTempFile: (filePath) => effect_1.Effect.runPromise(fileManager.deleteTempFile(filePath)),
126
+ releaseAllBlobUrls: () => effect_1.Effect.runPromise(fileManager.releaseAllBlobUrls()),
127
+ createTempFilePath: () => effect_1.Effect.runPromise(fileManager.createTempFilePath()),
128
+ createBlobUrl: (blob) => effect_1.Effect.runPromise(fileManager.createBlobUrl(blob)),
129
+ releaseBlobUrl: (url) => effect_1.Effect.runPromise(fileManager.releaseBlobUrl(url)),
130
+ };
131
+ const audioGenerator = new audio_generator_1.AudioGenerator(api, bridgeFileManager);
132
+ return new EffectAudioGeneratorServiceImpl(audioGenerator);
133
+ });
134
+ exports.makeEffectAudioGeneratorService = makeEffectAudioGeneratorService;
135
+ /**
136
+ * Layer providing Effect AudioGenerator service
137
+ */
138
+ exports.EffectAudioGeneratorServiceLive = effect_1.Layer.effect(exports.EffectAudioGeneratorContext, (0, exports.makeEffectAudioGeneratorService)());
139
+ /**
140
+ * Scoped layer that automatically manages resources
141
+ */
142
+ exports.EffectAudioGeneratorServiceScoped = effect_1.Layer.scoped(exports.EffectAudioGeneratorContext, effect_1.Effect.gen(function* () {
143
+ const service = yield* (0, exports.makeEffectAudioGeneratorService)();
144
+ // AudioGenerator doesn't need explicit cleanup but we can add monitoring
145
+ yield* effect_1.Effect.addFinalizer(() => effect_1.Effect.log('AudioGenerator service cleaned up'));
146
+ return service;
147
+ }));
148
+ /**
149
+ * Helper functions for audio generation workflows
150
+ */
151
+ /**
152
+ * Batch generate audio from multiple text inputs
153
+ */
154
+ const batchGenerateAudio = (texts, speaker, concurrency = 3) => {
155
+ const apiService = context_1.VoicevoxApiContext;
156
+ return effect_1.Effect.gen(function* () {
157
+ const service = yield* apiService;
158
+ const api = service.getApi();
159
+ // Generate all audio in parallel with limited concurrency
160
+ const audioDataArray = yield* effect_1.Effect.all(texts.map((text) => effect_1.Effect.gen(function* () {
161
+ const query = yield* (0, errors_1.safeAsync)(() => api.generateQuery(text, speaker), (error) => (0, errors_1.makeQueryGenerationError)('Batch query generation failed', text, speaker, error));
162
+ const audioData = yield* (0, errors_1.safeAsync)(() => api.synthesize(query, speaker), (error) => (0, errors_1.makeSynthesisError)('Batch synthesis failed', speaker, error));
163
+ return audioData;
164
+ })), { concurrency });
165
+ return audioDataArray;
166
+ });
167
+ };
168
+ exports.batchGenerateAudio = batchGenerateAudio;
169
+ /**
170
+ * Generate audio with custom preprocessing
171
+ */
172
+ const generateAudioWithPreprocessing = (text, speaker, preprocessor) => {
173
+ const apiService = context_1.VoicevoxApiContext;
174
+ return effect_1.Effect.gen(function* () {
175
+ const service = yield* apiService;
176
+ const api = service.getApi();
177
+ // Generate base query
178
+ const baseQuery = yield* (0, errors_1.safeAsync)(() => api.generateQuery(text, speaker), (error) => (0, errors_1.makeQueryGenerationError)('Failed to generate base query', text, speaker, error));
179
+ // Apply preprocessing
180
+ const processedQuery = preprocessor(baseQuery);
181
+ // Synthesize with processed query
182
+ const audioData = yield* (0, errors_1.safeAsync)(() => api.synthesize(processedQuery, speaker), (error) => (0, errors_1.makeSynthesisError)('Failed to synthesize processed audio', speaker, error));
183
+ return audioData;
184
+ });
185
+ };
186
+ exports.generateAudioWithPreprocessing = generateAudioWithPreprocessing;
187
+ //# sourceMappingURL=audio-generator-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-generator-service.js","sourceRoot":"","sources":["../../../src/effect/services/audio-generator-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Effect-based AudioPlayer service implementation
3
+ * Provides structured error handling and resource management for audio playback
4
+ */
5
+ import { Context, Effect, Layer, Ref } from 'effect';
6
+ import { type PlaybackError } from '../errors';
7
+ /**
8
+ * Enhanced AudioPlayer service with Effect-based operations
9
+ */
10
+ export interface EffectAudioPlayerService {
11
+ readonly playAudio: (filePath: string) => Promise<void>;
12
+ readonly playAudioEffect: (filePath: string) => Effect.Effect<void, PlaybackError>;
13
+ readonly playAudioWithTimeout: (filePath: string, timeoutMs: number) => Effect.Effect<void, PlaybackError>;
14
+ readonly playAudioWithRetry: (filePath: string, maxRetries?: number) => Effect.Effect<void, PlaybackError>;
15
+ readonly isPlaying: () => Effect.Effect<boolean, never>;
16
+ readonly stopPlayback: () => Effect.Effect<void, never>;
17
+ readonly healthCheck: () => Effect.Effect<boolean, never>;
18
+ readonly cleanup: () => Effect.Effect<void, never>;
19
+ }
20
+ export declare const EffectAudioPlayerContext: Context.Tag<EffectAudioPlayerService, EffectAudioPlayerService>;
21
+ /**
22
+ * Audio playback state for tracking
23
+ */
24
+ interface AudioPlayerState {
25
+ readonly isPlaying: boolean;
26
+ readonly currentFilePath?: string;
27
+ readonly playbackStartTime?: Date;
28
+ }
29
+ /**
30
+ * Effect-based implementation of AudioPlayer service
31
+ */
32
+ export declare class EffectAudioPlayerServiceImpl implements EffectAudioPlayerService {
33
+ private readonly playerState;
34
+ private readonly audioCommand;
35
+ constructor(playerState: Ref.Ref<AudioPlayerState>);
36
+ /**
37
+ * Traditional playAudio method (Promise-based)
38
+ */
39
+ playAudio: (filePath: string) => Promise<void>;
40
+ /**
41
+ * Play audio with Effect-based error handling and state management
42
+ */
43
+ playAudioEffect: (filePath: string) => Effect.Effect<void, PlaybackError>;
44
+ /**
45
+ * Play audio with timeout protection
46
+ */
47
+ playAudioWithTimeout: (filePath: string, timeoutMs: number) => Effect.Effect<void, PlaybackError>;
48
+ /**
49
+ * Play audio with retry logic
50
+ */
51
+ playAudioWithRetry: (filePath: string, maxRetries?: number) => Effect.Effect<void, PlaybackError>;
52
+ /**
53
+ * Check if audio is currently playing
54
+ */
55
+ isPlaying: () => Effect.Effect<boolean, never>;
56
+ /**
57
+ * Stop current playback (best effort, may not work on all platforms)
58
+ */
59
+ stopPlayback: () => Effect.Effect<void, never>;
60
+ /**
61
+ * Health check to verify audio playback capabilities
62
+ */
63
+ healthCheck: () => Effect.Effect<boolean, never>;
64
+ /**
65
+ * Clean up audio player resources
66
+ */
67
+ cleanup: () => Effect.Effect<void, never>;
68
+ }
69
+ /**
70
+ * Create AudioPlayer service instance
71
+ */
72
+ export declare const makeEffectAudioPlayerService: () => Effect.Effect<EffectAudioPlayerService, never>;
73
+ /**
74
+ * Layer providing Effect AudioPlayer service
75
+ */
76
+ export declare const EffectAudioPlayerServiceLive: Layer.Layer<EffectAudioPlayerService, never>;
77
+ /**
78
+ * Scoped layer that automatically cleans up resources on scope close
79
+ */
80
+ export declare const EffectAudioPlayerServiceScoped: Layer.Layer<EffectAudioPlayerService, never, never>;
81
+ /**
82
+ * Helper functions for audio playback workflows
83
+ */
84
+ /**
85
+ * Play multiple audio files in sequence
86
+ */
87
+ export declare const playAudioSequence: (filePaths: readonly string[]) => Effect.Effect<void, PlaybackError, EffectAudioPlayerService>;
88
+ /**
89
+ * Play multiple audio files in parallel (useful for sound effects)
90
+ */
91
+ export declare const playAudioParallel: (filePaths: readonly string[], concurrency?: number) => Effect.Effect<void, PlaybackError, EffectAudioPlayerService>;
92
+ /**
93
+ * Play audio with progress monitoring
94
+ */
95
+ export declare const playAudioWithProgress: (filePath: string, onProgress?: (elapsed: number) => void) => Effect.Effect<void, PlaybackError, EffectAudioPlayerService>;
96
+ /**
97
+ * Create a managed audio player that automatically stops on scope exit
98
+ */
99
+ export declare const withManagedAudioPlayer: <A, E>(program: Effect.Effect<A, E, EffectAudioPlayerService>) => Effect.Effect<A, E, EffectAudioPlayerService>;
100
+ export {};
101
+ //# sourceMappingURL=audio-player-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player-service.d.ts","sourceRoot":"","sources":["../../../src/effect/services/audio-player-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ /**
3
+ * Effect-based AudioPlayer service implementation
4
+ * Provides structured error handling and resource management for audio playback
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.withManagedAudioPlayer = exports.playAudioWithProgress = exports.playAudioParallel = exports.playAudioSequence = exports.EffectAudioPlayerServiceScoped = exports.EffectAudioPlayerServiceLive = exports.makeEffectAudioPlayerService = exports.EffectAudioPlayerServiceImpl = exports.EffectAudioPlayerContext = void 0;
8
+ const effect_1 = require("effect");
9
+ const effect_2 = require("effect");
10
+ const node_child_process_1 = require("node:child_process");
11
+ const errors_1 = require("../errors");
12
+ const utils_1 = require("../utils");
13
+ exports.EffectAudioPlayerContext = effect_1.Context.GenericTag('@voicevox/EffectAudioPlayer');
14
+ /**
15
+ * Cross-platform audio player utilities
16
+ */
17
+ const detectPlatformAudioCommand = () => {
18
+ const platform = process.platform;
19
+ switch (platform) {
20
+ case 'darwin': // macOS
21
+ return {
22
+ command: 'afplay',
23
+ args: (filePath) => [filePath]
24
+ };
25
+ case 'win32': // Windows
26
+ return {
27
+ command: 'powershell',
28
+ args: (filePath) => [
29
+ '-Command',
30
+ `Add-Type -AssemblyName PresentationCore; $player = New-Object System.Windows.Media.MediaPlayer; $player.Open('file:///${filePath.replace(/\\/g, '/')}'); $player.Play(); while ($player.NaturalDuration.HasTimeSpan -eq $false) { Start-Sleep -Milliseconds 100 }; Start-Sleep -Milliseconds ($player.NaturalDuration.TimeSpan.TotalMilliseconds); $player.Close()`
31
+ ]
32
+ };
33
+ default: // Linux and others
34
+ // Try different audio players in order of preference
35
+ const linuxPlayers = ['paplay', 'aplay', 'play', 'ffplay'];
36
+ for (const player of linuxPlayers) {
37
+ try {
38
+ // Simple check if command exists
39
+ require('child_process').execSync(`which ${player}`, { stdio: 'ignore' });
40
+ if (player === 'ffplay') {
41
+ return {
42
+ command: player,
43
+ args: (filePath) => ['-nodisp', '-autoexit', filePath]
44
+ };
45
+ }
46
+ return {
47
+ command: player,
48
+ args: (filePath) => [filePath]
49
+ };
50
+ }
51
+ catch {
52
+ continue;
53
+ }
54
+ }
55
+ // Fallback to aplay
56
+ return {
57
+ command: 'aplay',
58
+ args: (filePath) => [filePath]
59
+ };
60
+ }
61
+ };
62
+ /**
63
+ * Effect-based implementation of AudioPlayer service
64
+ */
65
+ class EffectAudioPlayerServiceImpl {
66
+ constructor(playerState) {
67
+ /**
68
+ * Traditional playAudio method (Promise-based)
69
+ */
70
+ this.playAudio = (filePath) => {
71
+ return new Promise((resolve, reject) => {
72
+ const child = (0, node_child_process_1.spawn)(this.audioCommand.command, this.audioCommand.args(filePath), {
73
+ stdio: 'ignore',
74
+ windowsHide: true
75
+ });
76
+ child.on('close', (code) => {
77
+ if (code === 0) {
78
+ resolve();
79
+ }
80
+ else {
81
+ reject(new Error(`Audio playback failed with exit code ${code}`));
82
+ }
83
+ });
84
+ child.on('error', (error) => {
85
+ reject(error);
86
+ });
87
+ });
88
+ };
89
+ /**
90
+ * Play audio with Effect-based error handling and state management
91
+ */
92
+ this.playAudioEffect = (filePath) => {
93
+ const self = this;
94
+ return (0, utils_1.logTimed)(`playAudioEffect-${filePath}`, effect_1.Effect.gen(function* () {
95
+ // Update state to playing
96
+ yield* effect_1.Ref.update(self.playerState, (state) => ({
97
+ ...state,
98
+ isPlaying: true,
99
+ currentFilePath: filePath,
100
+ playbackStartTime: new Date(),
101
+ }));
102
+ try {
103
+ // Perform the actual playback
104
+ yield* (0, errors_1.safeAsync)(() => self.playAudio(filePath), (error) => (0, errors_1.makePlaybackError)('Failed to play audio file', filePath, error));
105
+ // Update state to not playing
106
+ yield* effect_1.Ref.update(self.playerState, (state) => ({
107
+ ...state,
108
+ isPlaying: false,
109
+ currentFilePath: undefined,
110
+ playbackStartTime: undefined,
111
+ }));
112
+ }
113
+ catch (error) {
114
+ // Ensure state is reset on error
115
+ yield* effect_1.Ref.update(self.playerState, (state) => ({
116
+ ...state,
117
+ isPlaying: false,
118
+ currentFilePath: undefined,
119
+ playbackStartTime: undefined,
120
+ }));
121
+ throw error;
122
+ }
123
+ }));
124
+ };
125
+ /**
126
+ * Play audio with timeout protection
127
+ */
128
+ this.playAudioWithTimeout = (filePath, timeoutMs) => (0, utils_1.logTimed)(`playAudioWithTimeout-${filePath}-${timeoutMs}ms`, (0, utils_1.withTimeout)(this.playAudioEffect(filePath), effect_2.Duration.millis(timeoutMs)).pipe(effect_1.Effect.mapError((error) => error instanceof Error && error.message.includes('timeout')
129
+ ? (0, errors_1.makePlaybackError)('Audio playback timed out', filePath, error)
130
+ : error)));
131
+ /**
132
+ * Play audio with retry logic
133
+ */
134
+ this.playAudioWithRetry = (filePath, maxRetries = 3) => (0, utils_1.logTimed)(`playAudioWithRetry-${filePath}-retries-${maxRetries}`, (0, errors_1.retryWithJitter)(this.playAudioEffect(filePath), maxRetries, 500));
135
+ /**
136
+ * Check if audio is currently playing
137
+ */
138
+ this.isPlaying = () => {
139
+ const self = this;
140
+ return effect_1.Ref.get(self.playerState).pipe(effect_1.Effect.map((state) => state.isPlaying));
141
+ };
142
+ /**
143
+ * Stop current playback (best effort, may not work on all platforms)
144
+ */
145
+ this.stopPlayback = () => {
146
+ const self = this;
147
+ return (0, utils_1.logTimed)('stopPlayback', effect_1.Effect.gen(function* () {
148
+ // Update state to not playing
149
+ yield* effect_1.Ref.update(self.playerState, (state) => ({
150
+ ...state,
151
+ isPlaying: false,
152
+ currentFilePath: undefined,
153
+ playbackStartTime: undefined,
154
+ }));
155
+ // Note: Actual stopping of playback depends on platform and implementation
156
+ // This is mainly for state management
157
+ yield* effect_1.Effect.log('Playback stopped (state updated)');
158
+ }));
159
+ };
160
+ /**
161
+ * Health check to verify audio playback capabilities
162
+ */
163
+ this.healthCheck = () => {
164
+ const self = this;
165
+ return (0, utils_1.logTimed)('audioPlayerHealthCheck', effect_1.Effect.gen(function* () {
166
+ // Check if we can create an AudioPlayer instance without errors
167
+ const result = yield* effect_1.Effect.sync(() => {
168
+ try {
169
+ // Simple validation - check if audio command is available
170
+ return typeof self.audioCommand.command === 'string' && self.audioCommand.command.length > 0;
171
+ }
172
+ catch {
173
+ return false;
174
+ }
175
+ }).pipe(effect_1.Effect.catchAll(() => effect_1.Effect.succeed(false)));
176
+ return result;
177
+ }));
178
+ };
179
+ /**
180
+ * Clean up audio player resources
181
+ */
182
+ this.cleanup = () => {
183
+ const self = this;
184
+ return (0, utils_1.logTimed)('audioPlayerCleanup', effect_1.Effect.gen(function* () {
185
+ // Stop any current playback
186
+ yield* self.stopPlayback();
187
+ // Reset state
188
+ yield* effect_1.Ref.set(self.playerState, {
189
+ isPlaying: false,
190
+ currentFilePath: undefined,
191
+ playbackStartTime: undefined,
192
+ });
193
+ yield* effect_1.Effect.log('AudioPlayer service cleaned up');
194
+ }));
195
+ };
196
+ this.playerState = playerState;
197
+ this.audioCommand = detectPlatformAudioCommand();
198
+ }
199
+ }
200
+ exports.EffectAudioPlayerServiceImpl = EffectAudioPlayerServiceImpl;
201
+ /**
202
+ * Create AudioPlayer service instance
203
+ */
204
+ const makeEffectAudioPlayerService = () => effect_1.Effect.gen(function* () {
205
+ const playerState = yield* effect_1.Ref.make({
206
+ isPlaying: false,
207
+ currentFilePath: undefined,
208
+ playbackStartTime: undefined,
209
+ });
210
+ return new EffectAudioPlayerServiceImpl(playerState);
211
+ });
212
+ exports.makeEffectAudioPlayerService = makeEffectAudioPlayerService;
213
+ /**
214
+ * Layer providing Effect AudioPlayer service
215
+ */
216
+ exports.EffectAudioPlayerServiceLive = effect_1.Layer.effect(exports.EffectAudioPlayerContext, (0, exports.makeEffectAudioPlayerService)());
217
+ /**
218
+ * Scoped layer that automatically cleans up resources on scope close
219
+ */
220
+ exports.EffectAudioPlayerServiceScoped = effect_1.Layer.scoped(exports.EffectAudioPlayerContext, effect_1.Effect.gen(function* () {
221
+ const service = yield* (0, exports.makeEffectAudioPlayerService)();
222
+ // Add finalizer to cleanup resources when scope closes
223
+ yield* effect_1.Effect.addFinalizer(() => service.cleanup());
224
+ return service;
225
+ }));
226
+ /**
227
+ * Helper functions for audio playback workflows
228
+ */
229
+ /**
230
+ * Play multiple audio files in sequence
231
+ */
232
+ const playAudioSequence = (filePaths) => {
233
+ const playerService = exports.EffectAudioPlayerContext;
234
+ return effect_1.Effect.gen(function* () {
235
+ const service = yield* playerService;
236
+ // Play each file in sequence
237
+ for (const filePath of filePaths) {
238
+ yield* service.playAudioEffect(filePath);
239
+ }
240
+ });
241
+ };
242
+ exports.playAudioSequence = playAudioSequence;
243
+ /**
244
+ * Play multiple audio files in parallel (useful for sound effects)
245
+ */
246
+ const playAudioParallel = (filePaths, concurrency = 3) => {
247
+ const playerService = exports.EffectAudioPlayerContext;
248
+ return effect_1.Effect.gen(function* () {
249
+ const service = yield* playerService;
250
+ // Play all files in parallel with limited concurrency
251
+ yield* effect_1.Effect.all(filePaths.map((filePath) => service.playAudioEffect(filePath)), { concurrency });
252
+ });
253
+ };
254
+ exports.playAudioParallel = playAudioParallel;
255
+ /**
256
+ * Play audio with progress monitoring
257
+ */
258
+ const playAudioWithProgress = (filePath, onProgress) => {
259
+ const playerService = exports.EffectAudioPlayerContext;
260
+ return effect_1.Effect.gen(function* () {
261
+ const service = yield* playerService;
262
+ if (!onProgress) {
263
+ return yield* service.playAudioEffect(filePath);
264
+ }
265
+ // Start playback in a fiber
266
+ const playbackFiber = yield* effect_1.Effect.fork(service.playAudioEffect(filePath));
267
+ // Monitor progress
268
+ const progressFiber = yield* effect_1.Effect.fork(effect_1.Effect.gen(function* () {
269
+ const startTime = Date.now();
270
+ while (true) {
271
+ const isPlaying = yield* service.isPlaying();
272
+ if (!isPlaying)
273
+ break;
274
+ const elapsed = Date.now() - startTime;
275
+ onProgress(elapsed);
276
+ yield* effect_1.Effect.sleep(effect_2.Duration.millis(100));
277
+ }
278
+ }));
279
+ // Wait for playback to complete
280
+ yield* effect_1.Fiber.await(playbackFiber);
281
+ // Interrupt progress monitoring
282
+ yield* effect_1.Fiber.interrupt(progressFiber);
283
+ });
284
+ };
285
+ exports.playAudioWithProgress = playAudioWithProgress;
286
+ /**
287
+ * Create a managed audio player that automatically stops on scope exit
288
+ */
289
+ const withManagedAudioPlayer = (program) => {
290
+ const playerService = exports.EffectAudioPlayerContext;
291
+ return effect_1.Effect.gen(function* () {
292
+ const service = yield* playerService;
293
+ return yield* effect_1.Effect.acquireUseRelease(effect_1.Effect.void, () => program, () => service.stopPlayback());
294
+ });
295
+ };
296
+ exports.withManagedAudioPlayer = withManagedAudioPlayer;
297
+ //# sourceMappingURL=audio-player-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player-service.js","sourceRoot":"","sources":["../../../src/effect/services/audio-player-service.ts"],"names":[],"mappings":"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"}