Skip to content

Commit 850994f

Browse files
authored
Merge pull request #141 from alnitak/choose_output
Choose output playback device
2 parents f32e5ee + c481274 commit 850994f

30 files changed

+668
-62
lines changed

.vscode/launch.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@
88
"name": "Flutter debug",
99
"type": "dart",
1010
"request": "launch",
11-
"program": "lib/wave_data/wave_data.dart",
11+
"program": "lib/output_device/output_device.dart",
1212
"flutterMode": "debug",
1313
"cwd": "${workspaceFolder}/example"
1414
},
1515
{
1616
"name": "Flutter profile",
1717
"type": "dart",
1818
"request": "launch",
19-
"program": "lib/filters/pitchshift.dart",
19+
"program": "lib/main.dart",
2020
"flutterMode": "profile",
2121
"cwd": "${workspaceFolder}/example"
2222
},
2323
{
2424
"name": "Flutter release",
2525
"type": "dart",
2626
"request": "launch",
27-
"program": "lib/filters/pitchshift.dart",
27+
"program": "lib/main.dart",
2828
"flutterMode": "release",
2929
"cwd": "${workspaceFolder}/example"
3030
},

.vscode/tasks.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
{
1111
"label": "compile linux debug",
12-
"command": "cd ${workspaceFolder}/example; flutter build linux -t lib/wave_data/wave_data.dart --debug",
12+
"command": "cd ${workspaceFolder}/example; flutter build linux -t lib/output_device/output_device.dart --debug",
1313
"type": "shell"
1414
},
1515
{
@@ -19,17 +19,17 @@
1919
},
2020
{
2121
"label": "compile windows debug verbose",
22-
"command": "cd ${workspaceFolder}/example; flutter build windows -t lib/filters/pitchshift.dart --debug --verbose",
22+
"command": "cd ${workspaceFolder}/example; flutter build windows -t lib/main.dart --debug --verbose",
2323
"type": "shell"
2424
},
2525
{
2626
"label": "compile windows debug",
27-
"command": "cd ${workspaceFolder}/example; flutter build windows -t lib/filters/pitchshift.dart --debug",
27+
"command": "cd ${workspaceFolder}/example; flutter build windows -t lib/main.dart --debug",
2828
"type": "shell"
2929
},
3030
{
3131
"label": "compile web debug",
32-
"command": "cd ${workspaceFolder}/example; flutter run -d chrome --web-renderer canvaskit --web-browser-flag '--disable-web-security' -t lib/wave_data/wave_data.dart --release",
32+
"command": "cd ${workspaceFolder}/example; flutter run -d chrome --web-renderer canvaskit --web-browser-flag '--disable-web-security' -t lib/main.dart --release",
3333
"type": "shell"
3434
}
3535
]

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
### 2.1.7 ()
2+
- added `listPlaybackDevices` to get all the OS output devices available.
3+
- added `deviceId` parameter to the `init()` method. You can choose which device is delegated to output the audio.
4+
- added `changeDevice` method to change the playback device on-the-fly.
5+
16
### 2.1.6 (17 Oct 2024)
27
- fixed a bug that caused an error when loading a sound more than twice.
38

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import 'dart:developer' as dev;
2+
3+
import 'package:flutter/foundation.dart';
4+
import 'package:flutter/material.dart';
5+
import 'package:flutter_soloud/flutter_soloud.dart';
6+
import 'package:logging/logging.dart';
7+
8+
/// Output device example.
9+
///
10+
/// This example uses the default output device and present a dropdown
11+
/// menu to change from all available output devices.
12+
/// All this is made simple just using the `listPlaybackDevices` and
13+
/// `changeDevice` methods.
14+
///
15+
/// To get all output devices use `listPlaybackDevices` which returns
16+
/// a list of `PlaybackDevice`s class. Each items of this class
17+
/// contains the id, whether it's the default device (the one used by the OS)
18+
/// and the name.
19+
/// This method can be called even if the engine has not been initialized.
20+
///
21+
/// At any time it is possible to pass to `changeDevice` a `PlaybackDevice`
22+
/// which will change the output device.
23+
///
24+
/// Note: Android, iOS and Web, only support one output device which is
25+
/// the default.
26+
27+
void main() async {
28+
// The `flutter_soloud` package logs everything
29+
// (from severe warnings to fine debug messages)
30+
// using the standard `package:logging`.
31+
// You can listen to the logs as shown below.
32+
Logger.root.level = kDebugMode ? Level.FINE : Level.INFO;
33+
Logger.root.onRecord.listen((record) {
34+
dev.log(
35+
record.message,
36+
time: record.time,
37+
level: record.level.value,
38+
name: record.loggerName,
39+
zone: record.zone,
40+
error: record.error,
41+
stackTrace: record.stackTrace,
42+
);
43+
});
44+
45+
WidgetsFlutterBinding.ensureInitialized();
46+
47+
/// Initialize the player.
48+
await SoLoud.instance.init();
49+
50+
runApp(
51+
const MaterialApp(
52+
home: HelloFlutterSoLoud(),
53+
),
54+
);
55+
}
56+
57+
/// Simple usecase of flutter_soloud plugin
58+
class HelloFlutterSoLoud extends StatefulWidget {
59+
const HelloFlutterSoLoud({super.key});
60+
61+
@override
62+
State<HelloFlutterSoLoud> createState() => _HelloFlutterSoLoudState();
63+
}
64+
65+
class _HelloFlutterSoLoudState extends State<HelloFlutterSoLoud> {
66+
late TextEditingController textEditingController;
67+
late final List<PlaybackDevice> devices;
68+
late PlaybackDevice currentDevice;
69+
AudioSource? currentSound;
70+
71+
@override
72+
void initState() {
73+
super.initState();
74+
SoLoud.instance.loadAsset('assets/audio/8_bit_mentality.mp3').then((value) {
75+
currentSound = value;
76+
SoLoud.instance.play(currentSound!, looping: true, volume: 0.5);
77+
});
78+
79+
devices = SoLoud.instance.listPlaybackDevices();
80+
assert(devices.isNotEmpty, 'No devices found!');
81+
82+
currentDevice = devices.firstWhere(
83+
(d) => d.isDefault,
84+
orElse: () => devices.first,
85+
);
86+
textEditingController = TextEditingController(text: currentDevice.name);
87+
}
88+
89+
@override
90+
void dispose() {
91+
SoLoud.instance.deinit();
92+
super.dispose();
93+
}
94+
95+
@override
96+
Widget build(BuildContext context) {
97+
if (!SoLoud.instance.isInitialized) return const SizedBox.shrink();
98+
99+
return Scaffold(
100+
body: Center(
101+
child: DropdownMenu(
102+
controller: textEditingController,
103+
onSelected: (value) {
104+
SoLoud.instance.changeDevice(newDevice: devices[value!]);
105+
},
106+
dropdownMenuEntries: [
107+
for (var i = 0; i < devices.length; i++)
108+
DropdownMenuEntry(
109+
value: i,
110+
label: '(${devices[i].id}) - ${devices[i].name}',
111+
),
112+
],
113+
),
114+
),
115+
);
116+
}
117+
}

example/lib/wave_data/wave_data.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import 'package:flutter/material.dart';
77
import 'package:flutter_soloud/flutter_soloud.dart';
88
import 'package:logging/logging.dart';
99

10+
/// Waveform example.
11+
///
12+
/// This example demonstrates how read audio samples from a wave file.
1013
void main() async {
1114
// The `flutter_soloud` package logs everything
1215
// (from severe warnings to fine debug messages)
@@ -68,7 +71,7 @@ class _HelloFlutterSoLoudState extends State<HelloFlutterSoLoud> {
6871
children: [
6972
const SizedBox(height: 16),
7073
const Text(
71-
'Read N audio samples (here N = width) from audio file.',
74+
'Read N audio samples (here N = width*4) from audio file.',
7275
),
7376
OutlinedButton(
7477
onPressed: () async {

example/lib/waveform/waveform.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import 'package:logging/logging.dart';
77

88
/// Waveform example.
99
///
10+
/// This example demonstrates how to generate a waveform, play it, and change
11+
/// it's frequency on the fly.
1012
void main() {
1113
// The `flutter_soloud` package logs everything
1214
// (from severe warnings to fine debug messages)

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ packages:
100100
path: ".."
101101
relative: true
102102
source: path
103-
version: "2.1.5"
103+
version: "2.1.7"
104104
flutter_test:
105105
dependency: "direct dev"
106106
description: flutter

lib/flutter_soloud.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export 'src/enums.dart' hide PlayerErrors, PlayerStateNotification;
88
export 'src/exceptions/exceptions.dart';
99
export 'src/filter_params.dart';
1010
export 'src/filters/filters.dart' show FilterType;
11+
export 'src/helpers/playback_device.dart';
1112
export 'src/soloud.dart';
1213
export 'src/sound_handle.dart';
1314
export 'src/sound_hash.dart';

lib/src/bindings/bindings_player.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:typed_data';
44
import 'package:flutter_soloud/src/bindings/audio_data.dart';
55
import 'package:flutter_soloud/src/enums.dart';
66
import 'package:flutter_soloud/src/filters/filters.dart';
7+
import 'package:flutter_soloud/src/helpers/playback_device.dart';
78
import 'package:flutter_soloud/src/sound_handle.dart';
89
import 'package:flutter_soloud/src/sound_hash.dart';
910
import 'package:meta/meta.dart';
@@ -52,6 +53,7 @@ abstract class FlutterSoLoud {
5253

5354
/// Initialize the player. Must be called before any other player functions.
5455
///
56+
/// [deviceId] the device ID. -1 for default OS output device.
5557
/// [sampleRate] the sample rate. Usually is 22050, 44100 (CD quality)
5658
/// or 48000.
5759
/// [bufferSize] the audio buffer size. Usually is 2048, but can be also be
@@ -61,11 +63,21 @@ abstract class FlutterSoLoud {
6163
/// Returns [PlayerErrors.noError] if success.
6264
@mustBeOverridden
6365
PlayerErrors initEngine(
66+
int deviceId,
6467
int sampleRate,
6568
int bufferSize,
6669
Channels channels,
6770
);
6871

72+
/// Change the playback device.
73+
///
74+
/// [deviceId] the device ID. -1 for default OS output device.
75+
@mustBeOverridden
76+
PlayerErrors changeDevice(int deviceId);
77+
78+
/// List available playback devices.
79+
List<PlaybackDevice> listPlaybackDevices();
80+
6981
/// Must be called when the player is no more needed or when closing the app.
7082
@mustBeOverridden
7183
void deinit();

0 commit comments

Comments
 (0)