# ESP Playlist

[中文]

## Introduction

ESP Playlist is a media library and playlist management component for Espressif multimedia applications. It consists of two independent modules: a media library and a playlist. The media library records the name and location of each media file on the device. The playlist records playback order and the current position. The component provides directory scanning, media-library persistence, playlist JSON export and import, multi-instance management, and sequential, single-track repeat, list repeat, and shuffle modes. It is suited to local music players and spoken-content devices.

## Feature List

- Directory scanning: filters media files in a specified directory by recursion depth, file extension, and a custom callback, then adds them to the media library in batch

- Media library persistence: data is written to storage when using file system storage and can be reloaded after reboot; RAM storage is valid only during runtime

- Playlist construction: import from the media library with condition-based filtering, or load from a JSON file/memory buffer

- Playlist export: generates JSON that can be saved to a file, NVS, or delivered over the network

- Multi-instance management: multiple media library and playlist handles can be created simultaneously, each maintaining its own independent state

- Condition-based filtering: supports exact match, contains match, or prefix match on fields such as `name`, `url`, and `id`, with AND/OR combination

- Playback modes: no repeat, single-track repeat, list repeat, and shuffle, switched via the current track navigation interface

## Technical Deep Dive

### Media Library (esp_media_db)

The media library is a directory index of media files; it only stores `name` and `url`, and does not parse the media content itself. When `esp_media_db_init()` creates a handle, the storage method is selected through the `storage_type` field of `esp_media_db_cfg_t`: an `esp_db_storage_type_t` value of `ESP_DB_STORAGE_FS` means the data is written to a three-file database on the file system pointed to by `storage_path`, and can be reloaded after reboot with `esp_media_db_load()`; a value of `ESP_DB_STORAGE_RAM` means the data is kept only in heap memory, which suits scenarios that do not require persistence and are rebuilt frequently.

    esp_media_db_cfg_t db_cfg = {
        .storage_type = ESP_DB_STORAGE_FS,
        .storage_path = "/sdcard/__playlist",
    };
    esp_media_db_handle_t media_db = NULL;
    esp_media_db_init(&db_cfg, &media_db);
    esp_media_db_load(media_db);  /* load first if a database file already exists under storage_path */

There are two ways to add files: `esp_media_db_scan()` recursively scans a directory according to `path`, `scan_depth`, and `file_extensions` in `esp_media_db_scan_cfg_t`, with an optional `filter_cb` to perform a secondary check on each scanned URL; `esp_media_db_add()` directly writes a `name` / `url` entry already known to the caller. `skip_duplicate` applies only to `scan`: entries are always added normally when the media library is empty; when the media library already contains entries, `skip_duplicate = true` means all entries are added without comparing URLs, while `skip_duplicate = false` means entries that already exist (matched by URL) are skipped. When performing an incremental scan on a media library that already has content, `skip_duplicate = false` is typically set to avoid duplicate entries. `esp_media_db_add()` always skips existing URLs and has no `skip_duplicate` parameter.

`esp_media_db_remove()` deletes a specified entry by URL; `esp_media_db_clean()` only clears the in-process view of the media library and does not delete the database file on the file system, so calling `esp_media_db_load()` again restores it when needed; `esp_media_db_get_count()` returns the current entry count.

### Playlist (esp_playlist)

The playlist maintains an ordered sequence of entries and a current index in RAM, and `esp_playlist_new()` creates an empty instance. There are two independent paths for populating a playlist, with different behavior:

- `esp_playlist_import_media()` appends entries from a media library; when `filter` is `NULL` all entries are imported, and when an `esp_media_filter_t` is provided, entries are filtered by condition. After importing, the playlist becomes bound to that media library handle, and a subsequent import from a different handle returns `ESP_ERR_INVALID_STATE`. Such entries are stored inside the playlist only as references to the media library (DB entries), so navigation needs to look back at the media library to obtain `name` / `url`

- `esp_playlist_load()` / `esp_playlist_import_ram()` clear and replace the current list from a JSON file or memory buffer, independent of the media library; the parsed entries carry their own `name` / `url` directly (inline entries), so navigation does not need to look back at the media library

    esp_playlist_handle_t playlist = NULL;
    esp_playlist_new(&(esp_playlist_cfg_t) { .playlist_name = "default" }, &playlist);
    esp_playlist_import_media(playlist, media_db, NULL);  /* import all entries from the media library */

`esp_playlist_save()` / `esp_playlist_export_ram()` only export the playlist’s own JSON (name, order, entries), without involving the media library file; both share the same JSON format as `esp_playlist_load()` / `esp_playlist_import_ram()` and can be read and written interchangeably. `esp_playlist_export_ram()` returns a buffer that must be released by the caller with `free()`. `esp_playlist_clean()` clears the current list entries without deleting the JSON file on disk or the media library file.

### Current Track and Repeat Mode

The playlist maintains a zero-based current index, pointing to entry 0 by default. `esp_playlist_set_curr_index()` jumps to a specified index; `esp_playlist_curr()`, `esp_playlist_next()`, `esp_playlist_prev()`, and `esp_playlist_get_info()` are used to read entry information and populate it into an `esp_playlist_info_t` provided by the caller. Among these, `get_info` reads by a specified `index` and does not change the current index, while the other three either update or depend on the current index.

The boundary behavior of `next` / `prev` is determined by the `esp_playlist_repeat_mode_t` set via `esp_playlist_set_repeat_mode()`:

Mode | Behavior
--- | ---
`ESP_PLAYLIST_REPEAT_NONE` | Returns `ESP_ERR_NOT_FOUND` upon reaching a list boundary; does not repeat
`ESP_PLAYLIST_REPEAT_ONE` | Stays at the current index, repeatedly reading the same entry
`ESP_PLAYLIST_REPEAT_ALL` | Wraps around to the other end of the list upon reaching a boundary
`ESP_PLAYLIST_REPEAT_SHUFFLE` | Randomly selects an index each time `next` / `prev` is called

When an entry is a DB entry but its bound media library has become invalid, the navigation interfaces return `ESP_ERR_INVALID_STATE`; when the list is empty or a non-repeating boundary is reached, they return `ESP_ERR_NOT_FOUND`.

### Filter (esp_media_filter_t)

`esp_media_filter_t` consists of a number of `esp_media_filter_item_t` conditions, each specifying a field name (such as `name`, `url`, or `id`), an expected value, and an `esp_media_match_type_t` matching method (exact match `ESP_MEDIA_MATCH_EXACT`, contains match `ESP_MEDIA_MATCH_CONTAINS`, prefix match `ESP_MEDIA_MATCH_PREFIX`), with `match_all` determining whether the conditions are combined with AND or OR. This filter is also used for import filtering in `esp_playlist_import_media()`.

    esp_media_filter_item_t items[] = {
        { .key = "url", .expected = { .type = ESP_DB_FIELD_TYPE_STRING, .value.strv = ".mp3", .size = 5 },
          .match_type = ESP_MEDIA_MATCH_CONTAINS },
    };
    esp_media_filter_t filter = {
        .items = items,
        .item_count = 1,
        .match_all = true,
    };
    esp_playlist_import_media(playlist, media_db, &filter);

## Performance

Measured average per-operation times for the playlist_benchmark example on an ESP32-P4 Function EV Board (SD card, 1000 entries) are as follows; actual values vary with the SoC, SD card speed, and number of media items:

Operation | Scenario | Average Time
--- | --- | ---
`esp_media_db_scan`(cold scan, no deduplication) | 1000 files | 664.71 us/item
`esp_media_db_load` | 1000 entries | 66.34 us/item
`esp_playlist_import_media` | 1000 entries | 176.76 us/item
`esp_playlist_next` / `prev`(DB entries) | Single call | 156.71 / 205.23 us
`esp_playlist_next` / `prev`(inline entries) | Single call | 2.53 / 2.49 us
`esp_playlist_save` | 1000 entries, 73045 bytes | 366.81 us/item
`esp_playlist_load`(JSON) | 1000 entries, 73045 bytes | 105.63 us/item

Navigating DB entries (imported via `import_media`) is about two orders of magnitude slower than navigating inline entries (imported via `load` / `import_ram`), because the former must look back at the media library for `name` / `url` on every call, while the latter’s entries already carry complete information. Scenarios that switch tracks frequently should prefer the inline entry path.

## Application Examples

- playlist_benchmark demonstrates the complete flow of media library scanning/loading, playlist import and navigation, and JSON saving/loading, and outputs the benchmarked timing of each interface

Typical scenarios and the corresponding interfaces are as follows:

Scenario | Recommended Flow
--- | ---
Local music on SD card | Mount the SD card, scan the directory with `esp_media_db_scan`, import with `esp_playlist_import_media`, and save the playlist with `esp_playlist_save`
Fixed URL list on flash | Write fixed entries with `esp_media_db_add` and then import with `esp_playlist_import_media`
Restore on boot | Restore the media library with `esp_media_db_load`, restore the playlist JSON with `esp_playlist_load`
NVS / network-delivered list | Obtain JSON with `esp_playlist_export_ram` and store it independently; restore with `esp_playlist_import_ram`
Filter by name or URL | Construct an `esp_media_filter_t`, combined with matching methods such as `ESP_MEDIA_MATCH_EXACT`, `ESP_MEDIA_MATCH_CONTAINS`, `ESP_MEDIA_MATCH_PREFIX`

## FAQ

Q1: What is the difference between the media library and the playlist JSON?

The media library (a database file under `storage_path` when using file system storage) stores the set of `name` / `url` entries obtained through scanning or manual addition, recording which media files exist on the device. The playlist JSON only stores a single playlist’s name, order, and entries, recording the order in which items are played; the two are different persistence objects.

Q2: If only playlist.json is loaded, is the media library still needed?

No. The JSON entries already contain `name` and `url`, so after loading, the URL can be retrieved directly via `curr` / `next` / `prev` / `get_info` for playback. Such entries are inline entries and do not require looking back at the media library.

Q3: Can entries be imported by album or artist?

The current public interfaces do not parse metadata such as `album` or `artist` from the media file itself. If the media library entries already contain such extended fields, filtering can be achieved by matching the corresponding fields via `esp_media_filter_t`.

## API Reference

### Header File

- components/esp_playlist/include/esp_playlist.h

### Functions

esp_err_t esp_playlist_new(const esp_playlist_cfg_t *cfg, esp_playlist_handle_t *handle)

  Create an empty in-RAM playlist.

          Populate with esp_playlist_import_media(), esp_playlist_import_ram(), or
          esp_playlist_load(). RAM buffer export/import uses a separate format from the media DB
          three-file persistence.

  Parameters:

    - cfg – [in] Configuration; playlist_name must be non-NULL and non-empty

    - handle – [out] Receives the new handle on success

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If cfg, handle, or playlist_name is invalid

    - ESP_ERR_NO_MEM If allocation fails

esp_err_t esp_playlist_del(esp_playlist_handle_t handle)

  Destroy a playlist handle and free its resources.

  Parameters:

    handle – [in] Playlist handle

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle is NULL

esp_err_t esp_playlist_import_media(esp_playlist_handle_t handle, esp_media_db_handle_t media_db_handle, const esp_media_filter_t *filter)

  Import media entries from a catalog into the playlist.

          Appends matching catalog rows to the playlist (no dedup by media_id).
          On failure, entries appended during this call are removed before returning.
          Binds the playlist to media_db_handle; a later import from a different handle
          returns ESP_ERR_INVALID_STATE.

  Parameters:

    - handle – [in] Playlist handle

    - media_db_handle – [in] Source media catalog

    - filter – [in] Optional filter; NULL appends all catalog rows

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or media_db_handle is NULL, or filter is invalid

    - ESP_ERR_INVALID_STATE If the playlist is bound to another media DB

    - ESP_ERR_NOT_FOUND If the catalog is empty or no rows matched the filter

    - ESP_ERR_NO_MEM If allocation fails

    - ESP_FAIL On other internal media lookup errors

esp_err_t esp_playlist_load(esp_playlist_handle_t handle, const char *load_path)

  Replace the in-memory playlist from a JSON file.

          Not append semantics. JSON playlist format matches esp_playlist_save(),
          esp_playlist_export_ram(), and esp_playlist_import_ram(). Independent of
          esp_media_db VFS catalog files.

  Parameters:

    - handle – [in] Playlist handle

    - load_path – [in] Path to JSON playlist file

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or load_path is NULL

    - ESP_ERR_NO_MEM If allocation fails while parsing or building items

    - ESP_FAIL If the file cannot be read or JSON is invalid

esp_err_t esp_playlist_save(esp_playlist_handle_t handle, const char *save_path)

  Write the current playlist to a JSON file.

          JSON playlist format matches esp_playlist_export_ram(), esp_playlist_load(),
          and esp_playlist_import_ram().

  Parameters:

    - handle – [in] Playlist handle

    - save_path – [in] Path to JSON playlist file

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or save_path is NULL

    - ESP_ERR_NO_MEM If JSON allocation fails

    - ESP_FAIL If the file cannot be written

esp_err_t esp_playlist_import_ram(esp_playlist_handle_t handle, const char *buf, size_t buf_len)

  Replace the in-memory playlist from a JSON buffer in RAM.

          Same replace semantics as esp_playlist_load(). The buffer must contain JSON in
          the same playlist format as the file read by esp_playlist_load() (and as written
          by esp_playlist_save() / esp_playlist_export_ram()). Parsed entries become inline
          items with copied name and url strings.

  Parameters:

    - handle – [in] Playlist handle

    - buf – [in] JSON playlist text buffer

    - buf_len – [in] Byte length of buf; if 0, buf is treated as a NUL-terminated string

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or buf is NULL

    - ESP_ERR_NO_MEM If allocation fails while parsing or building items

    - ESP_FAIL If buffer content is invalid or missing required fields

esp_err_t esp_playlist_export_ram(esp_playlist_handle_t handle, char **out_buf, size_t *out_len)

  Export the current playlist to a heap-allocated JSON buffer.

          JSON uses the same playlist format as esp_playlist_save() writes to a file and
          as esp_playlist_load() / esp_playlist_import_ram() accept. The returned string is
          NUL-terminated. Caller must release it with free().

  Parameters:

    - handle – [in] Playlist handle

    - out_buf – [out] Receives the JSON buffer on success; set to NULL on failure

    - out_len – [out] Optional; receives strlen(out_buf); may be NULL

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or out_buf is NULL

    - ESP_ERR_NO_MEM If allocation fails

    - ESP_FAIL If serialization fails

esp_err_t esp_playlist_clean(esp_playlist_handle_t handle)

  Clear all items from the in-RAM playlist.

          Does not delete JSON or media DB files on disk.

  Parameters:

    handle – [in] Playlist handle

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle is NULL

esp_err_t esp_playlist_set_repeat_mode(esp_playlist_handle_t handle, esp_playlist_repeat_mode_t repeat_mode)

  Set repeat mode for navigation APIs.

  Parameters:

    - handle – [in] Playlist handle

    - repeat_mode – [in] Repeat behavior

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle is NULL or repeat_mode is out of range

esp_err_t esp_playlist_set_curr_index(esp_playlist_handle_t handle, int index)

  Set the current playback index without loading item info.

          Invalidates the esp_playlist_curr() cache. Default index after esp_playlist_new()
          is 0.

  Parameters:

    - handle – [in] Playlist handle

    - index – [in] Zero-based index; must be < item count

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle is NULL or index < 0

    - ESP_ERR_NOT_FOUND If index >= item count

esp_err_t esp_playlist_next(esp_playlist_handle_t handle, esp_playlist_info_t *info)

  Advance to the next item and fill info.

          Updates current index according to repeat_mode. REPEAT_ALL wraps at the end;
          REPEAT_NONE returns ESP_ERR_NOT_FOUND at the last item.

  Parameters:

    - handle – [in] Playlist handle

    - info – [out] Caller buffer; strings are copied on success

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or info is NULL

    - ESP_ERR_NOT_FOUND If the list is empty or the boundary is reached

    - ESP_ERR_INVALID_STATE If a DB item has no bound media catalog

    - ESP_FAIL On internal media lookup failure

esp_err_t esp_playlist_prev(esp_playlist_handle_t handle, esp_playlist_info_t *info)

  Move to the previous item and fill info.

          Updates current index according to repeat_mode. REPEAT_ALL wraps at the start;
          REPEAT_NONE returns ESP_ERR_NOT_FOUND at the first item.

  Parameters:

    - handle – [in] Playlist handle

    - info – [out] Caller buffer; strings are copied on success

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or info is NULL

    - ESP_ERR_NOT_FOUND If the list is empty or the boundary is reached

    - ESP_ERR_INVALID_STATE If a DB item has no bound media catalog

    - ESP_FAIL On internal media lookup failure

esp_err_t esp_playlist_curr(esp_playlist_handle_t handle, esp_playlist_info_t *info)

  Read the current item without changing the index.

          Uses an in-RAM cache when valid; otherwise loads from the bound media catalog
          or inline JSON items.

  Parameters:

    - handle – [in] Playlist handle

    - info – [out] Caller buffer; strings are copied on success

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or info is NULL

    - ESP_ERR_NOT_FOUND If the list is empty

    - ESP_ERR_INVALID_STATE If a DB item has no bound media catalog

    - ESP_FAIL On internal media lookup failure

esp_err_t esp_playlist_get_info(esp_playlist_handle_t handle, int index, esp_playlist_info_t *info)

  Read one item by index without changing the current playback index.

  Parameters:

    - handle – [in] Playlist handle

    - index – [in] Zero-based index; must be < item count

    - info – [out] Caller buffer; strings are copied on success

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or info is NULL, or index < 0

    - ESP_ERR_NOT_FOUND If index >= item count

    - ESP_ERR_INVALID_STATE If a DB item has no bound media catalog

    - ESP_FAIL On internal media lookup failure

esp_err_t esp_playlist_get_count(esp_playlist_handle_t handle, int *count)

  Get the number of items in the playlist.

  Parameters:

    - handle – [in] Playlist handle

    - count – [out] Receives item count on success

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or count is NULL

### Structures

struct esp_playlist_info_t

  Snapshot of one playlist entry for navigation APIs.

          Caller supplies the structure; APIs copy strings into fixed buffers.
          URLs longer than ESP_PLAYLIST_URL_MAX - 1 are truncated with a trailing NUL.

  Public Members

  char playlist_name[ESP_PLAYLIST_NAME_MAX]

    Playlist name

  char media_name[ESP_PLAYLIST_MEDIA_NAME_MAX]

    Media display name

  char media_url[ESP_PLAYLIST_URL_MAX]

    Media URL

  int index

    Zero-based index in the list

struct esp_playlist_cfg_t

  Playlist creation configuration.

  Public Members

  const char *playlist_name

    Non-empty playlist name; copied internally

### Macros

ESP_PLAYLIST_NAME_MAX

  Maximum length of playlist name string (including NUL). Configurable via menuconfig.

ESP_PLAYLIST_MEDIA_NAME_MAX

  Maximum length of media display name in esp_playlist_info_t (including NUL). Configurable via menuconfig.

ESP_PLAYLIST_URL_MAX

  Maximum length of media URL in esp_playlist_info_t (including NUL). Configurable via menuconfig.

### Type Definitions

typedef void *esp_playlist_handle_t

  Opaque handle for a playlist instance.

### Enumerations

enum esp_playlist_repeat_mode_t

  Repeat mode for esp_playlist_next() and esp_playlist_prev().

  Values:

  enumerator ESP_PLAYLIST_REPEAT_NONE

    Stop at list boundary (ESP_ERR_NOT_FOUND)

  enumerator ESP_PLAYLIST_REPEAT_ONE

    Stay on current index

  enumerator ESP_PLAYLIST_REPEAT_ALL

    Wrap at list ends

  enumerator ESP_PLAYLIST_REPEAT_SHUFFLE

    Pick a random index on next/prev

### Header File

- components/esp_playlist/include/esp_media_db.h

### Functions

esp_err_t esp_media_db_init(const esp_media_db_cfg_t *cfg, esp_media_db_handle_t *handle)

  Create a media catalog handle and empty runtime state.

          Does not load existing filesystem data. Call esp_media_db_load(), esp_media_db_scan(),
          or esp_media_db_add() to populate the catalog.

  Parameters:

    - cfg – [in] Storage type and path; must not be NULL

    - handle – [out] Receives the new handle on success; set to NULL on failure

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If cfg or handle is NULL, or storage_type is invalid

    - ESP_ERR_NO_MEM If allocation fails

    - ESP_FAIL If storage backend setup fails

esp_err_t esp_media_db_deinit(esp_media_db_handle_t handle)

  Release a catalog handle created by esp_media_db_init().

  Parameters:

    handle – [in] Catalog handle

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle is NULL

esp_err_t esp_media_db_load(esp_media_db_handle_t handle)

  Load catalog data from the filesystem three-file database.

          If loading fails, an empty catalog is created and ESP_OK is still returned
          after recreation (see implementation log).

  Parameters:

    handle – [in] Catalog handle

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle is NULL

    - ESP_ERR_NO_MEM If opening or recreating the internal library fails

esp_err_t esp_media_db_clean(esp_media_db_handle_t handle)

  Clear the in-memory catalog without deleting filesystem files.

  Parameters:

    handle – [in] Catalog handle

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle is NULL

esp_err_t esp_media_db_scan(esp_media_db_handle_t handle, const esp_media_db_scan_cfg_t *scan_cfg)

  Scan a directory tree and add matching files to the catalog.

          When skip_duplicate is false, URL deduplication applies only if the catalog
          already has entries; an empty catalog is scanned without deduplication.
          May be called multiple times (e.g. different mount points). Changes persist
          on the filesystem when storage_type is ESP_DB_STORAGE_FS.

  Parameters:

    - handle – [in] Catalog handle

    - scan_cfg – [in] Scan path, scan_depth, extensions, skip_duplicate, and callback

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or scan_cfg is NULL, or scan_cfg fields are invalid

    - ESP_ERR_NO_MEM If the internal library cannot be opened or scan fails

    - ESP_FAIL On other internal scan errors

esp_err_t esp_media_db_add(esp_media_db_handle_t handle, const esp_media_db_item_t *items, int count)

  Add one or more items to the catalog.

          Skips items whose URL already exists. name and url pointers are stored by
          reference (not copied into a separate RAM cache). Persists on filesystem after add.

  Parameters:

    - handle – [in] Catalog handle

    - items – [in] Array of count items; each url must be non-NULL

    - count – [in] Number of entries in items; must be > 0

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle, items is NULL, or count <= 0

    - ESP_ERR_NO_MEM If the internal library cannot be opened or add fails

    - ESP_FAIL On other internal add errors

esp_err_t esp_media_db_remove(esp_media_db_handle_t handle, const esp_media_db_item_t *items, int count)

  Remove catalog items matching the given URLs.

  Parameters:

    - handle – [in] Catalog handle

    - items – [in] Array of count items; each url must be non-NULL

    - count – [in] Number of entries in items; must be > 0

  Returns:

    - ESP_OK On success (including when no rows matched)

    - ESP_ERR_INVALID_ARG If handle, items is NULL, count <= 0, or an item url is NULL

    - ESP_ERR_NO_MEM If allocation or internal library access fails

    - ESP_FAIL On other internal remove errors

esp_err_t esp_media_db_get_count(esp_media_db_handle_t handle, int *count)

  Get the number of rows in the catalog.

  Parameters:

    - handle – [in] Catalog handle

    - count – [out] Receives the item count on success

  Returns:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If handle or count is NULL

    - ESP_ERR_NO_MEM If the internal library cannot be opened

    - ESP_FAIL On other internal query errors

### Structures

struct esp_media_db_cfg_t

  Media catalog initialization configuration.

  Public Members

  esp_db_storage_type_t storage_type

    FS persistence or RAM-only

  const char *storage_path

    Filesystem base path (e.g. /sdcard/__playlist), or logical name for RAM backend

### Type Definitions

typedef void *esp_media_db_handle_t

  Opaque handle for a media catalog instance.

### Header File

- components/esp_playlist/include/esp_media_db_types.h

### Structures

struct esp_db_field_value_t

  Typed value container for catalog columns and filter operands.

  Public Members

  esp_db_field_type_t type

    Active member of value

  int intv

    ESP_DB_FIELD_TYPE_INT

  float floatv

    ESP_DB_FIELD_TYPE_FLOAT

  bool boolv

    ESP_DB_FIELD_TYPE_BOOL

  const char *strv

    ESP_DB_FIELD_TYPE_STRING; lifetime per API contract

  const int *intarrv

    ESP_DB_FIELD_TYPE_INT_ARRAY

  union esp_db_field_value_t::[anonymous] value

    Payload selected by type

  int size

    STRING: byte length (often strlen+1); INT_ARRAY: n*sizeof(int); scalars: sizeof(int), sizeof(float), or sizeof(bool)

struct esp_media_db_item_t

  Media catalog item passed to add/remove APIs.

  Public Members

  const char *name

    Display name (catalog column “name”)

  const char *url

    Media locator (catalog column “url”)

struct esp_media_filter_item_t

  Single filter condition on a catalog column.

  Public Members

  const char *key

    Column name, e.g. “name”, “url”, or “id”

  esp_db_field_value_t expected

    Expected value; type must match the column

  esp_media_match_type_t match_type

    Comparison mode

struct esp_media_filter_t

  Combined filter with AND or OR semantics.

  Public Members

  const esp_media_filter_item_t *items

    Array of item_count conditions

  uint8_t item_count

    Number of entries in items

  bool match_all

    true: AND all conditions; false: OR

struct esp_media_db_scan_cfg_t

  Directory scan configuration for esp_media_db_scan().

  Public Members

  bool skip_duplicate

    true: skip URL dedup; false: dedup when catalog is non-empty

  const char *path

    Scan root directory

  uint8_t scan_depth

    Max recursion depth under path (0 = path only)

  const char *const *file_extensions

    Allowed extensions; NULL if count is 0

  uint8_t file_extension_count

    Length of file_extensions; 0 disables filter

  esp_media_scan_filter_cb_t filter_cb

    Optional post-scan callback; NULL to disable

  void *filter_cb_ctx

    Context for filter_cb

### Macros

ESP_MEDIA_INVALID_ID

  Invalid media ID; valid row IDs are non-negative (0, 1, 2, …).

### Type Definitions

typedef int esp_media_id_t

  Media catalog row identifier.

typedef bool (*esp_media_scan_filter_cb_t)(void *ctx, const char *url)

  Scan callback to accept or reject a discovered file URL.

  Param ctx:

    [in] Opaque context from esp_media_db_scan_cfg_t::filter_cb_ctx

  Param url:

    [in] File URL discovered during scan

  Return:

    - true to add the file to the catalog, false to skip it

### Enumerations

enum esp_db_storage_type_t

  Storage backend kind for the media catalog.

  Values:

  enumerator ESP_DB_STORAGE_FS

    Persist catalog under storage_path on filesystem

  enumerator ESP_DB_STORAGE_RAM

    Runtime-only; heap-backed, not on filesystem

enum esp_db_field_type_t

  Typed field value used in filters and playlist metadata.

  Values:

  enumerator ESP_DB_FIELD_TYPE_INVALID

    Invalid or unset type

  enumerator ESP_DB_FIELD_TYPE_INT

    Single integer

  enumerator ESP_DB_FIELD_TYPE_FLOAT

    Single-precision float

  enumerator ESP_DB_FIELD_TYPE_STRING

    NUL-terminated C string

  enumerator ESP_DB_FIELD_TYPE_BOOL

    Boolean

  enumerator ESP_DB_FIELD_TYPE_INT_ARRAY

    Dense int array

enum esp_media_match_type_t

  String comparison mode for a single filter condition.

  Values:

  enumerator ESP_MEDIA_MATCH_EXACT

    Exact match for string or scalar

  enumerator ESP_MEDIA_MATCH_CONTAINS

    Substring match (strings only)

  enumerator ESP_MEDIA_MATCH_PREFIX

    Prefix match (strings only)

Provide feedback about this document