Skip to content

Architecture

localghost edited this page Sep 13, 2014 · 31 revisions

Threading

  • Main (UI)
  • Audio
  • Spotify

Q&A

  • Should each thread contain a private message loop?
    Yes
  • Should session management be on a separate thread?
    Yes, see here
  • Are session callbacks run on a main thread (in particular, are they run on the thread they were registered at)?
    No

Components

  • UI (platform specific)
  • Configuration
  • Parser (use INI format and boost property tree library)
  • Search engine
  • Search
  • SearchQuery
  • Audio system (audio playing subsystem will be platform specific)
  • MainLoop (platform specific; used to register sp_session_process_events)
  • Session (split it into sub-interfaces? hardly possible!)

Things to reconsider

Configuration

load/save

Currently configuration management is not very flexible. Load/save API is coupled with what properties configuration object stores. Thus, if a second configuration object would be needed it would need to contain its own load/save API crafted specifically for it needs. In that case it would be a good idea to decouple load/save API from a configuration object. This, however, would require for the configuration object to be a mapping container (simple solution) or it would have to provide serializing/deserializing API. The actual loading/saving could be done by a separate entity - Configuration Manager.

external updates

Configuration Manager could additionally watch for external changes in the configuration file (edited by user via an external editor) and either trigger configuration update in run-time or if necessary forward notification to the user with suggestion to restart the application.

life expectancy

This component should outlive all others.

Session

Music delivery

Preallocate some memory for buffering

  1. Allocate a buffer (pool?) for delivered frames
  2. music_delivery fills a buffer if it is unused (up to the size of the buffer), if not 0 is returned so that libspotify resends the frames
  3. music_delivery calls on_frame_delivered (on engine thread)
  4. on_frame_delivered launches all the signals
  5. on_frame_delivered marks the buffer as unused

Base

Message loop

Should active_ flag be set not only via a task but explicitly in the stop() method as well?

Pros

  • If there are many tasks in the queue all of the non-timed tasks would have to be executed before the one that sets the active_ flag but this way loop can finish at the next iteration (but is it a good approach?)

Cons

  • It has to be atomic

If it is decided that active_ should be set in stop() as well then queue would have to be cleared so that on next call to start(), though not a common use case, old tasks are not restored (don't I want that?). This would have to be done probably in the start() method since it can't be done in stop() (since quit task is queued there).