flet-audio 0.85.2__tar.gz → 0.85.3.dev0__tar.gz

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 (20) hide show
  1. {flet_audio-0.85.2/src/flet_audio.egg-info → flet_audio-0.85.3.dev0}/PKG-INFO +2 -2
  2. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/pyproject.toml +2 -2
  3. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flet_audio/audio.py +1 -0
  4. flet_audio-0.85.3.dev0/src/flet_audio/types.py +119 -0
  5. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0/src/flet_audio.egg-info}/PKG-INFO +2 -2
  6. flet_audio-0.85.3.dev0/src/flet_audio.egg-info/requires.txt +1 -0
  7. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flutter/flet_audio/lib/src/audio.dart +39 -9
  8. flet_audio-0.85.2/src/flet_audio/types.py +0 -94
  9. flet_audio-0.85.2/src/flet_audio.egg-info/requires.txt +0 -1
  10. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/LICENSE +0 -0
  11. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/README.md +0 -0
  12. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/setup.cfg +0 -0
  13. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flet_audio/__init__.py +0 -0
  14. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flet_audio.egg-info/SOURCES.txt +0 -0
  15. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flet_audio.egg-info/dependency_links.txt +0 -0
  16. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flet_audio.egg-info/top_level.txt +0 -0
  17. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flutter/flet_audio/lib/flet_audio.dart +0 -0
  18. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flutter/flet_audio/lib/src/extension.dart +0 -0
  19. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flutter/flet_audio/lib/src/utils/audio.dart +0 -0
  20. {flet_audio-0.85.2 → flet_audio-0.85.3.dev0}/src/flutter/flet_audio/pubspec.yaml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet-audio
3
- Version: 0.85.2
3
+ Version: 0.85.3.dev0
4
4
  Summary: Provides audio integration and playback in Flet apps.
5
5
  Author-email: Flet contributors <hello@flet.dev>
6
6
  License-Expression: Apache-2.0
@@ -11,7 +11,7 @@ Project-URL: Issues, https://github.com/flet-dev/flet/issues
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Requires-Dist: flet==0.85.2
14
+ Requires-Dist: flet==0.85.3.dev0
15
15
  Dynamic: license-file
16
16
 
17
17
  # flet-audio
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "flet-audio"
3
- version = "0.85.2"
3
+ version = "0.85.3.dev0"
4
4
  description = "Provides audio integration and playback in Flet apps."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Flet contributors", email = "hello@flet.dev" }]
7
7
  license = "Apache-2.0"
8
8
  requires-python = ">=3.10"
9
9
  dependencies = [
10
- "flet==0.85.2",
10
+ "flet==0.85.3.dev0",
11
11
  ]
12
12
 
13
13
  [project.urls]
@@ -107,6 +107,7 @@ class Audio(ft.Service):
107
107
 
108
108
  Args:
109
109
  position: The position to start playback from.
110
+ Defaults to the beginning of the audio.
110
111
  """
111
112
  await self._invoke_method(
112
113
  method_name="play",
@@ -0,0 +1,119 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from typing import TYPE_CHECKING
4
+
5
+ import flet as ft
6
+
7
+ if TYPE_CHECKING:
8
+ from flet_audio.audio import Audio # noqa
9
+
10
+ __all__ = [
11
+ "AudioDurationChangeEvent",
12
+ "AudioPositionChangeEvent",
13
+ "AudioState",
14
+ "AudioStateChangeEvent",
15
+ "ReleaseMode",
16
+ ]
17
+
18
+
19
+ class ReleaseMode(Enum):
20
+ """
21
+ Determines what happens to the player's resources (the buffered audio and
22
+ the underlying native player) when playback finishes or is stopped, and
23
+ therefore how quickly, and at what cost, the same audio can be played again.
24
+ """
25
+
26
+ RELEASE = "release"
27
+ """
28
+ Frees all resources once playback completes, as if
29
+ :meth:`flet_audio.Audio.release` had been called automatically.
30
+ This is the default mode.
31
+
32
+ The buffered audio and the native player are released, so nothing is kept in
33
+ memory while the audio is idle. Playing again is still supported, but the
34
+ source is **loaded again from scratch** first (and a remote file is
35
+ re-downloaded), which adds a short delay before playback starts.
36
+
37
+ Best when replays are rare or may never happen and keeping memory usage to a
38
+ minimum matters.
39
+
40
+ Note:
41
+ - On Android, the native media player is resource-intensive; this mode
42
+ lets it go and re-buffers the data only when needed.
43
+ - On iOS and macOS, behaves like :meth:`flet_audio.Audio.release`.
44
+ """
45
+
46
+ LOOP = "loop"
47
+ """
48
+ Automatically restarts playback from the beginning every time it completes,
49
+ creating a continuous loop. All resources are kept buffered.
50
+
51
+ Best for audio that should repeat indefinitely, such as background music.
52
+
53
+ Note:
54
+ Resources are never released automatically in this mode. To free them,
55
+ change the source or call :meth:`flet_audio.Audio.release`.
56
+ """
57
+
58
+ STOP = "stop"
59
+ """
60
+ Stops playback when the audio completes but keeps all resources (the
61
+ buffered audio and the native player) intact.
62
+
63
+ Because nothing is released, playing again is **immediate**: the audio
64
+ restarts straight from the retained buffer, with no reloading or
65
+ re-downloading. The trade-off is that these resources stay in memory while
66
+ the audio is idle.
67
+
68
+ Best when you intend to replay the same audio and want instant,
69
+ network-free playback (for example, short sound effects or repeated tones).
70
+ """
71
+
72
+
73
+ class AudioState(Enum):
74
+ """The state of the audio player."""
75
+
76
+ STOPPED = "stopped"
77
+ """The audio player is stopped."""
78
+
79
+ PLAYING = "playing"
80
+ """The audio player is currently playing audio."""
81
+
82
+ PAUSED = "paused"
83
+ """The audio player is paused and can be resumed."""
84
+
85
+ COMPLETED = "completed"
86
+ """The audio player has successfully reached the end of the audio."""
87
+
88
+ DISPOSED = "disposed"
89
+ """The audio player has been disposed of and should not be used anymore."""
90
+
91
+
92
+ @dataclass
93
+ class AudioStateChangeEvent(ft.Event["Audio"]):
94
+ """
95
+ Event triggered when the audio playback state changes.
96
+ """
97
+
98
+ state: AudioState
99
+ """The current state of the audio player."""
100
+
101
+
102
+ @dataclass
103
+ class AudioPositionChangeEvent(ft.Event["Audio"]):
104
+ """
105
+ Event triggered when the audio playback position changes.
106
+ """
107
+
108
+ position: int
109
+ """The current playback position in milliseconds."""
110
+
111
+
112
+ @dataclass
113
+ class AudioDurationChangeEvent(ft.Event["Audio"]):
114
+ """
115
+ Event triggered when the audio duration changes.
116
+ """
117
+
118
+ duration: ft.Duration
119
+ """The duration of the audio."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet-audio
3
- Version: 0.85.2
3
+ Version: 0.85.3.dev0
4
4
  Summary: Provides audio integration and playback in Flet apps.
5
5
  Author-email: Flet contributors <hello@flet.dev>
6
6
  License-Expression: Apache-2.0
@@ -11,7 +11,7 @@ Project-URL: Issues, https://github.com/flet-dev/flet/issues
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Requires-Dist: flet==0.85.2
14
+ Requires-Dist: flet==0.85.3.dev0
15
15
  Dynamic: license-file
16
16
 
17
17
  # flet-audio
@@ -0,0 +1 @@
1
+ flet==0.85.3.dev0
@@ -85,20 +85,14 @@ class AudioService extends FletService {
85
85
  _src = resolvedSrc.uri;
86
86
  _srcBytes = null;
87
87
  srcChanged = true;
88
-
89
- var assetSrc = control.backend.getAssetSource(_src!);
90
- if (assetSrc.isFile) {
91
- await player.setSourceDeviceFile(assetSrc.path);
92
- } else {
93
- await player.setSourceUrl(assetSrc.path);
94
- }
88
+ await _applySource();
95
89
  } else if (resolvedSrc.bytes != null &&
96
90
  (_srcBytes == null || !listEquals(_srcBytes, resolvedSrc.bytes))) {
97
91
  // bytes
98
92
  _srcBytes = resolvedSrc.bytes;
99
93
  _src = null;
100
94
  srcChanged = true;
101
- await player.setSourceBytes(resolvedSrc.bytes!);
95
+ await _applySource();
102
96
  }
103
97
 
104
98
  if (srcChanged) {
@@ -136,12 +130,42 @@ class AudioService extends FletService {
136
130
  }();
137
131
  }
138
132
 
133
+ /// Pushes the currently tracked source ([_src] or [_srcBytes]) to the native
134
+ /// [player], preparing it for playback.
135
+ ///
136
+ /// Used both when the source changes (from [update]) and to re-prepare
137
+ /// playback after the player has reached [PlayerState.completed] under
138
+ /// [ReleaseMode.release], where the native source has already been freed.
139
+ Future<void> _applySource() async {
140
+ if (_src != null) {
141
+ final assetSrc = control.backend.getAssetSource(_src!);
142
+ if (assetSrc.isFile) {
143
+ await player.setSourceDeviceFile(assetSrc.path);
144
+ } else {
145
+ await player.setSourceUrl(assetSrc.path);
146
+ }
147
+ } else if (_srcBytes != null) {
148
+ await player.setSourceBytes(_srcBytes!);
149
+ }
150
+ }
151
+
139
152
  Future<dynamic> _invokeMethod(String name, dynamic args) async {
140
153
  debugPrint("Audio.$name($args)");
141
154
  switch (name) {
142
155
  case "play":
143
156
  final position = parseDuration(args["position"]);
144
- if (position != null) {
157
+ if (player.state == PlayerState.completed) {
158
+ // Playback finished. Under ReleaseMode.release the native source has
159
+ // been freed, so re-prepare it before resuming.
160
+ if ((_releaseMode ?? ReleaseMode.release) == ReleaseMode.release) {
161
+ await _applySource();
162
+ }
163
+ // Position is already reset to the start after completion, so only
164
+ // seek when a specific non-zero position was requested.
165
+ if (position != null && position > Duration.zero) {
166
+ await player.seek(position);
167
+ }
168
+ } else if (position != null) {
145
169
  await player.seek(position);
146
170
  }
147
171
  await player.resume();
@@ -158,6 +182,12 @@ class AudioService extends FletService {
158
182
  case "seek":
159
183
  final position = parseDuration(args["position"]);
160
184
  if (position != null) {
185
+ if (player.state == PlayerState.completed &&
186
+ (_releaseMode ?? ReleaseMode.release) == ReleaseMode.release) {
187
+ // Source was freed on completion (see "play"); re-prepare it,
188
+ // otherwise the seek would hang waiting for onSeekComplete.
189
+ await _applySource();
190
+ }
161
191
  await player.seek(position);
162
192
  }
163
193
  break;
@@ -1,94 +0,0 @@
1
- from dataclasses import dataclass
2
- from enum import Enum
3
- from typing import TYPE_CHECKING
4
-
5
- import flet as ft
6
-
7
- if TYPE_CHECKING:
8
- from flet_audio.audio import Audio # noqa
9
-
10
- __all__ = [
11
- "AudioDurationChangeEvent",
12
- "AudioPositionChangeEvent",
13
- "AudioState",
14
- "AudioStateChangeEvent",
15
- "ReleaseMode",
16
- ]
17
-
18
-
19
- class ReleaseMode(Enum):
20
- """The behavior of Audio player when an audio is finished or stopped."""
21
-
22
- RELEASE = "release"
23
- """
24
- Releases all resources, just like calling release method.
25
-
26
- Info:
27
- - On Android, the media player is quite resource-intensive, and this will
28
- let it go. Data will be buffered again when needed (if it's a remote file,
29
- it will be downloaded again).
30
- - On iOS and macOS, works just like
31
- :meth:`flet_audio.Audio.release` method.
32
- """
33
-
34
- LOOP = "loop"
35
- """
36
- Keeps buffered data and plays again after completion, creating a loop.
37
- Notice that calling stop method is not enough to release the resources
38
- when this mode is being used.
39
- """
40
-
41
- STOP = "stop"
42
- """
43
- Stops audio playback but keep all resources intact.
44
- Use this if you intend to play again later.
45
- """
46
-
47
-
48
- class AudioState(Enum):
49
- """The state of the audio player."""
50
-
51
- STOPPED = "stopped"
52
- """The audio player is stopped."""
53
-
54
- PLAYING = "playing"
55
- """The audio player is currently playing audio."""
56
-
57
- PAUSED = "paused"
58
- """The audio player is paused and can be resumed."""
59
-
60
- COMPLETED = "completed"
61
- """The audio player has successfully reached the end of the audio."""
62
-
63
- DISPOSED = "disposed"
64
- """The audio player has been disposed of and should not be used anymore."""
65
-
66
-
67
- @dataclass
68
- class AudioStateChangeEvent(ft.Event["Audio"]):
69
- """
70
- Event triggered when the audio playback state changes.
71
- """
72
-
73
- state: AudioState
74
- """The current state of the audio player."""
75
-
76
-
77
- @dataclass
78
- class AudioPositionChangeEvent(ft.Event["Audio"]):
79
- """
80
- Event triggered when the audio playback position changes.
81
- """
82
-
83
- position: int
84
- """The current playback position in milliseconds."""
85
-
86
-
87
- @dataclass
88
- class AudioDurationChangeEvent(ft.Event["Audio"]):
89
- """
90
- Event triggered when the audio duration changes.
91
- """
92
-
93
- duration: ft.Duration
94
- """The duration of the audio."""
@@ -1 +0,0 @@
1
- flet==0.85.2
File without changes
File without changes
File without changes