Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

v1 source realm

Package radio is GnoRadio's radio rules, release 1: a main station that plays the whole catalog through the genre sta...

Overview

Package radio is GnoRadio's radio rules, release 1: a main station that plays the whole catalog through the genre stations, one station per genre, "New this week" (the newest tracks) and "Listeners' choice" (the tracks listeners picked). Everyone tuned to a station hears the same track at the same second, computed from block time; no streaming server is involved. Between picks the main station simulcasts one genre station an hour, by the time of day (flow.gno); it has no rotation of its own.

Each station has a rotation (every playable track of its genre, looping) stored in fixed-size blocks so that every operation costs the same whatever the catalog size, and a short schedule of tracks programmed by listeners. While a programmed track plays the rotation pauses, then resumes where it was. Adding, removing or editing a track never makes listeners jump.

It keeps no state but its admin role. Every record lives in the data realm (gno.land/r/nym-alexiscolin000/gnoradio/data), in the "radio/…" collections only the current radio writer may change (db.gno). It reads the catalog through its value getters; sponsored picks are paid from data's vault through the catalog.

Constants 2

const MainStation, NewStation, ChoiceStation, numStations, newCap, choiceCap, maxQueue, maxPerArtistQ, maxSyncBatch, maxRefreshBatch, foldAfter, queueCooldown, replayGap, maxAheadAir, maxNote, noteCertLife, hideAfter, muteFor, bookMin, bookMax, maxBookedHour, maxKept, maxBooked, maxTrack, recordHeadroom, plainSlot

 1const (
 2	MainStation     = 0
 3	NewStation      = NumGenres + 1 // the newest newCap ingested tracks
 4	ChoiceStation   = NumGenres + 2 // the last choiceCap distinct listener picks
 5	numStations     = ChoiceStation + 1
 6	newCap          = 300
 7	choiceCap       = 500
 8	maxQueue        = 30 // upcoming slots per station
 9	maxPerArtistQ   = 2  // upcoming slots per artist and station
10	maxSyncBatch    = 200
11	maxRefreshBatch = 50
12	foldAfter       = 3600          // programmed slots ended this long ago fold into the epoch
13	queueCooldown   = 3600          // a listener may queue once per station per hour
14	replayGap       = 3 * 3600      // a track picked on a station cannot be picked there again for 3 hours, by anyone
15	maxAheadAir     = 7200          // listener-programmed airtime ahead on a station, seconds
16	maxNote         = 40            // characters of a dedication
17	noteCertLife    = 900           // seconds a moderation certificate may still have to live
18	hideAfter       = 3             // distinct reputable listeners (sponsorBlock) reporting a dedication hide it
19	muteFor         = 7 * 24 * 3600 // a second hidden dedication within this time mutes its author this long
20	bookMin         = 15 * 60       // a pick booked for a time: at least this far ahead
21	bookMax         = 24 * 3600     // and at most this far
22	maxBookedHour   = 4             // booked picks per station and clock hour (UTC)
23	maxKept         = 3 * maxQueue  // listener slots a station keeps, aired ones included until they fold
24	maxBooked       = maxQueue / 2  // booked picks waiting per station
25	maxTrack        = 1200          // the catalog's longest track, seconds
26	recordHeadroom  = 1024          // bytes a station record keeps free for the writes that follow a pick
27	plainSlot       = 72            // record bytes of a listener slot without a dedication: 25, an address, at most 7 of gap
28)
source

Station ids are stored keys in the permanent data realm (schedules, drops, notes, curator ranks): Main 0, genres 1..NumGenres, New, Choice. A later release must keep them, and add any new station after Choice.

const NumGenres

1const NumGenres = catalog.NumGenres
source

NumGenres is the catalog's: genre stations are 1..NumGenres.

Functions 50

func ActivityJSON

Action
1func ActivityJSON(limit int) string
source

ActivityJSON returns the programming feed, newest first (limit <= 64).

func ClaimPickPayout

crossing Action
1func ClaimPickPayout(cur realm, stationID int, start int64)
source

ClaimPickPayout sends the caller the refund of their sponsored pick that started at start on stationID, once it has aired in full.

func CuratorJSON

Action
1func CuratorJSON(addr address) string
source

CuratorJSON returns a listener's curator record: all time, this week, and their place in this week's top across stations (0 when outside the top 10).

func CuratorQueue

crossing Action
1func CuratorQueue(cur realm, stationID, trackID int)
source

CuratorQueue programs a track like Queue but without the per-listener and per-artist quotas (the duplicate, genre and queue-size rules still apply). Radio admin only.

func DropSlot

crossing Action
1func DropSlot(cur realm, stationID, trackID int)
source

DropSlot silences a track in one station's rotation (moderation of last resort). It stays silent through Refresh until RestoreSlot. Radio admin only.

func EditTrack

crossing Action
1func EditTrack(cur realm, trackID int, title string, genre int, duration, credits, audio, audioSHA, cover, coverSHA string)
source

EditTrack fixes a track's details (the arguments are catalog.EditFor's). A new genre or duration is applied to the stations in the same transaction, as Refresh does; other details need nothing on air.

func HourGenre

Action
1func HourGenre(at int64) int
source

HourGenre is the genre Main relays at unix time at (0: none), for pages that explain it.

func ImportTrack

crossing Action
1func ImportTrack(cur realm, artistID int, title string, genre int, duration, license, credits, audio, audioSHA, cover, coverSHA, sourceURL, attribution string) int
source

ImportTrack adds a curated or Audius track to an unclaimed artist (the arguments are catalog.ImportFor's) and puts it on the air, New this week left out: an import is not a new release. The catalog admin only, from its wallet or a realm that holds the role (a launch import).

func ImportTracks

crossing Action
1func ImportTracks(cur realm, batch string) int
source

ImportTracks imports up to maxImportBatch tracks in one transaction, so the realms load once for the batch instead of once per track. batch holds one track per line ("\n"), ImportTrack's 12 arguments separated by tabs ("\t"; neither can appear in a valid field). All or nothing: a bad track panics the whole transaction (a malformed line is named before anything is written). It returns the id of the last track. Admin only, as ImportTrack.

func MutedUntil

Action
1func MutedUntil(who address) int64
source

MutedUntil returns the unix time until which who's dedications are paused after reports, 0 when they are not: the moderation robot refuses to sign for a muted author.

func NoteMessage

Action
1func NoteMessage(author address, stationID int, note string, expires int64) string
source

NoteMessage is what the moderation robot signs to approve a dedication by author on stationID until expires (unix seconds), on this chain and this GnoRadio deployment (its data realm) only: "gnoradio-note|<chain id>|<data realm>|<author>|<station>|<note>|<expires>". A certificate seen in a public transaction serves no other wallet, station or deployment.

func NowPlaying

Action
1func NowPlaying(stationID int) (trackID int, offset int64, queued bool)
source

NowPlaying returns what a station plays at the last block: the track, the offset into it in seconds, and whether a listener programmed it. trackID is 0 when nothing plays. Clients should prefer ScheduleJSON and their clock.

func OfferAdmin

crossing Action
1func OfferAdmin(cur realm, to address)
source

OfferAdmin offers the admin role to an address (offering it to the admin cancels the offer); AcceptAdmin takes it. Each change is mirrored to the data realm, so the next release keeps the admin.

func OnAirNote

Action
1func OnAirNote(stationID int) string
source

OnAirNote returns the dedication of the programmed slot on air ("" when none, or once reports hid it).

func OnAirPay

Action
1func OnAirPay(stationID int) int64
source

OnAirPay is the refund of the sponsored pick on air (0: none), for labels.

func Pending

Action
1func Pending() int
source

Pending returns how many catalog tracks are not on the stations yet: 0, since publishing puts a track on the air (Sync is the safety net).

func PickPayoutStatus

Action
1func PickPayoutStatus(addr address, stationID int, start int64) string
source

PickPayoutStatus says what ClaimPickPayout would do for addr's sponsored pick that started at start on stationID: "ok" (it pays), "airing" (not finished yet), "lapsed" (nothing to pay: lapsed or cancelled; collecting only clears it) or "none" (no such open pick).

func PickRules

Action
1func PickRules() (cooldown, replay, ahead int64, queue, perArtist int, bookFrom, bookTo int64, bookedPerHour, booked int)
source

PickRules returns the limits on listeners' picks, for pages that explain them: one pick per cooldown per station, a track not again within replay, at most ahead seconds and queue slots waiting, perArtist waiting per artist, booked picks bookFrom to bookTo ahead, bookedPerHour per clock hour and booked of the queue slots at most.

func PublishTrack

crossing Action
1func PublishTrack(cur realm, title string, genre int, duration, license, cmo, credits, audio, audioSHA, cover, coverSHA, splits, rights string) int
source

PublishTrack publishes a track by the caller's own artist profile (the arguments are catalog.PublishFor's) and puts it on the air in the same transaction: the main station, its genre station and New this week.

func Queue

crossing Action
1func Queue(cur realm, stationID, trackID int)
source

Queue programs a track on a station and adds it to Listeners' choice. It starts after the last track a listener programmed, or when the song on air ends: nothing is cut. On Main it starts at once over the hour's relay (the app crossfades), which resumes after it. Limits per station: one waiting slot per listener, two per artist, a track at most once, 30 upcoming.

func QueueAt

crossing Action
1func QueueAt(cur realm, stationID, trackID int, at int64)
source

QueueAt is Queue for a chosen time: at (unix, UTC) between 15 minutes and 24 hours from now; 0 is Queue. The pick starts at the first track boundary at or after at (on Main, at at: the relay's track fades out as for any pick), unless listener picks fill that moment, then right after them. It keeps its time: later picks go before it only if they end by then, else after it. Every Queue rule applies, the 3-hour replay gap around at; the 2-hour airtime cap does not, but at most 4 picks are booked per station and clock hour and at most 15 booked picks wait per station.

func QueueSponsored

crossing Action
1func QueueSponsored(cur realm, stationID, trackID int)
source

QueueSponsored is Queue paid by the artist: once the pick has aired in full, ClaimPickPayout sends the picker the artist's refund (catalog PromoOffer). No dedication. A wallet has one sponsored pick open per station: it must be collected (or have lapsed) before the next.

func QueueSponsoredAt

crossing Action
1func QueueSponsoredAt(cur realm, stationID, trackID int, at int64)
source

QueueSponsoredAt is QueueSponsored for a chosen time (see QueueAt; 0: now). The refund lapses 7 days after the booked time plus the track's length.

func QueueWithNote

crossing Action
1func QueueWithNote(cur realm, stationID, trackID int, note string, expires int64, sigHex string)
source

QueueWithNote is Queue with a dedication shown on air ("for Marie!"). The moderation robot judges it before the transaction (word filter and a moderation model, app/netlify/functions/dedication.mts) and signs NoteMessage(note, expires): the listener sends that certificate and pays their own gas, so a dedication shows at once and costs GnoRadio nothing. It must also pass p/gnoradio/safe (plain text, no link, no blocked word). Listeners can report it: three reports hide it and give its author a strike; a second hidden dedication within a week pauses their dedications for a week (ReportNote). The pause is per wallet: an author can dedicate again from a fresh one, which reports hide and pause the same way (accepted residual; the robot and the word filter still judge every note).

func QueueWithNoteAt

crossing Action
1func QueueWithNoteAt(cur realm, stationID, trackID int, at int64, note string, expires int64, sigHex string)
source

QueueWithNoteAt is QueueWithNote for a chosen time (see QueueAt; 0: now).

func Ready

crossing Action
1func Ready(cur realm)
source

Ready tells the data realm that this release is on chain (see data.Propose). Anyone may call it.

func Refresh

crossing Action
1func Refresh(cur realm, trackID int)
source

Refresh re-reads a track from the catalog and updates its rotation slots: a hidden track goes silent, a restored one comes back, an edited duration is applied. Programmed slots of a track that is no longer playable are dropped. Anyone may call it. A slot the admin dropped stays silent.

func RefreshArtist

crossing Action
1func RefreshArtist(cur realm, artistID, offset int) int
source

RefreshArtist refreshes up to maxRefreshBatch synced tracks of an artist, from offset in the artist's track list, so hiding (or restoring) a whole artist takes a few calls instead of one per track. It returns the offset to pass next, or 0 when the list is done. Anyone may call it.

func Render

1func Render(_ string) string
source

Render points gnoweb visitors to the GnoRadio site; a retired release says which realm took over.

func RenounceAdmin

crossing Action
1func RenounceAdmin(cur realm)
source

RenounceAdmin gives the admin role up for good, for this release and the next ones.

func ReportNote

crossing Action
1func ReportNote(cur realm, stationID int, start int64)
source

ReportNote flags the dedication of the slot starting at start. Only a listener with the reputation sponsored picks need (a first pick a week old, 3 normal picks this 15-day period and the one before: sponsorBlock) may report, so throwaway wallets cannot; the third such listener hides it at once, with no moderator involved. A first hidden dedication is a strike; a second within muteFor pauses its author's dedications for muteFor (the admin can lift it: Unmute).

func RestoreNote

crossing Action
1func RestoreNote(cur realm, stationID int, start int64)
source

RestoreNote shows again a dedication hidden by reports by mistake and clears its author's strike (Unmute lifts a pause). Radio admin only.

func RestoreSlot

crossing Action
1func RestoreSlot(cur realm, stationID, trackID int)
source

RestoreSlot undoes DropSlot: the track plays again on that station if the catalog still allows it. Radio admin only.

func ScheduleJSON

Action
1func ScheduleJSON(stationID, horizon int) string
source

ScheduleJSON returns what a station plays from now until now+horizon seconds (60..7200, at most 60 entries): programmed slots and the rotation between them (on Main, the hour's genre station, simulcast and cut at each hour). A client plays entry i from offset+max(0, clock-start) and resyncs on "now". "relay" marks, on Main, an entry that is not Main's own slot but the hour's genre station simulcast (its picks included). "sponsored" is the refund its artist pays the picker (0: a normal pick), "at" the time a booked pick asked for (0: none). "booked" lists every booked pick still to air, whatever the horizon, and those that aired in the last hour (they count toward their clock hour's cap until they fold): {"track","start","end","at","by","note"}. Fetch it again every few minutes, not every second.

func SetModBot

crossing Action
1func SetModBot(cur realm, pubKeyHex string)
source

SetModBot names the moderation robot by its Ed25519 public key in hex ("" turns dedications off). Radio admin only.

func SponsoredJSON

Action
1func SponsoredJSON(addr address) string
source

SponsoredJSON lists a wallet's sponsored picks not collected yet, with whether it may take new ones and each one's PickPayoutStatus: {"block":"why not, or empty","open":[{"station","start","track","end","amount","status"}]}.

func StationInfo

Action
1func StationInfo(stationID int) (tracks int, loop int64, queued int)
source

StationInfo returns how many tracks rotate on a station and the loop length.

func StationName

Action
1func StationName(stationID int) string
source

StationName is "Main", the genre name, "New this week" or "Listeners' choice".

func Sync

crossing Action
1func Sync(cur realm, max int) int
source

Sync ingests up to max catalog tracks not yet on the stations into the main station, the station of their genre and New; the catalog's most liked tracks join Listeners' choice. Main's flow needs no Sync (flow.gno). Anyone may call it. PublishTrack and ImportTrack put each new track on the air themselves (publish.gno), so this is a safety net: a track is never ingested twice (the flow record counts the synced ones). A track that is not playable yet is added silent (duration 0) and Refresh turns it on.

func TipOnAir

crossing Action
1func TipOnAir(cur realm, stationID, trackID, supportPct int, ref address)
source

TipOnAir tips the artist of trackID: the attached ugnot go through the catalog, which pays the artist and collaborators exactly as catalog.TipWithSupport does. When trackID is a listener's pick on air on stationID (or ended less than two minutes ago), the artist's promo share goes to that listener; the radio reads the picker from its own schedule. ref is who shared the link the tipper came from ("" for none): picker and ref split the promo share, never more.

func TopCuratorsJSON

Action
1func TopCuratorsJSON(stationID int) string
source

TopCuratorsJSON returns TopCurators as JSON with the week's start (unix).

func Unmute

crossing Action
1func Unmute(cur realm, who address)
source

Unmute lets a muted listener dedicate again before the week ends, e.g. after reports by throwaway wallets. Radio admin only.

func Unqueue

crossing Action
1func Unqueue(cur realm, stationID, trackID int)
source

Unqueue removes a track's programmed slots from a station; one on air ends now. Radio admin (curator) only.

func Activities

Action
1func Activities(limit int) []Activity
source

Activities returns up to limit entries, newest first.

func CuratorOf

Action
1func CuratorOf(addr address) Curator
source

CuratorOf returns a listener's curator record, all time.

func TopCurators

Action
1func TopCurators(stationID int) []Curator
source

TopCurators returns this week's top curators of a station (allStations: every station), best first, with their counts for the week. Picks and tips received on air score one point each.

func UpNext

Action
1func UpNext(stationID int) []Slot
source

UpNext returns the slots listeners programmed on a station that have not started yet.

Types 3

type Activity

struct
1type Activity struct {
2	Kind    string // queue | curator | sponsored
3	By      address
4	Track   int
5	Station int
6	Start   int64
7	At      int64
8}
source

Activity is one programming action on a station.

type Curator

struct
1type Curator struct {
2	Address address
3	Picks   int
4	Tips    int   // tips received while their picks were on air
5	Earned  int64 // ugnot from those tips
6	Promo   int64 // ugnot refunded by artists for sponsored picks (sponsor.gno)
7}
source

Curator is a picker's record, all time or for one week.

type Slot

struct
 1type Slot struct {
 2	Track      int
 3	Start      int64
 4	Dur        int64
 5	By         address
 6	Note       string // the picker's dedication, checked by p/gnoradio/safe and the moderation robot
 7	NoteHidden bool   // hidden by reports or the admin
 8	Pay        int64  // a sponsored pick: the ugnot its artist reserved to refund the picker (sponsor.gno)
 9	At         int64  // a booked pick: the time asked (unix); it starts at the first track boundary at or after it
10	artist     int    // a listener slot's artist (a track never changes artist): the per-artist rules read it
11	body       string // the encoded slot without its start, reused while it does not change (db.gno)
12	bdur       int64  // the duration body holds
13}
source

Slot is a track a listener (or a curator) programmed on a station. Dur is captured when queued so later catalog edits cannot move the timeline.

Imports 16

Source Files 13