- Overview
- Architecture
- API Reference
- Configuration
- Matrix Integration
- Audio System
- Storage Management
- Error Handling
- Performance Optimization
- Security Considerations
- Troubleshooting Guide
Airwave Automator Free is a Chrome extension built with Manifest V3 that combines radio streaming capabilities with Matrix chat integration. The extension uses a side panel interface and provides real-time audio streaming with chat functionality.
- Background Service Worker: Manages global audio playback and inter-page communication
- Side Panel Interface: Main user interface with Radio, Chat, and Options pages
- Matrix SDK Integration: Custom minimal Matrix client implementation
- Audio Management: HTML5 audio with Web Audio API visualization
- Storage System: Chrome storage API for persistent settings
Airwave Automator Free/
├── manifest.json # Extension configuration
├── background.js # Service worker
├── popup.html/js # Extension popup
├── radio.html/js # Radio player interface
├── matrix.html/js # Matrix chat interface
├── options.html/js # Settings interface
├── styles.css # Global styling
├── assets/ # Static assets
│ └── logo.png # Extension logo
└── third_party/ # External dependencies
├── matrix/
│ └── browser-matrix.min.js # Custom Matrix SDK
└── sonic-widget.min.js # SonicPanel integration
- User Interaction → UI Components → Background Script
- Matrix Events → Matrix SDK → Chat Interface
- Audio Streams → HTML5 Audio → Visualizer → UI Updates
- Settings Changes → Chrome Storage → Persistent State
AA_SET_SIDEPANEL_PATH: Change the side panel pageAA_PLAY_AUDIO: Start global audio playbackAA_STOP_AUDIO: Stop global audio playbackAA_SET_VOLUME: Adjust global audio volume
// Play audio globally across all pages
playGlobalAudio(streamUrl, volume)
// Stop global audio playback
stopGlobalAudio()
// Set global audio volume
setGlobalVolume(volume)// Initialize Matrix client
const client = new MatrixClient({
baseUrl: 'https://matrix.org',
accessToken: 'your_token',
userId: '@user:server',
deviceId: 'device_id'
})
// Login to Matrix
await client.login('m.login.password', {
user: '@user:server',
password: 'password'
})
// Join a room
await client.joinRoom('#room:server')
// Send a message
await client.sendTextMessage('#room:server', 'Hello!')
// Perform sync
await client.performSync(limit)sync: Emitted when sync completesRoom.timeline: Emitted when new messages arrive
// Setup audio visualization
setupViz()
// Initialize SonicPanel widget
initSonicWidget(port)
// Fetch SonicPanel metadata
fetchSonicInfo()
// Save/restore audio state
saveAudioState()
restoreAudioState()// Open a Matrix room
openMatrixRoom(roomId)
// Join a room
joinRoom()
// Join recommended room
joinRecommendedRoom(roomId)
// Render room list
renderMatrixRooms(rooms){
"manifest_version": 3,
"name": "Airwave Automator Free",
"version": "1.0.26",
"permissions": ["storage", "sidePanel"],
"host_permissions": ["https://*/*", "http://*/*"],
"background": {
"service_worker": "background.js"
},
"side_panel": {
"default_path": "radio.html"
}
}// Stream object structure
{
name: "Stream Name",
url: "http://stream.example.com:8000",
port: 8000,
apiUrl: "http://api.example.com/get_info.php",
volume: 0.8
}// Matrix settings structure
{
homeserver: "https://matrix.org",
user: "@user:server",
password: "password",
loggedIn: true,
refreshInterval: 1
}The custom Matrix SDK implements proper sync token handling for incremental updates:
// Sync with token for incremental updates
let syncUrl = `${baseUrl}/_matrix/client/v3/sync?limit=${limit}&timeout=1000`;
if (this.nextBatchToken) {
syncUrl += `&since=${this.nextBatchToken}`;
}Prevents duplicate messages by checking event IDs:
const existingEvent = room.timeline.events.find(e =>
e.eventData.event_id === eventData.event_id
);
if (!existingEvent) {
room.timeline.events.push(event);
this.emit("Room.timeline", event, room);
}- Automatic room creation and updates
- Fuzzy room ID matching
- Member management
- Timeline event processing
/r0/login- User authentication/v3/sync- Event synchronization/v3/rooms/{roomId}/join- Join rooms/v3/rooms/{roomId}/send/m.room.message- Send messages/v3/directory/room/{roomAlias}- Resolve room aliases
The extension implements a global audio system that persists across page navigation:
// Background script manages global audio
let globalAudioPlayer = null;
function playGlobalAudio(streamUrl, volume) {
if (!globalAudioPlayer) {
globalAudioPlayer = new Audio();
}
globalAudioPlayer.src = streamUrl;
globalAudioPlayer.volume = volume;
globalAudioPlayer.play();
}Uses Web Audio API for real-time visualization:
function setupViz() {
const audioContext = new AudioContext();
const analyser = audioContext.createAnalyser();
const source = audioContext.createMediaElementSource(player);
source.connect(analyser);
analyser.connect(audioContext.destination);
// Render visualization frames
function render() {
requestAnimationFrame(render);
// Update canvas visualization
}
}Automatic metadata fetching and display:
function initSonicWidget(port) {
const script = document.createElement('script');
script.src = 'third_party/sonic-widget.min.js';
script.onload = () => {
// Initialize SonicPanel widget
};
document.head.appendChild(script);
}// Sync storage for settings
chrome.storage.sync.set({ aa_streams: streams });
chrome.storage.sync.set({ aa_matrix_settings: matrixSettings });
// Local storage for audio state
chrome.storage.local.set({ aa_audio_state: audioState });
chrome.storage.local.get(['aa_audio_state']);- Streams: Stored in
chrome.storage.sync(syncs across devices) - Matrix Settings: Stored in
chrome.storage.sync - Audio State: Stored in
chrome.storage.local(device-specific) - UI State: Managed in memory, restored on page load
try {
await matrixAuthed.joinRoom(roomId);
} catch (error) {
console.error('Failed to join room:', error);
let suggestion = '';
if (error.message.includes('404')) {
suggestion = '\n\nTry these popular public rooms...';
}
alert(`Failed to join room: ${error.message}${suggestion}`);
}player.addEventListener('error', (e) => {
console.error('Audio error:', e);
matrixStatus.textContent = 'Audio error: ' + e.message;
matrixStatus.className = 'status error';
});- Automatic retry mechanisms
- Graceful degradation
- User-friendly error messages
- Fallback options
- 1-second refresh interval for near real-time updates
- Incremental sync using tokens
- Event deduplication to prevent spam
- Timeout parameters for faster responses
- Global audio management reduces resource usage
- Efficient visualization using requestAnimationFrame
- Memory management for audio contexts
- Background playback optimization
- Lazy loading of Matrix SDK
- Efficient DOM updates
- Debounced user inputs
- Optimized event listeners
"content_security_policy": {
"extension_pages": "script-src 'self' data: https: http:; img-src 'self' data: https: http:; connect-src 'self' https: http: wss: ws:;"
}- End-to-end encryption support
- Secure token storage in Chrome storage
- HTTPS-only Matrix connections
- Input validation for user data
- Local storage for sensitive data
- No data collection or transmission
- User control over all settings
- Secure credential handling
- Check stream URL accessibility
- Verify Chrome audio permissions
- Check for ad blocker interference
- Test with different stream formats
- Verify Matrix credentials
- Check homeserver accessibility
- Ensure proper Matrix ID format (@user:server)
- Test with different homeserver
- Check Matrix connection status
- Verify room membership
- Use "Force Fresh Sync" button
- Check console for errors
- Reload extension in chrome://extensions/
- Check browser console for errors
- Clear extension data if needed
- Reinstall extension
The extension includes comprehensive logging:
console.log('Matrix SDK performing sync with limit:', limit);
console.log('Sync response received:', data);
console.log('Added new message event:', eventData.event_id);- Test Message: Adds dummy message to timeline
- Debug Timeline: Shows timeline state information
- Refresh Rooms: Forces room list refresh
- Force Fresh Sync: Resets sync token and performs fresh sync
- Monitor Matrix sync response times
- Track audio playback performance
- Monitor memory usage
- Check for memory leaks
- Use consistent indentation (2 spaces)
- Include comprehensive comments
- Follow JavaScript best practices
- Implement proper error handling
- Test with multiple Matrix homeservers
- Verify audio playback across different stream types
- Test extension behavior across page navigation
- Validate error handling scenarios
- Regular dependency updates
- Security patch management
- Performance monitoring
- User feedback integration
Technical Support: For technical issues, contact support@spunwebtechnology.com or join #airwavesupport:matrix.org