MediaManager is a high-performance music library organizer designed with a modern split architecture: a powerful backend daemon and a responsive GUI frontend communicating through blazing-fast Unix Domain Sockets (for local use) or gRPC (for client-server usage).
┌──────────────────────────────┐
│ User's Computer │
│ ┌────────────────────────┐ │
│ │ MediaManager GUI │ │
│ └──────────┬─────────────┘ │
│ │ Unix Socket │
│ ┌──────────▼─────────────┐ │
│ │ MediaManager Core │ │
│ └──────────┬─────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ Music Files │ │
│ └─────────────┘ │
└──────────────────────────────┘
Use case: Single user, personal music library on their PC/Mac
┌─────────────────────────┐ ┌──────────────────┐
│ Home Server/NAS │ │ User's Desktop │
│ ┌──────────────────┐ │ │ ┌────────────┐ │
│ │ MediaManager Core│ │◄────────┤ │ GUI │ │
│ └────────┬─────────┘ │ gRPC │ └────────────┘ │
│ │ │ └──────────────────┘
│ ┌──────▼──────┐ │
│ │ Music Files │ │
│ │ 10TB NAS │ │
│ └─────────────┘ │
└─────────────────────────┘
Use case: Centralized music library, multiple users/devices
MediaManager supports two communication methods depending on your deployment:
When to use: GUI and Core on the same machine
Advantages:
Protocol: Length-prefixed Protocol Buffers messages
When to use: GUI connecting to remote Core (NAS, server)
Advantages:
Protocol: HTTP/2 with Protocol Buffers
Both communication methods use Protocol Buffers for serialization:
protobuf
message Request { string request_id = 1; // UUID for tracking bytes payload = 2; // Command (ScanLibrary, SearchTrack, etc.) map<string, string> headers = 3; // Metadata (Command-Type, Auth-Token) }
protobuf
message Response { string request_id = 1; // Matches request int32 status_code = 2; // 200 = OK, 404 = Not Found, etc. bytes payload = 3; // Result data map<string, string> headers = 4; // Additional info }
The backend-agnostic design means you can build MediaManager UIs in any language or framework:
| Technology | Protocol | Pros |
|---|---|---|
| JavaFX | Unix Socket | Native Java, rich components |
| Electron | gRPC (JS) | Web tech, cross-platform |
| Qt (C++) | Unix Socket/gRPC | Native performance |
| Flutter | gRPC (Dart) | Beautiful, modern UI |
| Technology | Protocol | Pros |
|---|---|---|
| React/Vue | gRPC-Web | Modern SPA, real-time updates |
| Next.js | gRPC via API routes | SSR, SEO-friendly |
| Svelte | gRPC-Web | Lightweight, fast |
⚠️ Note: The application is not yet ready to run, but you can start developing an interface by following this guide.
🔗 Available at: https://git.gustavomiranda.xyz/GHMiranda/MediaManager-core
bash
git clone https://git.gustavomiranda.xyz/GHMiranda/MediaManager-core
cd MediaManager-core
bash
# Check the .proto files to understand available commands ls src/main/proto/
bash
mvn generate-sources
┌─────────────────────────────────────────────┐
│ Client Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ GUI │ │ CLI │ │ Web │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
└───────┼─────────────┼─────────────┼─────────┘
│ │ │
│ Unix Socket │ Unix Socket │ gRPC
│ │ │
┌───────▼─────────────▼─────────────▼─────────┐
│ MediaManager Core │
│ ┌──────────────────────────────────────┐ │
│ │ IPC Layer │ │
│ │ ┌──────────┐ ┌─────────────┐ │ │
│ │ │ Unix │ │ gRPC │ │ │
│ │ │ Socket │ │ Server │ │ │
│ │ └──────────┘ └─────────────┘ │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ DelegateActionManager │ │
│ │ (Request Router) │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ LibraryService │ │
│ │ ┌──────────┐ ┌─────────────────┐ │ │
│ │ │ Scanner │ │ Metadata │ │ │
│ │ │ │ │ Extractor │ │ │
│ │ └──────────┘ └─────────────────┘ │ │
│ │ ┌──────────┐ ┌─────────────────┐ │ │
│ │ │Organizer │ │ Analyzer │ │ │
│ │ └──────────┘ └─────────────────┘ │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ Database Service │ │
│ │ (SQLite / PostgreSQL) │ │
│ └──────────────────────────────────────┘ │
└──────────────────┬───────────────────────────┘
│
┌──────▼──────┐
│ Music Files │
│ Library │
└─────────────┘
The separation between Core and UI provides unprecedented flexibility:
Choose the best tool for your needs:
Run different UIs simultaneously:
Ready to learn more? Explore these guides:
| Component | Technology | Purpose |
|---|---|---|
| Language | Java 17+ | Core daemon implementation |
| Build System | Maven | Dependency management, protobuf compilation |
| IPC (Local) | Unix Domain Sockets | High-speed local communication |
| IPC (Remote) | gRPC | Network-based RPC |
| Serialization | Protocol Buffers 3.x | Efficient binary format |
| Database | SQLite / PostgreSQL | Metadata storage |
| Metadata | JAudioTagger | Audio tag reading/writing |
| Concurrency | ExecutorService | Multi-threaded client handling |
| Logging | Log4j 2 | Structured logging |
java
public class SimpleMediaManagerClient { public static void main(String[] args) throws Exception { // Connect to local Core via Unix socket SocketChannel channel = SocketChannel.open(StandardProtocolFamily.UNIX); channel.connect(UnixDomainSocketAddress.of("/tmp/mediamanager.sock"));
// Create a search command SearchCommand search = SearchCommand.newBuilder() .setQuery("artist:Beatles") .setLimit(10) .build();
Request request = Request.newBuilder() .setRequestId(UUID.randomUUID().toString()) .setPayload(search.toByteString()) .putHeaders("Command-Type", "Search") .build();
// Send with length prefix byte[] data = request.toByteArray(); ByteBuffer buffer = ByteBuffer.allocate(4 + data.length); buffer.putInt(data.length); // Size buffer.put(data); // Payload buffer.flip(); channel.write(buffer);
// Read response ByteBuffer sizeBuffer = ByteBuffer.allocate(4); channel.read(sizeBuffer); sizeBuffer.flip(); int responseSize = sizeBuffer.getInt();
ByteBuffer responseBuffer = ByteBuffer.allocate(responseSize); channel.read(responseBuffer); responseBuffer.flip();
Response response = Response.parseFrom(responseBuffer.array()); SearchResults results = SearchResults.parseFrom(response.getPayload());
// Display results System.out.println("Found " + results.getTracksCount() + " tracks:"); for (Track track : results.getTracksList()) { System.out.printf("%s - %s (%s)\n",
track.getArtist(),
track.getTitle(), track.getAlbum()); }
channel.close(); } }
Ready to start building? Head to Development Environment Setup and create your first MediaManager client!