chromecast_dlna_finder 1.5.1
chromecast_dlna_finder: ^1.5.1 copied to clipboard
A Dart package for discovering Chromecast devices and DLNA renderers.
Chromecast DLNA Finder #
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-compatibleairplaytype - Kept types:
airplayRxVideo,airplayRxAudio,airplayTx
Migration Guide:
- If you were checking for
DeviceType.airplayTxMobileorDeviceType.airplayTxDesktop, useDeviceType.airplayTxinstead - If you were checking for the generic
DeviceType.airplay, use the specific type (airplayRxVideo,airplayRxAudio, orairplayTx) 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('- [32m${device.name}[0m (${device.ip})');
}
print('Discovered DLNA devices:');
for (final device in devices['dlna'] ?? []) {
print('- [34m${device.name}[0m (${device.ip})');
}
// New: AirPlay RX and TX output
print('Discovered AirPlay RX devices:');
for (final device in devices['airplay_rx'] ?? []) {
print('- [35m${device.name}[0m (${device.ip})');
}
print('Discovered AirPlay TX devices:');
for (final device in devices['airplay_tx'] ?? []) {
print('- [36m${device.name}[0m (${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 devicesdlnaRenderer,dlnaMediaServer- DLNA devicesairplayRxVideo,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
-lor in code viaLocalizationManager().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.