native icon indicating copy to clipboard operation
native copied to clipboard

WIP: Swiftgen prototype and example

Open liamappelbe opened this issue 1 year ago • 6 comments
trafficstars

This is a prototype of swiftgen, and an example program that uses the Swift AVAudioPlayer API to play some audio from Dart.

example/generate_code.dart uses swiftgen to generate Dart bindings like this:

await generate(Config(
  target: Target(
    triple: 'x86_64-apple-macosx14.0',
    sdk: Uri.directory(
        '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk'),
  ),
  input: SwiftModuleInput(module: 'AVFAudio'),
  tempDir: Uri.directory('temp'),
  outputModule: 'AVFAudioWrapper',
  objcSwiftFile: Uri.file('avf_audio_wrapper.swift'),
  ffigen: FfiGenConfig(
    output: Uri.file('avf_audio_bindings.dart'),
    outputObjC: Uri.file('avf_audio_wrapper.m'),
    externalVersions: ffigen.ExternalVersions(
      ios: ffigen.Versions(min: Version(12, 0, 0)),
      macos: ffigen.Versions(min: Version(10, 14, 0)),
    ),
    objcInterfaces: ffigen.DeclarationFilters(
      shouldInclude: (decl) => decl.originalName == 'AVAudioPlayerWrapper',
    ),
  ),
));

Then example/play_audio.dart uses the generated Dart bindings to play audio:

for (final file in args) {
  final fileStr = NSString(file);
  print('Loading $fileStr');
  final fileUrl = NSURL.fileURLWithPath_(fileStr);
  final player = AVAudioPlayerWrapper.alloc()
      .initWithContentsOf_error_(fileUrl, nullptr);
  if (player == null) {
    print('Failed to load audio');
    continue;
  }
  final durationSeconds = player.duration.ceil();
  print('$durationSeconds sec');
  final status = player.play();
  if (status) {
    print('Playing...');
    await Future<void>.delayed(Duration(seconds: durationSeconds));
  } else {
    print('Failed to play audio.');
  }
}

There are a few remaining hacks to iron out, due to https://github.com/dart-lang/native/issues/1775 and https://github.com/dart-lang/native/issues/1774.

liamappelbe avatar Jul 22 '24 08:07 liamappelbe

PR Health

Breaking changes :heavy_check_mark:
Package Change Current Version New Version Needed Version Looking good?

This check can be disabled by tagging the PR with skip-breaking-check.

Changelog Entry :heavy_check_mark:
Package Changed Files

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check.

API leaks :heavy_check_mark:

The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.

Package Leaked API symbol Leaking sources

This check can be disabled by tagging the PR with skip-leaking-check.

License Headers :heavy_check_mark:
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
Files
no missing headers

All source files should start with a license header.

Unrelated files missing license headers
Files
pkgs/objective_c/lib/src/ns_input_stream.dart

This check can be disabled by tagging the PR with skip-license-check.

github-actions[bot] avatar Aug 06 '24 05:08 github-actions[bot]

Hey there, would you be able to briefly explain how could I run this locally? Should I execute example/generate_code.dart?

orestesgaolin avatar Jan 16 '25 10:01 orestesgaolin

@orestesgaolin Yeah, if you want to try the example you can run example/generate_code.dart to regenerate the bindings (avf_audio_bindings.dart etc) and example/play_audio.dart foo.mp3 to run the example.

liamappelbe avatar Jan 16 '25 23:01 liamappelbe

Given we have a merged https://github.com/dart-lang/native/tree/main/pkgs/swiftgen, I presume this can be closed.

dcharkes avatar Mar 26 '25 07:03 dcharkes

I don't see swiftgen updated on main... Is that something that needs to be synchronized with google's repos? screenshot_20250326_085933

orestesgaolin avatar Mar 26 '25 08:03 orestesgaolin

Oh, it's an empty directory, my bad! (I was in overzealous spring-cleaning-mode!)

dcharkes avatar Mar 26 '25 08:03 dcharkes

Coverage Status

coverage: 83.521%. remained the same when pulling 7f979f0e6362db51bf7ed005527a7b23ab0f81b9 on swiftgen2 into d7ab0d55e01c0eb3c35c5af9fefd84c53ef55215 on main.

coveralls avatar Sep 01 '25 03:09 coveralls

https://github.com/dart-lang/native/pull/2585

liamappelbe avatar Sep 01 '25 05:09 liamappelbe