Developer Guide

Complete guide for developers contributing to the LegacyStream project

Introduction

LegacyStream is an open-source, high-performance audio streaming server built with C++ and Qt. This guide provides comprehensive information for developers who want to contribute to the project.

Project Goals

  • High Performance: Optimized for Windows with IOCP
  • Multi-Protocol Support: IceCast and SHOUTcast compatibility
  • Modern Architecture: Modular, extensible design
  • Developer Friendly: Comprehensive documentation and tools
  • Cross-Platform: Windows-focused with potential for other platforms

Technology Stack

  • Language: C++17/20
  • Framework: Qt 6.x
  • Build System: CMake
  • Testing: Google Test
  • Documentation: Doxygen
  • Version Control: Git

Architecture Overview

Core Components

LegacyStream follows a modular architecture with clear separation of concerns:

Core Module

  • ServerManager: Central coordination and lifecycle management
  • ConfigurationManager: Settings and configuration management
  • PerformanceManager: Performance optimization and monitoring
  • LogManager: Logging and debugging facilities

Streaming Module

  • StreamManager: Audio stream management
  • CodecManager: Audio codec handling
  • ProtocolManager: IceCast/SHOUTcast protocols
  • HttpServer: HTTP server implementation

GUI Module

  • MainWindow: Primary GUI interface
  • ThemeManager: UI theming and customization
  • AccessibilityManager: Accessibility features

Design Patterns

  • Singleton Pattern: Used for managers and global services
  • Observer Pattern: Event-driven architecture
  • Factory Pattern: Object creation and management
  • Strategy Pattern: Pluggable algorithms and protocols

Data Flow

  1. Audio input is captured or loaded from files
  2. Audio data is processed and encoded
  3. Encoded data is buffered and queued
  4. HTTP server delivers streams to clients
  5. Real-time statistics are collected and displayed

Development Setup

Prerequisites

  • Windows 10/11: Development environment
  • Visual Studio 2019/2022: C++ compiler and IDE
  • Qt 6.x: Application framework
  • CMake 3.16+: Build system
  • Git: Version control

Environment Setup

  1. Clone the repository:
    git clone https://github.com/legacystream/legacystream.git
    cd legacystream
  2. Install Qt 6.x and set environment variables
  3. Install Visual Studio with C++ development tools
  4. Install CMake and add to PATH
  5. Install additional dependencies:
    # Install vcpkg for dependencies
    git clone https://github.com/Microsoft/vcpkg.git
    cd vcpkg
    .\bootstrap-vcpkg.bat
    .\vcpkg install openssl:x64-windows
    .\vcpkg install zlib:x64-windows

Building from Source

# Create build directory
mkdir build
cd build

# Configure with CMake
cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake

# Build the project
cmake --build . --config Release

# Run tests
ctest --output-on-failure
Tip: Use Visual Studio's CMake integration for a better development experience.

Code Organization

Directory Structure

LegacyStream/
├── include/           # Header files
│   ├── core/         # Core functionality
│   ├── gui/          # GUI components
│   ├── streaming/    # Streaming modules
│   ├── ssl/          # Security components
│   └── realtime/     # Real-time features
├── src/              # Source files
│   ├── core/         # Core implementation
│   ├── gui/          # GUI implementation
│   ├── streaming/    # Streaming implementation
│   └── ssl/          # Security implementation
├── tests/            # Test files
├── docs/             # Documentation
├── scripts/          # Build and deployment scripts
└── resources/        # Application resources

Naming Conventions

  • Classes: PascalCase (e.g., StreamManager)
  • Functions: camelCase (e.g., startStream())
  • Variables: camelCase (e.g., streamName)
  • Constants: UPPER_SNAKE_CASE (e.g., MAX_CONNECTIONS)
  • Files: PascalCase (e.g., StreamManager.h)

File Organization

  • One class per header/source file pair
  • Header files contain declarations only
  • Source files contain implementations
  • Use forward declarations when possible
  • Include guards for all header files

Coding Standards

C++ Standards

  • Use C++17/20 features where appropriate
  • Prefer modern C++ over C-style code
  • Use smart pointers instead of raw pointers
  • Use RAII for resource management
  • Prefer const correctness

Code Style

// Good example
class StreamManager {
public:
    explicit StreamManager(QObject* parent = nullptr);
    ~StreamManager();
    
    bool startStream(const QString& streamName);
    void stopStream(const QString& streamName);
    
private:
    void initializeStream();
    void cleanupStream();
    
    QString m_streamName;
    bool m_isRunning = false;
};

Documentation

  • Use Doxygen comments for all public APIs
  • Include examples in documentation
  • Document exceptions and error conditions
  • Keep documentation up to date

Error Handling

  • Use exceptions for exceptional conditions
  • Return error codes for expected failures
  • Log errors with appropriate detail
  • Provide meaningful error messages

Testing

Test Types

  • Unit Tests: Test individual components
  • Integration Tests: Test component interactions
  • Performance Tests: Test performance characteristics
  • GUI Tests: Test user interface functionality

Writing Tests

#include 
#include "StreamManager.h"

class StreamManagerTest : public ::testing::Test {
protected:
    void SetUp() override {
        manager = std::make_unique();
    }

    void TearDown() override {
        manager.reset();
    }

    std::unique_ptr manager;
};

TEST_F(StreamManagerTest, StartStream_ValidName_ReturnsTrue) {
    // Arrange
    QString streamName = "test_stream";
    
    // Act
    bool result = manager->startStream(streamName);
    
    // Assert
    EXPECT_TRUE(result);
    EXPECT_TRUE(manager->isStreamRunning(streamName));
}

Running Tests

# Run all tests
ctest --output-on-failure

# Run specific test
./tests/StreamManagerTest --gtest_filter=StartStream_ValidName_ReturnsTrue

# Run with verbose output
ctest --verbose

Documentation

Code Documentation

/**
 * @brief Manages audio streams and their lifecycle
 * 
 * The StreamManager class provides functionality to create, start, stop,
 * and monitor audio streams. It handles stream configuration, encoding,
 * and delivery to clients.
 * 
 * @example
 * @code
 * StreamManager manager;
 * manager.startStream("my_stream");
 * @endcode
 */
class StreamManager : public QObject {
    Q_OBJECT
public:
    /**
     * @brief Starts a new audio stream
     * @param streamName The name of the stream to start
     * @return true if stream started successfully, false otherwise
     * @throws std::runtime_error if stream configuration is invalid
     */
    bool startStream(const QString& streamName);
};

API Documentation

  • Document all public APIs with Doxygen
  • Include usage examples
  • Document parameters and return values
  • Explain error conditions and exceptions

Architecture Documentation

  • Maintain architecture diagrams
  • Document design decisions
  • Keep component relationships current
  • Document data flow and state management

Contribution Guidelines

Before Contributing

  • Read the project documentation
  • Check existing issues and pull requests
  • Discuss major changes in issues first
  • Ensure your development environment is set up

Development Workflow

  1. Fork the repository
  2. Create a feature branch:
    git checkout -b feature/your-feature-name
  3. Make your changes following coding standards
  4. Write tests for new functionality
  5. Update documentation as needed
  6. Run the full test suite
  7. Commit your changes with clear messages
  8. Push to your fork and create a pull request

Commit Messages

Use clear, descriptive commit messages:

feat: add support for AAC audio codec
fix: resolve memory leak in StreamManager
docs: update API documentation
test: add unit tests for new features
refactor: improve error handling in HttpServer

Pull Request Guidelines

  • Provide a clear description of changes
  • Include tests for new functionality
  • Update documentation if needed
  • Ensure all tests pass
  • Follow the project's coding standards

Build System

CMake Configuration

# CMakeLists.txt example
cmake_minimum_required(VERSION 3.16)
project(LegacyStream VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Core Widgets Network)
find_package(OpenSSL REQUIRED)

add_executable(LegacyStream
    src/main.cpp
    src/core/ServerManager.cpp
    src/streaming/StreamManager.cpp
)

target_link_libraries(LegacyStream
    Qt6::Core
    Qt6::Widgets
    Qt6::Network
    OpenSSL::SSL
    OpenSSL::Crypto
)

Build Configurations

  • Debug: Development with debug symbols
  • Release: Optimized production build
  • RelWithDebInfo: Release with debug info
  • MinSizeRel: Minimal size release

Dependencies

  • Qt 6.x: Application framework
  • OpenSSL: SSL/TLS support
  • Google Test: Testing framework
  • Doxygen: Documentation generation

Deployment

Release Process

  1. Update version numbers in CMakeLists.txt
  2. Update CHANGELOG.md with release notes
  3. Create a release tag:
    git tag -a v1.0.0 -m "Release version 1.0.0"
    git push origin v1.0.0
  4. Build release packages
  5. Test release packages
  6. Upload to release page

Packaging

  • Create Windows installer with NSIS
  • Include all required dependencies
  • Provide portable version
  • Include documentation and examples

Continuous Integration

  • Automated builds on multiple platforms
  • Automated testing
  • Code quality checks
  • Automated deployment

API Reference

Core APIs

// ServerManager API
class ServerManager {
public:
    bool initialize();
    void shutdown();
    bool isRunning() const;
    
    // Stream management
    bool createStream(const QString& name);
    bool startStream(const QString& name);
    bool stopStream(const QString& name);
    bool deleteStream(const QString& name);
};

// ConfigurationManager API
class ConfigurationManager {
public:
    void loadConfiguration(const QString& file);
    void saveConfiguration(const QString& file);
    QVariant getValue(const QString& key);
    void setValue(const QString& key, const QVariant& value);
};

Streaming APIs

// StreamManager API
class StreamManager {
public:
    bool addMountPoint(const QString& path, const StreamConfig& config);
    bool removeMountPoint(const QString& path);
    QList getActiveStreams() const;
    
    // Audio processing
    void setAudioFormat(const QString& stream, const AudioFormat& format);
    void setBitrate(const QString& stream, int bitrate);
    void setSampleRate(const QString& stream, int sampleRate);
};

GUI APIs

// MainWindow API
class MainWindow : public QMainWindow {
public:
    void showStreamManager();
    void showConfiguration();
    void showStatistics();
    void showLogs();
};

Troubleshooting

Common Build Issues

Qt Not Found

# Set Qt6_DIR environment variable
set Qt6_DIR=C:\Qt\6.5.0\msvc2019_64\lib\cmake\Qt6

# Or specify in CMake
cmake .. -DQt6_DIR=C:\Qt\6.5.0\msvc2019_64\lib\cmake\Qt6

OpenSSL Not Found

# Use vcpkg for dependencies
cmake .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake

Compiler Errors

  • Ensure you're using C++17 or later
  • Check that all required headers are included
  • Verify Qt modules are properly linked
  • Check for missing dependencies

Runtime Issues

Application Won't Start

  • Check if all DLLs are in PATH
  • Verify Qt plugins are accessible
  • Check for missing configuration files
  • Review application logs

Streaming Issues

  • Verify audio codecs are available
  • Check network port availability
  • Review stream configuration
  • Check firewall settings

Debugging

  • Use Visual Studio debugger
  • Enable debug logging
  • Use Qt Creator for GUI debugging
  • Check Windows Event Viewer