Skip to content

Exports & Integration

ARS CarPlay does not register traditional exports['ars_carplay'] functions. Its integration surface is exposed through ox_lib callbacks and client events that other resources can call/trigger. This page documents the stable, intentional interfaces.

Note: Internal NUI callbacks (musicAction, vehicleAction, navigationAction, radioAction, radioFetchStations, saveSettings, getInitialState, uiReady, closeUI) are for the Preact UI only. They are not guaranteed stable for external use.

Call these from any server script via lib.callback.await('ars_carplay:<name>', source, payload).

Retrieve the persisted settings blob for a player/vehicle.

local res = lib.callback.await('ars_carplay:getSettings', source, {
scope = 'plate', -- 'plate' | 'player' (matches Config.CarPlay.settingsScope)
plate = 'ABC123' -- required when scope = 'plate'
})
-- res = { ok = true, settings = { lastApp = 'music', layout = 'cluster', ... }, persistable = true }
  • Side: Server
  • Scope: Matches Config.CarPlay.settingsScope (plate = per-vehicle, player = per-character).
  • Persistable: true if the vehicle is owned (or scope is player), false for NPC/unowned vehicles (memory-only).

Persist a partial settings patch (merged onto existing blob).

local ok = lib.callback.await('ars_carplay:saveSettings', source, {
scope = 'plate',
plate = 'ABC123',
data = { layout = 'desktop', lastApp = 'navigation' }
})
-- ok = true | false
  • Side: Server
  • Data: Any subset of CarPlaySettings (layout, lastApp, speedUnit, tablet.position, music.{station,volume}).

Unified audio control for Music and Internet Radio. Routes to xsound server exports.

local res = lib.callback.await('ars_carplay:audio:command', source, {
app = 'music', -- 'music' | 'radio'
cmd = 'play', -- 'play' | 'pause' | 'resume' | 'stop' | 'setVolume' | 'seek' | 'position'
url = 'https://...', -- required for 'play'
volume = 0.5, -- 0.0 - 1.0
coords = vector3(x,y,z), -- required for positional play
loop = false, -- 'play' only
distance = 25.0, -- positional only
seconds = 30.0 -- 'seek' only
})
-- res = { ok = true, name = 'carplay_ABC123' }
  • Side: Server (called from client via lib.callback.await)
  • Positional vs Local: If coords provided → PlayUrlPos with source = -1 (broadcast to all, 3D proximity). Otherwise → PlayUrl with source = player (local only).
  • Sound ID: Derived from the vehicle plate (carplay_<PLATE> for music, carplay_radio_<PLATE> for radio). All players in the same vehicle share the handle.

Search/browse internet radio stations via the Radio Browser API.

local res = lib.callback.await('ars_carplay:fetchStations', source, {
tag = 'rock', -- Radio Browser tag (bytagexact)
-- OR
search = 'jazz fm' -- free-text search
})
-- res = { ok = true, stations = { { name, url, favicon, tags, codec, bitrate }, ... }, disabled = false }
  • Side: Server
  • Cache: Results cached for Config.Radio.browser.cacheSeconds (default 300s).
  • Disabled: Returns { ok = true, stations = {}, disabled = true } if Config.Radio.browser.enabled = false.

Trigger these from any client script to control the UI.

Force-open the CarPlay dashboard (respects vehicle/driver/class gates).

TriggerEvent('ars_carplay:client:openUI')
-- Internally calls Client.CanUseCarPlay() → shows error notification if not allowed

Force-close the CarPlay dashboard.

TriggerEvent('ars_carplay:client:closeUI')

The Bridge global is not an export — it’s a shared table populated by the active framework’s guarded files (frameworks/<fw>/shared.lua, client.lua, server.lua). Other resources should not depend on Bridge directly; use your framework’s native exports instead.

If you need to check vehicle ownership from another script, replicate the logic in frameworks/<fw>/server.lua → Bridge.IsVehicleOwned (soft oxmysql query with fallback).


-- server/main.lua (example)
RegisterCommand('givecarplay', function(source)
TriggerClientEvent('ars_carplay:client:openUI', source)
end)

Read Player’s Saved Layout from Another Script

Section titled “Read Player’s Saved Layout from Another Script”
-- server/main.lua
local res = lib.callback.await('ars_carplay:getSettings', source, {
scope = 'plate',
plate = GetVehicleNumberPlateText(GetVehiclePedIsIn(GetPlayerPed(source)))
})
if res.ok and res.settings.layout then
print('Player prefers layout:', res.settings.layout)
end

Play a Track via Server Script (e.g., DJ Job)

Section titled “Play a Track via Server Script (e.g., DJ Job)”
-- server/dj.lua
lib.callback.await('ars_carplay:audio:command', playerSrc, {
app = 'music',
cmd = 'play',
url = 'https://example.com/track.mp3',
volume = 0.7,
coords = GetEntityCoords(GetVehiclePedIsIn(GetPlayerPed(playerSrc))),
distance = 30.0
})

Edit Config.Radio.stations in config.lua (escrow-ignored). Each entry:

{ name = 'My Station', url = 'https://stream.example.com/live.mp3', genre = 'Electronic', bitrate = 128 }

URLs must be direct stream links (.mp3, .aac, .m3u8), not playlist pages.


Note: This guide is written by a third party. If you find any incorrect or outdated information, please contact us on Discord so we can update it for you.