bluefireteam / audioplayers

A Flutter package to play multiple audio files simultaneously (Android/iOS/web/Linux/Windows/macOS)
https://pub.dartlang.org/packages/audioplayers
MIT License
2.01k stars 845 forks source link

Platform thread issue with Windows #1635

Open wqjuser opened 1 year ago

wqjuser commented 1 year ago

Checklist

Current bug behaviour

i can not get the local file duration on windows, the problem is: [ERROR:flutter/shell/common/shell.cc(1004)] The 'xyz.luan/audioplayers/events/9a557e92-e57b-474c-a555-5b7d4be5d3d3' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel. See https://docs.flutter.dev/platform-integration/platform-channels#channels-and-platform-threading for more information. flutter: AudioPlayers Exception: AudioPlayerException( DeviceFileSource(path: G:/Huituxuan/Test/audio/2023-9-8/scene1.wav), PlatformException(WindowsAudioError, Error setting url to 'G:/Huituxuan/Test/audio/2023-9-8/scene1.wav'., false, null) flutter: Error: PlatformException(WindowsAudioError, Error setting url to 'G:/Huituxuan/Test/audio/2023-9-8/scene1.wav'., false, null)

Expected behaviour

it should return the duration

Steps to reproduce

just use this lab to get local file duration

Code sample

Future<int> getAudioDuration(String filePath) async {
    int duration = 0;
    ap.AudioPlayer player = ap.AudioPlayer();
    filePath = filePath.replaceAll('\', '/');
    try {
      await player.setSourceDeviceFile(filePath);
      player.getDuration().then((value) {
        commonPrint('the duration is $value');
        if (value != null) {
          duration = value.inMicroseconds;
        }
      });
    } catch (e) {
      commonPrint('Error: $e');
    } finally {
      player.dispose();
    }
    return duration;
  }

Affected platforms

Windows

Platform details

windows 11

AudioPlayers Version

5.0.1

Build mode

debug

Audio Files/URLs/Sources

scene1.zip

Screenshots

No response

Logs

Full Logs ``` [ERROR:flutter/shell/common/shell.cc(1004)] The 'xyz.luan/audioplayers/events/be394a89-f117-44a4-886a-db79404e5bd7' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel. See https://docs.flutter.dev/platform-integration/platform-channels#channels-and-platform-threading for more information. flutter: AudioPlayers Exception: AudioPlayerException( UrlSource(url: G:\绘图轩\测试\audio\2023-9-1\scene1.wav), PlatformException(WindowsAudioError, Error setting url to 'G:\绘图轩\测试\audio\2023-9-1\scene1.wav'., false, null) flutter: Error: PlatformException(WindowsAudioError, Error setting url to 'G:\绘图轩\测试\audio\2023-9-1\scene1.wav'., false, null) flutter: 文件路径是G:\绘图轩\测试\audio\2023-9-1\scene2.wav [ERROR:flutter/shell/common/shell.cc(1004)] The 'xyz.luan/audioplayers/events/acff6b71-1731-4221-99ea-daf1f59a5ea9' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel. See https://docs.flutter.dev/platform-integration/platform-channels#channels-and-platform-threading for more information. ``` Flutter doctor: ``` (base) PS G:\AndroidStudioProjects\tuitu> flutter doctor Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 3.13.2, on Microsoft Windows [版本 10.0.23536.1000], locale zh-CN) [√] Windows Version (Installed version of Windows is version 10 or higher) [√] Android toolchain - develop for Android devices (Android SDK version 33.0.1) [√] Chrome - develop for the web [√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.7.3) [√] Android Studio (version 2022.3) [√] IntelliJ IDEA Ultimate Edition (version 2023.2) [!] Proxy Configuration ! NO_PROXY is not set [√] Connected device (3 available) [√] Network resources ! Doctor found issues in 1 category. ```

Related issues / more information

No response

Working on PR

yeah

wqjuser commented 1 year ago

The AudioPlayers Version is 5.1.0 not 5.0.1

Gustl22 commented 1 year ago

@wqjuser thank you for the report. Feel free to open a PR if you can fix it :)

massimilianoporzio commented 1 year ago

Still persists in 5.2.0.

yoyoNTNU commented 1 year ago

Maybe the problem comes from here(packages/audioplayers_windows/windows/audioplayers_windows_plugin.cpp)

else if (method_call.method_name().compare("getDuration") == 0) {
    auto duration = player->GetDuration();
    result->Success(isnan(duration)
                        ? EncodableValue(std::monostate{})
                        : EncodableValue(ConvertSecondsToMs(duration)));
    return;
  }

Can anyone solve it?

6ag commented 1 year ago

On the Windows platform, when the Flutter version is 3.13.8, there will be error log information when playing audio files, but it does not affect playback. It seems this is the same issue.

[ERROR:flutter/shell/common/shell.cc(1004)] The 'xyz.luan/audioplayers/events/145fdaf0-3121-466f-9062-6c03f1067ea5' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel.
See https://docs.flutter.dev/platform-integration/platform-channels#channels-and-platform-threading for more information.
Archanciel commented 1 year ago

Same problem with version 5.2.0 on Windows 10.

Gustl22 commented 1 year ago

@wqjuser your provided file is actually no 'wav' file it's:

ID : 890956371 (0x351AEA53)
Format : Opus
Duration : 5 s 707 ms
Channel(s) : 1 channel
Channel layout : C
Sampling rate : 48.0 kHz
Compression mode : Lossy
Writing library : Encoded with GStreamer opusenc

I could only reproduce another error with this test:

  testWidgets('test windows thread',
      (WidgetTester tester) async {
    int duration = 0;
    AudioPlayer player = AudioPlayer();
    try {
      final filePath = await player.audioCache.loadPath(wavAsset1);
      await player.setSourceDeviceFile(filePath);
      player.getDuration().then((value) {
        print('the duration is $value');
        if (value != null) {
          duration = value.inMicroseconds;
        }
      });
    } catch (e) {
      print('Error: $e');
    } finally {
      player.dispose();
    }
    print(duration);
  });
AudioPlayers Exception: AudioPlayerException(
    DeviceFileSource(path: /C:/.../scene1.wav), 
    PlatformException(WindowsAudioError, Failed to set source. For troubleshooting, see: https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, D:\Tmp\Coding\git\bluefireteam\audioplayers\packages\audioplayers\example\windows\flutter\ephemeral\.plugin_symlinks\audioplayers_windows\windows\audio_player.cpp(71)\audioplayers_windows_plugin.dll!00007FFBE6976269: (caller: 00007FFBE694F32D) Exception(1) tid(4a9c) C00D36C4 The byte stream type of the given URL is unsupported.    [AudioPlayer::SetSourceUrl(sourceResolver->CreateObjectFromURL( winrt::to_hstring(url).c_str(), sourceResolutionFlags, nullptr, &objectType, reinterpret_cast<IUnknown**>(mediaSource.put_void())))]
, null)
dart:async/broadcast_stream_controller.dart 250:44         _BroadcastStreamController.addError
package:flutter/src/services/platform_channel.dart 670:24  EventChannel.receiveBroadcastStream.<fn>.<fn>
package:flutter/src/services/binding.dart 579:35           _DefaultBinaryMessenger.setMessageHandler.<fn>
dart:ui/hooks.dart 347:15                                  _invoke2.<fn>
dart:async/zone.dart 1399:13                               _rootRun
dart:async/zone.dart 1301:19                               _CustomZone.run
dart:async/zone.dart 1209:7                                _CustomZone.runGuarded
dart:ui/hooks.dart 346:10                                  _invoke2
dart:ui/channel_buffers.dart 45:5                          _ChannelCallbackRecord.invoke
dart:ui/channel_buffers.dart 135:31                        _Channel.push
dart:ui/channel_buffers.dart 343:17                        ChannelBuffers.push
dart:ui/platform_dispatcher.dart 741:22                    PlatformDispatcher._dispatchPlatformMessage
dart:ui/hooks.dart 257:31                                  _dispatchPlatformMessage

Which is expected: See #1255

~Please provide a test which reports this error. I remember I got it once, but couldn't reproduce it since. Maybe someone has a valid test for it.~

Edit: I could now easily reproduce by just playing any source from the example app...but not in the tests... I think it has more to do with IMFMediaEngineNotify events, as they may get emitted by a different thread. But the playback works fine non the less. The duration is another issue, that Windows doesn't support the source. Or it's the std::thread in the SetSourceUrl function.

massimilianoporzio commented 1 year ago

I noticed every time I restart the app the Logged errors in the console are slowing down.... Trying to restart many time the app and the error messages become very slow (the app takes more time to start)

Il giorno mar 24 ott 2023 alle ore 16:12 Gustl22 @.***> ha scritto:

@wqjuser https://github.com/wqjuser your provided file is actually no 'wav' file it's:

ID : 890956371 (0x351AEA53) Format : Opus Duration : 5 s 707 ms Channel(s) : 1 channel Channel layout : C Sampling rate : 48.0 kHz Compression mode : Lossy Writing library : Encoded with GStreamer opusenc

I could only reproduce another error with this test:

testWidgets('test windows thread', (WidgetTester tester) async { int duration = 0; AudioPlayer player = AudioPlayer(); try { final filePath = await player.audioCache.loadPath(wavAsset1); await player.setSourceDeviceFile(filePath); player.getDuration().then((value) { print('the duration is $value'); if (value != null) { duration = value.inMicroseconds; } }); } catch (e) { print('Error: $e'); } finally { player.dispose(); } print(duration); });

AudioPlayers Exception: AudioPlayerException( DeviceFileSource(path: /C:/.../scene1.wav), PlatformException(WindowsAudioError, Failed to set source. For troubleshooting, see: https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, D:\Tmp\Coding\git\bluefireteam\audioplayers\packages\audioplayers\example\windows\flutter\ephemeral.plugin_symlinks\audioplayers_windows\windows\audio_player.cpp(71)\audioplayers_windows_plugin.dll!00007FFBE6976269: (caller: 00007FFBE694F32D) Exception(1) tid(4a9c) C00D36C4 The byte stream type of the given URL is unsupported. [AudioPlayer::SetSourceUrl(sourceResolver->CreateObjectFromURL( winrt::to_hstring(url).c_str(), sourceResolutionFlags, nullptr, &objectType, reinterpret_cast<IUnknown**>(mediaSource.put_void())))] , null) dart:async/broadcast_stream_controller.dart 250:44 _BroadcastStreamController.addError package:flutter/src/services/platform_channel.dart 670:24 EventChannel.receiveBroadcastStream.. package:flutter/src/services/binding.dart 579:35 _DefaultBinaryMessenger.setMessageHandler. dart:ui/hooks.dart 347:15 _invoke2. dart:async/zone.dart 1399:13 _rootRun dart:async/zone.dart 1301:19 _CustomZone.run dart:async/zone.dart 1209:7 _CustomZone.runGuarded dart:ui/hooks.dart 346:10 _invoke2 dart:ui/channel_buffers.dart 45:5 _ChannelCallbackRecord.invoke dart:ui/channel_buffers.dart 135:31 _Channel.push dart:ui/channel_buffers.dart 343:17 ChannelBuffers.push dart:ui/platform_dispatcher.dart 741:22 PlatformDispatcher._dispatchPlatformMessage dart:ui/hooks.dart 257:31 _dispatchPlatformMessage

Which is expected: See #1255 https://github.com/bluefireteam/audioplayers/issues/1255

Please provide a test which reports this error. I remember I got it once, but couldn't reproduce it since. Maybe someone has a valid test for it.

— Reply to this email directly, view it on GitHub https://github.com/bluefireteam/audioplayers/issues/1635#issuecomment-1777304108, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFCVPF7L277YXND2KDQHKD3YA7EGHAVCNFSM6AAAAAA4PZXVB6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZXGMYDIMJQHA . You are receiving this because you commented.Message ID: @.***>

Gustl22 commented 1 year ago

This shouldn't be a problem right now, it's only a warning. I searched for an alternative, but unfortunately it's not that trivial to send events from the main / ui thread in windows: https://stackoverflow.com/a/3783845/5164462 https://github.com/flutter/flutter/blob/d36a843335aae6f6b60acb6b6d005e47d61f1c6e/examples/platform_channel/windows/runner/flutter_window.cpp#L118 https://docs.flutter.dev/platform-integration/platform-channels#jumping-to-the-ui-thread-in-android

I rechecked and it's definitely caused by the IMFMediaEngineNotify event coming from another thread.

@azchohfi maybe you can give a hint, as you have more experience and created the windows implementation? I also pushed to 1635-windows-thread for some prework.

azchohfi commented 11 months ago

You can do that by using the registrar->RegisterTopLevelWindowProcDelegate method and having a queue to send these messages back. I think it would work.

azchohfi commented 11 months ago

Here is an example: https://github.com/google/flutter-desktop-embedding/blob/master/plugins/window_size/windows/window_size_plugin.cpp

Gustl22 commented 11 months ago

@azchohfi big thanks for the hint. I added the code, but I wonder how to properly emit this event from the IMFMediaEngineNotify Event. The existing examples use an already present event from the system. https://github.com/bluefireteam/audioplayers/commit/a804c9da238cb192c52798c8567eaa957d4db4ee I come back to dig deeper in this another day :)

azchohfi commented 11 months ago

You can create your own events, with your won IDs. You would probably have to hook it there and listen to your custom event and send the event to the view's HWND from the IMFMEN. A queue (thread locked) might be needed. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage

amorenew commented 5 months ago

@Gustl22 @azchohfi I need to support you but I wonder how I could find good resources to build Windows apps in C++ or what I need to be helpful for Flutter Windows?

stone300 commented 4 months ago

The same error with audioplayers: ^6.0.0

Gustl22 commented 4 months ago

@amorenew this is a good resource to start with: https://docs.flutter.dev/packages-and-plugins/developing-packages And also https://github.com/bluefireteam/audioplayers/blob/main/contributing.md

As for every platform, basically you run the example app in one IDE. Then you open the nested windows folder of the example in another IDE instance and can connect to the already running app to debug. The code of the federated plugin then can be found and edited in the folder: windows/flutter/ephemeral/.plugin_symlinks/audioplayers_windows/windows/. See: https://docs.flutter.dev/packages-and-plugins/developing-packages#step-2d-add-linux-platform-code-h-cc It is not recommended to open the audioplayers_windows package directly in the IDE as then the libs are not set up correctly and no highlighting is supported.

Hope this helps and good luck. I try to help, but my time is currently quite limited.

amorenew commented 4 months ago

Thanks a lot 🥇