chromecast_dlna_finder 1.5.1 copy "chromecast_dlna_finder: ^1.5.1" to clipboard
chromecast_dlna_finder: ^1.5.1 copied to clipboard

A Dart package for discovering Chromecast devices and DLNA renderers.

Chromecast DLNA Finder #

pub package

A Dart package for discovering Chromecast, DLNA, and AirPlay devices on your local network, providing easy-to-use APIs for scanning, categorizing, and interacting with these devices.

Features #

  • ๐Ÿ” Scan for all Chromecast, DLNA, and AirPlay devices on your local network
  • ๐Ÿ“Š Automatic device categorization (Chromecast Dongle, Chromecast Audio, DLNA Renderer, DLNA Media Server, AirPlay RX Video, AirPlay RX Audio, AirPlay TX)
  • ๐ŸŒ Support for both command-line tools and Dart/Flutter/desktop applications
  • ๐Ÿ”„ Continuous scanning mode support
  • ๐ŸŒ Multilingual support (English, Traditional Chinese, Simplified Chinese, Japanese, German, French, Spanish, Italian, Russian, Portuguese, Hong Kong Chinese, and more)
  • ๐Ÿ“ฑ Cross-platform (macOS, Linux, Windows, Android, iOS)
  • ๐Ÿ–ฅ๏ธ Logger system with flexible output (stderr, stdout, broadcast for app UI)

Installation #

Use Dart's pub package manager to install:

dart pub add chromecast_dlna_finder

Or manually add it to your pubspec.yaml file:

dependencies:
  chromecast_dlna_finder: ^1.5.0

What's new in v1.5.0 #

  • mDNS ๆŽƒๆๆ”น็”จๅ…ฑ็”จ MDnsClient๏ผˆ้ฟๅ…้‡่ค‡ bind 5353๏ผ‰๏ผŒApple ๅนณๅฐๅ‰‡้€้Ž Flutter MethodChannel (Bonjour) ๆŸฅ่ฉขใ€‚
  • ็งป้™คๅŽŸ็”Ÿ native_mdns_scanner / FFI ไบŒ้€ฒไฝไพ่ณด๏ผŒ็™ผไฝˆ้ซ”็ฉๆ›ดๅฐ๏ผŒFlutter ๅฐˆๆกˆ้œ€็ขบไฟๅทฒๅŠ ๅ…ฅๆœฌๅฅ—ไปถๆไพ›็š„ MethodChannel plug-inใ€‚
  • API ไป็ถญๆŒ v1.4 ็š„ AirPlay 3 ๅž‹ๅˆฅ๏ผˆRX Video / RX Audio / TX๏ผ‰่ˆ‡ๅฐๆ‡‰็š„ isAirplay* ๅˆคๆ–ท๏ผŒไฟๆŒๆ—ขๆœ‰็›ธๅฎนๆ€งใ€‚
  • findDevices/findDevicesAsJson* ๆ–ฐๅขž enableMdns ๅƒๆ•ธ๏ผŒๆ–นไพฟๅœจๅ—้™็ถฒ่ทฏ็’ฐๅขƒไธ‹ๆšซๅœ mDNSใ€‚

โš ๏ธ Breaking Changes in v1.4.0 #

AirPlay Device Type Simplification: The AirPlay device type enumeration has been simplified from 5 types to 3 types for cleaner classification:

  • Removed types: airplayTxMobile, airplayTxDesktop, and backward-compatible airplay type
  • Kept types: airplayRxVideo, airplayRxAudio, airplayTx

Migration Guide:

  • If you were checking for DeviceType.airplayTxMobile or DeviceType.airplayTxDesktop, use DeviceType.airplayTx instead
  • If you were checking for the generic DeviceType.airplay, use the specific type (airplayRxVideo, airplayRxAudio, or airplayTx) or the helper methods (isAirplay, isAirplayRx, isAirplayTx)
  • All existing isAirplay* getter methods continue to work and maintain backward compatibility

New Direct mDNS Service Mapping:

  • _airplay._tcp โ†’ airplayRxVideo (AirPlay video receiver)
  • _raop._tcp โ†’ airplayRxAudio (AirPlay audio receiver)
  • _companion-link._tcp โ†’ airplayTx (AirPlay transmitter)

Architecture Overview #

The package follows a modular architecture:

lib/
โ”œโ”€โ”€ chromecast_dlna_finder.dart    # Main export file
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ chromecast_dlna_finder_base.dart  # Core functionality
    โ”œโ”€โ”€ discovery/                  # Device discovery modules
    โ”‚   โ”œโ”€โ”€ device.dart            # Device model & type definitions
    โ”‚   โ”œโ”€โ”€ discovery_service.dart  # Main discovery orchestrator
    โ”‚   โ”œโ”€โ”€ mdns_scanner.dart      # Chromecast discovery via mDNS
    โ”‚   โ”œโ”€โ”€ ssdp_scanner.dart      # DLNA discovery via SSDP
    โ”‚   โ””โ”€โ”€ cached_device.dart     # Device caching mechanism
    โ”œโ”€โ”€ locales/                   # Internationalization
    โ”‚   โ”œโ”€โ”€ en.json                # English strings
    โ”‚   โ”œโ”€โ”€ zh_TW.json             # Traditional Chinese
    โ”‚   โ”œโ”€โ”€ zh_CN.json             # Simplified Chinese
    โ”‚   โ”œโ”€โ”€ ja.json                # Japanese
    โ”‚   โ”œโ”€โ”€ de.json                # German
    โ”‚   โ”œโ”€โ”€ fr.json                # French
    โ”‚   โ”œโ”€โ”€ es.json                # Spanish
    โ”‚   โ”œโ”€โ”€ it.json                # Italian
    โ”‚   โ”œโ”€โ”€ ru.json                # Russian
    โ”‚   โ”œโ”€โ”€ pt.json                # Portuguese
    โ”‚   โ”œโ”€โ”€ zh_HK.json             # Hong Kong Chinese
    โ”‚   โ””โ”€โ”€ ...                    # More languages
    โ””โ”€โ”€ util/                      # Utility classes
        โ”œโ”€โ”€ dlna_device_utils.dart  # DLNA-specific helpers
        โ”œโ”€โ”€ localization.dart      # Localization infrastructure
        โ”œโ”€โ”€ localization_manager.dart # Localization logic
        โ”œโ”€โ”€ logger.dart            # Logging system
        โ””โ”€โ”€ platform_info.dart     # Platform detection

Key Components:

  • ChromecastDlnaFinder: Main entry point for all operations
  • Discovery Service: Coordinates the scanning process between different protocols
  • Device Model: Unified representation of both Chromecast and DLNA devices
  • Scanner Modules: Specialized modules for each protocol (mDNS, SSDP)
  • Localization System: Custom i18n implementation for multilingual support with fallback (e.g. zh_TW_Hant โ†’ zh_TW โ†’ zh)
  • Logger: Flexible logger supporting stderr, stdout, and broadcast (for app/Flutter UI)

Usage #

As a Command-Line Tool #

Install the CLI tool globally:

dart pub global activate chromecast_dlna_finder

Run a scan:

chromecast_dlna_finder --scan-duration 5

Command-line options:

Options:
  -h, --help            Show help information
  -t, --scan-duration=<seconds>  Scan duration in seconds (default: 5)
  -m, --minify          Output minified JSON
  -q, --quiet           Suppress progress messages
  -d, --debug           Enable verbose debug information
  -l, --lang=<language>  Specify language (e.g., en, zh-TW, ja, de, fr, es, it, ru, pt, zh-HK, zh-CN)

In Dart/Flutter/PC App Code #

import 'package:chromecast_dlna_finder/chromecast_dlna_finder.dart';

Future<void> main() async {
  // Initialize logger for app/Flutter UI log listening
  final logger = AppLogger();
  logger.setOutputs({LoggerOutput.broadcast});
  await logger.init();

  // Listen to log stream (for UI or custom handling)
  final subscription = logger.broadcastStream?.listen((record) {
    print('[APP LOG][${record.level}] ${record.message}');
  });

  // Initialize the scanner with injected logger
  final finder = ChromecastDlnaFinder(logger: logger);

  // Scan for devices
  final devices = await finder.findDevices(scanDuration: Duration(seconds: 5));

  // Output all discovered devices
  print('Discovered Chromecast devices:');
  for (final device in devices['chromecast'] ?? []) {
    print('- ${device.name} (${device.ip})');
  }

  print('Discovered DLNA devices:');
  for (final device in devices['dlna'] ?? []) {
    print('- ${device.name} (${device.ip})');
  }

  // New: AirPlay RX and TX output
  print('Discovered AirPlay RX devices:');
  for (final device in devices['airplay_rx'] ?? []) {
    print('- ${device.name} (${device.ip})');
  }

  print('Discovered AirPlay TX devices:');
  for (final device in devices['airplay_tx'] ?? []) {
    print('- ${device.name} (${device.ip})');
  }

  // Release resources
  await finder.dispose();
  await logger.dispose();
  await subscription?.cancel();
}

Output Format #

The scan results are output in the following JSON structure (fields vary depending on actual scan results):

{
  "all": [ ... ],
  "chromecast": [ ... ],
  "dlna": [ ... ],
  "dlna_rx": [ ... ],
  "dlna_tx": [ ... ],
  "airplay": [ ... ],
  "airplay_rx": [ ... ],
  "airplay_tx": [ ... ],
  "count": {
    "chromecast": { "total": 1, "rx": 1, "tx": 0 },
    "dlna": { "total": 1, "rx": 1, "tx": 0 },
    "airplay": { "total": 3, "rx": 3, "tx": 3 }
  },
  "error": [],
  "status": true
}

Device Information #

Each device object contains the following information (sensitive information is replaced with ***):

{
  "name": "***",
  "ip": "***",
  "type": "chromecastDongle",
  "model": "***",
  "location": "***",
  "id": "***",
  "friendlyName": "***",
  "port": 8009,
  "extra": { /* ...extra device info... */ },
  "mdnsTypes": [ "_airplay._tcp" ]
}

Available Device Types:

  • chromecastDongle, chromecastAudio - Chromecast devices
  • dlnaRenderer, dlnaMediaServer - DLNA devices
  • airplayRxVideo, airplayRxAudio, airplayTx - AirPlay devices (v1.4.0+)

Command Line Example (Sensitive Information Hidden) #

% dart bin/chromecast_dlna_finder.dart
[2025-05-22 13:23:42.446][INFO] [Config] Logging system configured: outputs={LoggerOutput.stderr}, minLevel=AppLogLevel.info
{
  "all": [
    { "name": "***", "ip": "***", "type": "chromecastDongle", ... },
    { "name": "***", "ip": "***", "type": "dlnaRenderer", ... },
    { "name": "***", "ip": "***", "type": "airplayRxVideo", ... }
    // ... others ...
  ],
  "chromecast": [ { "name": "***", "ip": "***", ... } ],
  "dlna": [ { "name": "***", "ip": "***", ... } ],
  "airplay": [ { "name": "***", "ip": "***", ... } ],
  "airplay_rx": [ { "name": "***", "ip": "***", ... } ],
  "airplay_tx": [ { "name": "***", "ip": "***", ... } ],
  "dlna_rx": [ { "name": "***", "ip": "***", ... } ],
  "dlna_tx": [],
  "count": {
    "chromecast": { "total": 1, "rx": 1, "tx": 0 },
    "dlna": { "total": 1, "rx": 1, "tx": 0 },
    "airplay": { "total": 3, "rx": 3, "tx": 3 }
  },
  "error": [],
  "status": true
}

Advanced Usage #

AirPlay Device Classification (v1.4.0+) #

import 'package:chromecast_dlna_finder/chromecast_dlna_finder.dart';

Future<void> main() async {
  final finder = ChromecastDlnaFinder();
  final devices = await finder.findDevices(scanDuration: Duration(seconds: 5));
  
  for (final device in devices['all'] ?? []) {
    if (device.isAirplay) {
      print('AirPlay Device: ${device.name}');
      print('  Type: ${device.type}');
      print('  RX Video: ${device.isAirplayRxVideo}');
      print('  RX Audio: ${device.isAirplayRxAudio}');
      print('  TX: ${device.isAirplayTx}');
      print('  mDNS Types: ${device.mdnsTypes}');
    }
  }
  
  await finder.dispose();
}

Getting Device Control URLs (DLNA Renderers Only) #

import 'package:chromecast_dlna_finder/chromecast_dlna_finder.dart';

Future<void> main() async {
  final finder = ChromecastDlnaFinder();
  final devices = await finder.findDevices(scanDuration: Duration(seconds: 5));
  for (final device in devices['dlna_renderer'] ?? []) {
    print('Renderer: ${device.name}');
    print('  - AVTransport control URL: ${device.avTransportControlUrl}');
    print('  - Rendering control URL: ${device.renderingControlUrl}');
  }
  await finder.dispose();
}

Logger Output Control #

  • To output logs to stderr (CLI):
    AppLogger().setOutputs({LoggerOutput.stderr});
    
  • To output logs to broadcast stream (for app/Flutter UI):
    AppLogger().setOutputs({LoggerOutput.broadcast});
    
  • To disable all logs:
    AppLogger().setOutputs({});
    

Multilingual Support & Fallback #

  • Supported languages: English, Traditional Chinese (zh_TW), Simplified Chinese (zh_CN, zh), Japanese (ja), German (de), French (fr), Spanish (es), Italian (it), Russian (ru), Portuguese (pt), Hong Kong Chinese (zh_HK), and more.
  • Fallback order: language-region-variant โ†’ language-region โ†’ language (e.g. zh_TW_Hant โ†’ zh_TW โ†’ zh)
  • You can specify language via CLI -l or in code via LocalizationManager().init(locale: 'ja').

Running Tests #

This package includes comprehensive tests. To run them with detailed output:

# Run all tests with expanded output
dart test --reporter expanded

# Run specific test file
dart test test/scanners_mock_test.dart --reporter expanded

Network Requirements #

  • Chromecast discovery uses mDNS (multicast DNS), requiring UDP port 5353
  • DLNA discovery uses SSDP protocol, requiring UDP port 1900 and related HTTP ports

License #

MIT

Contributing #

Contributions welcome! Please submit issues and suggestions to the GitHub repository.

0
likes
160
points
147
downloads

Publisher

verified publisherchangyy.app

Weekly Downloads

A Dart package for discovering Chromecast devices and DLNA renderers.

Repository (GitHub)
View/report issues

Topics

#chromecast #dlna #appletv #mdns #bonjour

Documentation

API reference

License

MIT (license)

Dependencies

args, flutter, logcraft, multicast_dns, path, xml, yaml

More

Packages that depend on chromecast_dlna_finder